diff --git a/Cargo.toml b/Cargo.toml index d994e81..71f2d99 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sol-trade-sdk" -version = "1.2.0" +version = "1.2.1" edition = "2021" authors = [ "William ", diff --git a/README.md b/README.md index 62aadb8..cd8b2d1 100644 --- a/README.md +++ b/README.md @@ -87,14 +87,14 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.0" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.1" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -sol-trade-sdk = "1.2.0" +sol-trade-sdk = "1.2.1" ``` ## ๐Ÿ› ๏ธ Usage Examples diff --git a/README_CN.md b/README_CN.md index a6beee8..7d64842 100755 --- a/README_CN.md +++ b/README_CN.md @@ -87,14 +87,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk ```toml # ๆทปๅŠ ๅˆฐๆ‚จ็š„ Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.0" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.2.1" } ``` ### ไฝฟ็”จ crates.io ```toml # ๆทปๅŠ ๅˆฐๆ‚จ็š„ Cargo.toml -sol-trade-sdk = "1.2.0" +sol-trade-sdk = "1.2.1" ``` ## ๐Ÿ› ๏ธ ไฝฟ็”จ็คบไพ‹ diff --git a/examples/cli_trading/src/main.rs b/examples/cli_trading/src/main.rs index 1948d3e..d7827b0 100644 --- a/examples/cli_trading/src/main.rs +++ b/examples/cli_trading/src/main.rs @@ -620,9 +620,9 @@ async fn handle_buy_pumpfun( durable_nonce: None, }; match client.buy(buy_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully bought tokens from PumpFun!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to buy tokens from PumpFun: {}", e); @@ -669,9 +669,9 @@ async fn handle_buy_pumpswap( durable_nonce: None, }; match client.buy(buy_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully bought tokens from PumpSwap!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to buy tokens from PumpSwap: {}", e); @@ -717,9 +717,9 @@ async fn handle_buy_bonk( durable_nonce: None, }; match client.buy(buy_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully bought tokens from Bonk!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to buy tokens from Bonk: {}", e); @@ -769,9 +769,9 @@ async fn handle_buy_raydium_v4( durable_nonce: None, }; match client.buy(buy_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully bought tokens from Raydium V4!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to buy tokens from Raydium V4: {}", e); @@ -821,9 +821,9 @@ async fn handle_buy_raydium_cpmm( durable_nonce: None, }; match client.buy(buy_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully bought tokens from Raydium CPMM!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to buy tokens from Raydium CPMM: {}", e); @@ -984,9 +984,9 @@ async fn handle_sell_pumpfun( }; match client.sell(sell_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully sold tokens from PumpFun!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to sell tokens from PumpFun: {}", e); @@ -1035,7 +1035,7 @@ async fn handle_sell_pumpswap( durable_nonce: None, }; match client.sell(sell_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully sold tokens from PumpSwap!"); println!(" โœ… Transaction Signature: {}", signature); } @@ -1086,9 +1086,9 @@ async fn handle_sell_bonk( durable_nonce: None, }; match client.sell(sell_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully sold tokens from Bonk!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to sell tokens from Bonk: {}", e); @@ -1140,9 +1140,9 @@ async fn handle_sell_raydium_v4( durable_nonce: None, }; match client.sell(sell_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully sold tokens from Raydium V4!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to sell tokens from Raydium V4: {}", e); @@ -1194,9 +1194,9 @@ async fn handle_sell_raydium_cpmm( durable_nonce: None, }; match client.sell(sell_params).await { - Ok(signature) => { + Ok((_, signature)) => { println!(" โœ… Successfully sold tokens from Raydium CPMM!"); - println!(" โœ… Transaction Signature: {}", signature); + println!(" โœ… Transaction Signature: {:?}", signature); } Err(e) => { println!(" โŒ Failed to sell tokens from Raydium CPMM: {}", e); diff --git a/src/lib.rs b/src/lib.rs index 4f5472c..18b0c8e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -257,7 +257,7 @@ impl SolanaTrade { /// - Network or RPC errors occur /// - Insufficient SOL balance for the purchase /// - Required accounts cannot be created or accessed - pub async fn buy(&self, params: TradeBuyParams) -> Result { + pub async fn buy(&self, params: TradeBuyParams) -> Result<(bool, Signature), anyhow::Error> { if params.slippage_basis_points.is_none() { println!( "slippage_basis_points is none, use default slippage basis points: {}", @@ -346,7 +346,7 @@ impl SolanaTrade { /// - Insufficient token balance for the sale /// - Token account doesn't exist or is not properly initialized /// - Required accounts cannot be created or accessed - pub async fn sell(&self, params: TradeSellParams) -> Result { + pub async fn sell(&self, params: TradeSellParams) -> Result<(bool, Signature), anyhow::Error> { if params.slippage_basis_points.is_none() { println!( "slippage_basis_points is none, use default slippage basis points: {}", @@ -447,7 +447,7 @@ impl SolanaTrade { mut params: TradeSellParams, amount_token: u64, percent: u64, - ) -> Result { + ) -> Result<(bool, Signature), anyhow::Error> { if percent == 0 || percent > 100 { return Err(anyhow::anyhow!("Percentage must be between 1 and 100")); } diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index 00c3e57..f9ec145 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -26,7 +26,7 @@ impl GenericTradeExecutor { #[async_trait::async_trait] impl TradeExecutor for GenericTradeExecutor { - async fn swap(&self, params: SwapParams) -> Result { + async fn swap(&self, params: SwapParams) -> Result<(bool, Signature)> { let start = Instant::now(); // ๆš‚ๆ—ถๆ”ฏๆŒ่ฟ™ไธ‰็งใ€‚ๅŽ็ปญ้‡ๆž„ๆ‰ฉๅฑ•builder ๆ”ฏๆŒๆ‰€ๆœ‰็š„ swap let is_buy = params.input_mint == crate::constants::SOL_TOKEN_ACCOUNT diff --git a/src/trading/core/parallel.rs b/src/trading/core/parallel.rs index 7cc01d3..681de26 100755 --- a/src/trading/core/parallel.rs +++ b/src/trading/core/parallel.rs @@ -18,7 +18,7 @@ pub async fn buy_parallel_execute( params: SwapParams, instructions: Vec, protocol_name: &'static str, -) -> Result { +) -> Result<(bool, Signature)> { parallel_execute( params.swqos_clients, params.payer, @@ -41,7 +41,7 @@ pub async fn sell_parallel_execute( params: SwapParams, instructions: Vec, protocol_name: &'static str, -) -> Result { +) -> Result<(bool, Signature)> { parallel_execute( params.swqos_clients, params.payer, @@ -75,7 +75,7 @@ async fn parallel_execute( is_buy: bool, wait_transaction_confirmed: bool, with_tip: bool, -) -> Result { +) -> Result<(bool, Signature)> { if swqos_clients.is_empty() { return Err(anyhow!("swqos_clients is empty")); } @@ -88,7 +88,8 @@ async fn parallel_execute( return Err(anyhow!("No Rpc Default Swqos configured.")); } let cores = core_affinity::get_core_ids().unwrap(); - let mut handles: Vec>> = Vec::with_capacity(swqos_clients.len()); + let mut handles: Vec>> = + Vec::with_capacity(swqos_clients.len()); let instructions = Arc::new(instructions); @@ -169,12 +170,21 @@ async fn parallel_execute( start = Instant::now(); - swqos_client + let mut err = None; + + let success = match swqos_client .send_transaction( if is_buy { TradeType::Buy } else { TradeType::Sell }, &transaction, ) - .await?; + .await + { + Ok(()) => true, + Err(e) => { + err = Some(e); + false + } + }; println!( "[{:?}] - [{:?}] - Submitting transaction instructions: {:?}", @@ -183,11 +193,11 @@ async fn parallel_execute( start.elapsed() ); - transaction - .signatures - .first() - .ok_or_else(|| anyhow!("Transaction has no signatures")) - .cloned() + if let Some(signature) = transaction.signatures.first() { + return Ok((success, signature.clone(), err.unwrap())); + } else { + return Err(anyhow!("Transaction has no signatures")); + } }); handles.push(handle); @@ -211,7 +221,7 @@ async fn parallel_execute( if !wait_transaction_confirmed { if let Some(result) = rx.recv().await { match result { - Ok(Ok(sig)) => return Ok(sig), + Ok(Ok((success, sig, _))) => return Ok((success, sig)), Ok(Err(e)) => errors.push(format!("Task error: {}", e)), Err(e) => errors.push(format!("Join error: {}", e)), } @@ -219,16 +229,22 @@ async fn parallel_execute( return Err(anyhow!("No transaction signature available")); } + let mut last_signature = None; + while let Some(result) = rx.recv().await { match result { - Ok(Ok(sig)) => { - return Ok(sig); + Ok(Ok((success, sig, err))) => { + if success { + return Ok((success, sig)); + } + errors.push(format!("Task error: {}", err)); + last_signature = Some(sig); } Ok(Err(e)) => errors.push(format!("Task error: {}", e)), Err(e) => errors.push(format!("Join error: {}", e)), } } - // If no success, return error - return Err(anyhow!("All transactions failed: {:?}", errors)); + println!("All transactions failed: {:?}", errors); + return Ok((false, last_signature.unwrap())); } diff --git a/src/trading/core/traits.rs b/src/trading/core/traits.rs index 574b484..ef6e51c 100755 --- a/src/trading/core/traits.rs +++ b/src/trading/core/traits.rs @@ -5,7 +5,7 @@ use solana_sdk::{instruction::Instruction, signature::Signature}; /// ไบคๆ˜“ๆ‰ง่กŒๅ™จtrait - ๅฎšไน‰ไบ†ๆ‰€ๆœ‰ไบคๆ˜“ๅ่ฎฎ้ƒฝ้œ€่ฆๅฎž็Žฐ็š„ๆ ธๅฟƒๆ–นๆณ• #[async_trait::async_trait] pub trait TradeExecutor: Send + Sync { - async fn swap(&self, params: SwapParams) -> Result; + async fn swap(&self, params: SwapParams) -> Result<(bool, Signature)>; /// ่Žทๅ–ๅ่ฎฎๅ็งฐ fn protocol_name(&self) -> &'static str; }