feat: refactor trade API to return execution status with signature
- Bump version from 1.2.0 to 1.2.1 - Change trade methods return type from Signature to (bool, Signature) - Improve parallel execution error handling and status tracking - Update CLI examples to match new API interface - Enhance transaction success/failure reporting capabilities Breaking Change: Trade API now returns tuple (success_status, signature)
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sol-trade-sdk"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"William <byteblock6@gmail.com>",
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -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"
|
||||
```
|
||||
|
||||
## 🛠️ 使用示例
|
||||
|
||||
@@ -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);
|
||||
|
||||
+3
-3
@@ -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<Signature, anyhow::Error> {
|
||||
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<Signature, anyhow::Error> {
|
||||
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<Signature, anyhow::Error> {
|
||||
) -> Result<(bool, Signature), anyhow::Error> {
|
||||
if percent == 0 || percent > 100 {
|
||||
return Err(anyhow::anyhow!("Percentage must be between 1 and 100"));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ impl GenericTradeExecutor {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl TradeExecutor for GenericTradeExecutor {
|
||||
async fn swap(&self, params: SwapParams) -> Result<Signature> {
|
||||
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
|
||||
|
||||
@@ -18,7 +18,7 @@ pub async fn buy_parallel_execute(
|
||||
params: SwapParams,
|
||||
instructions: Vec<Instruction>,
|
||||
protocol_name: &'static str,
|
||||
) -> Result<Signature> {
|
||||
) -> Result<(bool, Signature)> {
|
||||
parallel_execute(
|
||||
params.swqos_clients,
|
||||
params.payer,
|
||||
@@ -41,7 +41,7 @@ pub async fn sell_parallel_execute(
|
||||
params: SwapParams,
|
||||
instructions: Vec<Instruction>,
|
||||
protocol_name: &'static str,
|
||||
) -> Result<Signature> {
|
||||
) -> 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<Signature> {
|
||||
) -> 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<JoinHandle<Result<Signature>>> = Vec::with_capacity(swqos_clients.len());
|
||||
let mut handles: Vec<JoinHandle<Result<(bool, Signature, anyhow::Error)>>> =
|
||||
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()));
|
||||
}
|
||||
|
||||
@@ -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<Signature>;
|
||||
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature)>;
|
||||
/// 获取协议名称
|
||||
fn protocol_name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user