1use crate::{actions::trade, parameters_json_schema, SolanaAgentKit};
16use rig::{
17 completion::ToolDefinition,
18 tool::{Tool, ToolEmbedding},
19};
20use serde::{Deserialize, Serialize};
21use serde_json::json;
22use std::sync::Arc;
23
24#[derive(Deserialize)]
25pub struct TradeArgs {
26 output_mint: String,
27 input_amount: f64,
28 input_mint: Option<String>,
29 slippage_bps: Option<u32>,
30}
31
32#[derive(Deserialize, Serialize)]
33pub struct TradeOutput {
34 pub signature: String,
35}
36
37#[derive(Debug, thiserror::Error)]
38#[error("Trade error")]
39pub struct TradeError;
40
41pub struct Trade {
42 agent: Arc<SolanaAgentKit>,
43}
44
45impl Trade {
46 pub fn new(agent: Arc<SolanaAgentKit>) -> Self {
47 Trade { agent }
48 }
49}
50
51impl Tool for Trade {
52 const NAME: &'static str = "trade";
53
54 type Error = TradeError;
55 type Args = TradeArgs;
56 type Output = TradeOutput;
57
58 async fn definition(&self, _prompt: String) -> ToolDefinition {
59 ToolDefinition {
60 name: "trade".to_string(),
61 description: r#"
62 This tool can be used to swap tokens to another token (It uses Jupiter Exchange).
63
64 [
65 {
66 input: {
67 outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
68 inputAmount: 1,
69 },
70 explanation: "Swap 1 SOL for USDC",
71 },
72 ],
73 [
74 {
75 input: {
76 outputMint: "So11111111111111111111111111111111111111112",
77 inputAmount: 100,
78 inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
79 slippageBps: 100,
80 },
81 explanation: "Swap 100 USDC for SOL with 1% slippage",
82 },
83 ],
84
85 "#
86 .to_string(),
87 parameters: parameters_json_schema!(
88 output_mint: String,
89 input_amount: f64,
90 input_mint: String,
91 slippage_bps: u32,
92 ),
93 }
94 }
95
96 async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
97 let signature = trade(&self.agent, &args.output_mint, args.input_amount, args.input_mint, args.slippage_bps)
98 .await
99 .expect("trade");
100
101 Ok(TradeOutput { signature })
102 }
103}
104
105#[derive(Debug, thiserror::Error)]
106#[error("Init error")]
107pub struct InitError;
108
109impl ToolEmbedding for Trade {
110 type InitError = InitError;
111 type Context = ();
112 type State = Arc<SolanaAgentKit>;
113
114 fn init(_state: Self::State, _context: Self::Context) -> Result<Self, Self::InitError> {
115 Ok(Trade { agent: _state })
116 }
117
118 fn embedding_docs(&self) -> Vec<String> {
119 vec!["This tool can be used to swap tokens to another token (It uses Jupiter Exchange).".into()]
120 }
121
122 fn context(&self) -> Self::Context {}
123}