Update SWQOS submit behavior

This commit is contained in:
0xfnzero
2026-06-23 04:32:50 +08:00
parent 30df893c30
commit 9af86c8397
48 changed files with 50563 additions and 166 deletions
+80 -39
View File
@@ -187,8 +187,8 @@ pub struct SimpleBuyParams {
/// Recent blockhash for non-nonce transactions.
///
/// The SDK intentionally does not fetch blockhash on the hot path. Use
/// [`SimpleBuyParams::with_durable_nonce`] instead when submitting multiple
/// SWQoS lanes against a pinned nonce.
/// [`SimpleBuyParams::with_durable_nonce`] only when the caller specifically
/// wants durable-nonce transactions.
pub recent_blockhash: Option<Hash>,
/// Protocol-specific parameters, for example `DexParamEnum::PumpFun(...)`.
pub extension_params: DexParamEnum,
@@ -196,12 +196,15 @@ pub struct SimpleBuyParams {
pub gas_fee_strategy: GasFeeStrategy,
/// ATA creation/close behavior. See [`AccountPolicy`].
pub account_policy: AccountPolicy,
/// Optional Address Lookup Table to reduce transaction size.
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
/// Optional Address Lookup Tables to reduce transaction size.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
/// Wait until the transaction is confirmed before returning.
pub wait_tx_confirmed: bool,
/// Fast-submit mode only: wait for every SWQoS route's submit response so all
/// signatures can be returned.
/// Wait for every SWQoS route's submit response so all signatures can be
/// returned. Useful when confirming through poll-any semantics or monitoring
/// route variants externally. Recent-blockhash variants are not mutually
/// exclusive; durable nonce variants are.
pub wait_for_all_submits: bool,
/// Durable nonce info. Mutually exclusive with `recent_blockhash`.
pub durable_nonce: Option<DurableNonceInfo>,
@@ -235,12 +238,15 @@ pub struct SimpleSellParams {
pub gas_fee_strategy: GasFeeStrategy,
/// ATA creation/close behavior. See [`AccountPolicy`].
pub account_policy: AccountPolicy,
/// Optional Address Lookup Table to reduce transaction size.
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
/// Optional Address Lookup Tables to reduce transaction size.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
/// Wait until the transaction is confirmed before returning.
pub wait_tx_confirmed: bool,
/// Fast-submit mode only: wait for every SWQoS route's submit response so all
/// signatures can be returned.
/// Wait for every SWQoS route's submit response so all signatures can be
/// returned. Useful when confirming through poll-any semantics or monitoring
/// route variants externally. Recent-blockhash variants are not mutually
/// exclusive; durable nonce variants are.
pub wait_for_all_submits: bool,
/// Durable nonce info. Mutually exclusive with `recent_blockhash`.
pub durable_nonce: Option<DurableNonceInfo>,
@@ -281,7 +287,7 @@ impl SimpleBuyParams {
extension_params,
gas_fee_strategy,
account_policy: AccountPolicy::Auto,
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
wait_tx_confirmed: false,
wait_for_all_submits: false,
durable_nonce: None,
@@ -330,9 +336,10 @@ impl SimpleBuyParams {
self
}
/// Attach an Address Lookup Table to reduce transaction size.
pub fn address_lookup_table_account(mut self, value: AddressLookupTableAccount) -> Self {
self.address_lookup_table_account = Some(value);
/// Attach Address Lookup Tables to reduce transaction size.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub fn address_lookup_table_accounts(mut self, values: Vec<AddressLookupTableAccount>) -> Self {
self.address_lookup_table_accounts = values;
self
}
@@ -352,7 +359,7 @@ impl SimpleBuyParams {
self
}
/// In fast-submit mode, wait for all SWQoS submit responses and return every signature.
/// Wait for all SWQoS submit responses and return submitted signatures.
pub fn wait_for_all_submits(mut self, value: bool) -> Self {
self.wait_for_all_submits = value;
self
@@ -401,7 +408,7 @@ impl SimpleSellParams {
extension_params,
gas_fee_strategy,
account_policy: AccountPolicy::Auto,
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
wait_tx_confirmed: false,
wait_for_all_submits: false,
durable_nonce: None,
@@ -449,9 +456,10 @@ impl SimpleSellParams {
self
}
/// Attach an Address Lookup Table to reduce transaction size.
pub fn address_lookup_table_account(mut self, value: AddressLookupTableAccount) -> Self {
self.address_lookup_table_account = Some(value);
/// Attach Address Lookup Tables to reduce transaction size.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub fn address_lookup_table_accounts(mut self, values: Vec<AddressLookupTableAccount>) -> Self {
self.address_lookup_table_accounts = values;
self
}
@@ -471,7 +479,7 @@ impl SimpleSellParams {
self
}
/// In fast-submit mode, wait for all SWQoS submit responses and return every signature.
/// Wait for all SWQoS submit responses and return submitted signatures.
pub fn wait_for_all_submits(mut self, value: bool) -> Self {
self.wait_for_all_submits = value;
self
@@ -782,14 +790,16 @@ pub struct TradeBuyParams {
/// Protocol-specific parameters (PumpFun, Raydium, etc.)
pub extension_params: DexParamEnum,
// Extended configuration
/// Optional address lookup table for transaction size optimization
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
/// Optional address lookup tables for transaction size optimization.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
/// 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`.
/// When true, wait for every SWQOS route's HTTP submit response so all
/// submitted signatures are returned. This applies whether SDK confirmation
/// is enabled or the caller monitors externally. Recent-blockhash route
/// variants are not mutually exclusive; durable nonce variants are.
/// 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,
@@ -839,14 +849,16 @@ pub struct TradeSellParams {
/// Protocol-specific parameters (PumpFun, Raydium, etc.)
pub extension_params: DexParamEnum,
// Extended configuration
/// Optional address lookup table for transaction size optimization
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
/// Optional address lookup tables for transaction size optimization.
/// Pass one element for a single ALT or multiple elements for multi-ALT.
pub address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
/// 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`.
/// When true, wait for every SWQOS route's HTTP submit response so all
/// submitted signatures are returned. This applies whether SDK confirmation
/// is enabled or the caller monitors externally. Recent-blockhash route
/// variants are not mutually exclusive; durable nonce variants are.
/// 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,
@@ -906,7 +918,7 @@ impl From<SimpleBuyParams> for TradeBuyParams {
slippage_basis_points: params.slippage_basis_points,
recent_blockhash: params.recent_blockhash,
extension_params: params.extension_params,
address_lookup_table_account: params.address_lookup_table_account,
address_lookup_table_accounts: params.address_lookup_table_accounts,
wait_tx_confirmed: params.wait_tx_confirmed,
wait_for_all_submits: params.wait_for_all_submits,
create_input_token_ata,
@@ -942,7 +954,7 @@ impl From<SimpleSellParams> for TradeSellParams {
recent_blockhash: params.recent_blockhash,
with_tip: params.with_tip,
extension_params: params.extension_params,
address_lookup_table_account: params.address_lookup_table_account,
address_lookup_table_accounts: params.address_lookup_table_accounts,
wait_tx_confirmed: params.wait_tx_confirmed,
wait_for_all_submits: params.wait_for_all_submits,
create_output_token_ata,
@@ -1381,7 +1393,7 @@ impl TradingClient {
output_token_program: None,
input_amount: Some(params.input_token_amount),
slippage_basis_points: params.slippage_basis_points,
address_lookup_table_account: params.address_lookup_table_account,
address_lookup_table_accounts: params.address_lookup_table_accounts,
recent_blockhash: params.recent_blockhash,
wait_tx_confirmed: params.wait_tx_confirmed,
protocol_params,
@@ -1509,7 +1521,7 @@ impl TradingClient {
output_token_program: None,
input_amount: Some(params.input_token_amount),
slippage_basis_points: params.slippage_basis_points,
address_lookup_table_account: params.address_lookup_table_account,
address_lookup_table_accounts: params.address_lookup_table_accounts,
recent_blockhash: params.recent_blockhash,
wait_tx_confirmed: params.wait_tx_confirmed,
protocol_params,
@@ -1860,7 +1872,7 @@ mod tests {
extension_params: dummy_pumpfun_params(),
gas_fee_strategy: GasFeeStrategy::new(),
account_policy: AccountPolicy::HotPathMinimal,
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
wait_tx_confirmed: false,
wait_for_all_submits: false,
durable_nonce: None,
@@ -1891,7 +1903,7 @@ mod tests {
extension_params: dummy_pumpfun_params(),
gas_fee_strategy: GasFeeStrategy::new(),
account_policy: AccountPolicy::Auto,
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
wait_tx_confirmed: false,
wait_for_all_submits: false,
durable_nonce: None,
@@ -1931,6 +1943,35 @@ mod tests {
assert!(!low.wait_tx_confirmed);
}
#[test]
fn simple_buy_builder_maps_multiple_lookup_tables() {
let alt1 = AddressLookupTableAccount {
key: Pubkey::new_unique(),
addresses: vec![Pubkey::new_unique()],
};
let alt2 = AddressLookupTableAccount {
key: Pubkey::new_unique(),
addresses: vec![Pubkey::new_unique()],
};
let simple = SimpleBuyParams::new(
DexType::PumpFun,
TradeTokenType::SOL,
Pubkey::new_unique(),
BuyAmount::ExactInput(10_000),
dummy_pumpfun_params(),
Hash::new_unique(),
GasFeeStrategy::new(),
)
.address_lookup_table_accounts(vec![alt1.clone(), alt2.clone()]);
let low: TradeBuyParams = simple.into();
assert_eq!(low.address_lookup_table_accounts.len(), 2);
assert_eq!(low.address_lookup_table_accounts[0].key, alt1.key);
assert_eq!(low.address_lookup_table_accounts[1].key, alt2.key);
}
#[test]
fn simple_buy_builder_can_use_durable_nonce() {
let nonce_account = Pubkey::new_unique();
@@ -1970,7 +2011,7 @@ mod tests {
extension_params: dummy_pumpfun_params(),
gas_fee_strategy: GasFeeStrategy::new(),
account_policy: AccountPolicy::Auto,
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
wait_tx_confirmed: false,
wait_for_all_submits: false,
durable_nonce: None,
+1 -1
View File
@@ -365,7 +365,7 @@ mod tests {
output_token_program: None,
input_amount: Some(100_000),
slippage_basis_points: Some(100),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::Bonk(bonk_params()),
+1 -1
View File
@@ -347,7 +347,7 @@ mod tests {
output_token_program: None,
input_amount: Some(100_000),
slippage_basis_points: Some(100),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::MeteoraDammV2(protocol_params),
+3 -3
View File
@@ -944,7 +944,7 @@ mod tests {
output_token_program: None,
input_amount: Some(10_000_000),
slippage_basis_points: Some(300),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::PumpFun(params),
@@ -1125,7 +1125,7 @@ mod tests {
150_000,
500_000,
&business_instructions,
None,
&[],
Some(solana_hash::Hash::new_unique()),
None,
"PumpFun",
@@ -1160,7 +1160,7 @@ mod tests {
150_000,
500_000,
&business_instructions,
None,
&[],
Some(solana_hash::Hash::new_unique()),
None,
"PumpFun",
+1 -1
View File
@@ -572,7 +572,7 @@ mod tests {
output_token_program: None,
input_amount: Some(100_000),
slippage_basis_points: Some(100),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::PumpSwap(pumpswap_params()),
+1 -1
View File
@@ -365,7 +365,7 @@ mod tests {
output_token_program: None,
input_amount: Some(100_000),
slippage_basis_points: Some(100),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::RaydiumAmmV4(protocol_params),
+1 -1
View File
@@ -377,7 +377,7 @@ mod tests {
output_token_program: None,
input_amount: Some(100_000),
slippage_basis_points: Some(100),
address_lookup_table_account: None,
address_lookup_table_accounts: Vec::new(),
recent_blockhash: None,
wait_tx_confirmed: false,
protocol_params: DexParamEnum::RaydiumCpmm(cpmm_params()),
+8 -8
View File
@@ -36,7 +36,7 @@ pub fn build_transaction(
unit_limit: u32,
unit_price: u64,
business_instructions: &[Instruction],
address_lookup_table_account: Option<&AddressLookupTableAccount>,
address_lookup_table_accounts: &[AddressLookupTableAccount],
recent_blockhash: Option<Hash>,
middleware_manager: Option<&Arc<MiddlewareManager>>,
protocol_name: &str,
@@ -51,7 +51,7 @@ pub fn build_transaction(
unit_limit,
unit_price,
business_instructions,
address_lookup_table_account,
address_lookup_table_accounts,
recent_blockhash,
middleware_manager,
protocol_name,
@@ -74,7 +74,7 @@ pub fn build_transaction(
with_tip && tip_amount > 0.0,
unit_limit,
unit_price,
address_lookup_table_account.is_some()
address_lookup_table_accounts.len()
);
}
if serialized_len <= PACKET_DATA_SIZE {
@@ -93,7 +93,7 @@ fn build_transaction_inner(
unit_limit: u32,
unit_price: u64,
business_instructions: &[Instruction],
address_lookup_table_account: Option<&AddressLookupTableAccount>,
address_lookup_table_accounts: &[AddressLookupTableAccount],
recent_blockhash: Option<Hash>,
middleware_manager: Option<&Arc<MiddlewareManager>>,
protocol_name: &str,
@@ -127,7 +127,7 @@ fn build_transaction_inner(
build_versioned_transaction(
payer,
instructions,
address_lookup_table_account,
address_lookup_table_accounts,
blockhash,
middleware_manager,
protocol_name,
@@ -138,7 +138,7 @@ fn build_transaction_inner(
fn build_versioned_transaction(
payer: &Arc<Keypair>,
instructions: Vec<Instruction>,
address_lookup_table_account: Option<&AddressLookupTableAccount>,
address_lookup_table_accounts: &[AddressLookupTableAccount],
blockhash: Hash,
middleware_manager: Option<&Arc<MiddlewareManager>>,
protocol_name: &str,
@@ -156,7 +156,7 @@ fn build_versioned_transaction(
let build_result = builder.build_zero_alloc(
&payer.pubkey(),
&full_instructions,
address_lookup_table_account,
address_lookup_table_accounts,
blockhash,
);
release_builder(builder);
@@ -190,7 +190,7 @@ mod tests {
80_000,
100_000,
&business_instructions,
None,
&[],
Some(Hash::new_unique()),
None,
"test",
+27 -26
View File
@@ -47,12 +47,13 @@ const SWQOS_POOL_WORKERS: usize = 18;
const SWQOS_QUEUE_CAP: usize = 128;
const SWQOS_DEDICATED_DEFAULT_THREADS: usize = 18;
const FAST_SUBMIT_RESULT_TIMEOUT: Duration = Duration::from_secs(5);
const FAST_SUBMIT_DRAIN_GRACE: Duration = Duration::from_millis(20);
/// Shared across all jobs in one batch; built once, cloned as single Arc per job (minimal hot-path clone).
struct SwqosSharedContext {
payer: Arc<Keypair>,
instructions: Arc<Vec<Instruction>>,
address_lookup_table_account: Option<AddressLookupTableAccount>,
address_lookup_table_accounts: Arc<Vec<AddressLookupTableAccount>>,
recent_blockhash: Option<Hash>,
durable_nonce: Option<DurableNonceInfo>,
middleware_manager: Option<Arc<MiddlewareManager>>,
@@ -92,7 +93,7 @@ async fn run_one_swqos_job(job: SwqosJob) {
job.unit_limit,
job.unit_price,
s.instructions.as_ref(),
s.address_lookup_table_account.as_ref(),
s.address_lookup_table_accounts.as_slice(),
s.recent_blockhash,
s.middleware_manager.as_ref(),
s.protocol_name,
@@ -508,10 +509,11 @@ impl ResultCollector {
}
}
/// 等待全部任务完成(不等待链上确认),然后收集并返回所有签名。用于「多路提交」时返回多笔签名。
/// 等待全部任务完成(不等待链上确认),然后收集并返回所有已返回的签名。
/// 轮询间隔 2ms,避免 50ms 间隔在最后一笔返回时多等几十 ms 拉高 submit 耗时。
/// Re-enabled via `SwapParams.wait_for_all_submits` for callers that confirm
/// externally against a pinned durable nonce and need every submitted sig.
/// Re-enabled via `SwapParams.wait_for_all_submits` for callers that need
/// every submitted signature, either for external monitoring or for
/// executor-level poll-any confirmation after parallel submit.
async fn wait_for_all_submitted(
&self,
timeout_secs: u64,
@@ -525,21 +527,10 @@ impl ResultCollector {
}
tokio::time::sleep(poll_interval).await;
}
// 「不等待链上确认」仍会等各 SWQOS 的 HTTP 回包;主循环在收齐或触达 `timeout_secs` 后结束。
// 若主窗口到时仍有未回包通道,晚到的 TaskResult 若立刻 drain 会丢签名——仅在该路径上拉长 grace。
let all_submitted = self.completed_count.load(Ordering::Acquire) >= self.total_tasks;
if all_submitted {
tokio::task::yield_now().await;
} else {
tokio::time::sleep(Duration::from_millis(600)).await;
while self.completed_count.load(Ordering::Acquire) < self.total_tasks {
if start.elapsed() > primary + Duration::from_secs(6) {
break;
}
tokio::time::sleep(Duration::from_millis(20)).await;
}
tokio::time::sleep(Duration::from_millis(120)).await;
}
// Bound the opt-in "all submits" path tightly. A slow relay must not
// delay poll-any confirmation by multiple seconds after the submit
// window; give only a short grace for a just-finished worker to publish.
tokio::time::sleep(FAST_SUBMIT_DRAIN_GRACE).await;
self.get_first()
}
}
@@ -608,7 +599,7 @@ pub async fn execute_parallel(
swqos_clients: &[Arc<SwqosClient>],
payer: Arc<Keypair>,
instructions: Vec<Instruction>,
address_lookup_table_account: Option<AddressLookupTableAccount>,
address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
recent_blockhash: Option<Hash>,
durable_nonce: Option<DurableNonceInfo>,
middleware_manager: Option<Arc<MiddlewareManager>>,
@@ -660,17 +651,13 @@ pub async fn execute_parallel(
return Err(anyhow!("No available gas fee strategy configs"));
}
if is_buy && selected_task_configs.len() > 1 && durable_nonce.is_none() {
return Err(anyhow!("Multiple swqos transactions require durable_nonce to be set.",));
}
// Task preparation completed: one shared context (clone once per batch), then minimal per-task data.
let channel_count = selected_task_configs.len().max(1);
let collector = Arc::new(ResultCollector::new(channel_count));
let shared = Arc::new(SwqosSharedContext {
payer,
instructions,
address_lookup_table_account,
address_lookup_table_accounts: Arc::new(address_lookup_table_accounts),
recent_blockhash,
durable_nonce,
middleware_manager,
@@ -848,4 +835,18 @@ mod tests {
assert_eq!(selected[0].gas_fee_config.2.cu_price, 700_000);
assert_eq!(selected[0].gas_fee_config.2.tip, 0.0);
}
#[tokio::test]
async fn wait_for_all_submitted_timeout_is_bounded() {
let collector = ResultCollector::new(1);
let start = Instant::now();
let result = collector.wait_for_all_submitted(0).await;
assert!(result.is_none());
assert!(
start.elapsed() < Duration::from_millis(150),
"wait_for_all_submitted should not add multi-second grace after timeout"
);
}
}
+9 -8
View File
@@ -96,6 +96,7 @@ impl TradeExecutor for GenericTradeExecutor {
total_start.as_ref().map(|s| s.elapsed()).unwrap_or(Duration::ZERO);
let before_submit_us = (params.log_enabled && crate::common::sdk_log::sdk_log_enabled())
.then(crate::common::clock::now_micros);
let address_lookup_table_accounts = params.address_lookup_table_accounts.clone();
if params.simulate {
let send_start = crate::common::sdk_log::sdk_log_enabled().then(Instant::now);
@@ -103,7 +104,7 @@ impl TradeExecutor for GenericTradeExecutor {
params.rpc,
params.payer,
final_instructions,
params.address_lookup_table_account,
address_lookup_table_accounts,
params.recent_blockhash,
params.durable_nonce,
params.middleware_manager,
@@ -157,16 +158,16 @@ 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;
// Each SWQOS lane may submit a distinct transaction because relay tips
// can use different accounts, so confirmation must be able to poll every
// returned signature when the caller opts in.
let wait_for_all_submits = params.wait_for_all_submits;
let sender_config = params.sender_concurrency_config();
let result = execute_parallel(
params.swqos_clients.as_slice(),
params.payer,
final_instructions,
params.address_lookup_table_account,
address_lookup_table_accounts,
params.recent_blockhash,
params.durable_nonce,
params.middleware_manager,
@@ -253,7 +254,7 @@ async fn simulate_transaction(
rpc: Option<Arc<SolanaRpcClient>>,
payer: Arc<Keypair>,
instructions: Vec<Instruction>,
address_lookup_table_account: Option<AddressLookupTableAccount>,
address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
recent_blockhash: Option<Hash>,
durable_nonce: Option<DurableNonceInfo>,
middleware_manager: Option<Arc<MiddlewareManager>>,
@@ -288,7 +289,7 @@ async fn simulate_transaction(
unit_limit,
unit_price,
&instructions,
address_lookup_table_account.as_ref(),
address_lookup_table_accounts.as_slice(),
recent_blockhash,
middleware_manager.as_ref(),
protocol_name,
+10 -8
View File
@@ -61,7 +61,7 @@ pub struct SwapParams {
pub output_token_program: Option<Pubkey>,
pub input_amount: Option<u64>,
pub slippage_basis_points: Option<u64>,
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
pub address_lookup_table_accounts: Vec<AddressLookupTableAccount>,
pub recent_blockhash: Option<Hash>,
pub wait_tx_confirmed: bool,
pub protocol_params: DexParamEnum,
@@ -82,13 +82,15 @@ 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`.
/// When true, wait for every SWQOS route's HTTP submit response before
/// returning so the result includes all submitted signatures.
///
/// This is useful when confirmation or external monitoring polls all
/// signatures: each route can submit a distinct transaction because relay
/// tips may use different accounts. With a durable nonce, at most one route
/// can consume the nonce; with a recent blockhash, multiple route variants
/// may be valid, so callers must choose strategy and account state
/// accordingly. Defaults to false for lower submit latency.
pub wait_for_all_submits: bool,
/// Use dedicated sender threads (internal; set via client.with_dedicated_sender_threads()).
pub use_dedicated_sender_threads: bool,
+6 -6
View File
@@ -55,7 +55,7 @@ impl PreallocatedTxBuilder {
///
/// # 交易版本自动选择
///
/// - **有地址查找表** (`lookup_table = Some`): 使用 `VersionedMessage::V0`
/// - **有地址查找表** (`lookup_tables` 非空): 使用 `VersionedMessage::V0`
/// - 支持地址查找表压缩
/// - 减少交易大小
/// - 需要 RPC 支持 V0
@@ -69,11 +69,11 @@ impl PreallocatedTxBuilder {
///
/// ```rust,ignore
/// // 无查找表 -> Legacy 消息
/// let msg = builder.build_zero_alloc(&payer, &ixs, None, blockhash);
/// let msg = builder.build_zero_alloc(&payer, &ixs, &[], blockhash);
/// assert!(matches!(msg, VersionedMessage::Legacy(_)));
///
/// // 有查找表 -> V0 消息
/// let msg = builder.build_zero_alloc(&payer, &ixs, Some(table_key), blockhash);
/// let msg = builder.build_zero_alloc(&payer, &ixs, &[lookup_table], blockhash);
/// assert!(matches!(msg, VersionedMessage::V0(_)));
/// ```
#[inline(always)]
@@ -81,17 +81,17 @@ impl PreallocatedTxBuilder {
&mut self,
payer: &Pubkey,
instructions: &[Instruction],
address_lookup_table_account: Option<&AddressLookupTableAccount>,
address_lookup_table_accounts: &[AddressLookupTableAccount],
recent_blockhash: Hash,
) -> Result<VersionedMessage> {
self.reset();
self.instructions.extend_from_slice(instructions);
if let Some(alt) = address_lookup_table_account {
if !address_lookup_table_accounts.is_empty() {
let message = v0::Message::try_compile(
payer,
&self.instructions,
std::slice::from_ref(alt),
address_lookup_table_accounts,
recent_blockhash,
)?;
Ok(VersionedMessage::V0(message))