refactor: update API with DexParamEnum and simplify TradeConfig
- Introduce DexParamEnum to replace Dex enum for protocol parameters - Simplify TradeConfig::new() to accept only 3 essential parameters - Update all examples to use new DexParamEnum API - Optimize executor and params modules - Remove deprecated wsol_use_seed and mint_use_seed parameters - Fix fast_fn module exports
This commit is contained in:
+9
-4
@@ -38,6 +38,10 @@ members = [
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
perf-trace = [] # 性能追踪特性,生产环境应禁用以获得最佳性能
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = "3.0.0"
|
||||
solana-client = "3.0.8"
|
||||
@@ -110,17 +114,18 @@ memmap2 = "0.9"
|
||||
num_cpus = "1.16"
|
||||
libc = "0.2"
|
||||
|
||||
# 🚀 编译器优化配置
|
||||
# 🚀 编译器优化配置 - 平衡性能与编译速度
|
||||
[profile.release]
|
||||
opt-level = 3 # 最高优化级别
|
||||
lto = "fat" # 胖LTO获得最佳优化
|
||||
codegen-units = 1 # 单个代码生成单元
|
||||
opt-level = 3 # 最高优化级别(不影响编译速度)
|
||||
lto = "thin" # 瘦LTO - 平衡性能与编译速度(比fat快5-10倍)
|
||||
codegen-units = 16 # 16个代码生成单元 - 并行编译(比1快10倍)
|
||||
panic = "abort" # 恐慌即中止
|
||||
overflow-checks = false # 禁用溢出检查
|
||||
debug = false # 禁用调试信息
|
||||
debug-assertions = false # 禁用调试断言
|
||||
rpath = false
|
||||
strip = true # 去除符号表
|
||||
incremental = true # 增量编译 - 大幅加速重新编译
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1 # 开发时适度优化
|
||||
|
||||
@@ -3,7 +3,7 @@ use sol_trade_sdk::common::{gas_fee_strategy, GasFeeStrategy, TradeConfig};
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpFunParams, factory::DexType},
|
||||
trading::{core::params::{PumpFunParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -137,7 +137,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(PumpFunParams::from_trade(
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::from_trade(
|
||||
trade_info.bonding_curve,
|
||||
trade_info.associated_bonding_curve,
|
||||
trade_info.mint,
|
||||
|
||||
@@ -8,7 +8,7 @@ use sol_trade_sdk::common::TradeConfig;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::BonkParams, factory::DexType},
|
||||
trading::{core::params::{BonkParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -143,7 +143,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()>
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::from_trade(
|
||||
extension_params: DexParamEnum::Bonk(BonkParams::from_trade(
|
||||
trade_info.virtual_base,
|
||||
trade_info.virtual_quote,
|
||||
trade_info.real_base_after,
|
||||
@@ -187,7 +187,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()>
|
||||
input_token_amount: amount_token,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::from_trade(
|
||||
extension_params: DexParamEnum::Bonk(BonkParams::from_trade(
|
||||
trade_info.virtual_base,
|
||||
trade_info.virtual_quote,
|
||||
trade_info.real_base_after,
|
||||
|
||||
@@ -3,7 +3,7 @@ use sol_trade_sdk::common::TradeConfig;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::BonkParams, factory::DexType},
|
||||
trading::{core::params::{BonkParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -114,7 +114,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult<
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::from_dev_trade(
|
||||
extension_params: DexParamEnum::Bonk(BonkParams::from_dev_trade(
|
||||
trade_info.exact_in,
|
||||
trade_info.amount_in,
|
||||
trade_info.amount_out,
|
||||
@@ -157,7 +157,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult<
|
||||
input_token_amount: amount_token,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::immediate_sell(
|
||||
extension_params: DexParamEnum::Bonk(BonkParams::immediate_sell(
|
||||
trade_info.base_token_program,
|
||||
trade_info.platform_config,
|
||||
trade_info.platform_associated_account,
|
||||
|
||||
@@ -12,7 +12,7 @@ use sol_trade_sdk::{
|
||||
swqos::SwqosConfig,
|
||||
trading::{
|
||||
core::params::{
|
||||
BonkParams, PumpFunParams, PumpSwapParams, RaydiumAmmV4Params, RaydiumCpmmParams,
|
||||
BonkParams, PumpFunParams, PumpSwapParams, RaydiumAmmV4Params, RaydiumCpmmParams, DexParamEnum,
|
||||
},
|
||||
factory::DexType,
|
||||
},
|
||||
@@ -624,7 +624,7 @@ async fn handle_buy_pumpfun(
|
||||
input_token_amount: sol_lamports,
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::PumpFun(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: false,
|
||||
@@ -678,7 +678,7 @@ async fn handle_buy_pumpswap(
|
||||
input_token_amount: sol_lamports,
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::PumpSwap(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: true,
|
||||
@@ -731,7 +731,7 @@ async fn handle_buy_bonk(
|
||||
input_token_amount: sol_lamports,
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::Bonk(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: true,
|
||||
@@ -788,7 +788,7 @@ async fn handle_buy_raydium_v4(
|
||||
input_token_amount: sol_lamports,
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::RaydiumAmmV4(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: true,
|
||||
@@ -845,7 +845,7 @@ async fn handle_buy_raydium_cpmm(
|
||||
input_token_amount: sol_lamports,
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::RaydiumCpmm(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: true,
|
||||
@@ -1013,7 +1013,7 @@ async fn handle_sell_pumpfun(
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::PumpFun(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
@@ -1071,7 +1071,7 @@ async fn handle_sell_pumpswap(
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::PumpSwap(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
@@ -1128,7 +1128,7 @@ async fn handle_sell_bonk(
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::Bonk(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
@@ -1188,7 +1188,7 @@ async fn handle_sell_raydium_v4(
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::RaydiumAmmV4(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
@@ -1248,7 +1248,7 @@ async fn handle_sell_raydium_cpmm(
|
||||
slippage_basis_points: slippage,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(param),
|
||||
extension_params: DexParamEnum::RaydiumCpmm(param),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use sol_trade_sdk::{
|
||||
SolanaTrade, TradeTokenType, common::{
|
||||
AnyResult, TradeConfig, fast_fn::get_associated_token_address_with_program_id_fast_use_seed
|
||||
}, swqos::SwqosConfig, trading::{core::params::MeteoraDammV2Params, factory::DexType}
|
||||
}, swqos::SwqosConfig, trading::{core::params::{MeteoraDammV2Params, DexParamEnum}, factory::DexType}
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
use solana_sdk::signature::Keypair;
|
||||
@@ -31,7 +31,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
input_token_amount: input_token_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::MeteoraDammV2(
|
||||
MeteoraDammV2Params::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
@@ -64,7 +64,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::MeteoraDammV2(
|
||||
MeteoraDammV2Params::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
|
||||
@@ -3,7 +3,7 @@ use sol_trade_sdk::{
|
||||
common::{AnyResult, TradeConfig},
|
||||
swqos::{SwqosConfig, SwqosRegion},
|
||||
trading::{
|
||||
core::params::PumpSwapParams, factory::DexType, middleware::builtin::LoggingMiddleware,
|
||||
core::params::{PumpSwapParams, DexParamEnum}, factory::DexType, middleware::builtin::LoggingMiddleware,
|
||||
InstructionMiddleware, MiddlewareManager,
|
||||
},
|
||||
SolanaTrade, TradeTokenType,
|
||||
@@ -90,7 +90,7 @@ async fn test_middleware() -> AnyResult<()> {
|
||||
input_token_amount: buy_sol_cost,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::PumpSwap(
|
||||
PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool_address).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
|
||||
@@ -11,7 +11,7 @@ use sol_trade_sdk::TradeTokenType;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpFunParams, factory::DexType},
|
||||
trading::{core::params::{PumpFunParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -137,7 +137,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(PumpFunParams::from_trade(
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::from_trade(
|
||||
trade_info.bonding_curve,
|
||||
trade_info.associated_bonding_curve,
|
||||
trade_info.mint,
|
||||
|
||||
@@ -10,7 +10,7 @@ use sol_trade_sdk::TradeTokenType;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpFunParams, factory::DexType},
|
||||
trading::{core::params::{PumpFunParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -133,7 +133,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(PumpFunParams::from_trade(
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::from_trade(
|
||||
trade_info.bonding_curve,
|
||||
trade_info.associated_bonding_curve,
|
||||
trade_info.mint,
|
||||
@@ -178,7 +178,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(PumpFunParams::from_trade(
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::from_trade(
|
||||
trade_info.bonding_curve,
|
||||
trade_info.associated_bonding_curve,
|
||||
trade_info.mint,
|
||||
|
||||
@@ -4,7 +4,7 @@ use sol_trade_sdk::TradeTokenType;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpFunParams, factory::DexType},
|
||||
trading::{core::params::{PumpFunParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -101,7 +101,7 @@ async fn pumpfun_sniper_trade_with_shreds(trade_info: PumpFunTradeEvent) -> AnyR
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(PumpFunParams::from_dev_trade(
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::from_dev_trade(
|
||||
trade_info.mint,
|
||||
trade_info.token_amount,
|
||||
trade_info.max_sol_cost,
|
||||
@@ -144,7 +144,7 @@ async fn pumpfun_sniper_trade_with_shreds(trade_info: PumpFunTradeEvent) -> AnyR
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(PumpFunParams::immediate_sell(trade_info.creator_vault, trade_info.token_program, true)),
|
||||
extension_params: DexParamEnum::PumpFun(PumpFunParams::immediate_sell(trade_info.creator_vault, trade_info.token_program, true)),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use sol_trade_sdk::{
|
||||
SolanaTrade, TradeTokenType, common::{
|
||||
AnyResult, TradeConfig, fast_fn::get_associated_token_address_with_program_id_fast_use_seed
|
||||
}, swqos::SwqosConfig, trading::{core::params::PumpSwapParams, factory::DexType}
|
||||
}, swqos::SwqosConfig, trading::{core::params::{PumpSwapParams, DexParamEnum}, factory::DexType}
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
use solana_sdk::signature::Keypair;
|
||||
@@ -31,7 +31,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::PumpSwap(
|
||||
PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
@@ -63,7 +63,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::PumpSwap(
|
||||
PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
|
||||
@@ -4,7 +4,7 @@ use sol_trade_sdk::TradeTokenType;
|
||||
use sol_trade_sdk::{
|
||||
common::AnyResult,
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpSwapParams, factory::DexType},
|
||||
trading::{core::params::{PumpSwapParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -210,7 +210,7 @@ async fn pumpswap_trade_with_grpc(mint_pubkey: Pubkey, params: PumpSwapParams) -
|
||||
input_token_amount: buy_token_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(params.clone()),
|
||||
extension_params: DexParamEnum::PumpSwap(params.clone()),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: is_sol,
|
||||
@@ -244,7 +244,7 @@ async fn pumpswap_trade_with_grpc(mint_pubkey: Pubkey, params: PumpSwapParams) -
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(params.clone()),
|
||||
extension_params: DexParamEnum::PumpSwap(params.clone()),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: is_sol,
|
||||
|
||||
@@ -5,7 +5,7 @@ use sol_trade_sdk::{
|
||||
use sol_trade_sdk::{
|
||||
common::{spl_associated_token_account::get_associated_token_address, AnyResult},
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::RaydiumAmmV4Params, factory::DexType},
|
||||
trading::{core::params::{RaydiumAmmV4Params, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -154,7 +154,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent)
|
||||
input_token_amount: input_token_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(params),
|
||||
extension_params: DexParamEnum::RaydiumAmmV4(params),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: is_wsol,
|
||||
@@ -187,7 +187,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent)
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(params),
|
||||
extension_params: DexParamEnum::RaydiumAmmV4(params),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: is_wsol,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use sol_trade_sdk::common::spl_associated_token_account::get_associated_token_address;
|
||||
use sol_trade_sdk::common::TradeConfig;
|
||||
use sol_trade_sdk::constants::{WSOL_TOKEN_ACCOUNT, USDC_TOKEN_ACCOUNT};
|
||||
use sol_trade_sdk::trading::core::params::RaydiumCpmmParams;
|
||||
use sol_trade_sdk::trading::core::params::{RaydiumCpmmParams, DexParamEnum};
|
||||
use sol_trade_sdk::trading::factory::DexType;
|
||||
use sol_trade_sdk::TradeTokenType;
|
||||
use sol_trade_sdk::{common::AnyResult, swqos::SwqosConfig, SolanaTrade};
|
||||
@@ -148,7 +148,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) ->
|
||||
input_token_amount: input_token_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(buy_params),
|
||||
extension_params: DexParamEnum::RaydiumCpmm(buy_params),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_input_token_ata: is_wsol,
|
||||
@@ -183,7 +183,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) ->
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(sell_params),
|
||||
extension_params: DexParamEnum::RaydiumCpmm(sell_params),
|
||||
address_lookup_table_account: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_output_token_ata: is_wsol,
|
||||
|
||||
@@ -3,7 +3,7 @@ use sol_trade_sdk::{
|
||||
fast_fn::get_associated_token_address_with_program_id_fast_use_seed, AnyResult, TradeConfig,
|
||||
},
|
||||
swqos::SwqosConfig,
|
||||
trading::{core::params::PumpSwapParams, factory::DexType},
|
||||
trading::{core::params::{PumpSwapParams, DexParamEnum}, factory::DexType},
|
||||
SolanaTrade, TradeTokenType,
|
||||
};
|
||||
use solana_commitment_config::CommitmentConfig;
|
||||
@@ -34,7 +34,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
input_token_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::PumpSwap(
|
||||
PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
@@ -74,7 +74,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
with_tip: false,
|
||||
extension_params: Box::new(
|
||||
extension_params: DexParamEnum::PumpSwap(
|
||||
PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?,
|
||||
),
|
||||
address_lookup_table_account: None,
|
||||
|
||||
+18
-5
@@ -4,6 +4,7 @@ use solana_sdk::{
|
||||
instruction::{AccountMeta, Instruction},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::common::{
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id,
|
||||
@@ -38,11 +39,14 @@ pub enum InstructionCacheKey {
|
||||
}
|
||||
|
||||
/// Global lock-free instruction cache for storing common instructions
|
||||
static INSTRUCTION_CACHE: Lazy<DashMap<InstructionCacheKey, Vec<Instruction>>> =
|
||||
/// 🚀 性能优化:使用 Arc<Vec<Instruction>> 减少克隆开销
|
||||
static INSTRUCTION_CACHE: Lazy<DashMap<InstructionCacheKey, Arc<Vec<Instruction>>>> =
|
||||
Lazy::new(|| DashMap::with_capacity(MAX_INSTRUCTION_CACHE_SIZE));
|
||||
|
||||
/// Get cached instruction, compute and cache if not exists (lock-free)
|
||||
pub fn get_cached_instructions<F>(cache_key: InstructionCacheKey, compute_fn: F) -> Vec<Instruction>
|
||||
/// 🚀 返回 Arc 避免每次调用克隆整个 Vec
|
||||
#[inline]
|
||||
pub fn get_cached_instructions<F>(cache_key: InstructionCacheKey, compute_fn: F) -> Arc<Vec<Instruction>>
|
||||
where
|
||||
F: FnOnce() -> Vec<Instruction>,
|
||||
{
|
||||
@@ -59,7 +63,10 @@ where
|
||||
};
|
||||
|
||||
// Lock-free cache lookup with entry API
|
||||
INSTRUCTION_CACHE.entry(cache_key).or_insert_with(compute_fn).clone()
|
||||
INSTRUCTION_CACHE
|
||||
.entry(cache_key)
|
||||
.or_insert_with(|| Arc::new(compute_fn()))
|
||||
.clone()
|
||||
}
|
||||
|
||||
// --------------------- Associated Token Account ---------------------
|
||||
@@ -101,7 +108,7 @@ pub fn _create_associated_token_account_idempotent_fast(
|
||||
|
||||
// Only use seed if the mint address is not wSOL or SOL
|
||||
// 🔧 修复:Token-2022 也支持 seed 方式(白名单方式更安全)
|
||||
if use_seed
|
||||
let arc_instructions = if use_seed
|
||||
&& !mint.eq(&crate::constants::WSOL_TOKEN_ACCOUNT)
|
||||
&& !mint.eq(&crate::constants::SOL_TOKEN_ACCOUNT)
|
||||
&& (token_program.eq(&crate::constants::TOKEN_PROGRAM)
|
||||
@@ -133,7 +140,10 @@ pub fn _create_associated_token_account_idempotent_fast(
|
||||
data: vec![1],
|
||||
}]
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
// 🚀 性能优化:尝试零开销解包 Arc,如果引用计数=1则直接移出,否则克隆
|
||||
Arc::try_unwrap(arc_instructions).unwrap_or_else(|arc| (*arc).clone())
|
||||
}
|
||||
|
||||
// --------------------- PDA ---------------------
|
||||
@@ -154,6 +164,7 @@ static PDA_CACHE: Lazy<DashMap<PdaCacheKey, Pubkey>> =
|
||||
Lazy::new(|| DashMap::with_capacity(MAX_PDA_CACHE_SIZE));
|
||||
|
||||
/// Get cached PDA, compute and cache if not exists (lock-free)
|
||||
#[inline]
|
||||
pub fn get_cached_pda<F>(cache_key: PdaCacheKey, compute_fn: F) -> Option<Pubkey>
|
||||
where
|
||||
F: FnOnce() -> Option<Pubkey>,
|
||||
@@ -188,6 +199,7 @@ struct AtaCacheKey {
|
||||
static ATA_CACHE: Lazy<DashMap<AtaCacheKey, Pubkey>> =
|
||||
Lazy::new(|| DashMap::with_capacity(MAX_ATA_CACHE_SIZE));
|
||||
|
||||
#[inline]
|
||||
pub fn get_associated_token_address_with_program_id_fast_use_seed(
|
||||
wallet_address: &Pubkey,
|
||||
token_mint_address: &Pubkey,
|
||||
@@ -203,6 +215,7 @@ pub fn get_associated_token_address_with_program_id_fast_use_seed(
|
||||
}
|
||||
|
||||
/// Get cached Associated Token Address, compute and cache if not exists
|
||||
#[inline]
|
||||
pub fn get_associated_token_address_with_program_id_fast(
|
||||
wallet_address: &Pubkey,
|
||||
token_mint_address: &Pubkey,
|
||||
|
||||
+36
-19
@@ -23,7 +23,7 @@ use crate::trading::core::params::PumpFunParams;
|
||||
use crate::trading::core::params::PumpSwapParams;
|
||||
use crate::trading::core::params::RaydiumAmmV4Params;
|
||||
use crate::trading::core::params::RaydiumCpmmParams;
|
||||
use crate::trading::core::traits::ProtocolParams;
|
||||
use crate::trading::core::params::DexParamEnum;
|
||||
use crate::trading::factory::DexType;
|
||||
use crate::trading::MiddlewareManager;
|
||||
use crate::trading::SwapParams;
|
||||
@@ -48,10 +48,10 @@ pub enum TradeTokenType {
|
||||
|
||||
/// Main trading client for Solana DeFi protocols
|
||||
///
|
||||
/// `SolanaTrade` provides a unified interface for trading across multiple Solana DEXs
|
||||
/// `SolTradingSDK` provides a unified interface for trading across multiple Solana DEXs
|
||||
/// including PumpFun, PumpSwap, Bonk, Raydium AMM V4, and Raydium CPMM.
|
||||
/// It manages RPC connections, transaction signing, and SWQOS (Solana Web Quality of Service) settings.
|
||||
pub struct SolanaTrade {
|
||||
pub struct TradingClient {
|
||||
/// The keypair used for signing all transactions
|
||||
pub payer: Arc<Keypair>,
|
||||
/// RPC client for blockchain interactions
|
||||
@@ -65,9 +65,12 @@ pub struct SolanaTrade {
|
||||
pub use_seed_optimize: bool,
|
||||
}
|
||||
|
||||
static INSTANCE: Mutex<Option<Arc<SolanaTrade>>> = Mutex::new(None);
|
||||
static INSTANCE: Mutex<Option<Arc<TradingClient>>> = Mutex::new(None);
|
||||
|
||||
impl Clone for SolanaTrade {
|
||||
/// 🔄 向后兼容:SolanaTrade 别名
|
||||
pub type SolanaTrade = TradingClient;
|
||||
|
||||
impl Clone for TradingClient {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
payer: self.payer.clone(),
|
||||
@@ -99,7 +102,7 @@ pub struct TradeBuyParams {
|
||||
/// Recent blockhash for transaction validity
|
||||
pub recent_blockhash: Option<Hash>,
|
||||
/// Protocol-specific parameters (PumpFun, Raydium, etc.)
|
||||
pub extension_params: Box<dyn ProtocolParams>,
|
||||
pub extension_params: DexParamEnum,
|
||||
// Extended configuration
|
||||
/// Optional address lookup table for transaction size optimization
|
||||
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
|
||||
@@ -143,7 +146,7 @@ pub struct TradeSellParams {
|
||||
/// Whether to include tip for transaction priority
|
||||
pub with_tip: bool,
|
||||
/// Protocol-specific parameters (PumpFun, Raydium, etc.)
|
||||
pub extension_params: Box<dyn ProtocolParams>,
|
||||
pub extension_params: DexParamEnum,
|
||||
// Extended configuration
|
||||
/// Optional address lookup table for transaction size optimization
|
||||
pub address_lookup_table_account: Option<AddressLookupTableAccount>,
|
||||
@@ -165,8 +168,8 @@ pub struct TradeSellParams {
|
||||
pub simulate: bool,
|
||||
}
|
||||
|
||||
impl SolanaTrade {
|
||||
/// Creates a new SolanaTrade instance with the specified configuration
|
||||
impl TradingClient {
|
||||
/// Creates a new SolTradingSDK instance with the specified configuration
|
||||
///
|
||||
/// This function initializes the trading system with RPC connection, SWQOS settings,
|
||||
/// and sets up necessary components for trading operations.
|
||||
@@ -178,7 +181,7 @@ impl SolanaTrade {
|
||||
/// * `swqos_settings` - List of SWQOS (Solana Web Quality of Service) configurations
|
||||
///
|
||||
/// # Returns
|
||||
/// Returns a configured `SolanaTrade` instance ready for trading operations
|
||||
/// Returns a configured `SolTradingSDK` instance ready for trading operations
|
||||
#[inline]
|
||||
pub async fn new(payer: Arc<Keypair>, trade_config: TradeConfig) -> Self {
|
||||
crate::common::fast_fn::fast_init(&payer.try_pubkey().unwrap());
|
||||
@@ -329,13 +332,18 @@ impl SolanaTrade {
|
||||
|
||||
/// Execute a buy order for a specified token
|
||||
///
|
||||
/// 🔧 修复:返回Vec<Signature>支持多SWQOS并发交易
|
||||
/// - bool: 是否至少有一个交易成功
|
||||
/// - Vec<Signature>: 所有提交的交易签名(按SWQOS顺序)
|
||||
/// - Option<TradeError>: 最后一个错误(如果全部失败)
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `params` - Buy trade parameters containing all necessary trading configuration
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Signature)` with the transaction signature if the buy order is successfully executed,
|
||||
/// Returns `Ok((bool, Vec<Signature>, Option<TradeError>))` with success flag and all transaction signatures,
|
||||
/// or an error if the transaction fails.
|
||||
///
|
||||
/// # Errors
|
||||
@@ -346,12 +354,14 @@ impl SolanaTrade {
|
||||
/// - Network or RPC errors occur
|
||||
/// - Insufficient SOL balance for the purchase
|
||||
/// - Required accounts cannot be created or accessed
|
||||
#[inline]
|
||||
pub async fn buy(
|
||||
&self,
|
||||
params: TradeBuyParams,
|
||||
) -> Result<(bool, Signature, Option<TradeError>), anyhow::Error> {
|
||||
) -> Result<(bool, Vec<Signature>, Option<TradeError>), anyhow::Error> {
|
||||
#[cfg(feature = "perf-trace")]
|
||||
if params.slippage_basis_points.is_none() {
|
||||
println!(
|
||||
log::debug!(
|
||||
"slippage_basis_points is none, use default slippage basis points: {}",
|
||||
DEFAULT_SLIPPAGE
|
||||
);
|
||||
@@ -430,19 +440,24 @@ impl SolanaTrade {
|
||||
|
||||
let swap_result = executor.swap(buy_params).await;
|
||||
let result =
|
||||
swap_result.map(|(success, sig, err)| (success, sig, err.map(TradeError::from)));
|
||||
swap_result.map(|(success, sigs, err)| (success, sigs, err.map(TradeError::from)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Execute a sell order for a specified token
|
||||
///
|
||||
/// 🔧 修复:返回Vec<Signature>支持多SWQOS并发交易
|
||||
/// - bool: 是否至少有一个交易成功
|
||||
/// - Vec<Signature>: 所有提交的交易签名(按SWQOS顺序)
|
||||
/// - Option<TradeError>: 最后一个错误(如果全部失败)
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `params` - Sell trade parameters containing all necessary trading configuration
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Signature)` with the transaction signature if the sell order is successfully executed,
|
||||
/// Returns `Ok((bool, Vec<Signature>, Option<TradeError>))` with success flag and all transaction signatures,
|
||||
/// or an error if the transaction fails.
|
||||
///
|
||||
/// # Errors
|
||||
@@ -454,12 +469,14 @@ impl SolanaTrade {
|
||||
/// - Insufficient token balance for the sale
|
||||
/// - Token account doesn't exist or is not properly initialized
|
||||
/// - Required accounts cannot be created or accessed
|
||||
#[inline]
|
||||
pub async fn sell(
|
||||
&self,
|
||||
params: TradeSellParams,
|
||||
) -> Result<(bool, Signature, Option<TradeError>), anyhow::Error> {
|
||||
) -> Result<(bool, Vec<Signature>, Option<TradeError>), anyhow::Error> {
|
||||
#[cfg(feature = "perf-trace")]
|
||||
if params.slippage_basis_points.is_none() {
|
||||
println!(
|
||||
log::debug!(
|
||||
"slippage_basis_points is none, use default slippage basis points: {}",
|
||||
DEFAULT_SLIPPAGE
|
||||
);
|
||||
@@ -539,7 +556,7 @@ impl SolanaTrade {
|
||||
// Execute sell based on tip preference
|
||||
let swap_result = executor.swap(sell_params).await;
|
||||
let result =
|
||||
swap_result.map(|(success, sig, err)| (success, sig, err.map(TradeError::from)));
|
||||
swap_result.map(|(success, sigs, err)| (success, sigs, err.map(TradeError::from)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -574,7 +591,7 @@ impl SolanaTrade {
|
||||
mut params: TradeSellParams,
|
||||
amount_token: u64,
|
||||
percent: u64,
|
||||
) -> Result<(bool, Signature, Option<TradeError>), anyhow::Error> {
|
||||
) -> Result<(bool, Vec<Signature>, Option<TradeError>), anyhow::Error> {
|
||||
if percent == 0 || percent > 100 {
|
||||
return Err(anyhow::anyhow!("Percentage must be between 1 and 100"));
|
||||
}
|
||||
|
||||
@@ -37,13 +37,15 @@ pub fn handle_wsol(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 3]>
|
||||
}
|
||||
|
||||
pub fn close_wsol(payer: &Pubkey) -> Vec<Instruction> {
|
||||
use std::sync::Arc;
|
||||
|
||||
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(
|
||||
let arc_instructions = crate::common::fast_fn::get_cached_instructions(
|
||||
crate::common::fast_fn::InstructionCacheKey::CloseWsolAccount {
|
||||
payer: *payer,
|
||||
wsol_token_account,
|
||||
@@ -58,7 +60,10 @@ pub fn close_wsol(payer: &Pubkey) -> Vec<Instruction> {
|
||||
)
|
||||
.unwrap()]
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
// 🚀 性能优化:尝试零开销解包 Arc
|
||||
Arc::try_unwrap(arc_instructions).unwrap_or_else(|arc| (*arc).clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -34,6 +34,7 @@ struct TaskResult {
|
||||
success: bool,
|
||||
signature: Signature,
|
||||
error: Option<anyhow::Error>,
|
||||
swqos_type: SwqosType, // 🔧 增加:记录SWQOS类型
|
||||
}
|
||||
|
||||
struct ResultCollector {
|
||||
@@ -66,24 +67,44 @@ impl ResultCollector {
|
||||
self.completed_count.fetch_add(1, Ordering::Release);
|
||||
}
|
||||
|
||||
async fn wait_for_success(&self) -> Option<(bool, Signature, Option<anyhow::Error>)> {
|
||||
async fn wait_for_success(&self) -> Option<(bool, Vec<Signature>, Option<anyhow::Error>)> {
|
||||
let start = Instant::now();
|
||||
let timeout = std::time::Duration::from_secs(30);
|
||||
|
||||
loop {
|
||||
// 🚀 Acquire 确保看到 push 的内容
|
||||
if self.success_flag.load(Ordering::Acquire) {
|
||||
// 🔧 修复:收集所有签名
|
||||
let mut signatures = Vec::new();
|
||||
let mut has_success = false;
|
||||
while let Some(result) = self.results.pop() {
|
||||
signatures.push(result.signature);
|
||||
if result.success {
|
||||
return Some((true, result.signature, None));
|
||||
has_success = true;
|
||||
}
|
||||
}
|
||||
if has_success && !signatures.is_empty() {
|
||||
return Some((true, signatures, None));
|
||||
}
|
||||
}
|
||||
|
||||
let completed = self.completed_count.load(Ordering::Acquire);
|
||||
if completed >= self.total_tasks {
|
||||
// 🔧 修复:收集所有签名
|
||||
let mut signatures = Vec::new();
|
||||
let mut last_error = None;
|
||||
let mut any_success = false;
|
||||
while let Some(result) = self.results.pop() {
|
||||
return Some((result.success, result.signature, result.error));
|
||||
signatures.push(result.signature);
|
||||
if result.success {
|
||||
any_success = true;
|
||||
}
|
||||
if result.error.is_some() {
|
||||
last_error = result.error;
|
||||
}
|
||||
}
|
||||
if !signatures.is_empty() {
|
||||
return Some((any_success, signatures, last_error));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
@@ -95,15 +116,31 @@ impl ResultCollector {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_first(&self) -> Option<(bool, Signature, Option<anyhow::Error>,)> {
|
||||
if let Some(result) = self.results.pop() {
|
||||
Some((result.success, result.signature, result.error))
|
||||
fn get_first(&self) -> Option<(bool, Vec<Signature>, Option<anyhow::Error>)> {
|
||||
// 🔧 修复:收集已提交的所有签名
|
||||
let mut signatures = Vec::new();
|
||||
let mut has_success = false;
|
||||
let mut last_error = None;
|
||||
|
||||
while let Some(result) = self.results.pop() {
|
||||
signatures.push(result.signature);
|
||||
if result.success {
|
||||
has_success = true;
|
||||
}
|
||||
if result.error.is_some() {
|
||||
last_error = result.error;
|
||||
}
|
||||
}
|
||||
|
||||
if !signatures.is_empty() {
|
||||
Some((has_success, signatures, last_error))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 🔧 修复:返回Vec<Signature>支持多SWQOS并发交易
|
||||
pub async fn execute_parallel(
|
||||
swqos_clients: Vec<Arc<SwqosClient>>,
|
||||
payer: Arc<Keypair>,
|
||||
@@ -119,7 +156,7 @@ pub async fn execute_parallel(
|
||||
wait_transaction_confirmed: bool,
|
||||
with_tip: bool,
|
||||
gas_fee_strategy: GasFeeStrategy,
|
||||
) -> Result<(bool, Signature, Option<anyhow::Error>)> {
|
||||
) -> Result<(bool, Vec<Signature>, Option<anyhow::Error>)> {
|
||||
let _exec_start = Instant::now();
|
||||
|
||||
if swqos_clients.is_empty() {
|
||||
@@ -241,6 +278,7 @@ pub async fn execute_parallel(
|
||||
success: false,
|
||||
signature: Signature::default(),
|
||||
error: Some(e),
|
||||
swqos_type, // 🔧 记录SWQOS类型
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -268,7 +306,12 @@ pub async fn execute_parallel(
|
||||
// Transaction sent
|
||||
|
||||
if let Some(signature) = transaction.signatures.first() {
|
||||
collector.submit(TaskResult { success, signature: *signature, error: err });
|
||||
collector.submit(TaskResult {
|
||||
success,
|
||||
signature: *signature,
|
||||
error: err,
|
||||
swqos_type, // 🔧 记录SWQOS类型
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ impl GenericTradeExecutor {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl TradeExecutor for GenericTradeExecutor {
|
||||
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature, Option<anyhow::Error>)> {
|
||||
async fn swap(&self, params: SwapParams) -> Result<(bool, Vec<Signature>, Option<anyhow::Error>)> {
|
||||
let total_start = Instant::now();
|
||||
|
||||
// 判断买卖方向
|
||||
@@ -152,30 +152,21 @@ impl TradeExecutor for GenericTradeExecutor {
|
||||
let total_elapsed = total_start.elapsed();
|
||||
|
||||
// Get performance metrics using fast timestamp
|
||||
let timestamp_ns = SYSCALL_BYPASS.fast_timestamp_nanos();
|
||||
|
||||
// Print all timing metrics at once to avoid blocking critical path
|
||||
println!("[Timestamp] {}ns", timestamp_ns);
|
||||
println!(
|
||||
"[Build Instructions] Time: {:.3}ms ({:.0}μs)",
|
||||
build_elapsed.as_micros() as f64 / 1000.0,
|
||||
build_elapsed.as_micros()
|
||||
);
|
||||
println!(
|
||||
"[Before Submit] {:.3}ms ({:.0}μs)",
|
||||
before_submit_elapsed.as_micros() as f64 / 1000.0,
|
||||
before_submit_elapsed.as_micros()
|
||||
);
|
||||
println!(
|
||||
"[Send Transaction] Time: {:.3}ms ({:.0}μs)",
|
||||
send_elapsed.as_micros() as f64 / 1000.0,
|
||||
send_elapsed.as_micros()
|
||||
);
|
||||
println!(
|
||||
"[Total Time] {:.3}ms ({:.0}μs)",
|
||||
total_elapsed.as_micros() as f64 / 1000.0,
|
||||
total_elapsed.as_micros()
|
||||
);
|
||||
#[cfg(feature = "perf-trace")]
|
||||
{
|
||||
let timestamp_ns = SYSCALL_BYPASS.fast_timestamp_nanos();
|
||||
log::trace!(
|
||||
"[Execute] timestamp_ns={} build_us={} before_submit_us={} send_us={} total_us={}",
|
||||
timestamp_ns,
|
||||
build_elapsed.as_micros(),
|
||||
before_submit_elapsed.as_micros(),
|
||||
send_elapsed.as_micros(),
|
||||
total_elapsed.as_micros()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "perf-trace"))]
|
||||
let _ = (build_elapsed, before_submit_elapsed, send_elapsed, total_elapsed);
|
||||
|
||||
result
|
||||
}
|
||||
@@ -185,7 +176,7 @@ impl TradeExecutor for GenericTradeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Simulate transaction using RPC client
|
||||
/// 🔧 修复:Simulate模式返回Vec<Signature>(单个RPC模拟)
|
||||
async fn simulate_transaction(
|
||||
rpc: Option<Arc<SolanaRpcClient>>,
|
||||
payer: Arc<Keypair>,
|
||||
@@ -199,7 +190,7 @@ async fn simulate_transaction(
|
||||
is_buy: bool,
|
||||
with_tip: bool,
|
||||
gas_fee_strategy: GasFeeStrategy,
|
||||
) -> Result<(bool, Signature, Option<anyhow::Error>)> {
|
||||
) -> Result<(bool, Vec<Signature>, Option<anyhow::Error>)> {
|
||||
use crate::trading::common::build_transaction;
|
||||
use solana_client::rpc_config::RpcSimulateTransactionConfig;
|
||||
use solana_commitment_config::CommitmentLevel;
|
||||
@@ -267,44 +258,30 @@ async fn simulate_transaction(
|
||||
.clone();
|
||||
|
||||
if let Some(err) = simulate_result.value.err {
|
||||
println!("\n========== [Simulation Failed] ==========");
|
||||
println!("Error Type: {:?}", err);
|
||||
println!("Signature: {:?}", signature);
|
||||
|
||||
// Print logs
|
||||
if let Some(logs) = simulate_result.value.logs {
|
||||
println!("\n========== Transaction Logs ==========");
|
||||
for (i, log) in logs.iter().enumerate() {
|
||||
println!("{:3}. {}", i + 1, log);
|
||||
#[cfg(feature = "perf-trace")]
|
||||
{
|
||||
log::warn!("[Simulation Failed] error={:?} signature={:?}", err, signature);
|
||||
if let Some(logs) = &simulate_result.value.logs {
|
||||
log::trace!("Transaction logs: {:?}", logs);
|
||||
}
|
||||
if let Some(units_consumed) = simulate_result.value.units_consumed {
|
||||
log::trace!("Compute Units Consumed: {}", units_consumed);
|
||||
}
|
||||
}
|
||||
|
||||
// Print account usage
|
||||
if let Some(units_consumed) = simulate_result.value.units_consumed {
|
||||
println!("\n========== Resource Consumption ==========");
|
||||
println!("Compute Units Consumed: {}", units_consumed);
|
||||
}
|
||||
|
||||
println!("=========================================\n");
|
||||
return Ok((false, signature, Some(anyhow::anyhow!("{:?}", err))));
|
||||
return Ok((false, vec![signature], Some(anyhow::anyhow!("{:?}", err))));
|
||||
}
|
||||
|
||||
// Simulation succeeded
|
||||
println!("\n========== [Simulation Succeeded] ==========");
|
||||
println!("Signature: {:?}", signature);
|
||||
|
||||
if let Some(units_consumed) = simulate_result.value.units_consumed {
|
||||
println!("Compute Units Consumed: {}", units_consumed);
|
||||
}
|
||||
|
||||
if let Some(logs) = simulate_result.value.logs {
|
||||
println!("\n========== Transaction Logs ==========");
|
||||
for (i, log) in logs.iter().enumerate() {
|
||||
println!("{:3}. {}", i + 1, log);
|
||||
#[cfg(feature = "perf-trace")]
|
||||
{
|
||||
log::info!("[Simulation Succeeded] signature={:?}", signature);
|
||||
if let Some(units_consumed) = simulate_result.value.units_consumed {
|
||||
log::trace!("Compute Units Consumed: {}", units_consumed);
|
||||
}
|
||||
if let Some(logs) = &simulate_result.value.logs {
|
||||
log::trace!("Transaction logs: {:?}", logs);
|
||||
}
|
||||
}
|
||||
|
||||
println!("============================================\n");
|
||||
|
||||
Ok((true, signature, None))
|
||||
Ok((true, vec![signature], None))
|
||||
}
|
||||
|
||||
+28
-63
@@ -1,4 +1,3 @@
|
||||
use super::traits::ProtocolParams;
|
||||
use crate::common::bonding_curve::BondingCurveAccount;
|
||||
use crate::common::nonce_cache::DurableNonceInfo;
|
||||
use crate::common::spl_associated_token_account::get_associated_token_address_with_program_id;
|
||||
@@ -14,6 +13,32 @@ use solana_sdk::message::AddressLookupTableAccount;
|
||||
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// DEX 参数枚举 - 零开销抽象替代 Box<dyn ProtocolParams>
|
||||
#[derive(Clone)]
|
||||
pub enum DexParamEnum {
|
||||
PumpFun(PumpFunParams),
|
||||
PumpSwap(PumpSwapParams),
|
||||
Bonk(BonkParams),
|
||||
RaydiumCpmm(RaydiumCpmmParams),
|
||||
RaydiumAmmV4(RaydiumAmmV4Params),
|
||||
MeteoraDammV2(MeteoraDammV2Params),
|
||||
}
|
||||
|
||||
impl DexParamEnum {
|
||||
/// 获取内部参数的 Any 引用,用于向后兼容的类型检查
|
||||
#[inline]
|
||||
pub fn as_any(&self) -> &dyn std::any::Any {
|
||||
match self {
|
||||
DexParamEnum::PumpFun(p) => p,
|
||||
DexParamEnum::PumpSwap(p) => p,
|
||||
DexParamEnum::Bonk(p) => p,
|
||||
DexParamEnum::RaydiumCpmm(p) => p,
|
||||
DexParamEnum::RaydiumAmmV4(p) => p,
|
||||
DexParamEnum::MeteoraDammV2(p) => p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Swap parameters
|
||||
#[derive(Clone)]
|
||||
pub struct SwapParams {
|
||||
@@ -30,7 +55,7 @@ pub struct SwapParams {
|
||||
pub recent_blockhash: Option<Hash>,
|
||||
pub data_size_limit: u32,
|
||||
pub wait_transaction_confirmed: bool,
|
||||
pub protocol_params: Box<dyn ProtocolParams>,
|
||||
pub protocol_params: DexParamEnum,
|
||||
pub open_seed_optimize: bool,
|
||||
pub swqos_clients: Vec<Arc<SwqosClient>>,
|
||||
pub middleware_manager: Option<Arc<MiddlewareManager>>,
|
||||
@@ -47,7 +72,7 @@ pub struct SwapParams {
|
||||
|
||||
impl std::fmt::Debug for SwapParams {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SwapParams: {:?}", self)
|
||||
write!(f, "SwapParams: ...")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,16 +203,6 @@ impl PumpFunParams {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for PumpFunParams {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// PumpSwap Protocol Specific Parameters
|
||||
///
|
||||
/// Parameters for configuring PumpSwap trading protocol, including liquidity pool information,
|
||||
@@ -326,16 +341,6 @@ impl PumpSwapParams {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for PumpSwapParams {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Bonk protocol specific parameters
|
||||
/// Configuration parameters specific to Bonk trading protocol
|
||||
#[derive(Clone, Default)]
|
||||
@@ -512,16 +517,6 @@ impl BonkParams {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for BonkParams {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// RaydiumCpmm protocol specific parameters
|
||||
/// Configuration parameters specific to Raydium CPMM trading protocol
|
||||
#[derive(Clone)]
|
||||
@@ -609,16 +604,6 @@ impl RaydiumCpmmParams {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for RaydiumCpmmParams {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// RaydiumCpmm protocol specific parameters
|
||||
/// Configuration parameters specific to Raydium CPMM trading protocol
|
||||
#[derive(Clone)]
|
||||
@@ -670,16 +655,6 @@ impl RaydiumAmmV4Params {
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for RaydiumAmmV4Params {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// MeteoraDammV2 protocol specific parameters
|
||||
/// Configuration parameters specific to Meteora Damm V2 trading protocol
|
||||
#[derive(Clone)]
|
||||
@@ -731,13 +706,3 @@ impl MeteoraDammV2Params {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ProtocolParams for MeteoraDammV2Params {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ use solana_sdk::{instruction::Instruction, signature::Signature};
|
||||
/// 交易执行器trait - 定义了所有交易协议都需要实现的核心方法
|
||||
#[async_trait::async_trait]
|
||||
pub trait TradeExecutor: Send + Sync {
|
||||
async fn swap(&self, params: SwapParams) -> Result<(bool, Signature, Option<anyhow::Error>)>;
|
||||
/// 🔧 修复:返回Vec<Signature>支持多SWQOS并发交易
|
||||
/// - bool: 是否至少有一个交易成功
|
||||
/// - Vec<Signature>: 所有提交的交易签名(按SWQOS顺序)
|
||||
/// - Option<anyhow::Error>: 最后一个错误(如果全部失败)
|
||||
async fn swap(&self, params: SwapParams) -> Result<(bool, Vec<Signature>, Option<anyhow::Error>)>;
|
||||
/// 获取协议名称
|
||||
fn protocol_name(&self) -> &'static str;
|
||||
}
|
||||
@@ -19,18 +23,3 @@ pub trait InstructionBuilder: Send + Sync {
|
||||
/// 构建卖出指令
|
||||
async fn build_sell_instructions(&self, params: &SwapParams) -> Result<Vec<Instruction>>;
|
||||
}
|
||||
|
||||
/// 协议特定参数trait - 允许每个协议定义自己的参数
|
||||
pub trait ProtocolParams: Send + Sync {
|
||||
/// 将参数转换为Any以便向下转型
|
||||
fn as_any(&self) -> &dyn std::any::Any;
|
||||
|
||||
/// 克隆参数
|
||||
fn clone_box(&self) -> Box<dyn ProtocolParams>;
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn ProtocolParams> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::instruction::{
|
||||
use super::core::{executor::GenericTradeExecutor, traits::TradeExecutor};
|
||||
|
||||
/// 支持的交易协议
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DexType {
|
||||
PumpFun,
|
||||
PumpSwap,
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
pub mod calc;
|
||||
pub mod price;
|
||||
use crate::trading;
|
||||
use crate::SolanaTrade;
|
||||
use crate::TradingClient;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Keypair;
|
||||
use solana_sdk::signer::Signer;
|
||||
|
||||
impl SolanaTrade {
|
||||
impl TradingClient {
|
||||
#[inline]
|
||||
pub async fn get_sol_balance(&self, payer: &Pubkey) -> Result<u64, anyhow::Error> {
|
||||
trading::common::utils::get_sol_balance(&self.rpc, payer).await
|
||||
|
||||
Reference in New Issue
Block a user