diff --git a/README.md b/README.md index ad56534..76592af 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: slippage_basis_points, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(params.clone()), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, diff --git a/README_CN.md b/README_CN.md index e509429..345ae4e 100755 --- a/README_CN.md +++ b/README_CN.md @@ -151,7 +151,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: slippage_basis_points, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(params.clone()), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, diff --git a/docs/ADDRESS_LOOKUP_TABLE.md b/docs/ADDRESS_LOOKUP_TABLE.md index d1e72e4..a0ad565 100644 --- a/docs/ADDRESS_LOOKUP_TABLE.md +++ b/docs/ADDRESS_LOOKUP_TABLE.md @@ -15,36 +15,11 @@ Address Lookup Tables are a Solana feature that allows you to store frequently u ## 🛠️ Implementation -### 1. Setting up Address Lookup Table Cache - -The SDK provides a global cache to manage address lookup tables: - -```rust -use sol_trade_sdk::common::address_lookup_cache::AddressLookupTableCache; -use solana_sdk::pubkey::Pubkey; -use std::str::FromStr; - -/// Setup lookup table cache -async fn setup_lookup_table_cache( - client: Arc, - lookup_table_address: Pubkey, -) -> AnyResult<()> { - AddressLookupTableCache::get_instance() - .set_address_lookup_table(client, &lookup_table_address) - .await - .map_err(|e| anyhow::anyhow!("Failed to set address lookup table: {}", e))?; - Ok(()) -} -``` - -### 2. Using Lookup Tables in Trade Parameters - Include lookup tables in your trade parameters: ```rust -// Initialize lookup table -let lookup_table_key = Pubkey::from_str("your_lookup_table_address_here").unwrap(); -setup_lookup_table_cache(client.rpc.clone(), lookup_table_key).await?; +let lookup_table_key = Pubkey::from_str("use_your_lookup_table_key_here").unwrap(); +let address_lookup_table_account = fetch_address_lookup_table_account(&client.rpc, &lookup_table_key).await.ok(); // Include lookup table in trade parameters let buy_params = sol_trade_sdk::TradeBuyParams { @@ -54,7 +29,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: Some(100), recent_blockhash: Some(recent_blockhash), extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)), - lookup_table_key: Some(lookup_table_key), // Include lookup table + address_lookup_table_account: address_lookup_table_account, // Include lookup table wait_transaction_confirmed: true, create_wsol_ata: false, close_wsol_ata: false, @@ -78,7 +53,6 @@ client.buy(buy_params).await?; ## ⚠️ Important Notes 1. **Lookup Table Address**: Must provide a valid address lookup table address -2. **Cache Management**: SDK automatically manages lookup table cache 3. **RPC Compatibility**: Ensure your RPC provider supports lookup tables 4. **Network Specific**: Lookup tables are network-specific (mainnet/devnet/testnet) 5. **Testing**: Always test on devnet before using on mainnet diff --git a/docs/ADDRESS_LOOKUP_TABLE_CN.md b/docs/ADDRESS_LOOKUP_TABLE_CN.md index 71aaf7b..069a07b 100644 --- a/docs/ADDRESS_LOOKUP_TABLE_CN.md +++ b/docs/ADDRESS_LOOKUP_TABLE_CN.md @@ -15,36 +15,11 @@ ## 🛠️ 实现方法 -### 1. 设置地址查找表缓存 - -SDK 提供了一个全局缓存来管理地址查找表: - -```rust -use sol_trade_sdk::common::address_lookup_cache::AddressLookupTableCache; -use solana_sdk::pubkey::Pubkey; -use std::str::FromStr; - -/// 设置查找表缓存 -async fn setup_lookup_table_cache( - client: Arc, - lookup_table_address: Pubkey, -) -> AnyResult<()> { - AddressLookupTableCache::get_instance() - .set_address_lookup_table(client, &lookup_table_address) - .await - .map_err(|e| anyhow::anyhow!("Failed to set address lookup table: {}", e))?; - Ok(()) -} -``` - -### 2. 在交易参数中使用查找表 - 在您的交易参数中包含查找表: ```rust -// 初始化查找表 -let lookup_table_key = Pubkey::from_str("your_lookup_table_address_here").unwrap(); -setup_lookup_table_cache(client.rpc.clone(), lookup_table_key).await?; +let lookup_table_key = Pubkey::from_str("use_your_lookup_table_key_here").unwrap(); +let address_lookup_table_account = fetch_address_lookup_table_account(&client.rpc, &lookup_table_key).await.ok(); // 在交易参数中包含查找表 let buy_params = sol_trade_sdk::TradeBuyParams { @@ -54,7 +29,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: Some(100), recent_blockhash: Some(recent_blockhash), extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)), - lookup_table_key: Some(lookup_table_key), // 包含查找表 + address_lookup_table_account: address_lookup_table_account, // 包含查找表 wait_transaction_confirmed: true, create_wsol_ata: false, close_wsol_ata: false, @@ -78,7 +53,6 @@ client.buy(buy_params).await?; ## ⚠️ 重要注意事项 1. **查找表地址**: 必须提供有效的地址查找表地址 -2. **缓存管理**: SDK 自动管理查找表缓存 3. **RPC 兼容性**: 确保您的 RPC 提供商支持查找表 4. **网络**: 查找表是特定于网络的(主网/开发网/测试网) 5. **测试**: 在主网使用前请务必在开发网测试 diff --git a/docs/NONCE_CACHE.md b/docs/NONCE_CACHE.md index 735ee4a..a133f05 100644 --- a/docs/NONCE_CACHE.md +++ b/docs/NONCE_CACHE.md @@ -57,7 +57,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: Some(100), recent_blockhash: Some(recent_blockhash), extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_wsol_ata: false, close_wsol_ata: false, diff --git a/docs/NONCE_CACHE_CN.md b/docs/NONCE_CACHE_CN.md index 36f8b5e..538ba02 100644 --- a/docs/NONCE_CACHE_CN.md +++ b/docs/NONCE_CACHE_CN.md @@ -57,7 +57,7 @@ let buy_params = sol_trade_sdk::TradeBuyParams { slippage_basis_points: Some(100), recent_blockhash: Some(recent_blockhash), extension_params: Box::new(PumpFunParams::from_trade(&trade_info, None)), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_wsol_ata: false, close_wsol_ata: false, diff --git a/docs/TRADING_PARAMETERS.md b/docs/TRADING_PARAMETERS.md index 15f3283..335c4cb 100644 --- a/docs/TRADING_PARAMETERS.md +++ b/docs/TRADING_PARAMETERS.md @@ -29,7 +29,7 @@ The `TradeBuyParams` struct contains all parameters required for executing buy o | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `lookup_table_key` | `Option` | ❌ | Address lookup table key for transaction optimization | +| `address_lookup_table_account` | `Option` | ❌ | Address lookup table for transaction optimization | | `wait_transaction_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | | `create_input_token_ata` | `bool` | ✅ | Whether to create input token Associated Token Account | | `close_input_token_ata` | `bool` | ✅ | Whether to close input token ATA after transaction | @@ -60,7 +60,7 @@ The `TradeSellParams` struct contains all parameters required for executing sell | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `lookup_table_key` | `Option` | ❌ | Address lookup table key for transaction optimization | +| `address_lookup_table_account` | `Option` | ❌ | Address lookup table for transaction optimization | | `wait_transaction_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation | | `create_output_token_ata` | `bool` | ✅ | Whether to create output token Associated Token Account | | `close_output_token_ata` | `bool` | ✅ | Whether to close output token ATA after transaction | @@ -100,7 +100,7 @@ These parameters control automatic account creation and management: These parameters enable advanced optimizations: -- **lookup_table_key**: Use address lookup tables for reduced transaction size +- **address_lookup_table_account**: Use address lookup tables for reduced transaction size - **open_seed_optimize**: Use seed-based account creation for lower CU consumption ### 🔄 Token Type Parameters @@ -134,8 +134,7 @@ The account management parameters provide granular control: ### 🔍 Address Lookup Tables -Before using `lookup_table_key`: -- Initialize `AddressLookupTableCache` to manage cached lookup tables +Before using `address_lookup_table_account`: - Lookup tables reduce transaction size and improve success rates - Particularly beneficial for complex transactions with many account references diff --git a/docs/TRADING_PARAMETERS_CN.md b/docs/TRADING_PARAMETERS_CN.md index cfcf418..0db166e 100644 --- a/docs/TRADING_PARAMETERS_CN.md +++ b/docs/TRADING_PARAMETERS_CN.md @@ -29,7 +29,7 @@ | 参数 | 类型 | 必需 | 描述 | |------|------|------|------| -| `lookup_table_key` | `Option` | ❌ | 用于交易优化的地址查找表键 | +| `address_lookup_table_account` | `Option` | ❌ | 用于交易优化的地址查找表 | | `wait_transaction_confirmed` | `bool` | ✅ | 是否等待交易确认 | | `create_input_token_ata` | `bool` | ✅ | 是否创建输入代币关联代币账户 | | `close_input_token_ata` | `bool` | ✅ | 交易后是否关闭输入代币 ATA | @@ -60,7 +60,7 @@ | 参数 | 类型 | 必需 | 描述 | |------|------|------|------| -| `lookup_table_key` | `Option` | ❌ | 用于交易优化的地址查找表键 | +| `address_lookup_table_account` | `Option` | ❌ | 用于交易优化的地址查找表 | | `wait_transaction_confirmed` | `bool` | ✅ | 是否等待交易确认 | | `create_output_token_ata` | `bool` | ✅ | 是否创建输出代币关联代币账户 | | `close_output_token_ata` | `bool` | ✅ | 交易后是否关闭输出代币 ATA | @@ -100,7 +100,7 @@ 这些参数启用高级优化: -- **lookup_table_key**: 使用地址查找表减少交易大小 +- **address_lookup_table_account**: 使用地址查找表减少交易大小 - **open_seed_optimize**: 使用基于 seed 的账户创建以降低 CU 消耗 ### 🔄 代币类型参数 @@ -134,8 +134,7 @@ ### 🔍 地址查找表 -使用 `lookup_table_key` 之前: -- 初始化 `AddressLookupTableCache` 来管理缓存的查找表 +使用 `address_lookup_table_account` 之前: - 查找表减少交易大小并提高成功率 - 对于有许多账户引用的复杂交易特别有益 diff --git a/examples/address_lookup/src/main.rs b/examples/address_lookup/src/main.rs index 8b9ecbd..6d5a86a 100644 --- a/examples/address_lookup/src/main.rs +++ b/examples/address_lookup/src/main.rs @@ -1,5 +1,4 @@ -use sol_trade_sdk::common::address_lookup_cache::AddressLookupTableCache; -use sol_trade_sdk::common::SolanaRpcClient; +use sol_trade_sdk::common::address_lookup::fetch_address_lookup_table_account; use sol_trade_sdk::common::TradeConfig; use sol_trade_sdk::{ common::AnyResult, @@ -97,18 +96,6 @@ fn create_event_callback() -> impl Fn(Box) { } } -/// Setup lookup table cache -async fn setup_lookup_table_cache( - client: Arc, - lookup_table_address: Pubkey, -) -> AnyResult<()> { - AddressLookupTableCache::get_instance() - .set_address_lookup_table(client, &lookup_table_address) - .await - .map_err(|e| anyhow::anyhow!("Failed to set address lookup table: {}", e))?; - Ok(()) -} - /// Create SolanaTrade client /// Initializes a new SolanaTrade client with configuration async fn create_solana_trade_client() -> AnyResult { @@ -136,8 +123,8 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul let recent_blockhash = client.rpc.get_latest_blockhash().await?; let lookup_table_key = Pubkey::from_str("use_your_lookup_table_key_here").unwrap(); - // Setup lookup table cache - setup_lookup_table_cache(client.rpc.clone(), lookup_table_key).await?; + let address_lookup_table_account = + fetch_address_lookup_table_account(&client.rpc, &lookup_table_key).await.ok(); // Buy tokens println!("Buying tokens from PumpFun..."); @@ -161,7 +148,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul trade_info.real_sol_reserves, None, )), - lookup_table_key: Some(lookup_table_key), // you still need to update the AddressLookupTableCache + address_lookup_table_account: address_lookup_table_account, wait_transaction_confirmed: true, create_input_token_ata: false, close_input_token_ata: false, diff --git a/examples/bonk_copy_trading/src/main.rs b/examples/bonk_copy_trading/src/main.rs index ee84ee6..148c54e 100644 --- a/examples/bonk_copy_trading/src/main.rs +++ b/examples/bonk_copy_trading/src/main.rs @@ -156,7 +156,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()> trade_info.creator_associated_account, trade_info.global_config, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: false, @@ -199,7 +199,7 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()> trade_info.creator_associated_account, trade_info.global_config, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, open_seed_optimize: false, with_tip: false, diff --git a/examples/bonk_sniper_trading/src/main.rs b/examples/bonk_sniper_trading/src/main.rs index ce0a02d..d04cec8 100644 --- a/examples/bonk_sniper_trading/src/main.rs +++ b/examples/bonk_sniper_trading/src/main.rs @@ -126,7 +126,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult< trade_info.creator_associated_account, trade_info.global_config, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -162,7 +162,7 @@ async fn bonk_sniper_trade_with_shreds(trade_info: BonkTradeEvent) -> AnyResult< trade_info.creator_associated_account, trade_info.global_config, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/cli_trading/src/main.rs b/examples/cli_trading/src/main.rs index f6d394b..17bf067 100644 --- a/examples/cli_trading/src/main.rs +++ b/examples/cli_trading/src/main.rs @@ -622,7 +622,7 @@ async fn handle_buy_pumpfun( slippage_basis_points: slippage, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: false, close_input_token_ata: false, @@ -672,7 +672,7 @@ async fn handle_buy_pumpswap( slippage_basis_points: slippage, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: false, @@ -721,7 +721,7 @@ async fn handle_buy_bonk( slippage_basis_points: slippage, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: false, @@ -774,7 +774,7 @@ async fn handle_buy_raydium_v4( slippage_basis_points: slippage, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: false, @@ -827,7 +827,7 @@ async fn handle_buy_raydium_cpmm( slippage_basis_points: slippage, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: false, @@ -991,7 +991,7 @@ async fn handle_sell_pumpfun( recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: false, @@ -1044,7 +1044,7 @@ async fn handle_sell_pumpswap( recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: false, @@ -1096,7 +1096,7 @@ async fn handle_sell_bonk( recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: false, @@ -1151,7 +1151,7 @@ async fn handle_sell_raydium_v4( recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: false, @@ -1206,7 +1206,7 @@ async fn handle_sell_raydium_cpmm( recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(param), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: false, diff --git a/examples/meteora_damm_v2_direct_trading/src/main.rs b/examples/meteora_damm_v2_direct_trading/src/main.rs index 1c96f58..05d85c5 100644 --- a/examples/meteora_damm_v2_direct_trading/src/main.rs +++ b/examples/meteora_damm_v2_direct_trading/src/main.rs @@ -35,7 +35,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( MeteoraDammV2Params::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -67,7 +67,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( MeteoraDammV2Params::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/middleware_system/src/main.rs b/examples/middleware_system/src/main.rs index c1108e4..8a9c045 100644 --- a/examples/middleware_system/src/main.rs +++ b/examples/middleware_system/src/main.rs @@ -92,7 +92,7 @@ async fn test_middleware() -> AnyResult<()> { extension_params: Box::new( PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool_address).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, diff --git a/examples/nonce_cache/src/main.rs b/examples/nonce_cache/src/main.rs index 5d14c7d..e151e83 100644 --- a/examples/nonce_cache/src/main.rs +++ b/examples/nonce_cache/src/main.rs @@ -148,7 +148,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul trade_info.real_sol_reserves, None, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: false, close_input_token_ata: false, diff --git a/examples/pumpfun_copy_trading/src/main.rs b/examples/pumpfun_copy_trading/src/main.rs index 4921204..f4c7cbd 100644 --- a/examples/pumpfun_copy_trading/src/main.rs +++ b/examples/pumpfun_copy_trading/src/main.rs @@ -144,7 +144,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul trade_info.real_sol_reserves, None, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: false, close_input_token_ata: false, @@ -186,7 +186,7 @@ async fn pumpfun_copy_trade_with_grpc(trade_info: PumpFunTradeEvent) -> AnyResul trade_info.real_sol_reserves, Some(true), )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: false, close_output_token_ata: false, diff --git a/examples/pumpfun_sniper_trading/src/main.rs b/examples/pumpfun_sniper_trading/src/main.rs index 82801d9..455b313 100644 --- a/examples/pumpfun_sniper_trading/src/main.rs +++ b/examples/pumpfun_sniper_trading/src/main.rs @@ -110,7 +110,7 @@ async fn pumpfun_sniper_trade_with_shreds(trade_info: PumpFunTradeEvent) -> AnyR trade_info.creator_vault, None, )), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -141,7 +141,7 @@ async fn pumpfun_sniper_trade_with_shreds(trade_info: PumpFunTradeEvent) -> AnyR recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(PumpFunParams::immediate_sell(trade_info.creator_vault, true)), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/pumpswap_direct_trading/src/main.rs b/examples/pumpswap_direct_trading/src/main.rs index e6ee260..23b935d 100644 --- a/examples/pumpswap_direct_trading/src/main.rs +++ b/examples/pumpswap_direct_trading/src/main.rs @@ -35,7 +35,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -66,7 +66,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/pumpswap_trading/src/main.rs b/examples/pumpswap_trading/src/main.rs index 02e0c69..b4670bc 100644 --- a/examples/pumpswap_trading/src/main.rs +++ b/examples/pumpswap_trading/src/main.rs @@ -194,7 +194,7 @@ async fn pumpswap_trade_with_grpc(mint_pubkey: Pubkey, params: PumpSwapParams) - slippage_basis_points: slippage_basis_points, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(params.clone()), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -227,7 +227,7 @@ async fn pumpswap_trade_with_grpc(mint_pubkey: Pubkey, params: PumpSwapParams) - recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(params.clone()), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/raydium_amm_v4_trading/src/main.rs b/examples/raydium_amm_v4_trading/src/main.rs index a319a04..263ca70 100644 --- a/examples/raydium_amm_v4_trading/src/main.rs +++ b/examples/raydium_amm_v4_trading/src/main.rs @@ -150,7 +150,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) slippage_basis_points: slippage_basis_points, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(params), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -182,7 +182,7 @@ async fn raydium_amm_v4_copy_trade_with_grpc(trade_info: RaydiumAmmV4SwapEvent) recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(params), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/raydium_cpmm_trading/src/main.rs b/examples/raydium_cpmm_trading/src/main.rs index fca1eb0..f7e9ee5 100644 --- a/examples/raydium_cpmm_trading/src/main.rs +++ b/examples/raydium_cpmm_trading/src/main.rs @@ -141,7 +141,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> slippage_basis_points: slippage_basis_points, recent_blockhash: Some(recent_blockhash), extension_params: Box::new(buy_params), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -175,7 +175,7 @@ async fn raydium_cpmm_copy_trade_with_grpc(trade_info: RaydiumCpmmSwapEvent) -> recent_blockhash: Some(recent_blockhash), with_tip: false, extension_params: Box::new(sell_params), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/examples/seed_trading/src/main.rs b/examples/seed_trading/src/main.rs index 941cc81..2ee7745 100644 --- a/examples/seed_trading/src/main.rs +++ b/examples/seed_trading/src/main.rs @@ -34,7 +34,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_input_token_ata: true, close_input_token_ata: true, @@ -73,7 +73,7 @@ async fn main() -> Result<(), Box> { extension_params: Box::new( PumpSwapParams::from_pool_address_by_rpc(&client.rpc, &pool).await?, ), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: true, create_output_token_ata: true, close_output_token_ata: true, diff --git a/src/common/address_lookup.rs b/src/common/address_lookup.rs new file mode 100755 index 0000000..cb4f260 --- /dev/null +++ b/src/common/address_lookup.rs @@ -0,0 +1,70 @@ +use crate::common::SolanaRpcClient; +use anyhow::Result; +use solana_address_lookup_table_interface::state::AddressLookupTable; +use solana_sdk::{ + message::{v0, AddressLookupTableAccount}, + pubkey::Pubkey, +}; + +pub async fn fetch_address_lookup_table_account( + rpc: &SolanaRpcClient, + lookup_table_address: &Pubkey, +) -> Result { + let account = rpc.get_account(lookup_table_address).await?; + let lookup_table = AddressLookupTable::deserialize(&account.data)?; + let address_lookup_table_account = AddressLookupTableAccount { + key: *lookup_table_address, + addresses: lookup_table.addresses.to_vec(), + }; + Ok(address_lookup_table_account) +} + +#[inline] +pub fn extract_lookup_table_indexes( + instructions: &[solana_sdk::instruction::Instruction], + lookup_table_account: &AddressLookupTableAccount, +) -> Option { + use std::collections::{HashMap, HashSet}; + + // 构建地址到索引的映射(O(1) 查找) + let addr_to_index: HashMap<&Pubkey, u8> = lookup_table_account + .addresses + .iter() + .enumerate() + .filter_map(|(idx, addr)| u8::try_from(idx).ok().map(|i| (addr, i))) + .collect(); + + // 收集所有需要的账户及其权限 + let mut writable_indexes = Vec::new(); + let mut readonly_indexes = Vec::new(); + let mut seen = HashSet::new(); + + for instruction in instructions { + for account_meta in &instruction.accounts { + // 跳过已处理的账户 + if !seen.insert(&account_meta.pubkey) { + continue; + } + + // 在查找表中查找账户 + if let Some(&index) = addr_to_index.get(&account_meta.pubkey) { + if account_meta.is_writable { + writable_indexes.push(index); + } else { + readonly_indexes.push(index); + } + } + } + } + + // 如果没有找到任何账户,返回 None + if writable_indexes.is_empty() && readonly_indexes.is_empty() { + return None; + } + + Some(v0::MessageAddressTableLookup { + account_key: lookup_table_account.key, + writable_indexes, + readonly_indexes, + }) +} diff --git a/src/common/address_lookup_cache.rs b/src/common/address_lookup_cache.rs deleted file mode 100755 index fd72478..0000000 --- a/src/common/address_lookup_cache.rs +++ /dev/null @@ -1,96 +0,0 @@ -use dashmap::DashMap; -use solana_address_lookup_table_interface::state::AddressLookupTable; -use solana_sdk::{message::AddressLookupTableAccount, pubkey::Pubkey}; -use std::{ - error::Error, - sync::{Arc, OnceLock}, -}; - -use crate::common::SolanaRpcClient; - -/// AddressLookupTableInfo struct, stores address lookup table related information -#[derive(Clone)] -pub struct AddressLookupTableInfo { - /// Address lookup table account address - pub lookup_table_address: Option, - /// Address lookup table content - pub address_lookup_table: Option, -} - -/// AddressLookupTableCache singleton for storing and managing address lookup tables -pub struct AddressLookupTableCache { - /// Lock-free hash map supporting high concurrent access - tables: DashMap, -} - -// Use static OnceLock to ensure thread safety of singleton pattern -static ADDRESS_LOOKUP_TABLE_CACHE: OnceLock> = OnceLock::new(); - -impl AddressLookupTableCache { - /// Get AddressLookupTableCache singleton instance - pub fn get_instance() -> Arc { - ADDRESS_LOOKUP_TABLE_CACHE - .get_or_init(|| Arc::new(AddressLookupTableCache { tables: DashMap::new() })) - .clone() - } - - /// Get lookup table information - pub async fn set_address_lookup_table( - &self, - client: Arc, - lookup_table_address: &Pubkey, - ) -> Result<(), Box> { - let account = client.get_account(lookup_table_address).await?; - let lookup_table = AddressLookupTable::deserialize(&account.data)?; - let address_lookup_table_account = AddressLookupTableAccount { - key: *lookup_table_address, - addresses: lookup_table.addresses.to_vec(), - }; - self.add_or_update_table(lookup_table_address.clone(), Some(address_lookup_table_account)); - Ok(()) - } - - /// Add or update address lookup table information - lock-free implementation - fn add_or_update_table( - &self, - lookup_table_address: Pubkey, - address_lookup_table: Option, - ) { - if let Some(mut entry) = self.tables.get_mut(&lookup_table_address) { - // Update existing table - if let Some(table) = address_lookup_table { - entry.address_lookup_table = Some(table); - } - } else { - // Add new table - self.tables.insert( - lookup_table_address, - AddressLookupTableInfo { - lookup_table_address: Some(lookup_table_address), - address_lookup_table, - }, - ); - } - } - - /// Get table content - high-performance lock-free implementation - fn get_table_content(&self, lookup_table_address: &Pubkey) -> AddressLookupTableAccount { - let result = self - .tables - .get(lookup_table_address) - .and_then(|entry| entry.address_lookup_table.clone()) - .unwrap_or_else(|| AddressLookupTableAccount { - key: *lookup_table_address, - addresses: Vec::new(), - }); - return result; - } -} - -/// Get address lookup table account -pub async fn get_address_lookup_table_account( - lookup_table_address: &Pubkey, -) -> AddressLookupTableAccount { - let cache = AddressLookupTableCache::get_instance(); - cache.get_table_content(lookup_table_address) -} diff --git a/src/common/mod.rs b/src/common/mod.rs index a6e9ca6..8fc314a 100755 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,4 +1,3 @@ -pub mod address_lookup_cache; pub mod bonding_curve; pub mod fast_fn; pub mod fast_timing; @@ -11,6 +10,7 @@ pub mod spl_token; pub mod spl_token_2022; pub mod subscription_handle; pub mod types; +pub mod address_lookup; pub use gas_fee_strategy::*; pub use types::*; diff --git a/src/lib.rs b/src/lib.rs index 2f48b0b..57c7d41 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ use common::SolanaRpcClient; use parking_lot::Mutex; use rustls::crypto::{ring::default_provider, CryptoProvider}; use solana_sdk::hash::Hash; +use solana_sdk::message::AddressLookupTableAccount; use solana_sdk::signer::Signer; use solana_sdk::{pubkey::Pubkey, signature::Keypair, signature::Signature}; use std::sync::Arc; @@ -93,7 +94,7 @@ pub struct TradeBuyParams { pub extension_params: Box, // Extended configuration /// Optional address lookup table for transaction size optimization - pub lookup_table_key: Option, + pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning pub wait_transaction_confirmed: bool, /// Whether to create input token associated token account @@ -135,7 +136,7 @@ pub struct TradeSellParams { pub extension_params: Box, // Extended configuration /// Optional address lookup table for transaction size optimization - pub lookup_table_key: Option, + pub address_lookup_table_account: Option, /// Whether to wait for transaction confirmation before returning pub wait_transaction_confirmed: bool, /// Whether to create output token associated token account @@ -292,7 +293,7 @@ impl SolanaTrade { output_token_program: None, input_amount: Some(params.input_token_amount), slippage_basis_points: params.slippage_basis_points, - lookup_table_key: params.lookup_table_key, + address_lookup_table_account: params.address_lookup_table_account, recent_blockhash: params.recent_blockhash, data_size_limit: 256 * 1024, wait_transaction_confirmed: params.wait_transaction_confirmed, @@ -385,7 +386,7 @@ impl SolanaTrade { output_token_program: None, input_amount: Some(params.input_token_amount), slippage_basis_points: params.slippage_basis_points, - lookup_table_key: params.lookup_table_key, + address_lookup_table_account: params.address_lookup_table_account, recent_blockhash: params.recent_blockhash, wait_transaction_confirmed: params.wait_transaction_confirmed, protocol_params: protocol_params.clone(), diff --git a/src/trading/common/address_lookup_manager.rs b/src/trading/common/address_lookup_manager.rs deleted file mode 100755 index 97b6fde..0000000 --- a/src/trading/common/address_lookup_manager.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::sync::Arc; - -use solana_sdk::{message::AddressLookupTableAccount, pubkey::Pubkey}; - -use crate::common::{ - address_lookup_cache::{get_address_lookup_table_account, AddressLookupTableCache}, - SolanaRpcClient, -}; - -/// Get address lookup table account list -/// If lookup_table_key is provided, get the corresponding account, otherwise return empty list -pub async fn get_address_lookup_table_accounts( - rpc: Option>, - lookup_table_key: Option, -) -> Vec { - match lookup_table_key { - Some(key) => { - let account = get_address_lookup_table_account(&key).await; - if account.addresses.len() == 0 { - if rpc.is_some() { - let _ = AddressLookupTableCache::get_instance() - .set_address_lookup_table(rpc.unwrap(), &key) - .await; - let new_account = get_address_lookup_table_account(&key).await; - if new_account.addresses.len() == 0 { - return Vec::new(); - } else { - return vec![new_account]; - } - } else { - return Vec::new(); - } - } - return vec![account]; - } - None => Vec::new(), - } -} diff --git a/src/trading/common/mod.rs b/src/trading/common/mod.rs index c73d130..0cd8278 100755 --- a/src/trading/common/mod.rs +++ b/src/trading/common/mod.rs @@ -1,7 +1,6 @@ pub mod nonce_manager; pub mod transaction_builder; pub mod compute_budget_manager; -pub mod address_lookup_manager; pub mod utils; pub mod wsol_manager; @@ -9,6 +8,5 @@ pub mod wsol_manager; pub use nonce_manager::*; pub use transaction_builder::*; pub use compute_budget_manager::*; -pub use address_lookup_manager::*; pub use utils::*; pub use wsol_manager::*; \ No newline at end of file diff --git a/src/trading/common/transaction_builder.rs b/src/trading/common/transaction_builder.rs index 7083f8c..5224a07 100755 --- a/src/trading/common/transaction_builder.rs +++ b/src/trading/common/transaction_builder.rs @@ -1,17 +1,11 @@ use solana_hash::Hash; use solana_sdk::{ - instruction::Instruction, - native_token::sol_str_to_lamports, - pubkey::Pubkey, - signature::Keypair, - signer::Signer, - transaction::VersionedTransaction, + instruction::Instruction, message::AddressLookupTableAccount, native_token::sol_str_to_lamports, pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::VersionedTransaction }; use solana_system_interface::instruction::transfer; use std::sync::Arc; use super::{ - address_lookup_manager::get_address_lookup_table_accounts, compute_budget_manager::compute_budget_instructions, nonce_manager::{add_nonce_instruction, get_transaction_blockhash}, }; @@ -27,7 +21,7 @@ pub async fn build_transaction( unit_limit: u32, unit_price: u64, business_instructions: Vec, - lookup_table_key: Option, + address_lookup_table_account: Option, recent_blockhash: Option, data_size_limit: u32, middleware_manager: Option>, @@ -72,15 +66,11 @@ pub async fn build_transaction( // Get blockhash for transaction let blockhash = get_transaction_blockhash(recent_blockhash, durable_nonce.clone()); - // Get address lookup table accounts - let address_lookup_table_accounts = - get_address_lookup_table_accounts(rpc, lookup_table_key).await; - // Build transaction build_versioned_transaction( payer, instructions, - address_lookup_table_accounts, + address_lookup_table_account, blockhash, middleware_manager, protocol_name, @@ -93,7 +83,7 @@ pub async fn build_transaction( async fn build_versioned_transaction( payer: Arc, instructions: Vec, - address_lookup_table_accounts: Vec, + address_lookup_table_account: Option, blockhash: Hash, middleware_manager: Option>, protocol_name: &str, @@ -111,16 +101,11 @@ async fn build_versioned_transaction( // 使用预分配的交易构建器以降低延迟 let mut builder = acquire_builder(); - let lookup_table_key = if !address_lookup_table_accounts.is_empty() { - address_lookup_table_accounts.first().map(|a| a.key) - } else { - None - }; let versioned_msg = builder.build_zero_alloc( &payer.pubkey(), &full_instructions, - lookup_table_key, + address_lookup_table_account, blockhash, ); diff --git a/src/trading/core/async_executor.rs b/src/trading/core/async_executor.rs index e67be9f..65b61ac 100644 --- a/src/trading/core/async_executor.rs +++ b/src/trading/core/async_executor.rs @@ -3,6 +3,7 @@ use anyhow::{anyhow, Result}; use crossbeam_queue::ArrayQueue; use solana_hash::Hash; +use solana_sdk::message::AddressLookupTableAccount; use solana_sdk::{ instruction::Instruction, pubkey::Pubkey, signature::Keypair, signature::Signature, }; @@ -96,7 +97,7 @@ pub async fn execute_parallel( payer: Arc, rpc: Option>, instructions: Vec, - lookup_table_key: Option, + address_lookup_table_account: Option, recent_blockhash: Option, durable_nonce: Option, data_size_limit: u32, @@ -168,6 +169,7 @@ pub async fn execute_parallel( let unit_price = gas_fee_strategy_config.2.cu_price; let rpc = rpc.clone(); let durable_nonce = durable_nonce.clone(); + let address_lookup_table_account = address_lookup_table_account.clone(); tokio::spawn(async move { let _task_start = Instant::now(); @@ -182,7 +184,7 @@ pub async fn execute_parallel( unit_limit, unit_price, instructions.as_ref().clone(), - lookup_table_key, + address_lookup_table_account, recent_blockhash, data_size_limit, middleware_manager, diff --git a/src/trading/core/executor.rs b/src/trading/core/executor.rs index a506994..59e80f6 100755 --- a/src/trading/core/executor.rs +++ b/src/trading/core/executor.rs @@ -87,7 +87,7 @@ impl TradeExecutor for GenericTradeExecutor { params.payer, params.rpc, final_instructions, - params.lookup_table_key, + params.address_lookup_table_account, params.recent_blockhash, params.durable_nonce, if is_buy { params.data_size_limit } else { 0 }, diff --git a/src/trading/core/mod.rs b/src/trading/core/mod.rs index 4d68271..1d78a67 100755 --- a/src/trading/core/mod.rs +++ b/src/trading/core/mod.rs @@ -1,7 +1,6 @@ pub mod params; pub mod traits; pub mod executor; -pub mod parallel; pub mod async_executor; pub mod transaction_pool; pub mod execution; \ No newline at end of file diff --git a/src/trading/core/params.rs b/src/trading/core/params.rs index 0061230..08ae9e7 100755 --- a/src/trading/core/params.rs +++ b/src/trading/core/params.rs @@ -8,6 +8,7 @@ use crate::swqos::{SwqosClient, TradeType}; use crate::trading::common::get_multi_token_balances; use crate::trading::MiddlewareManager; use solana_hash::Hash; +use solana_sdk::message::AddressLookupTableAccount; use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use std::sync::Arc; @@ -23,7 +24,7 @@ pub struct SwapParams { pub output_token_program: Option, pub input_amount: Option, pub slippage_basis_points: Option, - pub lookup_table_key: Option, + pub address_lookup_table_account: Option, pub recent_blockhash: Option, pub data_size_limit: u32, pub wait_transaction_confirmed: bool, diff --git a/src/trading/core/transaction_pool.rs b/src/trading/core/transaction_pool.rs index 3fdf56f..11810ae 100644 --- a/src/trading/core/transaction_pool.rs +++ b/src/trading/core/transaction_pool.rs @@ -9,10 +9,7 @@ use crossbeam_queue::ArrayQueue; use once_cell::sync::Lazy; use solana_sdk::{ - instruction::Instruction, - message::{v0, VersionedMessage, Message}, - pubkey::Pubkey, - hash::Hash, + hash::Hash, instruction::Instruction, message::{v0, AddressLookupTableAccount, Message, VersionedMessage}, pubkey::Pubkey }; use std::sync::Arc; /// 预分配的交易构建器 @@ -68,7 +65,7 @@ impl PreallocatedTxBuilder { &mut self, payer: &Pubkey, instructions: &[Instruction], - lookup_table: Option, + address_lookup_table_account: Option, recent_blockhash: Hash, ) -> VersionedMessage { // 重用已分配的 vector @@ -76,24 +73,32 @@ impl PreallocatedTxBuilder { self.instructions.extend_from_slice(instructions); // ✅ 如果有查找表,使用 V0 消息 - if let Some(table_key) = lookup_table { - self.lookup_tables.push(v0::MessageAddressTableLookup { - account_key: table_key, - writable_indexes: vec![], - readonly_indexes: vec![], - }); + if let Some(address_lookup_table_account) = address_lookup_table_account { + // self.lookup_tables.push(v0::MessageAddressTableLookup { + // account_key: table_key, + // writable_indexes: vec![], + // readonly_indexes: vec![], + // }); - // 使用 Message::new 创建 legacy 消息,然后提取编译后的指令 - let legacy_msg = Message::new(&self.instructions, Some(payer)); + // // 使用 Message::new 创建 legacy 消息,然后提取编译后的指令 + // let legacy_msg = Message::new(&self.instructions, Some(payer)); - // 构建 V0 消息 - let message = v0::Message { - header: legacy_msg.header, - account_keys: legacy_msg.account_keys, + // // 构建 V0 消息 + // let message = v0::Message { + // header: legacy_msg.header, + // account_keys: legacy_msg.account_keys, + // recent_blockhash, + // instructions: legacy_msg.instructions, + // address_table_lookups: self.lookup_tables.clone(), + // }; + + let message = v0::Message::try_compile( + payer, + &self.instructions, + &[address_lookup_table_account], recent_blockhash, - instructions: legacy_msg.instructions, - address_table_lookups: self.lookup_tables.clone(), - }; + ).expect("v0 message compile failed"); + VersionedMessage::V0(message) } else { diff --git a/test_latency.sh b/test_latency.sh index e952da8..5b52236 100755 --- a/test_latency.sh +++ b/test_latency.sh @@ -188,7 +188,7 @@ async fn main() -> AnyResult<()> { slippage_basis_points: Some(slippage), recent_blockhash: Some(recent_blockhash), extension_params: Box::new(params), - lookup_table_key: None, + address_lookup_table_account: None, wait_transaction_confirmed: false, // 不等待确认,测试最快提交速度 create_input_token_ata: true, close_input_token_ata: true,