refactor: Major SDK architecture refactoring and API consolidation

- Consolidate separate buy/sell modules into unified trading interface
- Remove protocol-specific buy/sell files (bonk, pumpfun, pumpswap)
- Add new trading constants and utility functions
- Simplify API with unified buy/sell methods supporting multiple protocols
- Enhance documentation with comprehensive examples and usage guides
- Add balance checking and token account management utilities
- Improve code organization and maintainability
This commit is contained in:
ysq
2025-07-10 18:14:21 +08:00
parent 57c2848a57
commit b891b2bc27
41 changed files with 1297 additions and 2744 deletions
-107
View File
@@ -1,107 +0,0 @@
use solana_hash::Hash;
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use std::sync::Arc;
use crate::swqos::SwqosClient;
use crate::trading::{
core::params::{PumpSwapParams, BonkParams},
factory::Protocol,
BuyParams, TradeFactory,
};
use crate::{common::PriorityFee, SolanaRpcClient};
// Constants for compute budget
// Increased from 64KB to 256KB to handle larger transactions
const MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT: u32 = 256 * 1024;
// Buy tokens from a Pumpswap pool
pub async fn buy(
rpc: Arc<SolanaRpcClient>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount_sol: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
auto_handle_wsol: bool,
) -> Result<(), anyhow::Error> {
// 创建执行器
let executor = TradeFactory::create_executor(Protocol::Bonk);
// 创建协议特定参数
let protocol_params = Box::new(BonkParams {
auto_handle_wsol: auto_handle_wsol,
virtual_base: Some(virtual_base),
virtual_quote: Some(virtual_quote),
real_base_before: Some(real_base_before),
real_quote_before: Some(real_quote_before),
});
// 创建买入参数
let buy_params = BuyParams {
rpc: Some(rpc.clone()),
payer: payer,
mint: mint,
creator: Pubkey::default(),
amount_sol: amount_sol,
slippage_basis_points: slippage_basis_points,
priority_fee: priority_fee,
lookup_table_key: lookup_table_key,
recent_blockhash: recent_blockhash,
data_size_limit: MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT,
protocol_params,
};
// 执行买入
executor.buy(buy_params).await?;
Ok(())
}
// Buy tokens using a MEV service
pub async fn buy_with_tip(
rpc: Arc<SolanaRpcClient>,
swqos_clients: Vec<Arc<SwqosClient>>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount_sol: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
auto_handle_wsol: bool,
) -> Result<(), anyhow::Error> {
// 创建执行器
let executor = TradeFactory::create_executor(Protocol::Bonk);
// 创建协议特定参数
let protocol_params = Box::new(BonkParams {
auto_handle_wsol: auto_handle_wsol,
virtual_base: Some(virtual_base),
virtual_quote: Some(virtual_quote),
real_base_before: Some(real_base_before),
real_quote_before: Some(real_quote_before),
});
// 创建买入参数
let buy_params = BuyParams {
rpc: Some(rpc.clone()),
payer: payer,
mint: mint,
creator: Pubkey::default(),
amount_sol: amount_sol,
slippage_basis_points: slippage_basis_points,
priority_fee: priority_fee,
lookup_table_key: lookup_table_key,
recent_blockhash: recent_blockhash,
data_size_limit: MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT,
protocol_params,
};
let buy_with_tip_params = buy_params.with_tip(swqos_clients);
// 执行买入
executor.buy_with_tip(buy_with_tip_params).await?;
Ok(())
}
+2 -21
View File
@@ -1,8 +1,5 @@
use anyhow::anyhow;
use solana_sdk::pubkey::Pubkey;
use spl_associated_token_account::get_associated_token_address;
use crate::{common::SolanaRpcClient, constants};
use crate::constants;
pub fn get_amount_out(
amount_in: u64,
@@ -56,20 +53,4 @@ pub fn get_vault_pda(pool_state: &Pubkey, mint: &Pubkey) -> Option<Pubkey> {
let program_id: &Pubkey = &constants::bonk::accounts::BONK;
let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id);
pda.map(|pubkey| pubkey.0)
}
pub async fn get_token_balance(
rpc: &SolanaRpcClient,
payer: &Pubkey,
mint: &Pubkey,
) -> Result<u64, anyhow::Error> {
println!("payer: {:?}", payer);
println!("mint: {:?}", mint);
let ata = get_associated_token_address(payer, mint);
let balance = rpc.get_token_account_balance(&ata).await?;
let balance_u64 = balance
.amount
.parse::<u64>()
.map_err(|_| anyhow!("Failed to parse token balance"))?;
Ok(balance_u64)
}
}
-2
View File
@@ -1,4 +1,2 @@
pub mod buy;
pub mod sell;
pub mod common;
pub mod pool;
-241
View File
@@ -1,241 +0,0 @@
use anyhow::anyhow;
use solana_hash::Hash;
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use solana_sdk::signature::Signer;
use std::sync::Arc;
use crate::common::{PriorityFee, SolanaRpcClient};
use crate::trading::bonk::common::get_token_balance;
use crate::swqos::SwqosClient;
use crate::trading::{
core::params::BonkParams, factory::Protocol, SellParams, TradeFactory,
};
// Sell tokens to a Pumpswap pool
pub async fn sell(
rpc: Arc<SolanaRpcClient>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount_token: Option<u64>,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
let executor = TradeFactory::create_executor(Protocol::Bonk);
// 创建PumpFun协议参数
let protocol_params = Box::new(BonkParams {
virtual_base: Some(virtual_base),
virtual_quote: Some(virtual_quote),
real_base_before: Some(real_base_before),
real_quote_before: Some(real_quote_before),
auto_handle_wsol: true,
});
// 创建卖出参数
let sell_params = SellParams {
rpc: Some(rpc.clone()),
payer: payer.clone(),
mint,
creator: Pubkey::default(),
amount_token: amount_token,
slippage_basis_points: slippage_basis_points,
priority_fee: priority_fee.clone(),
lookup_table_key,
recent_blockhash,
protocol_params,
};
// 执行卖出交易
executor.sell(sell_params).await?;
Ok(())
}
// Sell tokens by percentage
pub async fn sell_by_percent(
rpc: Arc<SolanaRpcClient>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
percent: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
if percent == 0 || percent > 100 {
return Err(anyhow!("Percentage must be between 1 and 100"));
}
let balance_u64 = get_token_balance(&rpc, &payer.pubkey(), &mint).await?;
let amount = balance_u64 * percent / 100;
sell(
rpc,
payer,
mint,
virtual_base,
virtual_quote,
real_base_before,
real_quote_before,
Some(amount),
slippage_basis_points,
priority_fee,
lookup_table_key,
recent_blockhash,
)
.await
}
/// Sell tokens by amount
pub async fn sell_by_amount(
rpc: Arc<SolanaRpcClient>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
sell(
rpc,
payer,
mint,
virtual_base,
virtual_quote,
real_base_before,
real_quote_before,
Some(amount),
slippage_basis_points,
priority_fee,
lookup_table_key,
recent_blockhash,
)
.await
}
// Sell tokens using a MEV service
pub async fn sell_with_tip(
rpc: Arc<SolanaRpcClient>,
swqos_clients: Vec<Arc<SwqosClient>>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount_token: Option<u64>,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
let executor = TradeFactory::create_executor(Protocol::Bonk);
// 创建PumpFun协议参数
let protocol_params = Box::new(BonkParams {
virtual_base: Some(virtual_base),
virtual_quote: Some(virtual_quote),
real_base_before: Some(real_base_before),
real_quote_before: Some(real_quote_before),
auto_handle_wsol: true,
});
// 创建卖出参数
let sell_params = SellParams {
rpc: Some(rpc.clone()),
payer: payer.clone(),
mint,
creator: Pubkey::default(),
amount_token: amount_token,
slippage_basis_points: slippage_basis_points,
priority_fee: priority_fee.clone(),
lookup_table_key,
recent_blockhash,
protocol_params,
};
let sell_with_tip_params = sell_params.with_tip(swqos_clients);
// 执行卖出交易
executor.sell_with_tip(sell_with_tip_params).await?;
Ok(())
}
// Sell tokens by percentage using a MEV service
pub async fn sell_by_percent_with_tip(
rpc: Arc<SolanaRpcClient>,
swqos_clients: Vec<Arc<SwqosClient>>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
percent: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
if percent == 0 || percent > 100 {
return Err(anyhow!("Percentage must be between 1 and 100"));
}
let balance_u64 = get_token_balance(&rpc, &payer.pubkey(), &mint).await?;
let amount = balance_u64 * percent / 100;
sell_with_tip(
rpc,
swqos_clients,
payer,
mint,
virtual_base,
virtual_quote,
real_base_before,
real_quote_before,
Some(amount),
slippage_basis_points,
priority_fee,
lookup_table_key,
recent_blockhash,
)
.await
}
// Sell tokens by amount using a MEV service
pub async fn sell_by_amount_with_tip(
rpc: Arc<SolanaRpcClient>,
swqos_clients: Vec<Arc<SwqosClient>>,
payer: Arc<Keypair>,
mint: Pubkey,
virtual_base: u128,
virtual_quote: u128,
real_base_before: u128,
real_quote_before: u128,
amount: u64,
slippage_basis_points: Option<u64>,
priority_fee: PriorityFee,
lookup_table_key: Option<Pubkey>,
recent_blockhash: Hash,
) -> Result<(), anyhow::Error> {
sell_with_tip(
rpc,
swqos_clients,
payer,
mint,
virtual_base,
virtual_quote,
real_base_before,
real_quote_before,
Some(amount),
slippage_basis_points,
priority_fee,
lookup_table_key,
recent_blockhash,
)
.await
}