solana_trader_client_rust/provider/http/
swap.rs1use crate::{
2 common::signing::SubmitParams,
3 provider::utils::{
4 convert_address_lookup_table, convert_jupiter_instructions, convert_raydium_instructions,
5 create_transaction_message,
6 },
7};
8
9use super::HTTPClient;
10use anyhow::Result;
11use serde_json::json;
12use base64::{engine::general_purpose, Engine};
13use solana_sdk::{
14 message::{v0, VersionedMessage},
15 transaction::VersionedTransaction,
16};
17use solana_trader_proto::api;
18
19impl HTTPClient {
20 pub async fn post_raydium_swap(
21 &self,
22 request: &api::PostRaydiumSwapRequest,
23 ) -> Result<api::PostRaydiumSwapResponse> {
24 let response = self
25 .client
26 .post(format!("{}/api/v2/raydium/swap", self.base_url))
27 .json(&request)
28 .send()
29 .await?;
30
31 self.handle_response(response).await
32 }
33
34 pub async fn post_raydium_route_swap(
35 &self,
36 request: &api::PostRaydiumRouteSwapRequest,
37 ) -> Result<api::PostRaydiumRouteSwapResponse> {
38 let response = self
39 .client
40 .post(format!("{}/api/v2/raydium/route-swap", self.base_url))
41 .json(&request)
42 .send()
43 .await?;
44
45 self.handle_response(response).await
46 }
47
48 pub async fn post_raydium_swap_instructions(
49 &self,
50 request: &api::PostRaydiumSwapInstructionsRequest,
51 ) -> Result<api::PostRaydiumSwapInstructionsResponse> {
52 let response = self
53 .client
54 .post(format!(
55 "{}/api/v2/raydium/swap-instructions",
56 self.base_url
57 ))
58 .json(&request)
59 .send()
60 .await?;
61
62 self.handle_response(response).await
63 }
64
65 pub async fn submit_raydium_swap_instructions(
66 &self,
67 request: api::PostRaydiumSwapInstructionsRequest,
68 submit_opts: SubmitParams,
69 use_bundle: bool,
70 ) -> Result<Vec<String>> {
71 let swap_instructions = self.post_raydium_swap_instructions(&request).await?;
72
73 let instructions = convert_raydium_instructions(&swap_instructions.instructions)?;
74
75 let response = self
76 .client
77 .get(format!(
78 "{}/api/v2/system/blockhash?offset=0",
79 self.base_url
80 ))
81 .send()
82 .await?;
83
84 let blockhash_response: api::GetRecentBlockHashResponseV2 =
85 self.handle_response(response).await?;
86
87 let tx_message = create_transaction_message(instructions, &blockhash_response.block_hash)?;
88
89 self.sign_and_submit(vec![tx_message], submit_opts, use_bundle)
90 .await
91 }
92
93 pub async fn post_raydium_cpmm_swap(
94 &self,
95 request: &api::PostRaydiumCpmmSwapRequest,
96 ) -> Result<api::PostRaydiumCpmmSwapResponse> {
97 let response = self
98 .client
99 .post(format!("{}/api/v2/raydium/cpmm-swap", self.base_url))
100 .json(&request)
101 .send()
102 .await?;
103
104 self.handle_response(response).await
105 }
106
107 pub async fn post_raydium_clmm_swap(
108 &self,
109 request: &api::PostRaydiumSwapRequest,
110 ) -> Result<api::PostRaydiumSwapResponse> {
111 let response = self
112 .client
113 .post(format!("{}/api/v2/raydium/clmm-swap", self.base_url))
114 .json(&request)
115 .send()
116 .await?;
117
118 self.handle_response(response).await
119 }
120
121 pub async fn post_raydium_clmm_route_swap(
122 &self,
123 request: &api::PostRaydiumRouteSwapRequest,
124 ) -> Result<api::PostRaydiumRouteSwapResponse> {
125 let response = self
126 .client
127 .post(format!("{}/api/v2/raydium/clmm-route-swap", self.base_url))
128 .json(&request)
129 .send()
130 .await?;
131
132 self.handle_response(response).await
133 }
134
135 pub async fn post_jupiter_swap(
136 &self,
137 request: &api::PostJupiterSwapRequest,
138 ) -> Result<api::PostJupiterSwapResponse> {
139 let response = self
140 .client
141 .post(format!("{}/api/v2/jupiter/swap", self.base_url))
142 .json(&request)
143 .send()
144 .await?;
145
146 self.handle_response(response).await
147 }
148
149 pub async fn post_jupiter_route_swap(
150 &self,
151 request: &api::PostJupiterRouteSwapRequest,
152 ) -> Result<api::PostJupiterRouteSwapResponse> {
153 let response = self
154 .client
155 .post(format!("{}/api/v2/jupiter/route-swap", self.base_url))
156 .json(&request)
157 .send()
158 .await?;
159
160 self.handle_response(response).await
161 }
162
163 pub async fn post_jupiter_swap_instructions(
164 &self,
165 request: &api::PostJupiterSwapInstructionsRequest,
166 ) -> Result<api::PostJupiterSwapInstructionsResponse> {
167 let response = self
168 .client
169 .post(format!(
170 "{}/api/v2/jupiter/swap-instructions",
171 self.base_url
172 ))
173 .json(&request)
174 .send()
175 .await?;
176
177 self.handle_response(response).await
178 }
179
180 pub async fn submit_jupiter_swap_instructions(
181 &self,
182 request: api::PostJupiterSwapInstructionsRequest,
183 submit_opts: SubmitParams,
184 use_bundle: bool,
185 ) -> Result<Vec<String>> {
186 let keypair = self.get_keypair()?;
187
188 let swap_instructions = self.post_jupiter_swap_instructions(&request).await?;
189
190 let address_lookup_tables =
191 convert_address_lookup_table(&swap_instructions.address_lookup_table_addresses)?;
192
193 let instructions = convert_jupiter_instructions(&swap_instructions.instructions)?;
194
195 let response = self
196 .client
197 .get(format!(
198 "{}/api/v2/system/blockhash?offset=0",
199 self.base_url
200 ))
201 .send()
202 .await?;
203
204 let blockhash_response: api::GetRecentBlockHashResponseV2 =
205 self.handle_response(response).await?;
206
207 let message = VersionedMessage::V0(v0::Message::try_compile(
208 &self.public_key.unwrap(),
209 &instructions,
210 &address_lookup_tables,
211 blockhash_response.block_hash.parse()?,
212 )?);
213
214 let tx: VersionedTransaction = VersionedTransaction::try_new(message, &[keypair])?;
215
216 let tx_message = api::TransactionMessage {
217 content: general_purpose::STANDARD.encode(bincode::serialize(&tx)?),
218 is_cleanup: false,
219 };
220
221 self.sign_and_submit(vec![tx_message], submit_opts, use_bundle)
222 .await
223 }
224
225 pub async fn post_trade_swap(
226 &self,
227 request: &api::TradeSwapRequest,
228 ) -> Result<api::TradeSwapResponse> {
229 let response = self
230 .client
231 .post(format!("{}/api/v2/trade/swap", self.base_url))
232 .json(&request)
233 .send()
234 .await?;
235
236 self.handle_response(response).await
237 }
238
239 pub async fn post_route_trade_swap(
240 &self,
241 request: &api::RouteTradeSwapRequest,
242 ) -> Result<api::TradeSwapResponse> {
243 let response = self
244 .client
245 .post(format!("{}/api/v2/trade/route-swap", self.base_url))
246 .json(&request)
247 .send()
248 .await?;
249
250 self.handle_response(response).await
251 }
252
253 pub async fn post_pump_fun_swap(
254 &self,
255 user_address: String,
256 bonding_curve_address: String,
257 token_address: String,
258 token_amount: f64,
259 creator: String,
260 sol_threshold: f64,
261 is_buy: bool,
262 slippage: f64,
263 compute_limit: u32,
264 compute_price: u64,
265 tip: Option<u64>
266 ) -> anyhow::Result<api::PostPumpFunSwapResponse> {
267 let url = format!("{}/api/v2/pumpfun/swap", self.base_url);
268 println!("{}", url);
269
270 let request_json = json!({
271 "userAddress": user_address,
272 "bondingCurveAddress": bonding_curve_address,
273 "tokenAddress": token_address,
274 "creator": creator,
275 "tokenAmount": token_amount,
276 "solThreshold": sol_threshold,
277 "isBuy": is_buy,
278 "slippage": slippage,
279 "computeLimit": compute_limit,
280 "computePrice": compute_price,
281 "tip": tip
282 });
283
284 let response = self
285 .client
286 .post(&url)
287 .json(&request_json)
288 .send()
289 .await?;
290
291 let result: api::PostPumpFunSwapResponse = self.handle_response(response).await?;
292
293 Ok(result)
294 }
295
296 pub async fn post_pump_fun_swap_sol(
297 &self,
298 user_address: String,
299 bonding_curve_address: String,
300 token_address: String,
301 creator: String,
302 sol_amount: f64,
303 slippage: f64,
304 compute_limit: u32,
305 compute_price: u64,
306 tip: Option<u64>
307 ) -> anyhow::Result<api::PostPumpFunSwapResponse> {
308 let url = format!("{}/api/v2/pumpfun/swap-sol", self.base_url);
309 println!("{}", url);
310
311 let request_json = json!({
312 "userAddress": user_address,
313 "bondingCurveAddress": bonding_curve_address,
314 "tokenAddress": token_address,
315 "creator": creator,
316 "solAmount": sol_amount,
317 "slippage": slippage,
318 "computeLimit": compute_limit,
319 "computePrice": compute_price,
320 "tip": tip
321 });
322
323 let response = self
324 .client
325 .post(&url)
326 .json(&request_json)
327 .send()
328 .await?;
329
330 let result: api::PostPumpFunSwapResponse = self.handle_response(response).await?;
331
332 Ok(result)
333 }
334
335}