Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7471bcba09 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sol-trade-sdk"
|
||||
version = "4.0.18"
|
||||
version = "4.0.19"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"William <byteblock6@gmail.com>",
|
||||
|
||||
@@ -259,7 +259,8 @@ Optional builder methods:
|
||||
| `.wait_for_all_submits(true)` | In fast-submit mode, wait for all SWQoS lane responses and return all signatures. |
|
||||
| `.simulate(true)` | Build and simulate the transaction instead of sending it. |
|
||||
| `.grpc_recv_us(ts)` | Attach upstream receive timestamp for latency tracing. |
|
||||
| `SimpleBuyParams::with_durable_nonce(...)` / `SimpleSellParams::with_durable_nonce(...)` | Use durable nonce instead of `recent_blockhash`. |
|
||||
| `.durable_nonce(nonce_info)` | Use durable nonce and clear `recent_blockhash`. Recommended when you start from `SimpleBuyParams::new(...)` / `SimpleSellParams::new(...)`. |
|
||||
| `SimpleBuyParams::with_durable_nonce(...)` / `SimpleSellParams::with_durable_nonce(...)` | Construct params directly with durable nonce instead of `recent_blockhash`. |
|
||||
| `SimpleSellParams::with_tip(false)` | Disable relay tips for sells. Buys use the gas fee strategy/tip settings. |
|
||||
|
||||
`TradeBuyParams` and `TradeSellParams` remain available as advanced low-level APIs. See the dedicated [Trading Parameters Reference](docs/TRADING_PARAMETERS.md).
|
||||
@@ -323,7 +324,29 @@ let temporal_config = SwqosConfig::Temporal(
|
||||
- If no custom URL is provided (`None`), the system will use the default endpoint for the specified `SwqosRegion`
|
||||
- This allows for maximum flexibility while maintaining backward compatibility
|
||||
|
||||
When using multiple MEV services, you need to use `Durable Nonce`. You need to use the `fetch_nonce_info` function to get the latest `nonce` value, and use it as the `durable_nonce` when trading.
|
||||
When using multiple MEV services, you need to use `Durable Nonce`. Fetch the latest nonce value and attach it to the high-level buy/sell params:
|
||||
|
||||
```rust
|
||||
use sol_trade_sdk::{fetch_nonce_info, AccountPolicy, BuyAmount, SimpleBuyParams};
|
||||
|
||||
let nonce_info = fetch_nonce_info(&client.infrastructure.rpc, nonce_account)
|
||||
.await
|
||||
.expect("nonce account must be initialized");
|
||||
|
||||
let buy_params = SimpleBuyParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
mint_pubkey,
|
||||
BuyAmount::WithMaxInput { quote_amount: buy_sol_amount },
|
||||
DexParamEnum::PumpFun(pumpfun_params),
|
||||
recent_blockhash, // will be cleared by `.durable_nonce(...)`
|
||||
gas_fee_strategy.clone(),
|
||||
)
|
||||
.durable_nonce(nonce_info)
|
||||
.account_policy(AccountPolicy::HotPathMinimal);
|
||||
|
||||
client.buy_simple(buy_params).await?;
|
||||
```
|
||||
|
||||
#### Astralane (Binary / Plain HTTP / QUIC)
|
||||
|
||||
|
||||
+25
-2
@@ -258,7 +258,8 @@ client.buy_simple(buy_params).await?;
|
||||
| `.wait_for_all_submits(true)` | fast-submit 模式下等待所有 SWQoS 通道返回,并拿到全部签名。 |
|
||||
| `.simulate(true)` | 只构建并模拟交易,不真正发送。 |
|
||||
| `.grpc_recv_us(ts)` | 传入上游收到事件的微秒时间戳,用于延迟追踪。 |
|
||||
| `SimpleBuyParams::with_durable_nonce(...)` / `SimpleSellParams::with_durable_nonce(...)` | 使用 durable nonce,不使用 `recent_blockhash`。 |
|
||||
| `.durable_nonce(nonce_info)` | 使用 durable nonce,并清空 `recent_blockhash`。如果你从 `SimpleBuyParams::new(...)` / `SimpleSellParams::new(...)` 开始构造,推荐用这个。 |
|
||||
| `SimpleBuyParams::with_durable_nonce(...)` / `SimpleSellParams::with_durable_nonce(...)` | 直接用 durable nonce 构造参数,不使用 `recent_blockhash`。 |
|
||||
| `SimpleSellParams::with_tip(false)` | 关闭卖出交易 relay tip。买入的 tip 使用 gas fee strategy 控制。 |
|
||||
|
||||
`TradeBuyParams` 和 `TradeSellParams` 仍保留为高级低层接口。详细说明见 [交易参数参考手册](docs/TRADING_PARAMETERS_CN.md)。
|
||||
@@ -322,7 +323,29 @@ let temporal_config = SwqosConfig::Temporal(
|
||||
- 如果没有提供自定义 URL(`None`),系统将使用指定 `SwqosRegion` 的默认端点
|
||||
- 这提供了最大的灵活性,同时保持向后兼容性
|
||||
|
||||
当使用多个MEV服务时,需要使用`Durable Nonce`。你需要使用`fetch_nonce_info`函数获取最新的`nonce`值,并在交易的时候将`durable_nonce`填入交易参数。
|
||||
当使用多个 MEV 服务时,需要使用 `Durable Nonce`。先获取最新 nonce,再挂到新的 buy/sell 参数上:
|
||||
|
||||
```rust
|
||||
use sol_trade_sdk::{fetch_nonce_info, AccountPolicy, BuyAmount, SimpleBuyParams};
|
||||
|
||||
let nonce_info = fetch_nonce_info(&client.infrastructure.rpc, nonce_account)
|
||||
.await
|
||||
.expect("nonce account must be initialized");
|
||||
|
||||
let buy_params = SimpleBuyParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
mint_pubkey,
|
||||
BuyAmount::WithMaxInput { quote_amount: buy_sol_amount },
|
||||
DexParamEnum::PumpFun(pumpfun_params),
|
||||
recent_blockhash, // 会被 `.durable_nonce(...)` 清空
|
||||
gas_fee_strategy.clone(),
|
||||
)
|
||||
.durable_nonce(nonce_info)
|
||||
.account_policy(AccountPolicy::HotPathMinimal);
|
||||
|
||||
client.buy_simple(buy_params).await?;
|
||||
```
|
||||
|
||||
#### Astralane(Binary / Plain / QUIC)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Use `SimpleBuyParams` and `SimpleSellParams` for new integrations. They keep the
|
||||
| `address_lookup_table_account` | `Option<AddressLookupTableAccount>` | ❌ | Optional ALT to reduce transaction size. |
|
||||
| `wait_tx_confirmed` | `bool` | ❌ | Whether to wait for chain confirmation before returning. Default is `false`. |
|
||||
| `wait_for_all_submits` | `bool` | ❌ | Fast-submit mode only: wait for every SWQoS lane response and return all signatures. |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | Durable nonce info. Use `SimpleBuyParams::with_durable_nonce(...)`; do not combine with `recent_blockhash`. |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | Durable nonce info. Use `.durable_nonce(nonce_info)` or `SimpleBuyParams::with_durable_nonce(...)`; do not combine with `recent_blockhash`. |
|
||||
| `simulate` | `bool` | ❌ | Build and simulate instead of submitting. Default is `false`. |
|
||||
| `grpc_recv_us` | `Option<i64>` | ❌ | Upstream receive timestamp in microseconds for latency tracing. |
|
||||
|
||||
@@ -50,7 +50,7 @@ Use `SimpleBuyParams` and `SimpleSellParams` for new integrations. They keep the
|
||||
| `address_lookup_table_account` | `Option<AddressLookupTableAccount>` | ❌ | Optional ALT to reduce transaction size. |
|
||||
| `wait_tx_confirmed` | `bool` | ❌ | Whether to wait for chain confirmation before returning. Default is `false`. |
|
||||
| `wait_for_all_submits` | `bool` | ❌ | Fast-submit mode only: wait for every SWQoS lane response and return all signatures. |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | Durable nonce info. Use `SimpleSellParams::with_durable_nonce(...)`; do not combine with `recent_blockhash`. |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | Durable nonce info. Use `.durable_nonce(nonce_info)` or `SimpleSellParams::with_durable_nonce(...)`; do not combine with `recent_blockhash`. |
|
||||
| `simulate` | `bool` | ❌ | Build and simulate instead of submitting. Default is `false`. |
|
||||
| `with_tip` | `bool` | ❌ | Whether sells include relay tips. Default is `true`; set with `.with_tip(false)`. |
|
||||
| `grpc_recv_us` | `Option<i64>` | ❌ | Upstream receive timestamp in microseconds for latency tracing. |
|
||||
@@ -74,6 +74,31 @@ Use `SimpleBuyParams` and `SimpleSellParams` for new integrations. They keep the
|
||||
| `CreateMissing` | Include ATA creation where possible. | Convenience matters more than smallest transaction size. |
|
||||
| `AssumePrepared` | Do not create or close token accounts; caller prepared everything. | Advanced deterministic flows. |
|
||||
|
||||
### Durable Nonce With Simple Params
|
||||
|
||||
`fetch_nonce_info` and `DurableNonceInfo` are re-exported from the crate root:
|
||||
|
||||
```rust
|
||||
use sol_trade_sdk::{fetch_nonce_info, SimpleBuyParams};
|
||||
|
||||
let nonce_info = fetch_nonce_info(&client.infrastructure.rpc, nonce_account)
|
||||
.await
|
||||
.expect("nonce account must be initialized");
|
||||
|
||||
let buy_params = SimpleBuyParams::new(
|
||||
dex_type,
|
||||
pay_with,
|
||||
mint,
|
||||
amount,
|
||||
extension_params,
|
||||
recent_blockhash,
|
||||
gas_fee_strategy,
|
||||
)
|
||||
.durable_nonce(nonce_info);
|
||||
```
|
||||
|
||||
Calling `.durable_nonce(...)` clears `recent_blockhash`; nonce transactions use the nonce value as the transaction blockhash.
|
||||
|
||||
## TradeBuyParams
|
||||
|
||||
`TradeBuyParams` is the advanced low-level buy API. New integrations should prefer `SimpleBuyParams` unless they need direct control over individual ATA flags.
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
| `address_lookup_table_account` | `Option<AddressLookupTableAccount>` | ❌ | 可选 ALT,用于减少交易体积。 |
|
||||
| `wait_tx_confirmed` | `bool` | ❌ | 是否等链上确认后再返回。默认 `false`。 |
|
||||
| `wait_for_all_submits` | `bool` | ❌ | fast-submit 模式下,是否等待所有 SWQoS 通道返回并拿到全部签名。 |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | durable nonce 信息。使用 `SimpleBuyParams::with_durable_nonce(...)` 设置,不要和 `recent_blockhash` 混用。 |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | durable nonce 信息。使用 `.durable_nonce(nonce_info)` 或 `SimpleBuyParams::with_durable_nonce(...)` 设置,不要和 `recent_blockhash` 混用。 |
|
||||
| `simulate` | `bool` | ❌ | 只构建并模拟交易,不提交。默认 `false`。 |
|
||||
| `grpc_recv_us` | `Option<i64>` | ❌ | 上游收到事件的微秒时间戳,用于延迟追踪。 |
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
| `address_lookup_table_account` | `Option<AddressLookupTableAccount>` | ❌ | 可选 ALT,用于减少交易体积。 |
|
||||
| `wait_tx_confirmed` | `bool` | ❌ | 是否等链上确认后再返回。默认 `false`。 |
|
||||
| `wait_for_all_submits` | `bool` | ❌ | fast-submit 模式下,是否等待所有 SWQoS 通道返回并拿到全部签名。 |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | durable nonce 信息。使用 `SimpleSellParams::with_durable_nonce(...)` 设置,不要和 `recent_blockhash` 混用。 |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | durable nonce 信息。使用 `.durable_nonce(nonce_info)` 或 `SimpleSellParams::with_durable_nonce(...)` 设置,不要和 `recent_blockhash` 混用。 |
|
||||
| `simulate` | `bool` | ❌ | 只构建并模拟交易,不提交。默认 `false`。 |
|
||||
| `with_tip` | `bool` | ❌ | 卖出交易是否带 relay tip。默认 `true`,可通过 `.with_tip(false)` 关闭。 |
|
||||
| `grpc_recv_us` | `Option<i64>` | ❌ | 上游收到事件的微秒时间戳,用于延迟追踪。 |
|
||||
@@ -74,6 +74,31 @@
|
||||
| `CreateMissing` | 尽量在交易内创建缺失 ATA。 | 更重视方便,不追求最小交易体积。 |
|
||||
| `AssumePrepared` | 不创建也不关闭 token account,调用方保证都已准备好。 | 高级确定性流程。 |
|
||||
|
||||
### Simple 参数使用 Durable Nonce
|
||||
|
||||
`fetch_nonce_info` 和 `DurableNonceInfo` 已从 crate root 重新导出:
|
||||
|
||||
```rust
|
||||
use sol_trade_sdk::{fetch_nonce_info, SimpleBuyParams};
|
||||
|
||||
let nonce_info = fetch_nonce_info(&client.infrastructure.rpc, nonce_account)
|
||||
.await
|
||||
.expect("nonce account must be initialized");
|
||||
|
||||
let buy_params = SimpleBuyParams::new(
|
||||
dex_type,
|
||||
pay_with,
|
||||
mint,
|
||||
amount,
|
||||
extension_params,
|
||||
recent_blockhash,
|
||||
gas_fee_strategy,
|
||||
)
|
||||
.durable_nonce(nonce_info);
|
||||
```
|
||||
|
||||
调用 `.durable_nonce(...)` 会清空 `recent_blockhash`;nonce 交易会使用 nonce value 作为 transaction blockhash。
|
||||
|
||||
## TradeBuyParams
|
||||
|
||||
`TradeBuyParams` 是高级低层买入 API。新接入建议优先使用 `SimpleBuyParams`,只有需要直接控制单个 ATA flag 时再使用它。
|
||||
|
||||
@@ -14,11 +14,11 @@ use sol_trade_sdk::{
|
||||
core::params::{DexParamEnum, PumpFunParams},
|
||||
factory::DexType,
|
||||
},
|
||||
AccountPolicy, BuyAmount, SellAmount, SimpleBuyParams, SimpleSellParams, SolanaTrade,
|
||||
TradeTokenType,
|
||||
AccountPolicy, BuyAmount, DurableNonceInfo, SellAmount, SimpleBuyParams, SimpleSellParams,
|
||||
SolanaTrade, TradeTokenType,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer};
|
||||
use solana_sdk::{hash::Hash, pubkey::Pubkey, signature::Keypair, signer::Signer};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -83,7 +83,41 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// client.buy_simple(buy_params).await?;
|
||||
let _ = buy_params;
|
||||
|
||||
// Durable nonce is supported by the same high-level params. In production,
|
||||
// fetch it with `sol_trade_sdk::fetch_nonce_info(...)` immediately before
|
||||
// building the transaction.
|
||||
let nonce_buy_params = SimpleBuyParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
mint,
|
||||
BuyAmount::WithMaxInput { quote_amount: 100_000 },
|
||||
pumpfun_params.clone(),
|
||||
recent_blockhash,
|
||||
gas_fee_strategy.clone(),
|
||||
)
|
||||
.durable_nonce(DurableNonceInfo {
|
||||
nonce_account: Some(Pubkey::new_unique()),
|
||||
current_nonce: Some(Hash::new_unique()),
|
||||
})
|
||||
.account_policy(AccountPolicy::HotPathMinimal);
|
||||
let _ = nonce_buy_params;
|
||||
|
||||
let sell_params = SimpleSellParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
mint,
|
||||
SellAmount::ExactInput(1_000_000),
|
||||
pumpfun_params.clone(),
|
||||
client.infrastructure.rpc.get_latest_blockhash().await?,
|
||||
gas_fee_strategy.clone(),
|
||||
)
|
||||
.slippage_basis_points(300)
|
||||
.account_policy(AccountPolicy::HotPathMinimal);
|
||||
|
||||
// client.sell_simple(sell_params).await?;
|
||||
let _ = sell_params;
|
||||
|
||||
let nonce_sell_params = SimpleSellParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
mint,
|
||||
@@ -92,11 +126,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
client.infrastructure.rpc.get_latest_blockhash().await?,
|
||||
gas_fee_strategy,
|
||||
)
|
||||
.slippage_basis_points(300)
|
||||
.durable_nonce(DurableNonceInfo {
|
||||
nonce_account: Some(Pubkey::new_unique()),
|
||||
current_nonce: Some(Hash::new_unique()),
|
||||
})
|
||||
.account_policy(AccountPolicy::HotPathMinimal);
|
||||
|
||||
// client.sell_simple(sell_params).await?;
|
||||
let _ = sell_params;
|
||||
let _ = nonce_sell_params;
|
||||
|
||||
println!("Built simple buy/sell params for payer {}", client.payer.pubkey());
|
||||
Ok(())
|
||||
|
||||
@@ -335,6 +335,16 @@ impl SimpleBuyParams {
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a durable nonce instead of the recent blockhash passed to [`Self::new`].
|
||||
///
|
||||
/// This clears `recent_blockhash` because nonce transactions must use the
|
||||
/// nonce value as their transaction blockhash.
|
||||
pub fn durable_nonce(mut self, value: DurableNonceInfo) -> Self {
|
||||
self.durable_nonce = Some(value);
|
||||
self.recent_blockhash = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Wait for confirmation before returning.
|
||||
pub fn wait_tx_confirmed(mut self, value: bool) -> Self {
|
||||
self.wait_tx_confirmed = value;
|
||||
@@ -444,6 +454,16 @@ impl SimpleSellParams {
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a durable nonce instead of the recent blockhash passed to [`Self::new`].
|
||||
///
|
||||
/// This clears `recent_blockhash` because nonce transactions must use the
|
||||
/// nonce value as their transaction blockhash.
|
||||
pub fn durable_nonce(mut self, value: DurableNonceInfo) -> Self {
|
||||
self.durable_nonce = Some(value);
|
||||
self.recent_blockhash = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Wait for confirmation before returning.
|
||||
pub fn wait_tx_confirmed(mut self, value: bool) -> Self {
|
||||
self.wait_tx_confirmed = value;
|
||||
@@ -1910,6 +1930,33 @@ mod tests {
|
||||
assert!(!low.wait_tx_confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_buy_builder_can_use_durable_nonce() {
|
||||
let nonce_account = Pubkey::new_unique();
|
||||
let nonce_hash = Hash::new_unique();
|
||||
let durable_nonce = DurableNonceInfo {
|
||||
nonce_account: Some(nonce_account),
|
||||
current_nonce: Some(nonce_hash),
|
||||
};
|
||||
|
||||
let simple = SimpleBuyParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
Pubkey::new_unique(),
|
||||
BuyAmount::ExactInput(10_000),
|
||||
dummy_pumpfun_params(),
|
||||
Hash::new_unique(),
|
||||
GasFeeStrategy::new(),
|
||||
)
|
||||
.durable_nonce(durable_nonce.clone());
|
||||
|
||||
let low: TradeBuyParams = simple.into();
|
||||
|
||||
assert!(low.recent_blockhash.is_none());
|
||||
assert_eq!(low.durable_nonce.as_ref().and_then(|n| n.nonce_account), Some(nonce_account));
|
||||
assert_eq!(low.durable_nonce.as_ref().and_then(|n| n.current_nonce), Some(nonce_hash));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_sell_auto_creates_non_sol_output_ata() {
|
||||
let simple = SimpleSellParams {
|
||||
@@ -1939,4 +1986,31 @@ mod tests {
|
||||
assert!(!low.close_output_token_ata);
|
||||
assert!(!low.close_mint_token_ata);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_sell_builder_can_use_durable_nonce() {
|
||||
let nonce_account = Pubkey::new_unique();
|
||||
let nonce_hash = Hash::new_unique();
|
||||
let durable_nonce = DurableNonceInfo {
|
||||
nonce_account: Some(nonce_account),
|
||||
current_nonce: Some(nonce_hash),
|
||||
};
|
||||
|
||||
let simple = SimpleSellParams::new(
|
||||
DexType::PumpFun,
|
||||
TradeTokenType::SOL,
|
||||
Pubkey::new_unique(),
|
||||
SellAmount::ExactInput(50_000),
|
||||
dummy_pumpfun_params(),
|
||||
Hash::new_unique(),
|
||||
GasFeeStrategy::new(),
|
||||
)
|
||||
.durable_nonce(durable_nonce.clone());
|
||||
|
||||
let low: TradeSellParams = simple.into();
|
||||
|
||||
assert!(low.recent_blockhash.is_none());
|
||||
assert_eq!(low.durable_nonce.as_ref().and_then(|n| n.nonce_account), Some(nonce_account));
|
||||
assert_eq!(low.durable_nonce.as_ref().and_then(|n| n.current_nonce), Some(nonce_hash));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ pub mod swqos;
|
||||
pub mod trading;
|
||||
pub mod utils;
|
||||
|
||||
pub use crate::common::nonce_cache::{fetch_nonce_info, DurableNonceInfo};
|
||||
// Re-export for SwqosConfig (Node1/BlockRazor transport; Astralane submission mode)
|
||||
pub use crate::swqos::{AstralaneTransport, SwqosTransport};
|
||||
pub use client::{
|
||||
|
||||
Reference in New Issue
Block a user