From 16996b24d448c4052af118740b54c3f208bdb315 Mon Sep 17 00:00:00 2001 From: vibes Date: Tue, 6 Jan 2026 10:32:56 +0000 Subject: [PATCH 1/4] Add buy_exact_sol_in and buy_exact_quote_in instruction support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add BUY_EXACT_SOL_IN_DISCRIMINATOR for PumpFun - Add BUY_EXACT_QUOTE_IN_DISCRIMINATOR for PumpSwap - Add use_exact_in_instruction field to SwapParams - When enabled, uses exact input instructions that spend exactly the specified SOL/quote amount with slippage applied to output tokens - Defaults to false for backwards compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/instruction/pumpfun.rs | 22 ++++++++++++++++++---- src/instruction/pumpswap.rs | 28 ++++++++++++++++++++++------ src/instruction/utils/pumpfun.rs | 5 +++++ src/instruction/utils/pumpswap.rs | 1 + src/lib.rs | 2 ++ src/trading/core/params.rs | 4 ++++ 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 9994a8e..4b02c08 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -9,7 +9,7 @@ use crate::{ use crate::{ instruction::utils::pumpfun::{ accounts, get_bonding_curve_pda, get_creator, get_user_volume_accumulator_pda, - global_constants::{self}, + global_constants::{self}, BUY_DISCRIMINATOR, BUY_EXACT_SOL_IN_DISCRIMINATOR, }, utils::calc::{ common::{calculate_with_slippage_buy, calculate_with_slippage_sell}, @@ -118,9 +118,23 @@ impl InstructionBuilder for PumpFunInstructionBuilder { } let mut buy_data = [0u8; 24]; - buy_data[..8].copy_from_slice(&[102, 6, 61, 18, 1, 218, 235, 234]); // Method ID - buy_data[8..16].copy_from_slice(&buy_token_amount.to_le_bytes()); - buy_data[16..24].copy_from_slice(&max_sol_cost.to_le_bytes()); + if params.use_exact_in_instruction { + // buy_exact_sol_in(spendable_sol_in: u64, min_tokens_out: u64) + // Spend exactly the input SOL amount, get at least min_tokens_out + let min_tokens_out = calculate_with_slippage_sell( + buy_token_amount, + params.slippage_basis_points.unwrap_or(DEFAULT_SLIPPAGE), + ); + buy_data[..8].copy_from_slice(&BUY_EXACT_SOL_IN_DISCRIMINATOR); + buy_data[8..16].copy_from_slice(¶ms.input_amount.unwrap_or(0).to_le_bytes()); + buy_data[16..24].copy_from_slice(&min_tokens_out.to_le_bytes()); + } else { + // buy(token_amount: u64, max_sol_cost: u64) + // Buy exactly token_amount tokens, pay up to max_sol_cost + buy_data[..8].copy_from_slice(&BUY_DISCRIMINATOR); + buy_data[8..16].copy_from_slice(&buy_token_amount.to_le_bytes()); + buy_data[16..24].copy_from_slice(&max_sol_cost.to_le_bytes()); + } // Determine fee recipient based on mayhem mode let fee_recipient_meta = if is_mayhem_mode { diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index eaa87cc..a25aa28 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -2,7 +2,7 @@ use crate::{ constants::trade::trade::DEFAULT_SLIPPAGE, instruction::utils::pumpswap::{ accounts, fee_recipient_ata, get_user_volume_accumulator_pda, BUY_DISCRIMINATOR, - SELL_DISCRIMINATOR, + BUY_EXACT_QUOTE_IN_DISCRIMINATOR, SELL_DISCRIMINATOR, }, trading::{ common::wsol_manager, @@ -187,11 +187,27 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { // Create instruction data let mut data = [0u8; 24]; if quote_is_wsol_or_usdc { - data[..8].copy_from_slice(&BUY_DISCRIMINATOR); - // base_amount_out - data[8..16].copy_from_slice(&token_amount.to_le_bytes()); - // max_quote_amount_in - data[16..24].copy_from_slice(&sol_amount.to_le_bytes()); + if params.use_exact_in_instruction { + // buy_exact_quote_in(spendable_quote_in: u64, min_base_amount_out: u64) + // Spend exactly the input SOL/quote amount, get at least min_base_amount_out + let min_base_amount_out = crate::utils::calc::common::calculate_with_slippage_sell( + token_amount, + params.slippage_basis_points.unwrap_or(DEFAULT_SLIPPAGE), + ); + data[..8].copy_from_slice(&BUY_EXACT_QUOTE_IN_DISCRIMINATOR); + // spendable_quote_in (exact SOL amount to spend) + data[8..16].copy_from_slice(¶ms.input_amount.unwrap_or(0).to_le_bytes()); + // min_base_amount_out (minimum tokens to receive) + data[16..24].copy_from_slice(&min_base_amount_out.to_le_bytes()); + } else { + // buy(base_amount_out: u64, max_quote_amount_in: u64) + // Buy exactly base_amount_out tokens, pay up to max_quote_amount_in + data[..8].copy_from_slice(&BUY_DISCRIMINATOR); + // base_amount_out + data[8..16].copy_from_slice(&token_amount.to_le_bytes()); + // max_quote_amount_in + data[16..24].copy_from_slice(&sol_amount.to_le_bytes()); + } } else { data[..8].copy_from_slice(&SELL_DISCRIMINATOR); // base_amount_in diff --git a/src/instruction/utils/pumpfun.rs b/src/instruction/utils/pumpfun.rs index ff445b6..55017b2 100644 --- a/src/instruction/utils/pumpfun.rs +++ b/src/instruction/utils/pumpfun.rs @@ -154,6 +154,11 @@ pub mod accounts { }; } +/// Instruction discriminators for PumpFun program +pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; +pub const BUY_EXACT_SOL_IN_DISCRIMINATOR: [u8; 8] = [56, 252, 116, 8, 158, 223, 205, 95]; +pub const SELL_DISCRIMINATOR: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173]; + pub struct Symbol; impl Symbol { diff --git a/src/instruction/utils/pumpswap.rs b/src/instruction/utils/pumpswap.rs index 5c466b7..bbaf4e9 100644 --- a/src/instruction/utils/pumpswap.rs +++ b/src/instruction/utils/pumpswap.rs @@ -136,6 +136,7 @@ pub mod accounts { } pub const BUY_DISCRIMINATOR: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234]; +pub const BUY_EXACT_QUOTE_IN_DISCRIMINATOR: [u8; 8] = [198, 46, 21, 82, 180, 217, 232, 112]; pub const SELL_DISCRIMINATOR: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173]; // Find a pool for a specific mint diff --git a/src/lib.rs b/src/lib.rs index 47c1ab7..46f24eb 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -508,6 +508,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, + use_exact_in_instruction: false, }; // Validate protocol params @@ -617,6 +618,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, + use_exact_in_instruction: false, }; // Validate protocol params diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 9e275db..1c0d097 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -67,6 +67,10 @@ pub struct SwapParams { pub fixed_output_amount: Option, pub gas_fee_strategy: GasFeeStrategy, pub simulate: bool, + /// Use exact input instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). + /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. + /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. + pub use_exact_in_instruction: bool, } impl std::fmt::Debug for SwapParams { From 18c769f7e3a06fc8a18e5808d4da6bfcffbd28d2 Mon Sep 17 00:00:00 2001 From: vibes Date: Tue, 6 Jan 2026 10:36:05 +0000 Subject: [PATCH 2/4] Add use_exact_in_instruction to TradeBuyParams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass through the new field from TradeBuyParams to SwapParams so users can opt-in to using buy_exact_sol_in and buy_exact_quote_in instructions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 46f24eb..dfdd41c 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,6 +187,10 @@ pub struct TradeBuyParams { pub gas_fee_strategy: GasFeeStrategy, /// Whether to simulate the transaction instead of executing it pub simulate: bool, + /// Use exact input instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). + /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. + /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. + pub use_exact_in_instruction: bool, } /// Parameters for executing sell orders across different DEX protocols @@ -508,7 +512,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, - use_exact_in_instruction: false, + use_exact_in_instruction: params.use_exact_in_instruction, }; // Validate protocol params From ea22d48919df6c6c9359137fee75e6bdb27b86a6 Mon Sep 17 00:00:00 2001 From: vibes Date: Tue, 6 Jan 2026 10:36:45 +0000 Subject: [PATCH 3/4] Rename use_exact_in_instruction to use_exact_sol_amount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More intuitive name that better describes what the flag does. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/instruction/pumpfun.rs | 2 +- src/instruction/pumpswap.rs | 2 +- src/lib.rs | 8 ++++---- src/trading/core/params.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 4b02c08..4e6695d 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -118,7 +118,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { } let mut buy_data = [0u8; 24]; - if params.use_exact_in_instruction { + if params.use_exact_sol_amount { // buy_exact_sol_in(spendable_sol_in: u64, min_tokens_out: u64) // Spend exactly the input SOL amount, get at least min_tokens_out let min_tokens_out = calculate_with_slippage_sell( diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index a25aa28..a8b0979 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -187,7 +187,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { // Create instruction data let mut data = [0u8; 24]; if quote_is_wsol_or_usdc { - if params.use_exact_in_instruction { + if params.use_exact_sol_amount { // buy_exact_quote_in(spendable_quote_in: u64, min_base_amount_out: u64) // Spend exactly the input SOL/quote amount, get at least min_base_amount_out let min_base_amount_out = crate::utils::calc::common::calculate_with_slippage_sell( diff --git a/src/lib.rs b/src/lib.rs index dfdd41c..fbbe10d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,10 +187,10 @@ pub struct TradeBuyParams { pub gas_fee_strategy: GasFeeStrategy, /// Whether to simulate the transaction instead of executing it pub simulate: bool, - /// Use exact input instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). + /// Use exact SOL amount instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. - pub use_exact_in_instruction: bool, + pub use_exact_sol_amount: bool, } /// Parameters for executing sell orders across different DEX protocols @@ -512,7 +512,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, - use_exact_in_instruction: params.use_exact_in_instruction, + use_exact_sol_amount: params.use_exact_sol_amount, }; // Validate protocol params @@ -622,7 +622,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, - use_exact_in_instruction: false, + use_exact_sol_amount: false, }; // Validate protocol params diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 1c0d097..a428f45 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -67,10 +67,10 @@ pub struct SwapParams { pub fixed_output_amount: Option, pub gas_fee_strategy: GasFeeStrategy, pub simulate: bool, - /// Use exact input instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). + /// Use exact SOL amount instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. - pub use_exact_in_instruction: bool, + pub use_exact_sol_amount: bool, } impl std::fmt::Debug for SwapParams { From c7f694e9a092ebec93a4039fc76b6f020219b308 Mon Sep 17 00:00:00 2001 From: vibes Date: Tue, 6 Jan 2026 11:53:09 +0000 Subject: [PATCH 4/4] Make use_exact_sol_amount optional with true default for PumpFun/PumpSwap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change use_exact_sol_amount from bool to Option - Default to true (via unwrap_or) for PumpFun and PumpSwap DEXes - Option is ignored for other DEXes (Raydium, Bonk, Meteora) - Update all examples to use None (which defaults to true for applicable DEXes) - Update README documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- README.md | 1 + README_CN.md | 1 + examples/address_lookup/src/main.rs | 1 + examples/bonk_copy_trading/src/main.rs | 1 + examples/bonk_sniper_trading/src/main.rs | 1 + examples/cli_trading/src/main.rs | 5 +++++ examples/meteora_damm_v2_direct_trading/src/main.rs | 1 + examples/middleware_system/src/main.rs | 1 + examples/nonce_cache/src/main.rs | 1 + examples/pumpfun_copy_trading/src/main.rs | 1 + examples/pumpfun_sniper_trading/src/main.rs | 1 + examples/pumpswap_direct_trading/src/main.rs | 1 + examples/pumpswap_trading/src/main.rs | 1 + examples/raydium_amm_v4_trading/src/main.rs | 1 + examples/raydium_cpmm_trading/src/main.rs | 1 + examples/seed_trading/src/main.rs | 1 + src/instruction/pumpfun.rs | 2 +- src/instruction/pumpswap.rs | 2 +- src/lib.rs | 9 +++++---- src/trading/core/params.rs | 7 ++++--- 20 files changed, 31 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8b18c72..d8ace02 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { fixed_output_token_amount: None, // Optional: specify exact output amount gas_fee_strategy: gas_fee_strategy.clone(), // Gas fee strategy configuration simulate: false, // Set to true for simulation only + use_exact_sol_amount: None, // Use exact SOL input for PumpFun/PumpSwap (defaults to true) }; ``` diff --git a/README_CN.md b/README_CN.md index b844e2c..6b30db1 100755 --- a/README_CN.md +++ b/README_CN.md @@ -174,6 +174,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { fixed_output_token_amount: None, // 可选:指定精确输出数量 gas_fee_strategy: gas_fee_strategy.clone(), // Gas 费用策略配置 simulate: false, // 设为 true 仅进行模拟 + use_exact_sol_amount: None, // 对 PumpFun/PumpSwap 使用精确 SOL 输入(默认为 true) }; ``` diff --git a/examples/address_lookup/src/main.rs b/examples/address_lookup/src/main.rs index e40a5f9..14ff199 100644 --- a/examples/address_lookup/src/main.rs +++ b/examples/address_lookup/src/main.rs @@ -160,6 +160,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/bonk_copy_trading/src/main.rs b/examples/bonk_copy_trading/src/main.rs index e9ba2a4..a58837a 100644 --- a/examples/bonk_copy_trading/src/main.rs +++ b/examples/bonk_copy_trading/src/main.rs @@ -175,6 +175,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()> fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/bonk_sniper_trading/src/main.rs b/examples/bonk_sniper_trading/src/main.rs index 49f7964..6df794d 100644 --- a/examples/bonk_sniper_trading/src/main.rs +++ b/examples/bonk_sniper_trading/src/main.rs @@ -143,6 +143,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult< fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/cli_trading/src/main.rs b/examples/cli_trading/src/main.rs index 31802ba..c60333d 100644 --- a/examples/cli_trading/src/main.rs +++ b/examples/cli_trading/src/main.rs @@ -634,6 +634,7 @@ async fn handle_buy_pumpfun( fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; match client.buy(buy_params).await { Ok((_, signature, _)) => { @@ -688,6 +689,7 @@ async fn handle_buy_pumpswap( fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; match client.buy(buy_params).await { Ok((_, signature, _)) => { @@ -741,6 +743,7 @@ async fn handle_buy_bonk( fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; match client.buy(buy_params).await { Ok((_, signature, _)) => { @@ -798,6 +801,7 @@ async fn handle_buy_raydium_v4( fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; match client.buy(buy_params).await { Ok((_, signature, _)) => { @@ -855,6 +859,7 @@ async fn handle_buy_raydium_cpmm( fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; match client.buy(buy_params).await { Ok((_, signature, _)) => { diff --git a/examples/meteora_damm_v2_direct_trading/src/main.rs b/examples/meteora_damm_v2_direct_trading/src/main.rs index 08ebd73..6297fdd 100644 --- a/examples/meteora_damm_v2_direct_trading/src/main.rs +++ b/examples/meteora_damm_v2_direct_trading/src/main.rs @@ -43,6 +43,7 @@ async fn main() -> Result<(), Box> { fixed_output_token_amount: Some(1), gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/middleware_system/src/main.rs b/examples/middleware_system/src/main.rs index b7ae8a8..ee6c82e 100644 --- a/examples/middleware_system/src/main.rs +++ b/examples/middleware_system/src/main.rs @@ -102,6 +102,7 @@ async fn test_middleware() -> AnyResult<()> { fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; println!("tip: This transaction will not succeed because we're using a test account. You can modify the code to initialize the payer with your own private key"); diff --git a/examples/nonce_cache/src/main.rs b/examples/nonce_cache/src/main.rs index 725aa32..852e122 100644 --- a/examples/nonce_cache/src/main.rs +++ b/examples/nonce_cache/src/main.rs @@ -160,6 +160,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy, simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/pumpfun_copy_trading/src/main.rs b/examples/pumpfun_copy_trading/src/main.rs index fd4ad6d..0bbfab8 100644 --- a/examples/pumpfun_copy_trading/src/main.rs +++ b/examples/pumpfun_copy_trading/src/main.rs @@ -163,6 +163,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/pumpfun_sniper_trading/src/main.rs b/examples/pumpfun_sniper_trading/src/main.rs index 6402853..36edaec 100644 --- a/examples/pumpfun_sniper_trading/src/main.rs +++ b/examples/pumpfun_sniper_trading/src/main.rs @@ -122,6 +122,7 @@ async fn pumpfun_sniper_trade_with_shreds(trade_info: PumpFunTradeEvent) -> AnyR fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/pumpswap_direct_trading/src/main.rs b/examples/pumpswap_direct_trading/src/main.rs index 11034ec..3ce7e18 100644 --- a/examples/pumpswap_direct_trading/src/main.rs +++ b/examples/pumpswap_direct_trading/src/main.rs @@ -43,6 +43,7 @@ async fn main() -> Result<(), Box> { fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index aef10c8..b259ac4 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -220,6 +220,7 @@ async fn pumpswap_trade_with_grpc(mint_pubkey: Pubkey, params: PumpSwapParams) - fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index f744704..77cbb74 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -173,6 +173,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index 6d27296..a033079 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -158,6 +158,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/examples/seed_trading/src/main.rs b/examples/seed_trading/src/main.rs index b824b6d..69cb186 100644 --- a/examples/seed_trading/src/main.rs +++ b/examples/seed_trading/src/main.rs @@ -46,6 +46,7 @@ async fn main() -> Result<(), Box> { fixed_output_token_amount: None, gas_fee_strategy: gas_fee_strategy.clone(), simulate: false, + use_exact_sol_amount: None, }; client.buy(buy_params).await?; diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 4e6695d..043951b 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -118,7 +118,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { } let mut buy_data = [0u8; 24]; - if params.use_exact_sol_amount { + if params.use_exact_sol_amount.unwrap_or(true) { // buy_exact_sol_in(spendable_sol_in: u64, min_tokens_out: u64) // Spend exactly the input SOL amount, get at least min_tokens_out let min_tokens_out = calculate_with_slippage_sell( diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index a8b0979..959bdb5 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -187,7 +187,7 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { // Create instruction data let mut data = [0u8; 24]; if quote_is_wsol_or_usdc { - if params.use_exact_sol_amount { + if params.use_exact_sol_amount.unwrap_or(true) { // buy_exact_quote_in(spendable_quote_in: u64, min_base_amount_out: u64) // Spend exactly the input SOL/quote amount, get at least min_base_amount_out let min_base_amount_out = crate::utils::calc::common::calculate_with_slippage_sell( diff --git a/src/lib.rs b/src/lib.rs index fbbe10d..d3d65dd 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -188,9 +188,10 @@ pub struct TradeBuyParams { /// Whether to simulate the transaction instead of executing it pub simulate: bool, /// Use exact SOL amount instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). - /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. - /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. - pub use_exact_sol_amount: bool, + /// When Some(true) or None (default), the exact SOL/quote amount is spent and slippage is applied to output tokens. + /// When Some(false), uses regular buy instruction where slippage is applied to SOL/quote input. + /// This option only applies to PumpFun and PumpSwap DEXes; it is ignored for other DEXes. + pub use_exact_sol_amount: Option, } /// Parameters for executing sell orders across different DEX protocols @@ -622,7 +623,7 @@ impl TradingClient { fixed_output_amount: params.fixed_output_token_amount, gas_fee_strategy: params.gas_fee_strategy, simulate: params.simulate, - use_exact_sol_amount: false, + use_exact_sol_amount: None, }; // Validate protocol params diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index a428f45..404808a 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -68,9 +68,10 @@ pub struct SwapParams { pub gas_fee_strategy: GasFeeStrategy, pub simulate: bool, /// Use exact SOL amount instructions (buy_exact_sol_in for PumpFun, buy_exact_quote_in for PumpSwap). - /// When true, the exact SOL/quote amount is spent and slippage is applied to output tokens. - /// When false (default), uses regular buy instruction where slippage is applied to SOL/quote input. - pub use_exact_sol_amount: bool, + /// When Some(true) or None (default), the exact SOL/quote amount is spent and slippage is applied to output tokens. + /// When Some(false), uses regular buy instruction where slippage is applied to SOL/quote input. + /// This option only applies to PumpFun and PumpSwap DEXes; it is ignored for other DEXes. + pub use_exact_sol_amount: Option, } impl std::fmt::Debug for SwapParams {