From bd1772bed20079850d8153161c353f2b64c4a90f Mon Sep 17 00:00:00 2001 From: HelvetiCrypt Date: Wed, 27 May 2026 08:02:49 +0000 Subject: [PATCH] Add SwapParams.wait_for_all_submits to restore all-routes signature collection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4.0.11 switched the fast-submit (`wait_tx_confirmed = false`) result loop from `wait_for_all_submitted` to `wait_for_first_submitted`. The new function returns as soon as one SWQOS route's HTTP submit completes and drains whatever signatures are in `ResultCollector.results` at that moment — slower routes' signatures arrive after the caller has returned. This is correct for fire-and-forget low-latency submits, but breaks callers that do their own on-chain confirmation against a pinned durable nonce. Only one of the submitted txs can land (nonce is consumed by whichever lands first), but the caller has no way of knowing in advance which route it will be. Their post-submit logic feeds every returned signature to `getSignatureStatuses` to find the landed one — with only the fastest HTTP responder returned (often not the one that lands), the landed tx isn't in the polled set. Adds an opt-in `SwapParams.wait_for_all_submits: bool` (default false, plumbed through `TradeBuyParams` / `TradeSellParams`). When true and `wait_tx_confirmed = false`, `execute_parallel` uses `wait_for_all_submitted` (still in the codebase, was `#[allow(dead_code)]`) so every submitted signature is returned. Zero behaviour change for current users. --- examples/address_lookup/src/main.rs | 1 + examples/bonk_copy_trading/src/main.rs | 2 ++ examples/bonk_sniper_trading/src/main.rs | 2 ++ examples/cli_trading/src/main.rs | 10 +++++++ .../src/main.rs | 2 ++ examples/middleware_system/src/main.rs | 1 + examples/nonce_cache/src/main.rs | 1 + examples/pumpfun_copy_trading/src/main.rs | 2 ++ examples/pumpfun_sniper_trading/src/main.rs | 2 ++ examples/pumpswap_direct_trading/src/main.rs | 2 ++ examples/pumpswap_trading/src/main.rs | 2 ++ examples/raydium_amm_v4_trading/src/main.rs | 2 ++ examples/raydium_cpmm_trading/src/main.rs | 2 ++ examples/seed_trading/src/main.rs | 2 ++ src/client/mod.rs | 12 +++++++++ src/instruction/bonk.rs | 1 + src/instruction/meteora_damm_v2.rs | 1 + src/instruction/pumpfun.rs | 1 + src/instruction/pumpswap.rs | 1 + src/instruction/raydium_amm_v4.rs | 1 + src/instruction/raydium_cpmm.rs | 1 + src/trading/core/async_executor.rs | 27 ++++++++++++++----- src/trading/core/executor.rs | 5 ++++ src/trading/core/params/dex_swap.rs | 8 ++++++ 24 files changed, 84 insertions(+), 7 deletions(-) diff --git a/examples/address_lookup/src/main.rs b/examples/address_lookup/src/main.rs index a31e2c2..d98a52d 100644 --- a/examples/address_lookup/src/main.rs +++ b/examples/address_lookup/src/main.rs @@ -179,6 +179,7 @@ async fn pumpfun_copy_trade_with_grpc( )), address_lookup_table_account, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: false, close_input_token_ata: false, create_mint_ata: true, diff --git a/examples/bonk_copy_trading/src/main.rs b/examples/bonk_copy_trading/src/main.rs index 72b3b86..767ab5f 100644 --- a/examples/bonk_copy_trading/src/main.rs +++ b/examples/bonk_copy_trading/src/main.rs @@ -171,6 +171,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()> )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: false, create_mint_ata: true, @@ -222,6 +223,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()> )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, with_tip: false, durable_nonce: None, create_output_token_ata: false, diff --git a/examples/bonk_sniper_trading/src/main.rs b/examples/bonk_sniper_trading/src/main.rs index bd2f012..3124edb 100644 --- a/examples/bonk_sniper_trading/src/main.rs +++ b/examples/bonk_sniper_trading/src/main.rs @@ -139,6 +139,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult< )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: true, create_mint_ata: true, @@ -183,6 +184,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult< )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: true, close_mint_token_ata: false, diff --git a/examples/cli_trading/src/main.rs b/examples/cli_trading/src/main.rs index a3d514f..639ac85 100644 --- a/examples/cli_trading/src/main.rs +++ b/examples/cli_trading/src/main.rs @@ -628,6 +628,7 @@ async fn handle_buy_pumpfun( extension_params: DexParamEnum::PumpFun(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: false, close_input_token_ata: false, create_mint_ata: create_mint_ata, @@ -684,6 +685,7 @@ async fn handle_buy_pumpswap( extension_params: DexParamEnum::PumpSwap(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: false, create_mint_ata: create_mint_ata, @@ -740,6 +742,7 @@ async fn handle_buy_bonk( extension_params: DexParamEnum::Bonk(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: false, create_mint_ata: create_mint_ata, @@ -800,6 +803,7 @@ async fn handle_buy_raydium_v4( extension_params: DexParamEnum::RaydiumAmmV4(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: false, create_mint_ata: create_mint_ata, @@ -861,6 +865,7 @@ async fn handle_buy_raydium_cpmm( extension_params: DexParamEnum::RaydiumCpmm(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: false, create_mint_ata: create_mint_ata, @@ -1031,6 +1036,7 @@ async fn handle_sell_pumpfun( extension_params: DexParamEnum::PumpFun(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: false, close_mint_token_ata: false, @@ -1090,6 +1096,7 @@ async fn handle_sell_pumpswap( extension_params: DexParamEnum::PumpSwap(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: false, close_mint_token_ata: false, @@ -1149,6 +1156,7 @@ async fn handle_sell_bonk( extension_params: DexParamEnum::Bonk(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: false, close_mint_token_ata: false, @@ -1211,6 +1219,7 @@ async fn handle_sell_raydium_v4( extension_params: DexParamEnum::RaydiumAmmV4(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: false, close_mint_token_ata: false, @@ -1274,6 +1283,7 @@ async fn handle_sell_raydium_cpmm( extension_params: DexParamEnum::RaydiumCpmm(param), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: false, close_mint_token_ata: false, diff --git a/examples/meteora_damm_v2_direct_trading/src/main.rs b/examples/meteora_damm_v2_direct_trading/src/main.rs index 1a5b65e..23000a2 100644 --- a/examples/meteora_damm_v2_direct_trading/src/main.rs +++ b/examples/meteora_damm_v2_direct_trading/src/main.rs @@ -43,6 +43,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: false, //if input token is SOL/WSOL,set to true,if input token is USDC,set to false. close_input_token_ata: false, //if input token is SOL/WSOL,set to true,if input token is USDC,set to false. create_mint_ata: true, @@ -84,6 +85,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: false, //if output token is SOL/WSOL,set to true,if output token is USDC,set to false. close_output_token_ata: false, //if output token is SOL/WSOL,set to true,if output token is USDC,set to false. close_mint_token_ata: false, diff --git a/examples/middleware_system/src/main.rs b/examples/middleware_system/src/main.rs index 1693185..d49017b 100644 --- a/examples/middleware_system/src/main.rs +++ b/examples/middleware_system/src/main.rs @@ -104,6 +104,7 @@ async fn test_middleware() -> AnyResult<()> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: true, create_mint_ata: true, diff --git a/examples/nonce_cache/src/main.rs b/examples/nonce_cache/src/main.rs index 8ddd81a..96c4a83 100644 --- a/examples/nonce_cache/src/main.rs +++ b/examples/nonce_cache/src/main.rs @@ -175,6 +175,7 @@ async fn pumpfun_copy_trade_with_grpc( )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: false, close_input_token_ata: false, create_mint_ata: true, diff --git a/examples/pumpfun_copy_trading/src/main.rs b/examples/pumpfun_copy_trading/src/main.rs index 811f857..bd4b9b8 100644 --- a/examples/pumpfun_copy_trading/src/main.rs +++ b/examples/pumpfun_copy_trading/src/main.rs @@ -169,6 +169,7 @@ async fn pumpfun_copy_trade(e: sol_parser_sdk::core::events::PumpFunTradeEvent) )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: false, close_input_token_ata: false, create_mint_ata: true, @@ -220,6 +221,7 @@ async fn pumpfun_copy_trade(e: sol_parser_sdk::core::events::PumpFunTradeEvent) )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: false, close_output_token_ata: false, close_mint_token_ata: false, diff --git a/examples/pumpfun_sniper_trading/src/main.rs b/examples/pumpfun_sniper_trading/src/main.rs index ec7bba8..72b5300 100644 --- a/examples/pumpfun_sniper_trading/src/main.rs +++ b/examples/pumpfun_sniper_trading/src/main.rs @@ -158,6 +158,7 @@ async fn pumpfun_sniper_trade(e: sol_parser_sdk::core::events::PumpFunTradeEvent )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: true, create_mint_ata: true, @@ -203,6 +204,7 @@ async fn pumpfun_sniper_trade(e: sol_parser_sdk::core::events::PumpFunTradeEvent )), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: true, close_mint_token_ata: false, diff --git a/examples/pumpswap_direct_trading/src/main.rs b/examples/pumpswap_direct_trading/src/main.rs index 7c18ce7..c27ab8a 100644 --- a/examples/pumpswap_direct_trading/src/main.rs +++ b/examples/pumpswap_direct_trading/src/main.rs @@ -42,6 +42,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: true, create_mint_ata: true, @@ -81,6 +82,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: true, close_mint_token_ata: false, diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index a19b663..114772d 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -236,6 +236,7 @@ async fn pumpswap_trade_with_grpc( extension_params: DexParamEnum::PumpSwap(params.clone()), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: is_sol, close_input_token_ata: is_sol, create_mint_ata: true, @@ -277,6 +278,7 @@ async fn pumpswap_trade_with_grpc( extension_params: DexParamEnum::PumpSwap(params.clone()), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: is_sol, close_output_token_ata: is_sol, close_mint_token_ata: false, diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index 712d5c7..79a8a10 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -157,6 +157,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) extension_params: DexParamEnum::RaydiumAmmV4(params), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: is_wsol, close_input_token_ata: is_wsol, create_mint_ata: true, @@ -199,6 +200,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) extension_params: DexParamEnum::RaydiumAmmV4(params), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: is_wsol, close_output_token_ata: is_wsol, close_mint_token_ata: false, diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index 4b4df8b..94a1d3d 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -161,6 +161,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> extension_params: DexParamEnum::RaydiumCpmm(buy_params), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: is_wsol, close_input_token_ata: is_wsol, create_mint_ata: true, @@ -201,6 +202,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> extension_params: DexParamEnum::RaydiumCpmm(sell_params), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: is_wsol, close_output_token_ata: is_wsol, close_mint_token_ata: false, diff --git a/examples/seed_trading/src/main.rs b/examples/seed_trading/src/main.rs index 2af964c..a4f3de6 100644 --- a/examples/seed_trading/src/main.rs +++ b/examples/seed_trading/src/main.rs @@ -42,6 +42,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_input_token_ata: true, close_input_token_ata: true, create_mint_ata: true, @@ -84,6 +85,7 @@ async fn main() -> Result<(), Box> { ), address_lookup_table_account: None, wait_tx_confirmed: true, + wait_for_all_submits: false, create_output_token_ata: true, close_output_token_ata: true, close_mint_token_ata: false, diff --git a/src/client/mod.rs b/src/client/mod.rs index 3f298eb..40462ff 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -362,6 +362,11 @@ pub struct TradeBuyParams { pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning pub wait_tx_confirmed: bool, + /// Fast-submit only (`wait_tx_confirmed = false`): when true, wait for every + /// SWQOS route's HTTP submit response so all submitted signatures are + /// returned. Set to true when confirming externally against a pinned + /// durable nonce; defaults to false. See `SwapParams.wait_for_all_submits`. + pub wait_for_all_submits: bool, /// Whether to create input token associated token account pub create_input_token_ata: bool, /// Whether to close input token associated token account after trade @@ -414,6 +419,11 @@ pub struct TradeSellParams { pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning pub wait_tx_confirmed: bool, + /// Fast-submit only (`wait_tx_confirmed = false`): when true, wait for every + /// SWQOS route's HTTP submit response so all submitted signatures are + /// returned. Set to true when confirming externally against a pinned + /// durable nonce; defaults to false. See `SwapParams.wait_for_all_submits`. + pub wait_for_all_submits: bool, /// Whether to create output token associated token account pub create_output_token_ata: bool, /// Whether to close output token associated token account after trade @@ -868,6 +878,7 @@ impl TradingClient { gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, log_enabled: self.log_enabled, + wait_for_all_submits: params.wait_for_all_submits, use_dedicated_sender_threads: self.use_dedicated_sender_threads, sender_thread_cores: self.sender_thread_cores.clone(), max_sender_concurrency: self.max_sender_concurrency, @@ -983,6 +994,7 @@ impl TradingClient { gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, log_enabled: self.log_enabled, + wait_for_all_submits: params.wait_for_all_submits, use_dedicated_sender_threads: self.use_dedicated_sender_threads, sender_thread_cores: self.sender_thread_cores.clone(), max_sender_concurrency: self.max_sender_concurrency, diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index 087bb16..b429c46 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -382,6 +382,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: true, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/instruction/meteora_damm_v2.rs b/src/instruction/meteora_damm_v2.rs index 5c102c9..a6878cf 100644 --- a/src/instruction/meteora_damm_v2.rs +++ b/src/instruction/meteora_damm_v2.rs @@ -364,6 +364,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: true, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 0591ca4..d5b97b8 100644 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -919,6 +919,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: false, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index 074405e..d036d83 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -589,6 +589,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: true, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index 4381851..cc1f58f 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -382,6 +382,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: true, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index 3999093..89e0566 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -394,6 +394,7 @@ mod tests { gas_fee_strategy: GasFeeStrategy::new(), simulate: true, log_enabled: false, + wait_for_all_submits: false, use_dedicated_sender_threads: false, sender_thread_cores: None, max_sender_concurrency: 0, diff --git a/src/trading/core/async_executor.rs b/src/trading/core/async_executor.rs index af3f4bb..3a966ce 100644 --- a/src/trading/core/async_executor.rs +++ b/src/trading/core/async_executor.rs @@ -496,7 +496,8 @@ impl ResultCollector { /// 等待全部任务完成(不等待链上确认),然后收集并返回所有签名。用于「多路提交」时返回多笔签名。 /// 轮询间隔 2ms,避免 50ms 间隔在最后一笔返回时多等几十 ms 拉高 submit 耗时。 - #[allow(dead_code)] + /// Re-enabled via `SwapParams.wait_for_all_submits` for callers that confirm + /// externally against a pinned durable nonce and need every submitted sig. async fn wait_for_all_submitted( &self, timeout_secs: u64, @@ -600,6 +601,7 @@ pub async fn execute_parallel( protocol_name: &'static str, is_buy: bool, wait_transaction_confirmed: bool, + wait_for_all_submits: bool, with_tip: bool, gas_fee_strategy: GasFeeStrategy, use_dedicated_sender_threads: bool, @@ -735,12 +737,23 @@ pub async fn execute_parallel( // All jobs enqueued (no spawn on hot path) if !wait_transaction_confirmed { - let ret = collector.wait_for_first_submitted(FAST_SUBMIT_RESULT_TIMEOUT).await.unwrap_or(( - false, - vec![], - Some(anyhow!("No SWQOS result within submit result window")), - vec![], - )); + let ret = if wait_for_all_submits { + collector.wait_for_all_submitted(FAST_SUBMIT_RESULT_TIMEOUT.as_secs()).await.unwrap_or( + ( + false, + vec![], + Some(anyhow!("No SWQOS result within submit result window")), + vec![], + ), + ) + } else { + collector.wait_for_first_submitted(FAST_SUBMIT_RESULT_TIMEOUT).await.unwrap_or(( + false, + vec![], + Some(anyhow!("No SWQOS result within submit result window")), + vec![], + )) + }; let (success, signatures, last_error, submit_timings) = ret; return Ok((success, signatures, last_error, submit_timings)); } diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index 5ecc226..26a7077 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -157,6 +157,10 @@ impl TradeExecutor for GenericTradeExecutor { } let need_confirm = params.wait_tx_confirmed; + // When the caller confirms externally (need_confirm = false) and opts in + // via SwapParams.wait_for_all_submits, return every route's signature so + // pinned-nonce confirmation can poll all of them. + let wait_for_all_submits = !need_confirm && params.wait_for_all_submits; let sender_config = params.sender_concurrency_config(); let result = execute_parallel( params.swqos_clients.as_slice(), @@ -169,6 +173,7 @@ impl TradeExecutor for GenericTradeExecutor { self.protocol_name, is_buy, false, // submit only here; confirmation and log timing handled below + wait_for_all_submits, if is_buy { true } else { params.with_tip }, params.gas_fee_strategy, params.use_dedicated_sender_threads, diff --git a/src/trading/core/params/dex_swap.rs b/src/trading/core/params/dex_swap.rs index 933027d..62f0cae 100644 --- a/src/trading/core/params/dex_swap.rs +++ b/src/trading/core/params/dex_swap.rs @@ -82,6 +82,14 @@ pub struct SwapParams { pub simulate: bool, /// Whether to output SDK logs (from TradeConfig.log_enabled). pub log_enabled: bool, + /// Fast-submit only (`wait_tx_confirmed = false`): when true, wait for every + /// SWQOS route's HTTP submit response so all submitted signatures are + /// returned. Defaults to false (post-4.0.11 behaviour: return after the + /// first route accepts). Set to true when the caller does its own on-chain + /// confirmation against a pinned durable nonce — only one route's tx can + /// land, but the caller cannot know which in advance, so it needs every + /// signature to poll via `getSignatureStatuses`. + pub wait_for_all_submits: bool, /// Use dedicated sender threads (internal; set via client.with_dedicated_sender_threads()). pub use_dedicated_sender_threads: bool, /// Core indices for dedicated sender threads (from TradeConfig.sender_thread_cores). Arc avoids cloning the Vec on hot path.