feat: add gas fee strategy system with examples

- Add GasFeeStrategy module supporting normal and high-low fee strategies
- Initialize gas fee strategies in all examples
- Update documentation and README with gas fee strategy configuration
- Improve nonce cache documentation emphasizing latest nonce usage
- Adjust default gas fee configuration parameters
- Remove duplicate imports and unused constant references
This commit is contained in:
ysq
2025-09-19 15:46:51 +08:00
parent e8abb65e2e
commit a53038855e
27 changed files with 342 additions and 83 deletions
+1
View File
@@ -32,6 +32,7 @@ members = [
"examples/wsol_wrapper",
"examples/seed_trading",
"examples/cli_trading",
"examples/gas_fee_strategy",
]
[lib]
+10 -2
View File
@@ -130,7 +130,14 @@ let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let client = SolanaTrade::new(Arc::new(payer), trade_config).await;
```
#### 2. Build Trading Parameters
#### 2. Configure Gas Fee Strategy
For detailed information about Gas Fee Strategy, see the [Gas Fee Strategy Reference](docs/GAS_FEE_STRATEGY.md).
```rust
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
```
#### 3. Build Trading Parameters
For detailed information about all trading parameters, see the [Trading Parameters Reference](docs/TRADING_PARAMETERS.md).
@@ -151,7 +158,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams {
};
```
#### 3. Execute Trading
#### 4. Execute Trading
```rust
client.buy(buy_params).await?;
@@ -184,6 +191,7 @@ Please ensure that the parameters your trading logic depends on are available in
| Nonce example | `cargo run --package nonce_cache` | [examples/nonce_cache](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/nonce_cache/src/main.rs) |
| Wrap/unwrap SOL to/from WSOL example | `cargo run --package wsol_wrapper` | [examples/wsol_wrapper](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/wsol_wrapper/src/main.rs) |
| Seed trading example | `cargo run --package seed_trading` | [examples/seed_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/seed_trading/src/main.rs) |
| Gas fee strategy example | `cargo run --package gas_fee_strategy` | [examples/gas_fee_strategy](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/gas_fee_strategy/src/main.rs) |
### ⚙️ SWQOS Service Configuration
+11 -2
View File
@@ -130,7 +130,15 @@ let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let client = SolanaTrade::new(Arc::new(payer), trade_config).await;
```
#### 2. 构建交易参数
#### 2. 配置 Gas Fee 策略
有关 Gas Fee 策略的详细信息,请参阅 [Gas Fee 策略参考手册](docs/GAS_FEE_STRATEGY_CN.md)。
```rust
// 使用内置策略
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
```
#### 3. 构建交易参数
有关所有交易参数的详细信息,请参阅 [交易参数参考手册](docs/TRADING_PARAMETERS_CN.md)。
@@ -151,7 +159,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams {
};
```
#### 3. 执行交易
#### 4. 执行交易
```rust
client.buy(buy_params).await?;
@@ -184,6 +192,7 @@ client.buy(buy_params).await?;
| Nonce示例 | `cargo run --package nonce_cache` | [examples/nonce_cache](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/nonce_cache/src/main.rs) |
| SOL与WSOL相互转换示例 | `cargo run --package wsol_wrapper` | [examples/wsol_wrapper](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/wsol_wrapper/src/main.rs) |
| Seed 优化交易示例 | `cargo run --package seed_trading` | [examples/seed_trading](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/seed_trading/src/main.rs) |
| Gas费用策略示例 | `cargo run --package gas_fee_strategy` | [examples/gas_fee_strategy](https://github.com/0xfnzero/sol-trade-sdk/tree/main/examples/gas_fee_strategy/src/main.rs) |
### ⚙️ SWQOS 服务配置说明
+65
View File
@@ -0,0 +1,65 @@
# 📊 Gas Fee Strategy Guide
This document introduces the Gas Fee strategy configuration and usage methods in Sol Trade SDK.
## Basic Usage
### 1. Overview
This module supports users to configure strategies for SwqosType under different TradeType (buy/sell).
- Normal strategy: One SwqosType sends one transaction, specifying cu_limit, cu_price, and tip.
- High-low fee strategy: One SwqosType sends two transactions simultaneously, one with low tip and high priority fee, another with high tip and low priority fee.
Each (SwqosType, TradeType) combination can only configure one strategy. Subsequent strategy configurations will override previous ones.
### 2. Using Built-in Strategies
```rust
use sol_trade_sdk::common::gas_fee_strategy::GasFeeStrategy;
// Use built-in strategies (includes normal strategies for various SwqosTypes)
GasFeeStrategy::init_builtin_fee_strategies();
```
### 3. Configuring Single Strategy
```rust
// Configure normal strategy for SwqosType::Jito during Buy
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
xxxxx, // cu_limit
xxxx, // cu_price
xxxxx // tip
);
```
### 4. Configuring High-Low Fee Strategy
```rust
// Configure high-low fee strategy for SwqosType::Jito during Buy
GasFeeStrategy::add_high_low_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
xxxxx, // cu_limit
xxxxx, // low cu_price
xxxxx, // high cu_price
xxxxx, // low tip
xxxxx // high tip
);
```
### 5. Viewing and Cleanup
```rust
// Remove a specific strategy
GasFeeStrategy::remove_strategy(SwqosType::Jito, TradeType::Buy);
// View all strategies
GasFeeStrategy::print_all_strategies();
// Clear all strategies
GasFeeStrategy::clear();
```
## 🔗 Related Documents
- [Example: Gas Fee Strategy](../examples/gas_fee_strategy/)
+65
View File
@@ -0,0 +1,65 @@
# 📊 Gas Fee 策略指南
本文档介绍 Sol Trade SDK 中的 Gas Fee 策略配置和使用方法。
## 基础使用
### 1. 说明
该模块支持用户配置 SwqosType 在不同 TradeType(buy/sell) 下的策略。
- normal 策略: 一个 SwqosType 发送一笔交易,指定 cu_limit、cu_price 和小费。
- 高低费率策略: 一个 SwqosType 同时发送两笔交易,一笔低小费高优先费,一笔高小费低优先费。
每个 (SwqosType, TradeType) 的组合仅可配置一个策略。后续配置的策略会覆盖之前的策略。
### 2. 使用内置策略
```rust
use sol_trade_sdk::common::gas_fee_strategy::GasFeeStrategy;
// 使用内置策略(内置了各个 SwqosType 的 normal 策略)
GasFeeStrategy::init_builtin_fee_strategies();
```
### 3. 配置单个策略
```rust
// 为 SwqosType::Jito 在 Buy 时配置 normal 策略
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
xxxxx, // cu_limit
xxxx, // cu_price
xxxxx // tip
);
```
### 4. 配置高低费率策略
```rust
// 为 SwqosType::Jito 在 Buy 时配置高低费率策略
GasFeeStrategy::add_high_low_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
xxxxx, // cu_limit
xxxxx, // low cu_price
xxxxx, // high cu_price
xxxxx, // low tip
xxxxx // high tip
);
```
### 5. 查看和清理
```rust
// 移除某个策略
GasFeeStrategy::remove_strategy(SwqosType::Jito, TradeType::Buy);
// 查看所有策略
GasFeeStrategy::print_all_strategies();
// 清空所有策略
GasFeeStrategy::clear();
```
## 🔗 相关文档
- [示例:Gas Fee 策略](../examples/gas_fee_strategy/)
+1 -1
View File
@@ -57,7 +57,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams {
mint: mint_pubkey,
sol_amount: buy_sol_amount,
slippage_basis_points: Some(100),
recent_blockhash: current_nonce, // Use nonce as blockhash
recent_blockhash: current_nonce, // Use nonce as blockhash. Please use the latest nonce value for each transaction.
extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)),
lookup_table_key: None,
wait_transaction_confirmed: true,
+1 -1
View File
@@ -57,7 +57,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams {
mint: mint_pubkey,
sol_amount: buy_sol_amount,
slippage_basis_points: Some(100),
recent_blockhash: current_nonce, // 使用 nonce 作为 blockhash
recent_blockhash: current_nonce, // 使用 nonce 作为 blockhash。请在每次交易时,都使用最新的 nonce 值。
extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)),
lookup_table_key: None,
wait_transaction_confirmed: true,
+2 -1
View File
@@ -19,7 +19,6 @@ use sol_trade_sdk::{
};
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpFunParams, factory::DexType},
SolanaTrade,
@@ -125,6 +124,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -14,7 +14,6 @@ use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{
use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc;
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::BonkParams, factory::DexType},
SolanaTrade,
@@ -111,6 +110,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -6,7 +6,6 @@ use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, Unif
use sol_trade_sdk::solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc};
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::BonkParams, factory::DexType},
SolanaTrade,
@@ -80,6 +79,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -3,7 +3,6 @@ use sol_trade_sdk::{
common::{
fast_fn::get_associated_token_address_with_program_id_fast_use_seed, AnyResult, TradeConfig,
},
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{
core::params::{
@@ -1285,6 +1284,8 @@ async fn initialize_real_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(payer, trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "gas_fee_strategy"
version = "0.1.0"
edition = "2021"
[dependencies]
sol-trade-sdk = { path = "../.." }
tokio = { version = "1.0", features = ["full"] }
+72
View File
@@ -0,0 +1,72 @@
use sol_trade_sdk::{
common::gas_fee_strategy::GasFeeStrategy,
swqos::{SwqosType, TradeType},
};
#[tokio::main]
async fn main() {
println!("🚀 Gas Fee Strategy Demo");
println!("========================");
// Initialize builtin strategies
println!("1. Initialize builtin strategies");
GasFeeStrategy::init_builtin_fee_strategies();
// Print all strategies
println!("\n2. Print all builtin strategies");
GasFeeStrategy::print_all_strategies();
// Clear all strategies
println!("\n3. Clear all strategies");
GasFeeStrategy::clear();
// Add normal fee strategy for SwqosType::Default on Buy
println!("\n4. Add normal fee strategy for SwqosType::Default on Buy");
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Default,
TradeType::Buy,
150000, // cu_limit
500000, // cu_price
0.0, // tip
);
// Add high-low fee strategy for SwqosType::Jito on Buy
println!("\n5. Add high-low fee strategy for SwqosType::Jito on Buy");
GasFeeStrategy::add_high_low_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
150000, // cu_limit
100, // low cu_price
10 * 1_000_000, // high cu_price
0.001, // low tip
0.1, // high tip
);
// Print all strategies
println!("\n6. Print all current strategies");
GasFeeStrategy::print_all_strategies();
// Add normal fee strategy for SwqosType::Jito on Buy (will override previous high-low strategy)
println!("\n7. Add normal fee strategy for SwqosType::Jito on Buy (will override previous high-low strategy)");
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
150000, // cu_limit
500000, // cu_price
0.0001, // tip
);
// Print all strategies
println!("\n8. Print all current strategies");
GasFeeStrategy::print_all_strategies();
// Remove strategy for SwqosType::Jito on Buy
println!("\n9. Remove strategy for SwqosType::Jito on Buy");
GasFeeStrategy::remove_strategy(SwqosType::Jito, TradeType::Buy);
// Print all strategies
println!("\n10. Print all current strategies");
GasFeeStrategy::print_all_strategies();
println!("\n✅ Gas Fee Strategy Demo completed!");
}
+2 -1
View File
@@ -1,7 +1,6 @@
use anyhow::Result;
use sol_trade_sdk::{
common::{AnyResult, TradeConfig},
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::{SwqosConfig, SwqosRegion},
trading::{
core::params::PumpSwapParams, factory::DexType, middleware::builtin::LoggingMiddleware,
@@ -67,6 +66,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -17,7 +17,6 @@ use sol_trade_sdk::{
};
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpFunParams, factory::DexType},
SolanaTrade,
@@ -106,6 +105,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -14,7 +14,6 @@ use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{
use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc;
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpFunParams, factory::DexType},
SolanaTrade,
@@ -105,6 +104,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -6,7 +6,6 @@ use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, Unif
use sol_trade_sdk::solana_streamer_sdk::{match_event, streaming::ShredStreamGrpc};
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpFunParams, factory::DexType},
SolanaTrade,
@@ -74,6 +73,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -1,6 +1,5 @@
use sol_trade_sdk::{
common::{AnyResult, TradeConfig},
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpSwapParams, factory::DexType},
SolanaTrade,
@@ -82,6 +81,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -13,7 +13,6 @@ use sol_trade_sdk::solana_streamer_sdk::{
};
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpSwapParams, factory::DexType},
SolanaTrade,
@@ -131,6 +130,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -14,7 +14,6 @@ use sol_trade_sdk::solana_streamer_sdk::streaming::yellowstone_grpc::{
use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc;
use sol_trade_sdk::{
common::AnyResult,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::RaydiumAmmV4Params, factory::DexType},
SolanaTrade,
@@ -105,6 +104,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+3 -4
View File
@@ -3,6 +3,7 @@ use std::sync::{
Arc,
};
use sol_trade_sdk::solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent};
use sol_trade_sdk::solana_streamer_sdk::streaming::YellowstoneGrpc;
use sol_trade_sdk::solana_streamer_sdk::{
match_event, streaming::event_parser::protocols::raydium_cpmm::RaydiumCpmmSwapEvent,
@@ -12,10 +13,6 @@ use sol_trade_sdk::{
common::TradeConfig,
solana_streamer_sdk::streaming::yellowstone_grpc::{AccountFilter, TransactionFilter},
};
use sol_trade_sdk::{
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
solana_streamer_sdk::streaming::event_parser::{Protocol, UnifiedEvent},
};
use sol_trade_sdk::{
instruction::utils::raydium_cpmm::accounts,
solana_streamer_sdk::streaming::event_parser::protocols::raydium_cpmm::parser::RAYDIUM_CPMM_PROGRAM_ID,
@@ -114,6 +111,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2 -1
View File
@@ -2,7 +2,6 @@ use sol_trade_sdk::{
common::{
fast_fn::get_associated_token_address_with_program_id_fast_use_seed, AnyResult, TradeConfig,
},
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
trading::{core::params::PumpSwapParams, factory::DexType},
SolanaTrade,
@@ -91,6 +90,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+2
View File
@@ -35,6 +35,8 @@ async fn create_solana_trade_client() -> AnyResult<SolanaTrade> {
];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade_client = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("SolanaTrade client created successfully!");
Ok(solana_trade_client)
}
+3 -6
View File
@@ -1,9 +1,4 @@
use sol_trade_sdk::{
common::TradeConfig,
constants::trade::trade::{DEFAULT_CU_LIMIT, DEFAULT_CU_PRICE},
swqos::SwqosConfig,
SolanaTrade,
};
use sol_trade_sdk::{common::TradeConfig, swqos::SwqosConfig, SolanaTrade};
use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};
use std::sync::Arc;
@@ -63,6 +58,8 @@ async fn create_solana_trade_client() -> Result<SolanaTrade, Box<dyn std::error:
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let solana_trade = SolanaTrade::new(Arc::new(payer), trade_config).await;
// init gas fee strategy
sol_trade_sdk::common::GasFeeStrategy::init_builtin_fee_strategies();
println!("✅ SolanaTrade client initialized successfully!");
Ok(solana_trade)
}
+72 -51
View File
@@ -1,3 +1,7 @@
use crate::constants::trade::trade::{
DEFAULT_BUY_TIP_FEE, DEFAULT_RPC_UNIT_LIMIT, DEFAULT_RPC_UNIT_PRICE, DEFAULT_SELL_TIP_FEE,
DEFAULT_TIP_UNIT_LIMIT, DEFAULT_TIP_UNIT_PRICE,
};
use crate::swqos::{SwqosType, TradeType};
use arc_swap::ArcSwap;
use std::collections::HashMap;
@@ -5,14 +9,14 @@ use std::sync::{Arc, LazyLock};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GasFeeStrategyType {
Default,
Normal,
LowTipHighCuPrice,
HighTipLowCuPrice,
}
impl GasFeeStrategyType {
pub fn values() -> Vec<Self> {
vec![Self::Default, Self::LowTipHighCuPrice, Self::HighTipLowCuPrice]
vec![Self::Normal, Self::LowTipHighCuPrice, Self::HighTipLowCuPrice]
}
}
@@ -23,7 +27,6 @@ pub struct GasFeeStrategyValue {
pub tip: f64,
}
// 静态存储策略数据
static STRATEGIES: LazyLock<
ArcSwap<HashMap<(SwqosType, TradeType, GasFeeStrategyType), GasFeeStrategyValue>>,
> = LazyLock::new(|| ArcSwap::from_pointee(HashMap::new()));
@@ -31,6 +34,47 @@ static STRATEGIES: LazyLock<
pub struct GasFeeStrategy;
impl GasFeeStrategy {
/// 初始化内置策略。
/// Initialize built-in strategies
pub fn init_builtin_fee_strategies() {
GasFeeStrategy::add_normal_fee_strategies(
&SwqosType::values()
.into_iter()
.filter(|swqos_type| !swqos_type.eq(&SwqosType::Default))
.collect::<Vec<SwqosType>>(),
TradeType::Buy,
DEFAULT_TIP_UNIT_PRICE,
DEFAULT_BUY_TIP_FEE,
DEFAULT_TIP_UNIT_LIMIT,
);
GasFeeStrategy::add_normal_fee_strategies(
&SwqosType::values()
.into_iter()
.filter(|swqos_type| !swqos_type.eq(&SwqosType::Default))
.collect::<Vec<SwqosType>>(),
TradeType::Sell,
DEFAULT_TIP_UNIT_PRICE,
DEFAULT_SELL_TIP_FEE,
DEFAULT_TIP_UNIT_LIMIT,
);
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Default,
TradeType::Buy,
DEFAULT_RPC_UNIT_LIMIT,
DEFAULT_RPC_UNIT_PRICE,
0.0,
);
GasFeeStrategy::add_normal_fee_strategy(
SwqosType::Default,
TradeType::Sell,
DEFAULT_RPC_UNIT_LIMIT,
DEFAULT_RPC_UNIT_PRICE,
0.0,
);
}
/// 为多个服务类型添加高低费率策略,会移除(SwqosType,TradeType)的默认策略。
/// Add high-low fee strategies for multiple service types, Will remove the default strategy of (SwqosType,TradeType)
pub fn add_high_low_fee_strategies(
swqos_types: &[SwqosType],
trade_type: TradeType,
@@ -62,6 +106,8 @@ impl GasFeeStrategy {
});
}
/// 为单个服务类型添加高低费率策略,会移除(SwqosType,TradeType)的默认策略。
/// Add high-low fee strategy for a single service type, Will remove the default strategy of (SwqosType,TradeType)
pub fn add_high_low_fee_strategy(
swqos_type: SwqosType,
trade_type: TradeType,
@@ -89,7 +135,9 @@ impl GasFeeStrategy {
});
}
pub fn add_default_fee_strategies(
/// 为多个服务类型添加标准费率策略,会移除(SwqosType,TradeType)的高低价策略。
/// Add normal fee strategies for multiple service types, Will remove the high-low strategies of (SwqosType,TradeType)
pub fn add_normal_fee_strategies(
swqos_types: &[SwqosType],
trade_type: TradeType,
cu_price: u64,
@@ -103,7 +151,7 @@ impl GasFeeStrategy {
let mut new_map = (**current_map).clone();
for swqos_type in swqos_types {
new_map.insert(
(*swqos_type, trade_type, GasFeeStrategyType::Default),
(*swqos_type, trade_type, GasFeeStrategyType::Normal),
GasFeeStrategyValue { cu_limit, cu_price, tip },
);
}
@@ -111,34 +159,40 @@ impl GasFeeStrategy {
});
}
pub fn add_default_fee_strategy(
/// 为单个服务类型添加标准费率策略,会移除(SwqosType,TradeType)的高低价策略。
/// Add normal fee strategy for a single service type, Will remove the high-low strategies of (SwqosType,TradeType)
pub fn add_normal_fee_strategy(
swqos_type: SwqosType,
trade_type: TradeType,
cu_limit: u32,
cu_price: u64,
tip: f64,
cu_limit: u32,
) {
GasFeeStrategy::remove_strategy(swqos_type, trade_type);
STRATEGIES.rcu(|current_map| {
let mut new_map = (**current_map).clone();
new_map.insert(
(swqos_type, trade_type, GasFeeStrategyType::Default),
(swqos_type, trade_type, GasFeeStrategyType::Normal),
GasFeeStrategyValue { cu_limit, cu_price, tip },
);
Arc::new(new_map)
});
}
/// 移除指定(SwqosType,TradeType)的策略。
/// Remove strategy for specified (SwqosType,TradeType)
pub fn remove_strategy(swqos_type: SwqosType, trade_type: TradeType) {
STRATEGIES.rcu(|current_map| {
let mut new_map = (**current_map).clone();
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::Default));
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::Normal));
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::LowTipHighCuPrice));
new_map.remove(&(swqos_type, trade_type, GasFeeStrategyType::HighTipLowCuPrice));
Arc::new(new_map)
});
}
/// 获取指定交易类型的所有策略。
/// Get all strategies for specified trade type
pub fn get_strategies(
trade_type: TradeType,
) -> Vec<(SwqosType, GasFeeStrategyType, GasFeeStrategyValue)> {
@@ -162,53 +216,20 @@ impl GasFeeStrategy {
result
}
/// 清空所有策略。
/// Clear all strategies
pub fn clear() {
STRATEGIES.store(Arc::new(HashMap::new()));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn demo() {
// 给SwqosType::Default 在 Buy 时添加默认策略
GasFeeStrategy::add_default_fee_strategy(
SwqosType::Default,
TradeType::Buy,
100,
0.0001,
10,
);
// 给SwqosType::Jito 在 Buy 时添加高低价策略
GasFeeStrategy::add_high_low_fee_strategy(
SwqosType::Jito,
TradeType::Buy,
10,
100,
10000,
0.001,
0.1,
);
// 获取所有 Buy 策略
let all_strategies = GasFeeStrategy::get_strategies(TradeType::Buy);
for strategy in all_strategies {
println!("strategy: {:?}", strategy);
/// 打印所有策略。
/// Print all strategies
pub fn print_all_strategies() {
for strategy in GasFeeStrategy::get_strategies(TradeType::Buy) {
println!("[buy] - {:?}", strategy);
}
println!("--------------------------------");
// 给SwqosType::Jito 在 Buy 时添加默认策略(会删除 jito 的高低价策略)
GasFeeStrategy::add_default_fee_strategy(SwqosType::Jito, TradeType::Buy, 100, 0.0001, 10);
// 获取所有 Buy 策略
let all_strategies = GasFeeStrategy::get_strategies(TradeType::Buy);
for strategy in all_strategies {
println!("strategy: {:?}", strategy);
for strategy in GasFeeStrategy::get_strategies(TradeType::Sell) {
println!("[sell] - {:?}", strategy);
}
// 删除SwqosType::Jito 在 Buy 时的策略
GasFeeStrategy::remove_strategy(SwqosType::Jito, TradeType::Buy);
// 清空策略
GasFeeStrategy::clear();
println!("--------------------------------");
println!("strategy {:?}", GasFeeStrategy::get_strategies(TradeType::Buy));
}
}
+2 -2
View File
@@ -1,9 +1,9 @@
pub mod trade {
pub const DEFAULT_SLIPPAGE: u64 = 1000; // 10%
pub const DEFAULT_TIP_UNIT_LIMIT: u32 = 78000;
pub const DEFAULT_TIP_UNIT_LIMIT: u32 = 150000;
pub const DEFAULT_TIP_UNIT_PRICE: u64 = 500000;
pub const DEFAULT_BUY_TIP_FEE: f64 = 0.0006;
pub const DEFAULT_SELL_TIP_FEE: f64 = 0.0001;
pub const DEFAULT_RPC_UNIT_LIMIT: u32 = 78000;
pub const DEFAULT_RPC_UNIT_LIMIT: u32 = 150000;
pub const DEFAULT_RPC_UNIT_PRICE: u64 = 500000;
}
+2 -2
View File
@@ -78,7 +78,7 @@ async fn parallel_execute(
.find(|swqos| matches!(swqos.get_swqos_type(), SwqosType::Default))
.is_none()
{
return Err(anyhow!("No Rpc Default Swqos configured"));
return Err(anyhow!("No Rpc Default Swqos configured."));
}
let cores = core_affinity::get_core_ids().unwrap();
let mut handles: Vec<JoinHandle<Result<Signature>>> = Vec::with_capacity(swqos_clients.len());
@@ -106,7 +106,7 @@ async fn parallel_execute(
.collect();
if task_configs.is_empty() {
return Err(anyhow!("No available gas fee strategy configs"));
return Err(anyhow!("No available gas fee strategy configs. Please configure GasFeeStrategy for specific SwqosType."));
}
for (i, swqos_client, gas_fee_strategy_config) in task_configs {