solana_trader_client_rust/provider/grpc/
swap.rs

1use anyhow::Result;
2use base64::{engine::general_purpose, Engine};
3use solana_sdk::{
4    message::{v0, VersionedMessage},
5    transaction::VersionedTransaction,
6};
7use solana_trader_proto::api::{self, PostPumpFunSwapRequestSol};
8use tonic::Request;
9
10use crate::{
11    common::signing::SubmitParams,
12    provider::utils::{
13        convert_address_lookup_table, convert_jupiter_instructions, convert_raydium_instructions,
14        create_transaction_message,
15    },
16};
17
18use super::GrpcClient;
19
20impl GrpcClient {
21    pub async fn post_raydium_swap(
22        &mut self,
23        request: &api::PostRaydiumSwapRequest,
24    ) -> Result<api::PostRaydiumSwapResponse> {
25        let response = self
26            .client
27            .post_raydium_swap(Request::new(request.clone()))
28            .await
29            .map_err(|e| anyhow::anyhow!("PostRaydiumSwap error: {}", e))?;
30
31        Ok(response.into_inner())
32    }
33
34    pub async fn post_raydium_route_swap(
35        &mut self,
36        request: &api::PostRaydiumRouteSwapRequest,
37    ) -> Result<api::PostRaydiumRouteSwapResponse> {
38        let response = self
39            .client
40            .post_raydium_route_swap(Request::new(request.clone()))
41            .await
42            .map_err(|e| anyhow::anyhow!("PostRaydiumRouteSwap error: {}", e))?;
43
44        Ok(response.into_inner())
45    }
46
47    pub async fn post_raydium_swap_instructions(
48        &mut self,
49        request: &api::PostRaydiumSwapInstructionsRequest,
50    ) -> Result<api::PostRaydiumSwapInstructionsResponse> {
51        Ok(self
52            .client
53            .post_raydium_swap_instructions(request.clone())
54            .await?
55            .into_inner())
56    }
57
58    pub async fn submit_raydium_swap_instructions(
59        &mut self,
60        request: api::PostRaydiumSwapInstructionsRequest,
61        submit_opts: SubmitParams,
62        use_bundle: bool,
63    ) -> Result<Vec<String>> {
64        let swap_instructions = self.post_raydium_swap_instructions(&request).await?;
65
66        let instructions = convert_raydium_instructions(&swap_instructions.instructions)?;
67
68        let block_hash = self
69            .client
70            .get_recent_block_hash_v2(api::GetRecentBlockHashRequestV2 { offset: 0 })
71            .await?
72            .into_inner()
73            .block_hash;
74
75        let tx_message = create_transaction_message(instructions, &block_hash)?;
76
77        self.sign_and_submit(vec![tx_message], submit_opts, use_bundle)
78            .await
79    }
80
81    pub async fn post_raydium_cpmm_swap(
82        &mut self,
83        request: &api::PostRaydiumCpmmSwapRequest,
84    ) -> Result<api::PostRaydiumCpmmSwapResponse> {
85        let response = self
86            .client
87            .post_raydium_cpmm_swap(Request::new(request.clone()))
88            .await
89            .map_err(|e| anyhow::anyhow!("PostRaydiumCPMMSwap error: {}", e))?;
90
91        Ok(response.into_inner())
92    }
93
94    pub async fn post_raydium_clmm_swap(
95        &mut self,
96        request: &api::PostRaydiumSwapRequest,
97    ) -> Result<api::PostRaydiumSwapResponse> {
98        let response = self
99            .client
100            .post_raydium_clmm_swap(Request::new(request.clone()))
101            .await
102            .map_err(|e| anyhow::anyhow!("PostRaydiumCLMMSwap error: {}", e))?;
103
104        Ok(response.into_inner())
105    }
106
107    pub async fn post_raydium_clmm_route_swap(
108        &mut self,
109        request: &api::PostRaydiumRouteSwapRequest,
110    ) -> Result<api::PostRaydiumRouteSwapResponse> {
111        let response = self
112            .client
113            .post_raydium_clmm_route_swap(Request::new(request.clone()))
114            .await
115            .map_err(|e| anyhow::anyhow!("PostRaydiumCLMMRouteSwap error: {}", e))?;
116
117        Ok(response.into_inner())
118    }
119
120    pub async fn post_jupiter_swap(
121        &mut self,
122        request: &api::PostJupiterSwapRequest,
123    ) -> Result<api::PostJupiterSwapResponse> {
124        let response = self
125            .client
126            .post_jupiter_swap(Request::new(request.clone()))
127            .await
128            .map_err(|e| anyhow::anyhow!("PostJupiterSwap error: {}", e))?;
129
130        Ok(response.into_inner())
131    }
132
133    pub async fn post_jupiter_route_swap(
134        &mut self,
135        request: &api::PostJupiterRouteSwapRequest,
136    ) -> Result<api::PostJupiterRouteSwapResponse> {
137        let response = self
138            .client
139            .post_jupiter_route_swap(Request::new(request.clone()))
140            .await
141            .map_err(|e| anyhow::anyhow!("PostJupiterRouteSwap error: {}", e))?;
142
143        Ok(response.into_inner())
144    }
145
146    pub async fn post_jupiter_swap_instructions(
147        &mut self,
148        request: &api::PostJupiterSwapInstructionsRequest,
149    ) -> Result<api::PostJupiterSwapInstructionsResponse> {
150        Ok(self
151            .client
152            .post_jupiter_swap_instructions(request.clone())
153            .await?
154            .into_inner())
155    }
156
157    pub async fn submit_jupiter_swap_instructions(
158        &mut self,
159        request: api::PostJupiterSwapInstructionsRequest,
160        submit_opts: SubmitParams,
161        use_bundle: bool,
162    ) -> Result<Vec<String>> {
163        let swap_instructions = self.post_jupiter_swap_instructions(&request).await?;
164
165        let address_lookup_table =
166            convert_address_lookup_table(&swap_instructions.address_lookup_table_addresses)?;
167
168        let instructions = convert_jupiter_instructions(&swap_instructions.instructions)?;
169
170        let blockhash = self
171            .client
172            .get_recent_block_hash_v2(api::GetRecentBlockHashRequestV2 { offset: 0 })
173            .await?
174            .into_inner()
175            .block_hash;
176
177        let message = VersionedMessage::V0(v0::Message::try_compile(
178            &self.public_key.unwrap(),
179            &instructions,
180            &address_lookup_table,
181            blockhash.parse()?,
182        )?);
183
184        let tx: VersionedTransaction =
185            VersionedTransaction::try_new(message, &[self.keypair.as_mut().unwrap()])?;
186
187        let tx_message = api::TransactionMessage {
188            content: general_purpose::STANDARD.encode(bincode::serialize(&tx)?),
189            is_cleanup: false,
190        };
191
192        self.sign_and_submit(vec![tx_message], submit_opts, use_bundle)
193            .await
194    }
195
196    pub async fn post_pump_swap(
197        &mut self,
198        request: &api::PostPumpFunSwapRequest,
199    ) -> Result<api::PostPumpFunSwapResponse> {
200        let response = self
201            .client
202            .post_pump_fun_swap(Request::new(request.clone()))
203            .await
204            .map_err(|e| anyhow::anyhow!("PostPumpFunSwap error: {}", e))?;
205
206        Ok(response.into_inner())
207    }
208
209    pub async fn post_pump_fun_swap_sol(
210        &mut self,
211        request: &PostPumpFunSwapRequestSol,
212    ) -> Result<api::PostPumpFunSwapResponse> {
213        let response: tonic::Response<api::PostPumpFunSwapResponse> = self
214            .client
215            .post_pump_fun_swap_sol(Request::new(request.clone()))
216            .await
217            .map_err(|e| anyhow::anyhow!("PostPumpFunSwapSol error: {}", e))?;
218
219        return Ok(response.into_inner())
220    }
221
222    pub async fn post_pump_fun_amm_swap(
223        &mut self,
224        request: &api::PostPumpFunAmmSwapRequest,
225    ) -> Result<api::PostPumpFunAmmSwapResponse> {
226        let response = self
227            .client
228            .post_pump_fun_amm_swap(Request::new(request.clone()))
229            .await
230            .map_err(|e| anyhow::anyhow!("PostPumpFunAmmSwap error: {}", e))?;
231
232        Ok(response.into_inner())
233    }
234
235    pub async fn post_trade_swap(
236        &mut self,
237        request: &api::TradeSwapRequest,
238    ) -> Result<api::TradeSwapResponse> {
239        let response = self
240            .client
241            .post_trade_swap(Request::new(request.clone()))
242            .await
243            .map_err(|e| anyhow::anyhow!("PostTradeSwap error: {}", e))?;
244
245        Ok(response.into_inner())
246    }
247
248    pub async fn post_route_trade_swap(
249        &mut self,
250        request: &api::RouteTradeSwapRequest,
251    ) -> Result<api::TradeSwapResponse> {
252        let response = self
253            .client
254            .post_route_trade_swap(Request::new(request.clone()))
255            .await
256            .map_err(|e| anyhow::anyhow!("PostRouteTradeSwap error: {}", e))?;
257
258        Ok(response.into_inner())
259    }
260}