solagent/tools/solana/
transfer.rs

1// Copyright 2025 zTgx
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{actions::transfer, 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 TransferArgs {
26    pub to: String,
27    pub amount: u64,
28    pub mint: Option<String>,
29}
30
31#[derive(Deserialize, Serialize)]
32pub struct TransferOutput {
33    pub tx: String,
34}
35
36#[derive(Debug, thiserror::Error)]
37#[error("Transfer error")]
38pub struct TransferError;
39
40pub struct Transfer {
41    agent: Arc<SolanaAgentKit>,
42}
43
44impl Transfer {
45    pub fn new(agent: Arc<SolanaAgentKit>) -> Self {
46        Transfer { agent }
47    }
48}
49
50impl Tool for Transfer {
51    const NAME: &'static str = "transfer";
52
53    type Error = TransferError;
54    type Args = TransferArgs;
55    type Output = TransferOutput;
56
57    async fn definition(&self, _prompt: String) -> ToolDefinition {
58        ToolDefinition {
59            name: "transfer".to_string(),
60            description: r#"
61            Transfer tokens or SOL to another address (also called as wallet address).
62
63            examples: [
64                [
65                    {
66                        input: {
67                            to: "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk",
68                            amount: 1,
69                        },
70                        output: {
71                            status: "success",
72                            message: "Transfer completed successfully",
73                            amount: 1,
74                            recipient: "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk",
75                            token: "SOL",
76                            transaction:
77                                "5UfgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
78                        },
79                        explanation: "Transfer 1 SOL to the recipient address",
80                    },
81                ],
82                [
83                    {
84                        input: {
85                            to: "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk",
86                            amount: 100,
87                            mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
88                        },
89                        output: {
90                            status: "success",
91                            message: "Transfer completed successfully",
92                            amount: 100,
93                            recipient: "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk",
94                            token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
95                            transaction:
96                                "4VfgJ5vVZxUxefDGqzqkVLHzHxVTyYH9StYyHKgvHYmXJgqJKxEqy9k4Rz9LpXrHF9kUZB7",
97                        },
98                        explanation: "Transfer 100 USDC tokens to the recipient address",
99                    },
100                ],
101            ],
102 
103            "#
104            .to_string(),
105            parameters: parameters_json_schema!(
106                to: String,
107                amount: f64,
108                mint: String,
109            ),
110        }
111    }
112
113    async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
114        let tx = transfer(&self.agent, &args.to, args.amount, args.mint).await.expect("transfer");
115
116        Ok(TransferOutput { tx })
117    }
118}
119
120#[derive(Debug, thiserror::Error)]
121#[error("Init error")]
122pub struct InitError;
123
124impl ToolEmbedding for Transfer {
125    type InitError = InitError;
126    type Context = ();
127    type State = Arc<SolanaAgentKit>;
128
129    fn init(_state: Self::State, _context: Self::Context) -> Result<Self, Self::InitError> {
130        Ok(Transfer { agent: _state })
131    }
132
133    fn embedding_docs(&self) -> Vec<String> {
134        vec!["Transfer tokens or SOL to another address (also called as wallet address).".into()]
135    }
136
137    fn context(&self) -> Self::Context {}
138}