Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/openapi/wallet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ components:
data_for_tool: {}
invoice_id:
type: string
inbox:
type: string
description: Inbox the invoice belongs to
auto_pay:
type: boolean
description: Automatically pay future invoices from this provider and tool
RestoreCoinbaseMPCWalletRequest:
type: object
required:
Expand Down
25 changes: 17 additions & 8 deletions shinkai-bin/shinkai-node/src/network/handle_commands_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ impl Node {
let listen_address_clone = self.listen_address;
let libp2p_manager_clone = self.libp2p_manager.clone();
tokio::spawn(async move {
let _ = Self::ping_all(
listen_address_clone,
libp2p_manager_clone,
)
.await;
let _ = Self::ping_all(listen_address_clone, libp2p_manager_clone).await;
});
}
NodeCommand::GetPublicKeys(sender) => {
Expand Down Expand Up @@ -1245,11 +1241,16 @@ impl Node {
let _ = Node::v2_api_get_shinkai_tool_metadata(db_clone, bearer, tool_router_key, res).await;
});
}
NodeCommand::V2ApiGetToolWithOffering { bearer, tool_key_name, res } => {
NodeCommand::V2ApiGetToolWithOffering {
bearer,
tool_key_name,
res,
} => {
let db_clone = Arc::clone(&self.db);
let node_name_clone = self.node_name.clone();
tokio::spawn(async move {
let _ = Node::v2_api_get_tool_with_offering(db_clone, node_name_clone, bearer, tool_key_name, res).await;
let _ = Node::v2_api_get_tool_with_offering(db_clone, node_name_clone, bearer, tool_key_name, res)
.await;
});
}
NodeCommand::V2ApiGetToolsWithOfferings { bearer, res } => {
Expand Down Expand Up @@ -1508,6 +1509,8 @@ impl Node {
bearer,
invoice_id,
data_for_tool,
inbox,
auto_pay,
res,
} => {
let db_clone = Arc::clone(&self.db);
Expand All @@ -1520,6 +1523,8 @@ impl Node {
bearer,
invoice_id,
data_for_tool,
inbox,
auto_pay,
node_name,
res,
)
Expand Down Expand Up @@ -1669,7 +1674,11 @@ impl Node {
let _ = Node::v2_api_get_job_scope(db_clone, bearer, job_id, res).await;
});
}
NodeCommand::V2ApiGetMessageTraces { bearer, message_id, res } => {
NodeCommand::V2ApiGetMessageTraces {
bearer,
message_id,
res,
} => {
let db_clone = Arc::clone(&self.db);
tokio::spawn(async move {
let _ = Node::v2_api_get_message_traces(db_clone, bearer, message_id, res).await;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,44 @@
use crate::{
managers::IdentityManager, network::{
managers::IdentityManager,
network::{
agent_payments_manager::{
external_agent_offerings_manager::ExtAgentOfferingsManager, my_agent_offerings_manager::MyAgentOfferingsManager
}, libp2p_manager::NetworkEvent, node::ProxyConnectionInfo, Node
}
external_agent_offerings_manager::ExtAgentOfferingsManager,
my_agent_offerings_manager::MyAgentOfferingsManager,
},
libp2p_manager::NetworkEvent,
node::ProxyConnectionInfo,
Node,
},
};
use ed25519_dalek::{SigningKey, VerifyingKey};

use libp2p::{request_response::ResponseChannel, PeerId};
use serde_json::json;
use shinkai_message_primitives::schemas::ws_types::WSUpdateHandler;
use shinkai_message_primitives::{
schemas::{
invoices::{Invoice, InvoiceRequest, InvoiceRequestNetworkError}, shinkai_name::ShinkaiName
}, shinkai_message::{
shinkai_message::{MessageBody, MessageData, ShinkaiMessage}, shinkai_message_error::ShinkaiMessageError, shinkai_message_extension::EncryptionStatus, shinkai_message_schemas::MessageSchemaType
}, shinkai_utils::{
encryption::clone_static_secret_key, shinkai_logging::{shinkai_log, ShinkaiLogLevel, ShinkaiLogOption}, shinkai_message_builder::{ShinkaiMessageBuilder, ShinkaiNameString}, signatures::{clone_signature_secret_key, signature_public_key_to_string}
}
invoices::{Invoice, InvoiceRequest, InvoiceRequestNetworkError},
shinkai_name::ShinkaiName,
},
shinkai_message::{
shinkai_message::{MessageBody, MessageData, ShinkaiMessage},
shinkai_message_error::ShinkaiMessageError,
shinkai_message_extension::EncryptionStatus,
shinkai_message_schemas::MessageSchemaType,
},
shinkai_utils::{
encryption::clone_static_secret_key,
shinkai_logging::{shinkai_log, ShinkaiLogLevel, ShinkaiLogOption},
shinkai_message_builder::{ShinkaiMessageBuilder, ShinkaiNameString},
signatures::{clone_signature_secret_key, signature_public_key_to_string},
},
};
use serde_json::json;
use shinkai_sqlite::SqliteManager;
use std::sync::{Arc, Weak};
use std::{io, net::SocketAddr};
use tokio::sync::Mutex;
use x25519_dalek::{PublicKey as EncryptionPublicKey, StaticSecret as EncryptionStaticKey};



pub enum PingPong {
Ping,
Pong,
Expand Down Expand Up @@ -518,7 +530,10 @@ pub async fn handle_network_message_cases(
),
);

eprintln!("🔑 InvoiceRequestNetworkError Received from: {:?} to {:?}", requester, receiver);
eprintln!(
"🔑 InvoiceRequestNetworkError Received from: {:?} to {:?}",
requester, receiver
);

let content = message.get_message_content().unwrap_or("".to_string());
match serde_json::from_str::<InvoiceRequestNetworkError>(&content) {
Expand Down Expand Up @@ -591,6 +606,25 @@ pub async fn handle_network_message_cases(
&format!("Failed to store invoice: {:?}", e),
);
}
let inbox_name = match message.get_message_inbox() {
Ok(name) => name,
Err(_) => String::new(),
};
let pref_key = format!(
"autopay:{}:{}:{}:{}",
invoice.requester_name.full_name,
invoice.provider_name.full_name,
invoice.shinkai_offering.tool_key,
inbox_name
);
if let Ok(Some(true)) = maybe_db.get_preference::<bool>(&pref_key) {
if let Err(e) = my_agent_offering_manager
.auto_pay_invoice(invoice.clone(), my_agent_offering_manager.node_name.clone())
.await
{
eprintln!("failed to auto pay invoice: {:?}", e);
}
}
if let Err(e) = maybe_db.add_tracing(
&invoice.invoice_id,
None,
Expand Down Expand Up @@ -649,8 +683,13 @@ pub async fn handle_network_message_cases(
Ok(invoice) => {
let mut ext_agent_offering_manager = ext_agent_offering_manager.lock().await;
if let Err(e) = ext_agent_offering_manager
.network_confirm_invoice_payment_and_process(requester, invoice, Some(message.external_metadata))
.await {
.network_confirm_invoice_payment_and_process(
requester,
invoice,
Some(message.external_metadata),
)
.await
{
shinkai_log(
ShinkaiLogOption::Network,
ShinkaiLogLevel::Error,
Expand Down Expand Up @@ -809,9 +848,12 @@ pub async fn send_ack(
);
}
} else {
return Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "No channel defined.")));
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"No channel defined.",
)));
}

Ok(())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,7 @@ impl Node {
let manager = my_agent_payments_manager.lock().await;

// Request the invoice
match manager
.network_request_invoice(network_tool, usage, None)
.await
{
match manager.network_request_invoice(network_tool, usage, None).await {
Ok(invoice_request) => {
let invoice_value = match serde_json::to_value(invoice_request) {
Ok(value) => value,
Expand Down Expand Up @@ -107,6 +104,8 @@ impl Node {
bearer: String,
invoice_id: String,
data_for_tool: Value,
inbox: Option<String>,
auto_pay: Option<bool>,
node_name: ShinkaiName,
res: Sender<Result<Value, APIError>>,
) -> Result<(), NodeError> {
Expand Down Expand Up @@ -216,12 +215,7 @@ impl Node {
let payment = match my_agent_offerings_manager
.lock()
.await
.pay_invoice_and_send_receipt(
invoice_id,
data_for_tool,
node_name.clone(),
None,
)
.pay_invoice_and_send_receipt(invoice_id, data_for_tool, node_name.clone(), None)
.await
{
Ok(payment) => payment,
Expand Down Expand Up @@ -250,6 +244,21 @@ impl Node {
}
};

if let Some(true) = auto_pay {
if let Some(inbox_name) = inbox.clone() {
let pref_key = format!(
"autopay:{}:{}:{}:{}",
invoice.requester_name.full_name,
invoice.provider_name.full_name,
invoice.shinkai_offering.tool_key,
inbox_name
);
if let Err(e) = db.set_preference(&pref_key, &true, Some("auto pay preference")) {
eprintln!("Failed to store auto-pay preference: {:?}", e);
}
}
}

// Send success response with payment details
let payment_value = match serde_json::to_value(payment) {
Ok(value) => value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use async_channel::Sender;
use serde::Deserialize;
use serde_json::Value;
use shinkai_message_primitives::schemas::{
coinbase_mpc_config::CoinbaseMPCWalletConfig, wallet_complementary::{WalletRole, WalletSource}, wallet_mixed::{Address, Asset, NetworkProtocolFamilyEnum}, x402_types::Network
coinbase_mpc_config::CoinbaseMPCWalletConfig,
wallet_complementary::{WalletRole, WalletSource},
wallet_mixed::{Address, Asset, NetworkProtocolFamilyEnum},
x402_types::Network,
};
use utoipa::{OpenApi, ToSchema};
use warp::Filter;
Expand Down Expand Up @@ -148,6 +151,10 @@ pub async fn create_local_wallet_handler(
pub struct PayInvoiceRequest {
pub invoice_id: String,
pub data_for_tool: Value,
#[serde(default)]
pub inbox: Option<String>,
#[serde(default)]
pub auto_pay: Option<bool>,
}

#[utoipa::path(
Expand All @@ -171,6 +178,8 @@ pub async fn pay_invoice_handler(
bearer,
invoice_id: payload.invoice_id,
data_for_tool: payload.data_for_tool,
inbox: payload.inbox,
auto_pay: payload.auto_pay,
res: res_sender,
})
.await
Expand Down Expand Up @@ -273,7 +282,10 @@ pub async fn get_wallet_balance_handler(
let bearer = authorization.strip_prefix("Bearer ").unwrap_or("").to_string();
let (res_sender, res_receiver) = async_channel::bounded(1);
sender
.send(NodeCommand::V2ApiGetWalletBalance { bearer, res: res_sender })
.send(NodeCommand::V2ApiGetWalletBalance {
bearer,
res: res_sender,
})
.await
.map_err(|_| warp::reject::reject())?;

Expand Down
2 changes: 2 additions & 0 deletions shinkai-libs/shinkai-http-api/src/node_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ pub enum NodeCommand {
bearer: String,
invoice_id: String,
data_for_tool: Value,
inbox: Option<String>,
auto_pay: Option<bool>,
res: Sender<Result<Value, APIError>>,
},
V2ApiListInvoices {
Expand Down
Loading