Release sol-trade-sdk 4.0.14
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
//! Pump.fun bonding-curve swap ix assembly ([`SwapParams`](crate::trading::core::params::SwapParams)).
|
||||
//!
|
||||
//! The SDK selects the legacy or V2 on-chain layout from `PumpFunParams.quote_mint`.
|
||||
//! `Pubkey::default()` keeps the smaller legacy SOL layout; explicit WSOL/native SOL
|
||||
//! or USDC uses the V2 27/26-account unified metas.
|
||||
//! `Pubkey::default()` and the Solscan SOL sentinel keep the smaller legacy SOL layout;
|
||||
//! explicit WSOL or USDC uses the V2 27/26-account unified metas.
|
||||
//! Default (`false`) keeps the smaller legacy SOL-paired instruction layout for latency.
|
||||
|
||||
use crate::{
|
||||
@@ -49,7 +49,8 @@ fn effective_pump_mint_token_program(protocol_params: &PumpFunParams) -> Pubkey
|
||||
}
|
||||
|
||||
/// Resolve quote mint and its token program from PumpFunParams.
|
||||
/// `Pubkey::default()` means legacy SOL-paired → use WSOL mint for V2 instructions.
|
||||
/// `Pubkey::default()` / `SOL_TOKEN_ACCOUNT` means legacy SOL-paired; use WSOL mint when a
|
||||
/// downstream V2 helper needs a concrete SPL quote mint.
|
||||
#[inline]
|
||||
fn effective_quote_mint_and_token_program(protocol_params: &PumpFunParams) -> (Pubkey, Pubkey) {
|
||||
let curve_quote_mint = protocol_params.bonding_curve.effective_quote_mint();
|
||||
@@ -126,7 +127,9 @@ fn should_use_v2_layout(params: &SwapParams) -> Result<bool> {
|
||||
.downcast_ref::<PumpFunParams>()
|
||||
.ok_or_else(|| anyhow!("Invalid protocol params for PumpFun"))?;
|
||||
let (quote_mint, _) = effective_quote_mint_and_token_program(protocol_params);
|
||||
Ok(protocol_params.quote_mint != Pubkey::default() || !is_sol_quote_mint("e_mint))
|
||||
let explicit_v2_quote = protocol_params.quote_mint != Pubkey::default()
|
||||
&& protocol_params.quote_mint != crate::constants::SOL_TOKEN_ACCOUNT;
|
||||
Ok(explicit_v2_quote || !is_sol_quote_mint("e_mint))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1111,7 +1114,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pumpfun_native_sol_quote_mint_normalizes_to_wsol() {
|
||||
fn pumpfun_solscan_sol_quote_mint_keeps_legacy_layout() {
|
||||
let mint = pump_mint();
|
||||
let params = PumpFunParams::from_trade(
|
||||
Pubkey::default(),
|
||||
@@ -1131,10 +1134,32 @@ mod tests {
|
||||
Some(false),
|
||||
);
|
||||
|
||||
assert_eq!(params.quote_mint, crate::constants::WSOL_TOKEN_ACCOUNT);
|
||||
assert_eq!(params.quote_mint, Pubkey::default());
|
||||
assert_eq!(params.bonding_curve.quote_mint, crate::constants::WSOL_TOKEN_ACCOUNT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pumpfun_with_solscan_sol_quote_mint_selects_v1() {
|
||||
let mut params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM);
|
||||
params.create_output_mint_ata = false;
|
||||
if let DexParamEnum::PumpFun(protocol_params) = &mut params.protocol_params {
|
||||
*protocol_params =
|
||||
protocol_params.clone().with_quote_mint(crate::constants::SOL_TOKEN_ACCOUNT);
|
||||
assert_eq!(protocol_params.quote_mint, Pubkey::default());
|
||||
assert_eq!(
|
||||
protocol_params.bonding_curve.quote_mint,
|
||||
crate::constants::WSOL_TOKEN_ACCOUNT
|
||||
);
|
||||
}
|
||||
|
||||
let ix = build_buy(¶ms).unwrap().pop().unwrap();
|
||||
assert_eq!(
|
||||
&ix.data[..8],
|
||||
crate::instruction::utils::pumpfun::BUY_EXACT_SOL_IN_DISCRIMINATOR
|
||||
);
|
||||
assert_eq!(ix.accounts.len(), 18);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pumpfun_v2_usdc_buy_rejects_sol_input() {
|
||||
let mut params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM);
|
||||
|
||||
@@ -46,6 +46,7 @@ use crate::{
|
||||
const SWQOS_POOL_WORKERS: usize = 18;
|
||||
const SWQOS_QUEUE_CAP: usize = 128;
|
||||
const SWQOS_DEDICATED_DEFAULT_THREADS: usize = 18;
|
||||
const FAST_SUBMIT_RESULT_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
/// Shared across all jobs in one batch; built once, cloned as single Arc per job (minimal hot-path clone).
|
||||
struct SwqosSharedContext {
|
||||
@@ -473,7 +474,7 @@ impl ResultCollector {
|
||||
|
||||
/// Fast submit mode for callers that do not wait for on-chain confirmation.
|
||||
/// Return as soon as one route accepts, a landed failure consumes the nonce, all routes finish,
|
||||
/// or a short submit window expires. Slow HTTP routes continue in worker tasks but no longer
|
||||
/// or the submit result window expires. Slow HTTP routes continue in worker tasks but no longer
|
||||
/// block post-buy monitoring / sell scheduling.
|
||||
async fn wait_for_first_submitted(
|
||||
&self,
|
||||
@@ -734,10 +735,10 @@ pub async fn execute_parallel(
|
||||
// All jobs enqueued (no spawn on hot path)
|
||||
|
||||
if !wait_transaction_confirmed {
|
||||
let ret = collector.wait_for_first_submitted(Duration::from_millis(500)).await.unwrap_or((
|
||||
let ret = collector.wait_for_first_submitted(FAST_SUBMIT_RESULT_TIMEOUT).await.unwrap_or((
|
||||
false,
|
||||
vec![],
|
||||
Some(anyhow!("No SWQOS result within fast submit window")),
|
||||
Some(anyhow!("No SWQOS result within submit result window")),
|
||||
vec![],
|
||||
));
|
||||
let (success, signatures, last_error, submit_timings) = ret;
|
||||
|
||||
@@ -15,8 +15,8 @@ use std::sync::Arc;
|
||||
/// ix 组装与链下询价见 [`Self::effective_creator_for_trade`]、[`crate::instruction::utils::pumpfun::resolve_creator_vault_for_ix_with_fee_sharing`]。
|
||||
///
|
||||
/// **V2 instructions**: The SDK selects the layout automatically from `quote_mint`.
|
||||
/// Leave `quote_mint` default for legacy SOL layout, pass WSOL/native SOL for SOL V2,
|
||||
/// or pass USDC for USDC-paired coins.
|
||||
/// Leave `quote_mint` default, or pass the Solscan SOL sentinel (`SOL_TOKEN_ACCOUNT`), for
|
||||
/// legacy SOL layout. Pass `WSOL_TOKEN_ACCOUNT` for SOL V2, or USDC for USDC-paired coins.
|
||||
#[derive(Clone)]
|
||||
pub struct PumpFunParams {
|
||||
pub bonding_curve: Arc<BondingCurveAccount>,
|
||||
@@ -40,12 +40,22 @@ pub struct PumpFunParams {
|
||||
/// Fee recipient for buy/sell account #2. Set from sol-parser-sdk (`tradeEvent.feeRecipient` / 同笔 create_v2+buy 回填的 `observed_fee_recipient`);热路径不查 RPC。
|
||||
/// `Pubkey::default()` 时只能使用 SDK 静态 fallback,可能落后于主网 Global;交易热路径应优先传入 gRPC / parser 观测值。
|
||||
pub fee_recipient: Pubkey,
|
||||
/// Quote mint for v2 instructions (default: `So11111111111111111111111111111111111111112` for SOL-paired).
|
||||
/// Quote mint layout selector. Default and `SOL_TOKEN_ACCOUNT` use legacy SOL layout.
|
||||
/// `WSOL_TOKEN_ACCOUNT` selects SOL v2; USDC selects USDC v2.
|
||||
/// For USDC-paired coins, set to `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`.
|
||||
pub quote_mint: Pubkey,
|
||||
}
|
||||
|
||||
impl PumpFunParams {
|
||||
#[inline]
|
||||
fn quote_mint_for_layout(quote_mint: Pubkey) -> Pubkey {
|
||||
if quote_mint == Pubkey::default() || quote_mint == crate::constants::SOL_TOKEN_ACCOUNT {
|
||||
Pubkey::default()
|
||||
} else {
|
||||
BondingCurveAccount::normalize_quote_mint(quote_mint)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn immediate_sell(
|
||||
creator_vault: Pubkey,
|
||||
token_program: Pubkey,
|
||||
@@ -151,17 +161,13 @@ impl PumpFunParams {
|
||||
close_token_account_when_sell: close_token_account_when_sell,
|
||||
token_program: token_program,
|
||||
fee_recipient,
|
||||
quote_mint: if quote_mint == Pubkey::default() {
|
||||
Pubkey::default()
|
||||
} else {
|
||||
effective_quote_mint
|
||||
},
|
||||
quote_mint: Self::quote_mint_for_layout(quote_mint),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build PumpFun params from event/parser data. Pass `quote_mint` from the event:
|
||||
/// `Pubkey::default()` for legacy SOL layout, `WSOL_TOKEN_ACCOUNT`/native SOL for SOL V2,
|
||||
/// and `USDC_TOKEN_ACCOUNT` for USDC V2.
|
||||
/// `Pubkey::default()` / `SOL_TOKEN_ACCOUNT` for legacy SOL layout,
|
||||
/// `WSOL_TOKEN_ACCOUNT` for SOL V2, and `USDC_TOKEN_ACCOUNT` for USDC V2.
|
||||
/// Also pass `is_cashback_coin` from the event so sells include the correct remaining accounts.
|
||||
///
|
||||
/// `mayhem_mode`:
|
||||
@@ -218,11 +224,7 @@ impl PumpFunParams {
|
||||
close_token_account_when_sell: close_token_account_when_sell,
|
||||
token_program: token_program,
|
||||
fee_recipient,
|
||||
quote_mint: if quote_mint == Pubkey::default() {
|
||||
Pubkey::default()
|
||||
} else {
|
||||
effective_quote_mint
|
||||
},
|
||||
quote_mint: Self::quote_mint_for_layout(quote_mint),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +319,7 @@ impl PumpFunParams {
|
||||
close_token_account_when_sell: None,
|
||||
token_program: mint_account.owner,
|
||||
fee_recipient: Pubkey::default(),
|
||||
quote_mint,
|
||||
quote_mint: Self::quote_mint_for_layout(quote_mint),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -357,15 +359,14 @@ impl PumpFunParams {
|
||||
}
|
||||
|
||||
/// Sets `quote_mint`. The instruction builder derives V1/V2 layout from this value.
|
||||
/// For SOL-paired coins, pass `WSOL_TOKEN_ACCOUNT` or leave default.
|
||||
/// For legacy SOL-paired coins, pass `SOL_TOKEN_ACCOUNT` or leave default.
|
||||
/// Pass `WSOL_TOKEN_ACCOUNT` only when you intentionally want SOL v2 layout.
|
||||
#[inline]
|
||||
pub fn with_quote_mint(mut self, quote_mint: Pubkey) -> Self {
|
||||
let effective_quote_mint = BondingCurveAccount::normalize_quote_mint(quote_mint);
|
||||
self.quote_mint =
|
||||
if quote_mint == Pubkey::default() { Pubkey::default() } else { effective_quote_mint };
|
||||
if let Some(curve) = Arc::get_mut(&mut self.bonding_curve) {
|
||||
*curve = curve.clone().with_quote_mint(effective_quote_mint);
|
||||
}
|
||||
self.quote_mint = Self::quote_mint_for_layout(quote_mint);
|
||||
let curve = Arc::make_mut(&mut self.bonding_curve);
|
||||
*curve = curve.clone().with_quote_mint(effective_quote_mint);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user