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:
+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