listen_kit/
actions.rs

1use reqwest::Client;
2use solana_client::nonblocking::rpc_client::RpcClient;
3use solana_sdk::pubkey::Pubkey;
4use solana_sdk::signature::Keypair;
5use solana_sdk::signer::Signer;
6use std::error::Error;
7use std::str::FromStr;
8
9use crate::deploy_token::{deploy_token, DeployTokenParams};
10use crate::price::fetch_token_price;
11use crate::trade::trade;
12use crate::transfer::{transfer_sol, transfer_spl};
13
14pub struct Actions {
15    pub keypair: Keypair,
16    pub rpc_client: RpcClient,
17    pub client: Client,
18}
19
20// TODO
21// * macro that takes the docstring to create tool description, method signature to create tool
22// * params and return type/error type, possible also just as a #[tool::description] macro
23// * include native arc integration as core dep
24// * add a potential flag to simulate before sending txs, return tx simulation, useful for larger
25// txs
26
27impl Actions {
28    pub fn new(private_key: String, rpc_url: String) -> Self {
29        let keypair = Keypair::from_base58_string(&private_key);
30        let rpc_client = RpcClient::new(rpc_url);
31        let client = Client::new();
32
33        Self {
34            keypair,
35            rpc_client,
36            client,
37        }
38    }
39    pub async fn trade(
40        &self,
41        input_mint: String,
42        input_amount: u64,
43        output_mint: String,
44        slippage_bps: u16,
45    ) -> Result<String, Box<dyn Error>> {
46        trade(
47            input_mint,
48            input_amount,
49            output_mint,
50            slippage_bps,
51            &self.keypair,
52        )
53        .await
54    }
55
56    pub async fn transfer_sol(
57        &self,
58        to: String,
59        amount: u64,
60    ) -> Result<String, Box<dyn Error>> {
61        transfer_sol(
62            Pubkey::from_str(&to)?,
63            amount,
64            &self.keypair,
65            &self.rpc_client,
66        )
67        .await
68    }
69
70    /// param amount is token amount, accounting for decimals
71    /// e.g. 1 Fartcoin = 1 * 10^6 (6 decimals)
72    pub async fn transfer_token(
73        &self,
74        to: String,
75        amount: u64,
76        mint: String,
77    ) -> Result<String, Box<dyn Error>> {
78        transfer_spl(
79            Pubkey::from_str(&to)?,
80            amount,
81            Pubkey::from_str(&mint)?,
82            &self.keypair,
83            &self.rpc_client,
84        )
85        .await
86    }
87
88    pub async fn wallet_address(&self) -> String {
89        self.keypair.pubkey().to_string()
90    }
91
92    pub async fn get_balance(&self) -> Result<u64, Box<dyn Error>> {
93        let balance =
94            self.rpc_client.get_balance(&self.keypair.pubkey()).await?;
95        Ok(balance)
96    }
97
98    /// get_token_balance returns the amount as String and the decimals as u8
99    /// in order to convert to UI amount: amount / 10^decimals
100    pub async fn get_token_balance(
101        &self,
102        mint: String,
103    ) -> Result<(String, u8), Box<dyn Error>> {
104        let mint = Pubkey::from_str(&mint)?;
105        let ata = spl_associated_token_account::get_associated_token_address(
106            &self.keypair.pubkey(),
107            &mint,
108        );
109        let balance = self.rpc_client.get_token_account_balance(&ata).await?;
110        Ok((balance.amount, balance.decimals))
111    }
112
113    pub async fn deploy_token(
114        &self,
115        deploy_token_params: DeployTokenParams,
116    ) -> Result<String, Box<dyn Error>> {
117        deploy_token(deploy_token_params, &self.keypair, &self.rpc_client)
118            .await
119    }
120
121    pub async fn fetch_token_price(
122        &self,
123        mint: String,
124    ) -> Result<f64, Box<dyn Error>> {
125        fetch_token_price(mint, &self.client).await
126    }
127
128    pub async fn buy_pump_token() -> Result<String, Box<dyn Error>> {
129        unimplemented!()
130    }
131
132    pub async fn sell_pump_token() -> Result<String, Box<dyn Error>> {
133        unimplemented!()
134    }
135
136    pub async fn fetch_metadata(&self) -> Result<String, Box<dyn Error>> {
137        unimplemented!()
138    }
139
140    /// research_token returns aggregated data from any link from metadata
141    pub async fn research_token(&self) -> Result<String, Box<dyn Error>> {
142        unimplemented!()
143    }
144
145    pub async fn get_token_data_by_ticker(
146        &self,
147    ) -> Result<String, Box<dyn Error>> {
148        unimplemented!()
149    }
150
151    pub async fn get_token_data_by_pubkey(
152        &self,
153    ) -> Result<String, Box<dyn Error>> {
154        unimplemented!()
155    }
156}