From eb8de36f503986e776ffdaf55d7049247572b6c3 Mon Sep 17 00:00:00 2001 From: Wood Date: Fri, 21 Nov 2025 13:05:39 +0800 Subject: [PATCH 1/5] refactor: split seed optimization config into wsol_use_seed and mint_use_seed - Split use_seed_optimize parameter into two independent configs: * wsol_use_seed: controls seed optimization for WSOL ATA operations (default: false) * mint_use_seed: controls seed optimization for other mint ATA operations (default: true) - Refactor TradeConfig to accept all parameters in new() constructor - Remove deprecated builder methods (with_seed_config, with_wsol_ata_config) - Add wsol_use_seed and mint_use_seed fields to SwapParams - Remove open_seed_optimize field from SwapParams - Update all instruction builders to use correct seed parameter: * Use params.wsol_use_seed for WSOL token operations * Use params.mint_use_seed for other token operations * Fix token type detection in bonk.rs, raydium_cpmm.rs, and raydium_amm_v4.rs to properly select wsol_use_seed when dealing with WSOL tokens - Update wsol_manager functions to accept is_use_seed parameter: * handle_wsol() * close_wsol() * create_wsol_ata() * wrap_sol_only() * wrap_wsol_to_sol() - Add wrap_wsol_to_sol() function with smart temporary account selection: * If source is seed-created, use normal ATA for temp account * If source is normal ATA, use seed ATA for temp account * Prevents address conflicts while optimizing performance This provides fine-grained control over seed optimization strategies, allowing different configurations for WSOL and other tokens. --- examples/wsol_wrapper/src/main.rs | 28 +++++-- src/common/types.rs | 27 +++---- src/instruction/bonk.rs | 18 ++--- src/instruction/meteora_damm_v2.rs | 18 ++--- src/instruction/pumpfun.rs | 6 +- src/instruction/pumpswap.rs | 18 ++--- src/instruction/raydium_amm_v4.rs | 18 ++--- src/instruction/raydium_cpmm.rs | 18 ++--- src/lib.rs | 59 +++++++++------ src/trading/common/wsol_manager.rs | 118 +++++++++++++++++++---------- src/trading/core/params.rs | 3 +- 11 files changed, 196 insertions(+), 135 deletions(-) diff --git a/examples/wsol_wrapper/src/main.rs b/examples/wsol_wrapper/src/main.rs index 5845afa..9d0b678 100644 --- a/examples/wsol_wrapper/src/main.rs +++ b/examples/wsol_wrapper/src/main.rs @@ -8,7 +8,7 @@ async fn main() -> Result<(), Box> { println!("🔄 WSOL Wrapper Example"); println!("This example demonstrates:"); println!("1. Wrapping SOL to WSOL"); - println!("2. Partial unwrapping WSOL back to SOL using seed account"); + println!("2. Partial unwrapping WSOL back to SOL using temporary account"); println!("3. Closing WSOL account and unwrapping remaining balance"); // Initialize SolanaTrade client @@ -18,8 +18,9 @@ async fn main() -> Result<(), Box> { println!("\n📦 Example 1: Wrapping SOL to WSOL"); let wrap_amount = 1_000_000; // 0.001 SOL in lamports println!("Wrapping {} lamports (0.001 SOL) to WSOL...", wrap_amount); + let is_use_seed = false; // 设置是否使用seed优化 - match solana_trade.wrap_sol_to_wsol(wrap_amount).await { + match solana_trade.wrap_sol_to_wsol(wrap_amount, is_use_seed).await { Ok(signature) => { println!("✅ Successfully wrapped SOL to WSOL!"); println!("Transaction signature: {}", signature); @@ -36,13 +37,17 @@ async fn main() -> Result<(), Box> { tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; // Example 2: Unwrap half of the WSOL back to SOL using seed account - println!("\n🔄 Example 2: Unwrapping half of WSOL back to SOL using seed account"); + println!("\n🔄 Example 2: Unwrapping half of WSOL back to SOL using temporary account"); let unwrap_amount = wrap_amount / 2; // Half of the wrapped amount - println!("Unwrapping {} lamports (0.0005 SOL) back to SOL using seed account...", unwrap_amount); + println!("Unwrapping {} lamports (0.0005 SOL) back to SOL using temporary account...", unwrap_amount); - match solana_trade.wrap_wsol_to_sol(unwrap_amount).await { + // 假设我们的WSOL ATA是使用seed创建的(根据实际情况设置) + // 如果是seed创建的,设置为true;如果是普通ATA,设置为false + let source_is_seed = is_use_seed; // 与is_use_seed保持一致 + + match solana_trade.wrap_wsol_to_sol(unwrap_amount, source_is_seed).await { Ok(signature) => { - println!("✅ Successfully unwrapped half of WSOL back to SOL using seed account!"); + println!("✅ Successfully unwrapped half of WSOL back to SOL using temporary account!"); println!("Transaction signature: {}", signature); println!("Explorer: https://solscan.io/tx/{}", signature); } @@ -59,7 +64,7 @@ async fn main() -> Result<(), Box> { println!("\n🔒 Example 3: Closing WSOL account and unwrapping remaining balance"); println!("Closing WSOL account and unwrapping all remaining balance to SOL..."); - match solana_trade.close_wsol().await { + match solana_trade.close_wsol(is_use_seed).await { Ok(signature) => { println!("✅ Successfully closed WSOL account and unwrapped remaining balance!"); println!("Transaction signature: {}", signature); @@ -81,7 +86,14 @@ async fn create_solana_trade_client() -> Result = vec![SwqosConfig::Default(rpc_url.clone())]; - let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment); + let trade_config = TradeConfig::new( + rpc_url, + swqos_configs, + commitment, + true, // create_wsol_ata_on_startup + false, // wsol_use_seed + true, // mint_use_seed + ); let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await; println!("✅ SolanaTrade client initialized successfully!"); Ok(solana_trade) diff --git a/src/common/types.rs b/src/common/types.rs index d6c6432..cea74cc 100755 --- a/src/common/types.rs +++ b/src/common/types.rs @@ -9,8 +9,10 @@ pub struct TradeConfig { /// Whether to create WSOL ATA on startup (default: true) /// If true, SDK will check WSOL ATA on initialization and create if not exists pub create_wsol_ata_on_startup: bool, - /// Whether to use seed optimization for all ATA operations (default: true) - pub use_seed_optimize: bool, + /// Whether to use seed optimization for WSOL ATA operations (default: false) + pub wsol_use_seed: bool, + /// Whether to use seed optimization for other mint ATA operations (default: true) + pub mint_use_seed: bool, } impl TradeConfig { @@ -18,28 +20,19 @@ impl TradeConfig { rpc_url: String, swqos_configs: Vec, commitment: CommitmentConfig, + create_wsol_ata_on_startup: bool, + wsol_use_seed: bool, + mint_use_seed: bool, ) -> Self { - println!("🔧 TradeConfig create_wsol_ata_on_startup default value: true"); - println!("🔧 TradeConfig use_seed_optimize default value: true"); Self { rpc_url, swqos_configs, commitment, - create_wsol_ata_on_startup: true, // 默认:启动时检查并创建 - use_seed_optimize: true, // 默认:使用seed优化 + create_wsol_ata_on_startup, + wsol_use_seed, + mint_use_seed, } } - - /// Create a TradeConfig with custom WSOL ATA settings - pub fn with_wsol_ata_config( - mut self, - create_wsol_ata_on_startup: bool, - use_seed_optimize: bool, - ) -> Self { - self.create_wsol_ata_on_startup = create_wsol_ata_on_startup; - self.use_seed_optimize = use_seed_optimize; - self - } } pub type SolanaRpcClient = solana_client::nonblocking::rpc_client::RpcClient; diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index f7655a7..8098ee3 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -86,7 +86,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &protocol_params.mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -97,7 +97,7 @@ impl InstructionBuilder for BonkInstructionBuilder { &crate::constants::WSOL_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + if usd1_pool { params.mint_use_seed } else { params.wsol_use_seed }, ); let base_vault_account = if protocol_params.base_vault == Pubkey::default() { @@ -122,7 +122,7 @@ impl InstructionBuilder for BonkInstructionBuilder { if params.create_input_mint_ata && !usd1_pool { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); } if params.create_output_mint_ata { @@ -132,7 +132,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &protocol_params.mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -167,7 +167,7 @@ impl InstructionBuilder for BonkInstructionBuilder { instructions.push(Instruction::new_with_bytes(accounts::BONK, &data, accounts.to_vec())); if params.close_input_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } Ok(instructions) @@ -246,7 +246,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &protocol_params.mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -257,7 +257,7 @@ impl InstructionBuilder for BonkInstructionBuilder { &crate::constants::WSOL_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.wsol_use_seed, ); let base_vault_account = if protocol_params.base_vault == Pubkey::default() { @@ -281,7 +281,7 @@ impl InstructionBuilder for BonkInstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.close_output_mint_ata && !usd1_pool { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); } let mut data = [0u8; 32]; @@ -314,7 +314,7 @@ impl InstructionBuilder for BonkInstructionBuilder { instructions.push(Instruction::new_with_bytes(accounts::BONK, &data, accounts.to_vec())); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/meteora_damm_v2.rs b/src/instruction/meteora_damm_v2.rs index fd8b54f..a22d04e 100644 --- a/src/instruction/meteora_damm_v2.rs +++ b/src/instruction/meteora_damm_v2.rs @@ -54,7 +54,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_b_program }, - params.open_seed_optimize, + params.wsol_use_seed, ); let output_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -65,7 +65,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_a_program }, - params.open_seed_optimize, + params.mint_use_seed, ); // ======================================== @@ -75,7 +75,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); } if params.create_output_mint_ata { @@ -85,7 +85,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -121,7 +121,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } Ok(instructions) @@ -165,7 +165,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_b_program }, - params.open_seed_optimize, + params.mint_use_seed, ); let output_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -176,7 +176,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_a_program }, - params.open_seed_optimize, + params.wsol_use_seed, ); // ======================================== @@ -185,7 +185,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); } // Create buy instruction @@ -218,7 +218,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { )); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 9994a8e..df34310 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -93,7 +93,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let user_volume_accumulator = @@ -112,7 +112,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &token_program, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -229,7 +229,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &token_program, - params.open_seed_optimize, + params.mint_use_seed, ); // ======================================== diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index eaa87cc..9f76580 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -108,14 +108,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), &base_mint, &base_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), "e_mint, "e_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); // Determine fee recipient based on mayhem mode @@ -136,7 +136,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { if create_wsol_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount, params.wsol_use_seed)); } if params.create_output_mint_ata { @@ -146,7 +146,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), if quote_is_wsol_or_usdc { &base_mint } else { "e_mint }, if quote_is_wsol_or_usdc { &base_token_program } else { "e_token_program }, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -209,7 +209,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { instructions.push(buy_instruction); if close_wsol_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } Ok(instructions) } @@ -308,14 +308,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), &base_mint, &base_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), "e_mint, "e_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); // ======================================== @@ -324,7 +324,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let mut instructions = Vec::with_capacity(3); if create_wsol_ata { - instructions.extend(wsol_manager::create_wsol_ata(¶ms.payer.pubkey())); + instructions.extend(wsol_manager::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); } // Create sell instruction @@ -386,7 +386,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { instructions.push(sell_instruction); if close_wsol_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index 6a87503..5d9bca5 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -64,14 +64,14 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.wsol_use_seed, ); let user_destination_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.mint_use_seed, ); // ======================================== @@ -81,7 +81,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); } if params.create_output_mint_ata { @@ -91,7 +91,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -130,7 +130,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } Ok(instructions) @@ -182,14 +182,14 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.mint_use_seed, ); let user_destination_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.wsol_use_seed, ); // ======================================== @@ -198,7 +198,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); } // Create buy instruction @@ -234,7 +234,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { )); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index ddab752..201c07a 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -86,13 +86,13 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.wsol_use_seed, ); let output_token_account = get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.output_mint, &mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let input_vault_account = get_vault_account( @@ -115,7 +115,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); } if params.create_output_mint_ata { @@ -125,7 +125,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ), ); } @@ -160,7 +160,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } Ok(instructions) @@ -230,13 +230,13 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.open_seed_optimize, + params.wsol_use_seed, ); let input_token_account = get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.input_mint, &mint_token_program, - params.open_seed_optimize, + params.mint_use_seed, ); let output_vault_account = get_vault_account( @@ -258,7 +258,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); } // Create sell instruction @@ -291,7 +291,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.close_output_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/lib.rs b/src/lib.rs index 7a2b9b1..38c0c03 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,9 +59,10 @@ pub struct SolanaTrade { pub swqos_clients: Vec>, /// Optional middleware manager for custom transaction processing pub middleware_manager: Option>, - /// Whether to use seed optimization for all ATA operations (default: true) - /// Applies to all token account creations across buy and sell operations - pub use_seed_optimize: bool, + /// Whether to use seed optimization for WSOL ATA operations (default: false) + pub wsol_use_seed: bool, + /// Whether to use seed optimization for other mint ATA operations (default: true) + pub mint_use_seed: bool, } static INSTANCE: Mutex>> = Mutex::new(None); @@ -73,7 +74,8 @@ impl Clone for SolanaTrade { rpc: self.rpc.clone(), swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), - use_seed_optimize: self.use_seed_optimize, + wsol_use_seed: self.wsol_use_seed, + mint_use_seed: self.mint_use_seed, } } } @@ -223,9 +225,9 @@ impl SolanaTrade { Err(_) => { // WSOL ATA不存在,创建它 println!("🔨 创建WSOL ATA: {}", wsol_ata); - // 使用seed优化创建WSOL ATA + // 使用配置中的wsol_use_seed设置创建WSOL ATA let create_ata_ixs = - crate::trading::common::wsol_manager::create_wsol_ata(&payer.pubkey()); + crate::trading::common::wsol_manager::create_wsol_ata(&payer.pubkey(), trade_config.wsol_use_seed); if !create_ata_ixs.is_empty() { // 构建并发送交易 @@ -273,7 +275,8 @@ impl SolanaTrade { rpc, swqos_clients, middleware_manager: None, - use_seed_optimize: trade_config.use_seed_optimize, + wsol_use_seed: trade_config.wsol_use_seed, + mint_use_seed: trade_config.mint_use_seed, }; let mut current = INSTANCE.lock(); @@ -386,7 +389,8 @@ impl SolanaTrade { .unwrap_or(256 * 1024), wait_transaction_confirmed: params.wait_transaction_confirmed, protocol_params: protocol_params.clone(), - open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 + wsol_use_seed: self.wsol_use_seed, // 使用wsol_use_seed配置 + mint_use_seed: self.mint_use_seed, // 使用mint_use_seed配置 swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), durable_nonce: params.durable_nonce, @@ -483,7 +487,8 @@ impl SolanaTrade { wait_transaction_confirmed: params.wait_transaction_confirmed, protocol_params: protocol_params.clone(), with_tip: params.with_tip, - open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 + wsol_use_seed: self.wsol_use_seed, // 使用wsol_use_seed配置 + mint_use_seed: self.mint_use_seed, // 使用mint_use_seed配置 swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), durable_nonce: params.durable_nonce, @@ -574,6 +579,7 @@ impl SolanaTrade { /// /// # Arguments /// * `amount` - The amount of SOL to wrap (in lamports) + /// * `is_use_seed` - Whether to use seed optimization for WSOL ATA creation /// /// # Returns /// * `Ok(String)` - Transaction signature if successful @@ -586,11 +592,11 @@ impl SolanaTrade { /// - wSOL associated token account creation fails /// - Transaction fails to execute or confirm /// - Network or RPC errors occur - pub async fn wrap_sol_to_wsol(&self, amount: u64) -> Result { + pub async fn wrap_sol_to_wsol(&self, amount: u64, is_use_seed: bool) -> Result { use crate::trading::common::wsol_manager::handle_wsol; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = handle_wsol(&self.payer.pubkey(), amount); + let instructions = handle_wsol(&self.payer.pubkey(), amount, is_use_seed); let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); @@ -603,6 +609,9 @@ impl SolanaTrade { /// transfers any remaining wSOL balance back to the account owner as native SOL. /// This is useful for cleaning up wSOL accounts and recovering wrapped SOL after trading operations. /// + /// # Arguments + /// * `is_use_seed` - Whether the WSOL ATA was created using seed optimization + /// /// # Returns /// * `Ok(String)` - Transaction signature if successful /// * `Err(anyhow::Error)` - If the transaction fails to execute @@ -614,11 +623,11 @@ impl SolanaTrade { /// - Account closure fails due to insufficient permissions /// - Transaction fails to execute or confirm /// - Network or RPC errors occur - pub async fn close_wsol(&self) -> Result { + pub async fn close_wsol(&self, is_use_seed: bool) -> Result { use crate::trading::common::wsol_manager::close_wsol; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = close_wsol(&self.payer.pubkey()); + let instructions = close_wsol(&self.payer.pubkey(), is_use_seed); let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); @@ -632,6 +641,9 @@ impl SolanaTrade { /// without transferring any SOL into it. This is useful when you want to set up /// the account infrastructure in advance without committing funds yet. /// + /// # Arguments + /// * `is_use_seed` - Whether to use seed optimization for WSOL ATA creation + /// /// # Returns /// * `Ok(String)` - Transaction signature if successful /// * `Err(anyhow::Error)` - If the transaction fails to execute @@ -643,12 +655,12 @@ impl SolanaTrade { /// - Transaction fails to execute or confirm /// - Network or RPC errors occur /// - Insufficient SOL for transaction fees - pub async fn create_wsol_ata(&self) -> Result { + pub async fn create_wsol_ata(&self, is_use_seed: bool) -> Result { use crate::trading::common::wsol_manager::create_wsol_ata; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = create_wsol_ata(&self.payer.pubkey()); + let instructions = create_wsol_ata(&self.payer.pubkey(), is_use_seed); // If instructions are empty, ATA already exists if instructions.is_empty() { @@ -664,16 +676,17 @@ impl SolanaTrade { Ok(signature.to_string()) } - /// 将 WSOL 转换为 SOL,使用 seed 账户 + /// 将 WSOL 转换为 SOL,使用临时账户 /// /// 这个函数实现以下步骤: - /// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 - /// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 - /// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 - /// 4. 添加关闭 WSOL seed 账号的指令 + /// 1. 创建临时 WSOL 账号(如果原始账号是seed创建,则临时账号使用普通ATA;否则使用seed) + /// 2. 获取临时账号的 ATA 地址 + /// 3. 添加从用户 WSOL ATA 转账到临时 ATA 账号的指令 + /// 4. 添加关闭临时 WSOL 账号的指令 /// /// # Arguments /// * `amount` - 要转换的 WSOL 数量(以 lamports 为单位) + /// * `source_is_seed` - 原始 WSOL 账号是否是 seed 创建的 /// /// # Returns /// * `Ok(String)` - 交易签名 @@ -683,16 +696,16 @@ impl SolanaTrade { /// /// 此函数在以下情况下会返回错误: /// - 用户 WSOL ATA 中余额不足 - /// - seed 账户创建失败 + /// - 临时账户创建失败 /// - 转账指令执行失败 /// - 交易执行或确认失败 /// - 网络或 RPC 错误 - pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result { + pub async fn wrap_wsol_to_sol(&self, amount: u64, source_is_seed: bool) -> Result { use crate::trading::common::wsol_manager::wrap_wsol_to_sol as wrap_wsol_to_sol_internal; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?; + let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount, source_is_seed)?; let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); diff --git a/src/trading/common/wsol_manager.rs b/src/trading/common/wsol_manager.rs index ffde170..28f8a42 100644 --- a/src/trading/common/wsol_manager.rs +++ b/src/trading/common/wsol_manager.rs @@ -8,13 +8,21 @@ use solana_sdk::{instruction::Instruction, message::AccountMeta, pubkey::Pubkey} use solana_system_interface::instruction::transfer; #[inline] -pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]> { - let wsol_token_account = +pub fn handle_wsol(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> SmallVec<[Instruction; 3]> { + let wsol_token_account = if is_use_seed { + crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( + &payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + true, + ) + } else { crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ); + ) + }; let mut insts = SmallVec::<[Instruction; 3]>::new(); insts.extend(create_associated_token_account_idempotent_fast( @@ -36,13 +44,21 @@ pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]> insts } -pub fn close_wsol(payer: &Pubkey) -> Vec { - let wsol_token_account = +pub fn close_wsol(payer: &Pubkey, is_use_seed: bool) -> Vec { + let wsol_token_account = if is_use_seed { + crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( + &payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + true, + ) + } else { crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ); + ) + }; crate::common::fast_fn::get_cached_instructions( crate::common::fast_fn::InstructionCacheKey::CloseWsolAccount { payer: *payer, @@ -62,24 +78,33 @@ pub fn close_wsol(payer: &Pubkey) -> Vec { } #[inline] -pub fn create_wsol_ata(payer: &Pubkey) -> Vec { - create_associated_token_account_idempotent_fast( +pub fn create_wsol_ata(payer: &Pubkey, is_use_seed: bool) -> Vec { + crate::common::fast_fn::create_associated_token_account_idempotent_fast_use_seed( &payer, &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, + is_use_seed, ) } /// 只充值SOL到已存在的WSOL ATA(不创建账户)- 标准方式 #[inline] -pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2]> { - let wsol_token_account = +pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> SmallVec<[Instruction; 2]> { + let wsol_token_account = if is_use_seed { + crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( + &payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + true, + ) + } else { crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ); + ) + }; let mut insts = SmallVec::<[Instruction; 2]>::new(); insts.extend([ @@ -95,55 +120,72 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2 insts } -/// 将 WSOL 转换为 SOL,使用 seed 账户 -/// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 -/// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 -/// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 -/// 4. 添加关闭 WSOL seed 账号的指令 +/// 将 WSOL 转换为 SOL,使用临时账户 +/// 1. 创建临时 WSOL 账号(如果原始账号是seed创建,则临时账号使用普通ATA;否则使用seed) +/// 2. 获取临时账号的 ATA 地址 +/// 3. 添加从用户 WSOL ATA 转账到临时 ATA 账号的指令 +/// 4. 添加关闭临时 WSOL 账号的指令 +/// +/// # Arguments +/// * `payer` - 支付者公钥 +/// * `amount` - 要转换的 WSOL 数量 +/// * `source_is_seed` - 原始 WSOL 账号是否是 seed 创建的 pub fn wrap_wsol_to_sol( payer: &Pubkey, amount: u64, + source_is_seed: bool, ) -> Result, anyhow::Error> { let mut instructions = Vec::new(); - // 1. 创建 WSOL seed 账户 - let seed_account_instructions = create_associated_token_account_use_seed( - payer, - payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - )?; - instructions.extend(seed_account_instructions); - - // 2. 获取 seed 账户的 ATA 地址 - let seed_ata_address = get_associated_token_address_with_program_id_use_seed( - payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - )?; - - // 3. 获取用户的 WSOL ATA 地址 - let user_wsol_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( + // 1. 分别获取普通ATA和seed ATA地址 + let normal_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, ); + let seed_ata = get_associated_token_address_with_program_id_use_seed( + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + )?; - // 4. 添加从用户 WSOL ATA 转账到 seed ATA 的指令 + // 2. 根据原始账号类型决定用户账号和临时账号 + // 如果原始账号是seed,则用户账号=seed_ata,临时账号=normal_ata(避免地址冲突) + // 如果原始账号是普通ATA,则用户账号=normal_ata,临时账号=seed_ata(提高性能) + let (user_wsol_ata, temp_ata_address, temp_account_instructions) = if source_is_seed { + let create_insts = crate::common::fast_fn::create_associated_token_account_idempotent_fast( + payer, + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + ); + (seed_ata, normal_ata, create_insts) + } else { + let create_insts = create_associated_token_account_use_seed( + payer, + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + )?; + (normal_ata, seed_ata, create_insts) + }; + instructions.extend(temp_account_instructions); + + // 3. 添加从用户 WSOL ATA 转账到临时 ATA 的指令 let transfer_instruction = crate::common::spl_token::transfer( &crate::constants::TOKEN_PROGRAM, &user_wsol_ata, - &seed_ata_address, + &temp_ata_address, payer, amount, &[], )?; instructions.push(transfer_instruction); - // 5. 添加关闭 WSOL seed 账户的指令 + // 4. 添加关闭临时 WSOL 账户的指令 let close_instruction = close_account( &crate::constants::TOKEN_PROGRAM, - &seed_ata_address, + &temp_ata_address, payer, payer, &[], diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 51858a9..0d51e17 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -31,7 +31,8 @@ pub struct SwapParams { pub data_size_limit: u32, pub wait_transaction_confirmed: bool, pub protocol_params: Box, - pub open_seed_optimize: bool, + pub wsol_use_seed: bool, + pub mint_use_seed: bool, pub swqos_clients: Vec>, pub middleware_manager: Option>, pub durable_nonce: Option, From ce83b5ae680aa75432a96a0a50a2830a4186ae39 Mon Sep 17 00:00:00 2001 From: Wood Date: Sat, 22 Nov 2025 01:41:06 +0800 Subject: [PATCH 2/5] Revert "refactor: split seed optimization config into wsol_use_seed and mint_use_seed" This reverts commit eb8de36f503986e776ffdaf55d7049247572b6c3. --- examples/wsol_wrapper/src/main.rs | 28 +++----- src/common/types.rs | 27 ++++--- src/instruction/bonk.rs | 18 ++--- src/instruction/meteora_damm_v2.rs | 18 ++--- src/instruction/pumpfun.rs | 6 +- src/instruction/pumpswap.rs | 18 ++--- src/instruction/raydium_amm_v4.rs | 18 ++--- src/instruction/raydium_cpmm.rs | 18 ++--- src/lib.rs | 59 ++++++---------- src/trading/common/wsol_manager.rs | 110 +++++++++-------------------- src/trading/core/params.rs | 3 +- 11 files changed, 131 insertions(+), 192 deletions(-) diff --git a/examples/wsol_wrapper/src/main.rs b/examples/wsol_wrapper/src/main.rs index 9d0b678..5845afa 100644 --- a/examples/wsol_wrapper/src/main.rs +++ b/examples/wsol_wrapper/src/main.rs @@ -8,7 +8,7 @@ async fn main() -> Result<(), Box> { println!("🔄 WSOL Wrapper Example"); println!("This example demonstrates:"); println!("1. Wrapping SOL to WSOL"); - println!("2. Partial unwrapping WSOL back to SOL using temporary account"); + println!("2. Partial unwrapping WSOL back to SOL using seed account"); println!("3. Closing WSOL account and unwrapping remaining balance"); // Initialize SolanaTrade client @@ -18,9 +18,8 @@ async fn main() -> Result<(), Box> { println!("\n📦 Example 1: Wrapping SOL to WSOL"); let wrap_amount = 1_000_000; // 0.001 SOL in lamports println!("Wrapping {} lamports (0.001 SOL) to WSOL...", wrap_amount); - let is_use_seed = false; // 设置是否使用seed优化 - match solana_trade.wrap_sol_to_wsol(wrap_amount, is_use_seed).await { + match solana_trade.wrap_sol_to_wsol(wrap_amount).await { Ok(signature) => { println!("✅ Successfully wrapped SOL to WSOL!"); println!("Transaction signature: {}", signature); @@ -37,17 +36,13 @@ async fn main() -> Result<(), Box> { tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; // Example 2: Unwrap half of the WSOL back to SOL using seed account - println!("\n🔄 Example 2: Unwrapping half of WSOL back to SOL using temporary account"); + println!("\n🔄 Example 2: Unwrapping half of WSOL back to SOL using seed account"); let unwrap_amount = wrap_amount / 2; // Half of the wrapped amount - println!("Unwrapping {} lamports (0.0005 SOL) back to SOL using temporary account...", unwrap_amount); + println!("Unwrapping {} lamports (0.0005 SOL) back to SOL using seed account...", unwrap_amount); - // 假设我们的WSOL ATA是使用seed创建的(根据实际情况设置) - // 如果是seed创建的,设置为true;如果是普通ATA,设置为false - let source_is_seed = is_use_seed; // 与is_use_seed保持一致 - - match solana_trade.wrap_wsol_to_sol(unwrap_amount, source_is_seed).await { + match solana_trade.wrap_wsol_to_sol(unwrap_amount).await { Ok(signature) => { - println!("✅ Successfully unwrapped half of WSOL back to SOL using temporary account!"); + println!("✅ Successfully unwrapped half of WSOL back to SOL using seed account!"); println!("Transaction signature: {}", signature); println!("Explorer: https://solscan.io/tx/{}", signature); } @@ -64,7 +59,7 @@ async fn main() -> Result<(), Box> { println!("\n🔒 Example 3: Closing WSOL account and unwrapping remaining balance"); println!("Closing WSOL account and unwrapping all remaining balance to SOL..."); - match solana_trade.close_wsol(is_use_seed).await { + match solana_trade.close_wsol().await { Ok(signature) => { println!("✅ Successfully closed WSOL account and unwrapped remaining balance!"); println!("Transaction signature: {}", signature); @@ -86,14 +81,7 @@ async fn create_solana_trade_client() -> Result = vec![SwqosConfig::Default(rpc_url.clone())]; - let trade_config = TradeConfig::new( - rpc_url, - swqos_configs, - commitment, - true, // create_wsol_ata_on_startup - false, // wsol_use_seed - true, // mint_use_seed - ); + let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment); let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await; println!("✅ SolanaTrade client initialized successfully!"); Ok(solana_trade) diff --git a/src/common/types.rs b/src/common/types.rs index cea74cc..d6c6432 100755 --- a/src/common/types.rs +++ b/src/common/types.rs @@ -9,10 +9,8 @@ pub struct TradeConfig { /// Whether to create WSOL ATA on startup (default: true) /// If true, SDK will check WSOL ATA on initialization and create if not exists pub create_wsol_ata_on_startup: bool, - /// Whether to use seed optimization for WSOL ATA operations (default: false) - pub wsol_use_seed: bool, - /// Whether to use seed optimization for other mint ATA operations (default: true) - pub mint_use_seed: bool, + /// Whether to use seed optimization for all ATA operations (default: true) + pub use_seed_optimize: bool, } impl TradeConfig { @@ -20,19 +18,28 @@ impl TradeConfig { rpc_url: String, swqos_configs: Vec, commitment: CommitmentConfig, - create_wsol_ata_on_startup: bool, - wsol_use_seed: bool, - mint_use_seed: bool, ) -> Self { + println!("🔧 TradeConfig create_wsol_ata_on_startup default value: true"); + println!("🔧 TradeConfig use_seed_optimize default value: true"); Self { rpc_url, swqos_configs, commitment, - create_wsol_ata_on_startup, - wsol_use_seed, - mint_use_seed, + create_wsol_ata_on_startup: true, // 默认:启动时检查并创建 + use_seed_optimize: true, // 默认:使用seed优化 } } + + /// Create a TradeConfig with custom WSOL ATA settings + pub fn with_wsol_ata_config( + mut self, + create_wsol_ata_on_startup: bool, + use_seed_optimize: bool, + ) -> Self { + self.create_wsol_ata_on_startup = create_wsol_ata_on_startup; + self.use_seed_optimize = use_seed_optimize; + self + } } pub type SolanaRpcClient = solana_client::nonblocking::rpc_client::RpcClient; diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index 8098ee3..f7655a7 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -86,7 +86,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &protocol_params.mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -97,7 +97,7 @@ impl InstructionBuilder for BonkInstructionBuilder { &crate::constants::WSOL_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - if usd1_pool { params.mint_use_seed } else { params.wsol_use_seed }, + params.open_seed_optimize, ); let base_vault_account = if protocol_params.base_vault == Pubkey::default() { @@ -122,7 +122,7 @@ impl InstructionBuilder for BonkInstructionBuilder { if params.create_input_mint_ata && !usd1_pool { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); } if params.create_output_mint_ata { @@ -132,7 +132,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &protocol_params.mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -167,7 +167,7 @@ impl InstructionBuilder for BonkInstructionBuilder { instructions.push(Instruction::new_with_bytes(accounts::BONK, &data, accounts.to_vec())); if params.close_input_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } Ok(instructions) @@ -246,7 +246,7 @@ impl InstructionBuilder for BonkInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &protocol_params.mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -257,7 +257,7 @@ impl InstructionBuilder for BonkInstructionBuilder { &crate::constants::WSOL_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.wsol_use_seed, + params.open_seed_optimize, ); let base_vault_account = if protocol_params.base_vault == Pubkey::default() { @@ -281,7 +281,7 @@ impl InstructionBuilder for BonkInstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.close_output_mint_ata && !usd1_pool { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); } let mut data = [0u8; 32]; @@ -314,7 +314,7 @@ impl InstructionBuilder for BonkInstructionBuilder { instructions.push(Instruction::new_with_bytes(accounts::BONK, &data, accounts.to_vec())); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/meteora_damm_v2.rs b/src/instruction/meteora_damm_v2.rs index a22d04e..fd8b54f 100644 --- a/src/instruction/meteora_damm_v2.rs +++ b/src/instruction/meteora_damm_v2.rs @@ -54,7 +54,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_b_program }, - params.wsol_use_seed, + params.open_seed_optimize, ); let output_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -65,7 +65,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_a_program }, - params.mint_use_seed, + params.open_seed_optimize, ); // ======================================== @@ -75,7 +75,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); } if params.create_output_mint_ata { @@ -85,7 +85,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -121,7 +121,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } Ok(instructions) @@ -165,7 +165,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_b_program }, - params.mint_use_seed, + params.open_seed_optimize, ); let output_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( @@ -176,7 +176,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { } else { &protocol_params.token_a_program }, - params.wsol_use_seed, + params.open_seed_optimize, ); // ======================================== @@ -185,7 +185,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); } // Create buy instruction @@ -218,7 +218,7 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder { )); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index df34310..9994a8e 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -93,7 +93,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let user_volume_accumulator = @@ -112,7 +112,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &token_program, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -229,7 +229,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &token_program, - params.mint_use_seed, + params.open_seed_optimize, ); // ======================================== diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index 9f76580..eaa87cc 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -108,14 +108,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), &base_mint, &base_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), "e_mint, "e_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); // Determine fee recipient based on mayhem mode @@ -136,7 +136,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { if create_wsol_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount, params.wsol_use_seed)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount)); } if params.create_output_mint_ata { @@ -146,7 +146,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), if quote_is_wsol_or_usdc { &base_mint } else { "e_mint }, if quote_is_wsol_or_usdc { &base_token_program } else { "e_token_program }, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -209,7 +209,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { instructions.push(buy_instruction); if close_wsol_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } Ok(instructions) } @@ -308,14 +308,14 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { ¶ms.payer.pubkey(), &base_mint, &base_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let user_quote_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), "e_mint, "e_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); // ======================================== @@ -324,7 +324,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let mut instructions = Vec::with_capacity(3); if create_wsol_ata { - instructions.extend(wsol_manager::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(wsol_manager::create_wsol_ata(¶ms.payer.pubkey())); } // Create sell instruction @@ -386,7 +386,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { instructions.push(sell_instruction); if close_wsol_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/raydium_amm_v4.rs b/src/instruction/raydium_amm_v4.rs index 5d9bca5..6a87503 100755 --- a/src/instruction/raydium_amm_v4.rs +++ b/src/instruction/raydium_amm_v4.rs @@ -64,14 +64,14 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.wsol_use_seed, + params.open_seed_optimize, ); let user_destination_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.mint_use_seed, + params.open_seed_optimize, ); // ======================================== @@ -81,7 +81,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); } if params.create_output_mint_ata { @@ -91,7 +91,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &crate::constants::TOKEN_PROGRAM, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -130,7 +130,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } Ok(instructions) @@ -182,14 +182,14 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { ¶ms.payer.pubkey(), ¶ms.input_mint, &crate::constants::TOKEN_PROGRAM, - params.mint_use_seed, + params.open_seed_optimize, ); let user_destination_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.wsol_use_seed, + params.open_seed_optimize, ); // ======================================== @@ -198,7 +198,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); } // Create buy instruction @@ -234,7 +234,7 @@ impl InstructionBuilder for RaydiumAmmV4InstructionBuilder { )); if params.close_output_mint_ata { - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index 201c07a..ddab752 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -86,13 +86,13 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.wsol_use_seed, + params.open_seed_optimize, ); let output_token_account = get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.output_mint, &mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let input_vault_account = get_vault_account( @@ -115,7 +115,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.create_input_mint_ata { instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in, params.wsol_use_seed)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), amount_in)); } if params.create_output_mint_ata { @@ -125,7 +125,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.output_mint, &mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ), ); } @@ -160,7 +160,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.close_input_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } Ok(instructions) @@ -230,13 +230,13 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), if is_wsol { &crate::constants::WSOL_TOKEN_ACCOUNT } else { &crate::constants::USDC_TOKEN_ACCOUNT }, &crate::constants::TOKEN_PROGRAM, - params.wsol_use_seed, + params.open_seed_optimize, ); let input_token_account = get_associated_token_address_with_program_id_fast_use_seed( ¶ms.payer.pubkey(), ¶ms.input_mint, &mint_token_program, - params.mint_use_seed, + params.open_seed_optimize, ); let output_vault_account = get_vault_account( @@ -258,7 +258,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { let mut instructions = Vec::with_capacity(3); if params.create_output_mint_ata { - instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::create_wsol_ata(¶ms.payer.pubkey())); } // Create sell instruction @@ -291,7 +291,7 @@ impl InstructionBuilder for RaydiumCpmmInstructionBuilder { if params.close_output_mint_ata { // Close wSOL ATA account, reclaim rent - instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey(), params.wsol_use_seed)); + instructions.extend(crate::trading::common::close_wsol(¶ms.payer.pubkey())); } if params.close_input_mint_ata { instructions.push(crate::common::spl_token::close_account( diff --git a/src/lib.rs b/src/lib.rs index 38c0c03..7a2b9b1 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,10 +59,9 @@ pub struct SolanaTrade { pub swqos_clients: Vec>, /// Optional middleware manager for custom transaction processing pub middleware_manager: Option>, - /// Whether to use seed optimization for WSOL ATA operations (default: false) - pub wsol_use_seed: bool, - /// Whether to use seed optimization for other mint ATA operations (default: true) - pub mint_use_seed: bool, + /// Whether to use seed optimization for all ATA operations (default: true) + /// Applies to all token account creations across buy and sell operations + pub use_seed_optimize: bool, } static INSTANCE: Mutex>> = Mutex::new(None); @@ -74,8 +73,7 @@ impl Clone for SolanaTrade { rpc: self.rpc.clone(), swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), - wsol_use_seed: self.wsol_use_seed, - mint_use_seed: self.mint_use_seed, + use_seed_optimize: self.use_seed_optimize, } } } @@ -225,9 +223,9 @@ impl SolanaTrade { Err(_) => { // WSOL ATA不存在,创建它 println!("🔨 创建WSOL ATA: {}", wsol_ata); - // 使用配置中的wsol_use_seed设置创建WSOL ATA + // 使用seed优化创建WSOL ATA let create_ata_ixs = - crate::trading::common::wsol_manager::create_wsol_ata(&payer.pubkey(), trade_config.wsol_use_seed); + crate::trading::common::wsol_manager::create_wsol_ata(&payer.pubkey()); if !create_ata_ixs.is_empty() { // 构建并发送交易 @@ -275,8 +273,7 @@ impl SolanaTrade { rpc, swqos_clients, middleware_manager: None, - wsol_use_seed: trade_config.wsol_use_seed, - mint_use_seed: trade_config.mint_use_seed, + use_seed_optimize: trade_config.use_seed_optimize, }; let mut current = INSTANCE.lock(); @@ -389,8 +386,7 @@ impl SolanaTrade { .unwrap_or(256 * 1024), wait_transaction_confirmed: params.wait_transaction_confirmed, protocol_params: protocol_params.clone(), - wsol_use_seed: self.wsol_use_seed, // 使用wsol_use_seed配置 - mint_use_seed: self.mint_use_seed, // 使用mint_use_seed配置 + open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), durable_nonce: params.durable_nonce, @@ -487,8 +483,7 @@ impl SolanaTrade { wait_transaction_confirmed: params.wait_transaction_confirmed, protocol_params: protocol_params.clone(), with_tip: params.with_tip, - wsol_use_seed: self.wsol_use_seed, // 使用wsol_use_seed配置 - mint_use_seed: self.mint_use_seed, // 使用mint_use_seed配置 + open_seed_optimize: self.use_seed_optimize, // 使用全局seed优化配置 swqos_clients: self.swqos_clients.clone(), middleware_manager: self.middleware_manager.clone(), durable_nonce: params.durable_nonce, @@ -579,7 +574,6 @@ impl SolanaTrade { /// /// # Arguments /// * `amount` - The amount of SOL to wrap (in lamports) - /// * `is_use_seed` - Whether to use seed optimization for WSOL ATA creation /// /// # Returns /// * `Ok(String)` - Transaction signature if successful @@ -592,11 +586,11 @@ impl SolanaTrade { /// - wSOL associated token account creation fails /// - Transaction fails to execute or confirm /// - Network or RPC errors occur - pub async fn wrap_sol_to_wsol(&self, amount: u64, is_use_seed: bool) -> Result { + pub async fn wrap_sol_to_wsol(&self, amount: u64) -> Result { use crate::trading::common::wsol_manager::handle_wsol; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = handle_wsol(&self.payer.pubkey(), amount, is_use_seed); + let instructions = handle_wsol(&self.payer.pubkey(), amount); let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); @@ -609,9 +603,6 @@ impl SolanaTrade { /// transfers any remaining wSOL balance back to the account owner as native SOL. /// This is useful for cleaning up wSOL accounts and recovering wrapped SOL after trading operations. /// - /// # Arguments - /// * `is_use_seed` - Whether the WSOL ATA was created using seed optimization - /// /// # Returns /// * `Ok(String)` - Transaction signature if successful /// * `Err(anyhow::Error)` - If the transaction fails to execute @@ -623,11 +614,11 @@ impl SolanaTrade { /// - Account closure fails due to insufficient permissions /// - Transaction fails to execute or confirm /// - Network or RPC errors occur - pub async fn close_wsol(&self, is_use_seed: bool) -> Result { + pub async fn close_wsol(&self) -> Result { use crate::trading::common::wsol_manager::close_wsol; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = close_wsol(&self.payer.pubkey(), is_use_seed); + let instructions = close_wsol(&self.payer.pubkey()); let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); @@ -641,9 +632,6 @@ impl SolanaTrade { /// without transferring any SOL into it. This is useful when you want to set up /// the account infrastructure in advance without committing funds yet. /// - /// # Arguments - /// * `is_use_seed` - Whether to use seed optimization for WSOL ATA creation - /// /// # Returns /// * `Ok(String)` - Transaction signature if successful /// * `Err(anyhow::Error)` - If the transaction fails to execute @@ -655,12 +643,12 @@ impl SolanaTrade { /// - Transaction fails to execute or confirm /// - Network or RPC errors occur /// - Insufficient SOL for transaction fees - pub async fn create_wsol_ata(&self, is_use_seed: bool) -> Result { + pub async fn create_wsol_ata(&self) -> Result { use crate::trading::common::wsol_manager::create_wsol_ata; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = create_wsol_ata(&self.payer.pubkey(), is_use_seed); + let instructions = create_wsol_ata(&self.payer.pubkey()); // If instructions are empty, ATA already exists if instructions.is_empty() { @@ -676,17 +664,16 @@ impl SolanaTrade { Ok(signature.to_string()) } - /// 将 WSOL 转换为 SOL,使用临时账户 + /// 将 WSOL 转换为 SOL,使用 seed 账户 /// /// 这个函数实现以下步骤: - /// 1. 创建临时 WSOL 账号(如果原始账号是seed创建,则临时账号使用普通ATA;否则使用seed) - /// 2. 获取临时账号的 ATA 地址 - /// 3. 添加从用户 WSOL ATA 转账到临时 ATA 账号的指令 - /// 4. 添加关闭临时 WSOL 账号的指令 + /// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 + /// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 + /// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 + /// 4. 添加关闭 WSOL seed 账号的指令 /// /// # Arguments /// * `amount` - 要转换的 WSOL 数量(以 lamports 为单位) - /// * `source_is_seed` - 原始 WSOL 账号是否是 seed 创建的 /// /// # Returns /// * `Ok(String)` - 交易签名 @@ -696,16 +683,16 @@ impl SolanaTrade { /// /// 此函数在以下情况下会返回错误: /// - 用户 WSOL ATA 中余额不足 - /// - 临时账户创建失败 + /// - seed 账户创建失败 /// - 转账指令执行失败 /// - 交易执行或确认失败 /// - 网络或 RPC 错误 - pub async fn wrap_wsol_to_sol(&self, amount: u64, source_is_seed: bool) -> Result { + pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result { use crate::trading::common::wsol_manager::wrap_wsol_to_sol as wrap_wsol_to_sol_internal; use solana_sdk::transaction::Transaction; let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount, source_is_seed)?; + let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?; let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); diff --git a/src/trading/common/wsol_manager.rs b/src/trading/common/wsol_manager.rs index 28f8a42..ffde170 100644 --- a/src/trading/common/wsol_manager.rs +++ b/src/trading/common/wsol_manager.rs @@ -8,21 +8,13 @@ use solana_sdk::{instruction::Instruction, message::AccountMeta, pubkey::Pubkey} use solana_system_interface::instruction::transfer; #[inline] -pub fn handle_wsol(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> SmallVec<[Instruction; 3]> { - let wsol_token_account = if is_use_seed { - crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( - &payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - true, - ) - } else { +pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]> { + let wsol_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ) - }; + ); let mut insts = SmallVec::<[Instruction; 3]>::new(); insts.extend(create_associated_token_account_idempotent_fast( @@ -44,21 +36,13 @@ pub fn handle_wsol(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> SmallVe insts } -pub fn close_wsol(payer: &Pubkey, is_use_seed: bool) -> Vec { - let wsol_token_account = if is_use_seed { - crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( - &payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - true, - ) - } else { +pub fn close_wsol(payer: &Pubkey) -> Vec { + let wsol_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ) - }; + ); crate::common::fast_fn::get_cached_instructions( crate::common::fast_fn::InstructionCacheKey::CloseWsolAccount { payer: *payer, @@ -78,33 +62,24 @@ pub fn close_wsol(payer: &Pubkey, is_use_seed: bool) -> Vec { } #[inline] -pub fn create_wsol_ata(payer: &Pubkey, is_use_seed: bool) -> Vec { - crate::common::fast_fn::create_associated_token_account_idempotent_fast_use_seed( +pub fn create_wsol_ata(payer: &Pubkey) -> Vec { + create_associated_token_account_idempotent_fast( &payer, &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - is_use_seed, ) } /// 只充值SOL到已存在的WSOL ATA(不创建账户)- 标准方式 #[inline] -pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> SmallVec<[Instruction; 2]> { - let wsol_token_account = if is_use_seed { - crate::common::fast_fn::get_associated_token_address_with_program_id_fast_use_seed( - &payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - true, - ) - } else { +pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2]> { + let wsol_token_account = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( &payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ) - }; + ); let mut insts = SmallVec::<[Instruction; 2]>::new(); insts.extend([ @@ -120,72 +95,55 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64, is_use_seed: bool) -> Small insts } -/// 将 WSOL 转换为 SOL,使用临时账户 -/// 1. 创建临时 WSOL 账号(如果原始账号是seed创建,则临时账号使用普通ATA;否则使用seed) -/// 2. 获取临时账号的 ATA 地址 -/// 3. 添加从用户 WSOL ATA 转账到临时 ATA 账号的指令 -/// 4. 添加关闭临时 WSOL 账号的指令 -/// -/// # Arguments -/// * `payer` - 支付者公钥 -/// * `amount` - 要转换的 WSOL 数量 -/// * `source_is_seed` - 原始 WSOL 账号是否是 seed 创建的 +/// 将 WSOL 转换为 SOL,使用 seed 账户 +/// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 +/// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 +/// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 +/// 4. 添加关闭 WSOL seed 账号的指令 pub fn wrap_wsol_to_sol( payer: &Pubkey, amount: u64, - source_is_seed: bool, ) -> Result, anyhow::Error> { let mut instructions = Vec::new(); - // 1. 分别获取普通ATA和seed ATA地址 - let normal_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( + // 1. 创建 WSOL seed 账户 + let seed_account_instructions = create_associated_token_account_use_seed( + payer, payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, - ); - let seed_ata = get_associated_token_address_with_program_id_use_seed( + )?; + instructions.extend(seed_account_instructions); + + // 2. 获取 seed 账户的 ATA 地址 + let seed_ata_address = get_associated_token_address_with_program_id_use_seed( payer, &crate::constants::WSOL_TOKEN_ACCOUNT, &crate::constants::TOKEN_PROGRAM, )?; - // 2. 根据原始账号类型决定用户账号和临时账号 - // 如果原始账号是seed,则用户账号=seed_ata,临时账号=normal_ata(避免地址冲突) - // 如果原始账号是普通ATA,则用户账号=normal_ata,临时账号=seed_ata(提高性能) - let (user_wsol_ata, temp_ata_address, temp_account_instructions) = if source_is_seed { - let create_insts = crate::common::fast_fn::create_associated_token_account_idempotent_fast( - payer, - payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - ); - (seed_ata, normal_ata, create_insts) - } else { - let create_insts = create_associated_token_account_use_seed( - payer, - payer, - &crate::constants::WSOL_TOKEN_ACCOUNT, - &crate::constants::TOKEN_PROGRAM, - )?; - (normal_ata, seed_ata, create_insts) - }; - instructions.extend(temp_account_instructions); + // 3. 获取用户的 WSOL ATA 地址 + let user_wsol_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + ); - // 3. 添加从用户 WSOL ATA 转账到临时 ATA 的指令 + // 4. 添加从用户 WSOL ATA 转账到 seed ATA 的指令 let transfer_instruction = crate::common::spl_token::transfer( &crate::constants::TOKEN_PROGRAM, &user_wsol_ata, - &temp_ata_address, + &seed_ata_address, payer, amount, &[], )?; instructions.push(transfer_instruction); - // 4. 添加关闭临时 WSOL 账户的指令 + // 5. 添加关闭 WSOL seed 账户的指令 let close_instruction = close_account( &crate::constants::TOKEN_PROGRAM, - &temp_ata_address, + &seed_ata_address, payer, payer, &[], diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 0d51e17..51858a9 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -31,8 +31,7 @@ pub struct SwapParams { pub data_size_limit: u32, pub wait_transaction_confirmed: bool, pub protocol_params: Box, - pub wsol_use_seed: bool, - pub mint_use_seed: bool, + pub open_seed_optimize: bool, pub swqos_clients: Vec>, pub middleware_manager: Option>, pub durable_nonce: Option, From 26cee93fb1c2a2043cfba67612a367ccd1876e8b Mon Sep 17 00:00:00 2001 From: Wood Date: Sun, 23 Nov 2025 20:18:01 +0800 Subject: [PATCH 3/5] feat: optimize WSOL wrap/unwrap with seed account reuse check - Add account existence check before creating seed account - Implement wrap_wsol_to_sol_without_create for reusing existing seed accounts - Prevent transaction failures when temporary seed account already exists - Improve WSOL conversion efficiency by avoiding redundant account creation --- src/lib.rs | 22 +++++++++-- src/trading/common/wsol_manager.rs | 61 +++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7a2b9b1..b6064c9 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -688,12 +688,28 @@ impl SolanaTrade { /// - 交易执行或确认失败 /// - 网络或 RPC 错误 pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result { - use crate::trading::common::wsol_manager::wrap_wsol_to_sol as wrap_wsol_to_sol_internal; + use crate::trading::common::wsol_manager::{wrap_wsol_to_sol as wrap_wsol_to_sol_internal, wrap_wsol_to_sol_without_create}; + use crate::common::seed::get_associated_token_address_with_program_id_use_seed; use solana_sdk::transaction::Transaction; - let recent_blockhash = self.rpc.get_latest_blockhash().await?; - let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?; + // 检查临时seed账户是否已存在 + let seed_ata_address = get_associated_token_address_with_program_id_use_seed( + &self.payer.pubkey(), + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + )?; + let account_exists = self.rpc.get_account(&seed_ata_address).await.is_ok(); + + let instructions = if account_exists { + // 如果账户已存在,使用不创建账户的版本 + wrap_wsol_to_sol_without_create(&self.payer.pubkey(), amount)? + } else { + // 如果账户不存在,使用创建账户的版本 + wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)? + }; + + let recent_blockhash = self.rpc.get_latest_blockhash().await?; let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey())); transaction.sign(&[&*self.payer], recent_blockhash); let signature = self.rpc.send_and_confirm_transaction(&transaction).await?; diff --git a/src/trading/common/wsol_manager.rs b/src/trading/common/wsol_manager.rs index ffde170..6ea6dfa 100644 --- a/src/trading/common/wsol_manager.rs +++ b/src/trading/common/wsol_manager.rs @@ -96,17 +96,22 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2 } /// 将 WSOL 转换为 SOL,使用 seed 账户 -/// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 -/// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 -/// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 -/// 4. 添加关闭 WSOL seed 账号的指令 +/// 1. 检查 seed 账户是否已存在 +/// 2. 如果不存在,使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号 +/// 3. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址 +/// 4. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令 +/// 5. 添加关闭 WSOL seed 账号的指令 +/// +/// 注意:此函数只生成指令,不检查账户是否存在(需要调用方在发送交易前检查) +/// 如果临时账户已存在,可以安全地跳过创建步骤,直接转账并关闭 pub fn wrap_wsol_to_sol( payer: &Pubkey, amount: u64, ) -> Result, anyhow::Error> { let mut instructions = Vec::new(); - // 1. 创建 WSOL seed 账户 + // 1. 创建 WSOL seed 账户(注意:如果账户已存在会失败) + // 调用方应该先检查账户是否存在,如果存在则跳过此步骤 let seed_account_instructions = create_associated_token_account_use_seed( payer, payer, @@ -152,3 +157,49 @@ pub fn wrap_wsol_to_sol( Ok(instructions) } + +/// 将 WSOL 转换为 SOL(仅转账和关闭,不创建账户) +/// 用于当临时seed账户已存在的情况 +pub fn wrap_wsol_to_sol_without_create( + payer: &Pubkey, + amount: u64, +) -> Result, anyhow::Error> { + let mut instructions = Vec::new(); + + // 1. 获取 seed 账户的 ATA 地址 + let seed_ata_address = get_associated_token_address_with_program_id_use_seed( + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + )?; + + // 2. 获取用户的 WSOL ATA 地址 + let user_wsol_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast( + payer, + &crate::constants::WSOL_TOKEN_ACCOUNT, + &crate::constants::TOKEN_PROGRAM, + ); + + // 3. 添加从用户 WSOL ATA 转账到 seed ATA 的指令 + let transfer_instruction = crate::common::spl_token::transfer( + &crate::constants::TOKEN_PROGRAM, + &user_wsol_ata, + &seed_ata_address, + payer, + amount, + &[], + )?; + instructions.push(transfer_instruction); + + // 4. 添加关闭 WSOL seed 账户的指令 + let close_instruction = close_account( + &crate::constants::TOKEN_PROGRAM, + &seed_ata_address, + payer, + payer, + &[], + )?; + instructions.push(close_instruction); + + Ok(instructions) +} From 3132981f8513a47f133e51dd1dba054c1d4e430c Mon Sep 17 00:00:00 2001 From: Wood Date: Sun, 23 Nov 2025 21:02:55 +0800 Subject: [PATCH 4/5] feat: add dynamic tip update methods to GasFeeStrategy - Add update_buy_tip() method to dynamically update buy tip while keeping other parameters unchanged - Add update_sell_tip() method to dynamically update sell tip while keeping other parameters unchanged - Enable simple one-line tip updates for all configured SWQOS providers - Support percentage-based dynamic tip calculation in trading bots --- src/common/gas_fee_strategy.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/common/gas_fee_strategy.rs b/src/common/gas_fee_strategy.rs index 396157c..6f2457a 100644 --- a/src/common/gas_fee_strategy.rs +++ b/src/common/gas_fee_strategy.rs @@ -317,6 +317,34 @@ impl GasFeeStrategy { self.strategies.store(Arc::new(HashMap::new())); } + /// 动态更新买入小费(保持其他参数不变) + /// Dynamically update buy tip (keep other parameters unchanged) + pub fn update_buy_tip(&self, buy_tip: f64) { + self.strategies.rcu(|current_map| { + let mut new_map = (**current_map).clone(); + for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() { + if *trade_type == TradeType::Buy { + value.tip = buy_tip; + } + } + Arc::new(new_map) + }); + } + + /// 动态更新卖出小费(保持其他参数不变) + /// Dynamically update sell tip (keep other parameters unchanged) + pub fn update_sell_tip(&self, sell_tip: f64) { + self.strategies.rcu(|current_map| { + let mut new_map = (**current_map).clone(); + for ((swqos_type, trade_type, strategy_type), value) in new_map.iter_mut() { + if *trade_type == TradeType::Sell { + value.tip = sell_tip; + } + } + Arc::new(new_map) + }); + } + /// 打印所有策略。 /// Print all strategies pub fn print_all_strategies(&self) { From 5358d9ea281fafde7fd526b62d9cc57dad0e0abd Mon Sep 17 00:00:00 2001 From: Wood Date: Mon, 24 Nov 2025 06:03:31 +0800 Subject: [PATCH 5/5] feat(swqos): add minimum tip constants and conditional transaction building - Define minimum tip constants for each SWQOS provider (JITO, NextBlock, Node1, etc.) - Add dynamic filtering in execute_parallel to skip transaction building when tip is below provider's minimum - Add missing SWQOS_ENDPOINTS_ASTRALANE constant - Ensure SWQOS clients are always initialized but transactions are conditionally built based on current tip amount --- src/constants/swqos.rs | 10 +++++++ src/trading/common/transaction_builder.rs | 16 +----------- src/trading/core/async_executor.rs | 32 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/constants/swqos.rs b/src/constants/swqos.rs index c5b245b..baeab1c 100755 --- a/src/constants/swqos.rs +++ b/src/constants/swqos.rs @@ -217,3 +217,13 @@ pub const SWQOS_ENDPOINTS_ASTRALANE: [&str; 8] = [ "http://lim.gateway.astralane.io/iris", ]; +pub const SWQOS_MIN_TIP_DEFAULT: f64 = 0.00001; // 其它SWQOS默认最低小费 +pub const SWQOS_MIN_TIP_JITO: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_NEXTBLOCK: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_ZERO_SLOT: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_TEMPORAL: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_BLOXROUTE: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_NODE1: f64 = 0.002; // 如需更高阈值可调整 +pub const SWQOS_MIN_TIP_FLASHBLOCK: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_BLOCKRAZOR: f64 = SWQOS_MIN_TIP_DEFAULT; +pub const SWQOS_MIN_TIP_ASTRALANE: f64 = SWQOS_MIN_TIP_DEFAULT; diff --git a/src/trading/common/transaction_builder.rs b/src/trading/common/transaction_builder.rs index a384af5..7304fbb 100755 --- a/src/trading/common/transaction_builder.rs +++ b/src/trading/common/transaction_builder.rs @@ -46,24 +46,10 @@ pub async fn build_transaction( // Add tip transfer instruction if with_tip && tip_amount > 0.0 { - // 🔧 Node1 最小小费金额限制:0.002 SOL(仅限 Node1) - const MIN_TIP_AMOUNT: f64 = 0.002; - - // 检查是否是 Node1 的 tip_account - let is_node1 = NODE1_TIP_ACCOUNTS.iter().any(|&account| account == *tip_account); - - let actual_tip_amount = if is_node1 && tip_amount < MIN_TIP_AMOUNT { - // Node1 要求最小 0.002 SOL - MIN_TIP_AMOUNT - } else { - // 其他 swqos 使用原始金额 - tip_amount - }; - instructions.push(transfer( &payer.pubkey(), tip_account, - sol_str_to_lamports(actual_tip_amount.to_string().as_str()).unwrap_or(0), + sol_str_to_lamports(tip_amount.to_string().as_str()).unwrap_or(0), )); } diff --git a/src/trading/core/async_executor.rs b/src/trading/core/async_executor.rs index 115b225..e5e6e0f 100644 --- a/src/trading/core/async_executor.rs +++ b/src/trading/core/async_executor.rs @@ -15,6 +15,18 @@ use crate::{ common::{GasFeeStrategy, SolanaRpcClient}, swqos::{SwqosClient, SwqosType, TradeType}, trading::{common::build_transaction, MiddlewareManager}, + constants::swqos::{ + SWQOS_MIN_TIP_DEFAULT, + SWQOS_MIN_TIP_JITO, + SWQOS_MIN_TIP_NEXTBLOCK, + SWQOS_MIN_TIP_ZERO_SLOT, + SWQOS_MIN_TIP_TEMPORAL, + SWQOS_MIN_TIP_BLOXROUTE, + SWQOS_MIN_TIP_NODE1, + SWQOS_MIN_TIP_FLASHBLOCK, + SWQOS_MIN_TIP_BLOCKRAZOR, + SWQOS_MIN_TIP_ASTRALANE, + }, }; #[repr(align(64))] @@ -142,6 +154,26 @@ pub async fn execute_parallel( gas_fee_strategy_configs .into_iter() .filter(|config| config.0.eq(&swqos_client.get_swqos_type())) + .filter(|config| { + // 当需要 tip 且不是 Default 时,按 provider 最低小费进行筛选 + if with_tip && !matches!(config.0, SwqosType::Default) { + let min_tip = match config.0 { + SwqosType::Jito => SWQOS_MIN_TIP_JITO, + SwqosType::NextBlock => SWQOS_MIN_TIP_NEXTBLOCK, + SwqosType::ZeroSlot => SWQOS_MIN_TIP_ZERO_SLOT, + SwqosType::Temporal => SWQOS_MIN_TIP_TEMPORAL, + SwqosType::Bloxroute => SWQOS_MIN_TIP_BLOXROUTE, + SwqosType::Node1 => SWQOS_MIN_TIP_NODE1, + SwqosType::FlashBlock => SWQOS_MIN_TIP_FLASHBLOCK, + SwqosType::BlockRazor => SWQOS_MIN_TIP_BLOCKRAZOR, + SwqosType::Astralane => SWQOS_MIN_TIP_ASTRALANE, + SwqosType::Default => SWQOS_MIN_TIP_DEFAULT, + }; + config.2.tip >= min_tip + } else { + true + } + }) .map(move |config| (i, swqos_client.clone(), config)) }) .collect();