Files
sol-trade-sdk/test_latency.sh
T

308 lines
10 KiB
Bash
Raw Normal View History

2025-10-06 23:40:27 +08:00
#!/bin/bash
# PumpFun 真实买入延迟测试
# 测试从调用buy到提交交易的完整流程
set -e
echo "================================"
echo " PumpFun 真实买入延迟测试"
echo "================================"
echo ""
# 检查 pkg-config
if ! command -v pkg-config &> /dev/null; then
echo "❌ 错误: 缺少 pkg-config"
echo ""
echo "请先安装 pkg-config:"
echo " brew install pkg-config"
echo ""
exit 1
fi
# 使用临时生成的私钥
if [ -z "$PAYER_KEYPAIR" ]; then
echo "📝 未设置PAYER_KEYPAIR,将在测试代码中生成临时密钥对"
PAYER_KEYPAIR="GENERATE_NEW" # 标记让测试代码生成新密钥对
else
echo "📝 使用用户提供的PAYER_KEYPAIR"
fi
# 使用真实的 PumpFun 代币
TEST_MINT=${TEST_MINT:-"Dna9Y9VwbFTfFzB4kN1hAbsMfPuwGHmrfD6LUQL2pump"}
echo "🪙 测试代币: $TEST_MINT"
RPC_URL=${RPC_URL:-"https://api.mainnet-beta.solana.com"}
echo "📡 RPC地址: $RPC_URL"
# SWQOS配置 - 4个并发发送节点
SWQOS_JITO=${SWQOS_JITO:-"https://mainnet.block-engine.jito.wtf/api/v1/transactions"}
SWQOS_BLOXROUTE=${SWQOS_BLOXROUTE:-"https://ny.solana.dex.blxrbdn.com"}
SWQOS_NEXTBLOCK=${SWQOS_NEXTBLOCK:-"https://api.nextblock.io/v1/solana"}
SWQOS_FLASHBLOCK=${SWQOS_FLASHBLOCK:-"https://api.flashblock.io/v1/solana"}
echo "🚀 SWQOS节点数: 4 (Jito, Bloxroute, NextBlock, FlashBlock)"
# 买入金额 (lamports, 默认0.001 SOL)
BUY_AMOUNT=${BUY_AMOUNT:-1000000}
echo "💰 买入金额: $BUY_AMOUNT lamports (0.001 SOL)"
# 滑点
SLIPPAGE=${SLIPPAGE:-1000}
echo "📊 滑点: $SLIPPAGE basis points (10%)"
# 设置日志级别
export RUST_LOG=${RUST_LOG:-"info,sol_trade_sdk=debug"}
echo "📊 日志级别: $RUST_LOG"
echo ""
echo "⚠️ 注意: 此测试使用临时生成的密钥对(无余额)"
echo " 测试目的: 验证交易构建和提交流程的延迟"
echo " 交易预期失败(余额不足),但会测量完整的性能数据"
echo ""
# 导出环境变量
export PAYER_KEYPAIR
export RPC_URL
export TEST_MINT
export BUY_AMOUNT
export SLIPPAGE
export SWQOS_JITO
export SWQOS_BLOXROUTE
export SWQOS_NEXTBLOCK
export SWQOS_FLASHBLOCK
# 清理可能存在的旧目录
rm -rf examples/pumpfun_buy_test
# 创建测试程序目录
mkdir -p examples/pumpfun_buy_test/src
# 创建测试程序
cat > examples/pumpfun_buy_test/src/main.rs << 'EOF'
use sol_trade_sdk::{
common::{TradeConfig, AnyResult},
constants::TOKEN_PROGRAM,
2025-10-06 23:40:27 +08:00
swqos::{SwqosConfig, SwqosRegion},
trading::{core::params::PumpFunParams, factory::DexType},
SolanaTrade, TradeTokenType, TradeBuyParams,
};
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{signature::{Keypair, Signer}, pubkey::Pubkey};
use std::sync::Arc;
use std::env;
#[tokio::main]
async fn main() -> AnyResult<()> {
env_logger::init();
println!("\n🚀 初始化 PumpFun 交易客户端...\n");
// 生成临时测试密钥对
let payer_key = env::var("PAYER_KEYPAIR").unwrap_or_else(|_| "GENERATE_NEW".to_string());
let payer = if payer_key == "GENERATE_NEW" {
println!("📝 生成临时测试密钥对...");
Keypair::new()
} else {
Keypair::from_base58_string(&payer_key)
};
println!("📝 钱包地址: {}", payer.pubkey());
let rpc_url = env::var("RPC_URL").unwrap_or_else(|_| "https://api.mainnet-beta.solana.com".to_string());
let commitment = CommitmentConfig::confirmed();
// 配置4个SWQOS节点并发发送
let swqos_configs: Vec<SwqosConfig> = vec![
SwqosConfig::Jito(
String::new(), // uuid
SwqosRegion::Default,
Some(env::var("SWQOS_JITO").unwrap_or_else(|_| "https://mainnet.block-engine.jito.wtf/api/v1/transactions".to_string()))
),
SwqosConfig::Bloxroute(
String::new(), // api_token
SwqosRegion::Default,
Some(env::var("SWQOS_BLOXROUTE").unwrap_or_else(|_| "https://ny.solana.dex.blxrbdn.com".to_string()))
),
SwqosConfig::NextBlock(
String::new(), // api_token
SwqosRegion::Default,
Some(env::var("SWQOS_NEXTBLOCK").unwrap_or_else(|_| "https://api.nextblock.io/v1/solana".to_string()))
),
SwqosConfig::FlashBlock(
String::new(), // api_token
SwqosRegion::Default,
Some(env::var("SWQOS_FLASHBLOCK").unwrap_or_else(|_| "https://api.flashblock.io/v1/solana".to_string()))
),
];
println!("🚀 SWQOS配置: {} 个并发节点", swqos_configs.len());
let trade_config = TradeConfig::new(rpc_url, swqos_configs, commitment);
let client = SolanaTrade::new(Arc::new(payer), trade_config).await;
// 设置 PumpFun 的 gas 策略
sol_trade_sdk::common::GasFeeStrategy::set_global_fee_strategy(200000, 1000000, 0.005, 0.01);
println!("✅ 客户端初始化完成\n");
let mint_str = env::var("TEST_MINT").expect("TEST_MINT not set");
let mint = mint_str.parse().expect("Invalid mint address");
let buy_amount = env::var("BUY_AMOUNT")
.unwrap_or_else(|_| "1000000".to_string())
.parse::<u64>()
.expect("Invalid buy amount");
let slippage = env::var("SLIPPAGE")
.unwrap_or_else(|_| "1000".to_string())
.parse::<u64>()
.expect("Invalid slippage");
println!("🔍 获取最新区块哈希...");
let recent_blockhash = client.rpc.get_latest_blockhash().await?;
println!("✅ 区块哈希: {}\n", recent_blockhash);
println!("================================");
println!(" PumpFun 买入延迟测试");
println!("================================");
println!("🪙 代币: {}", mint);
println!("💰 金额: {} lamports", buy_amount);
println!("📊 滑点: {} basis points", slippage);
println!("================================\n");
// PumpFun买入参数 (占位;实际路径应使用 RPC 或事件填充)
2025-10-06 23:40:27 +08:00
let params = PumpFunParams::from_trade(
Pubkey::default(), // bonding_curve
Pubkey::default(), // associated_bonding_curve
mint, // mint
Pubkey::default(), // creator
Pubkey::default(), // creator_vault
0, // virtual_token_reserves
0, // virtual_sol_reserves
0, // real_token_reserves
0, // real_sol_reserves
None, // close_token_account_when_sell
Pubkey::default(), // fee_recipient
TOKEN_PROGRAM,
false, // is_cashback_coin
None, // mayhem_modeNone=按 fee_recipient 推断)
2025-10-06 23:40:27 +08:00
);
let buy_params = TradeBuyParams {
dex_type: DexType::PumpFun,
input_token_type: TradeTokenType::SOL,
mint,
input_token_amount: buy_amount,
slippage_basis_points: Some(slippage),
recent_blockhash: Some(recent_blockhash),
extension_params: Box::new(params),
address_lookup_table_account: None,
2025-10-06 23:40:27 +08:00
wait_transaction_confirmed: false, // 不等待确认,测试最快提交速度
create_input_token_ata: true,
close_input_token_ata: true,
create_mint_ata: true,
open_seed_optimize: false,
durable_nonce: None,
fixed_output_token_amount: None,
};
println!("⏱️ 开始执行买入流程...");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
match client.buy(buy_params).await {
Ok((success, signature)) => {
println!("\n================================");
println!(" ✅ 买入流程完成");
println!("================================");
println!("✅ 提交成功: {}", success);
println!("📝 签名: {}", signature);
println!("================================\n");
}
Err(e) => {
println!("\n================================");
println!(" ⚠️ 买入流程完成(交易失败)");
println!("================================");
println!("️ 错误: {:?}", e);
println!("\n💡 说明: 交易失败是预期的(测试账户无余额)");
println!(" 耗时统计见上方SDK日志输出");
println!("================================\n");
}
}
// 显示性能统计
println!("================================");
println!(" 性能优化模块状态");
println!("================================\n");
use sol_trade_sdk::swqos::serialization::get_serializer_stats;
let (available, capacity) = get_serializer_stats();
println!("📦 序列化器缓冲池:");
println!(" 容量: {}", capacity);
println!(" 可用: {}", available);
println!(" 使用: {}", capacity - available);
use sol_trade_sdk::trading::core::transaction_pool::get_pool_stats;
let (pool_available, pool_capacity) = get_pool_stats();
println!("\n🔧 交易构建器池:");
println!(" 容量: {}", pool_capacity);
println!(" 可用: {}", pool_available);
println!(" 使用: {}", pool_capacity - pool_available);
println!("\n================================");
println!("✅ 延迟测试完成!");
println!("================================\n");
println!("💡 提示: 查看上面的日志了解各环节详细耗时");
println!(" 日志中包含每个步骤的 step 和 total 时间\n");
Ok(())
}
EOF
# 创建 Cargo.toml
cat > examples/pumpfun_buy_test/Cargo.toml << 'EOF'
[package]
name = "pumpfun_buy_test"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "pumpfun_buy_test"
path = "src/main.rs"
[dependencies]
sol-trade-sdk = { path = "../.." }
solana-sdk = "3.0.0"
solana-commitment-config = "3.0.0"
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"
env_logger = "0.11"
EOF
# 添加到workspace
if ! grep -q "examples/pumpfun_buy_test" Cargo.toml; then
sed -i.bak '/members = \[/a\
"examples/pumpfun_buy_test",
' Cargo.toml
rm -f Cargo.toml.bak
fi
echo "================================"
echo " 开始编译和运行测试..."
echo "================================"
echo ""
# 编译并运行
cargo run --release -p pumpfun_buy_test
# 从workspace中移除
sed -i.bak '/examples\/pumpfun_buy_test/d' Cargo.toml
rm -f Cargo.toml.bak
# 清理
echo ""
echo "清理测试文件..."
rm -rf examples/pumpfun_buy_test
echo ""
echo "================================"
echo " 测试完成"
echo "================================"