From e976af69355fb0ce88439b24abadd18ebd1c1807 Mon Sep 17 00:00:00 2001 From: ysq Date: Sun, 3 Aug 2025 22:51:11 +0800 Subject: [PATCH] feat: upgrade to v0.2.12 and refactor system instructions --- Cargo.toml | 5 +-- README.md | 4 +-- README_CN.md | 4 +-- rustfmt.toml | 7 ++++ src/instruction/bonk.rs | 19 +++-------- src/instruction/pumpfun.rs | 6 ++-- src/instruction/pumpswap.rs | 31 +++++------------ src/instruction/raydium_cpmm.rs | 41 ++++++----------------- src/trading/common/nonce_manager.rs | 19 ++++------- src/trading/common/transaction_builder.rs | 28 +++++----------- src/trading/common/utils.rs | 24 ++++--------- 11 files changed, 62 insertions(+), 126 deletions(-) create mode 100644 rustfmt.toml diff --git a/Cargo.toml b/Cargo.toml index 4c013b9..b5a5acd 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sol-trade-sdk" -version = "0.2.11" +version = "0.2.12" edition = "2021" authors = ["William ", "sgxiang ", "wei <1415121722@qq.com>"] repository = "https://github.com/0xfnzero/sol-trade-sdk" @@ -13,7 +13,7 @@ readme = "README.md" crate-type = ["cdylib", "rlib"] [dependencies] -solana-streamer-sdk = "0.1.8" +solana-streamer-sdk = "0.1.9" solana-sdk = "2.1.16" solana-client = "2.1.16" solana-program = "2.1.16" @@ -68,3 +68,4 @@ arrayref = "0.3.6" borsh-derive = "1.5.5" indicatif = "0.17.11" pumpfun_program = { version = "4.3.0", package = "pumpfun" } +solana-system-interface = "1.0.0" diff --git a/README.md b/README.md index d095dd9..b901ad7 100755 --- a/README.md +++ b/README.md @@ -31,14 +31,14 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.2.11" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.2.12" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -sol-trade-sdk = "0.2.11" +sol-trade-sdk = "0.2.12" ``` ## Usage Examples diff --git a/README_CN.md b/README_CN.md index 1157b2e..741aedf 100755 --- a/README_CN.md +++ b/README_CN.md @@ -31,14 +31,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.2.11" } +sol-trade-sdk = { path = "./sol-trade-sdk", version = "0.2.12" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -sol-trade-sdk = "0.2.11" +sol-trade-sdk = "0.2.12" ``` ## 使用示例 diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..5a59d38 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,7 @@ +max_width = 100 +hard_tabs = false +tab_spaces = 4 +edition = "2021" +use_small_heuristics = "Max" +newline_style = "Unix" + diff --git a/src/instruction/bonk.rs b/src/instruction/bonk.rs index ddbe045..3a23377 100755 --- a/src/instruction/bonk.rs +++ b/src/instruction/bonk.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use solana_sdk::{instruction::Instruction, signer::Signer}; +use solana_system_interface::instruction::transfer; use spl_associated_token_account::instruction::create_associated_token_account_idempotent; use spl_token::instruction::close_account; @@ -105,11 +106,7 @@ impl BonkInstructionBuilder { ); instructions.push( // 将SOL转入wSOL ATA账户 - solana_sdk::system_instruction::transfer( - ¶ms.payer.pubkey(), - &user_quote_token_account, - amount_in, - ), + transfer(¶ms.payer.pubkey(), &user_quote_token_account, amount_in), ); // 同步wSOL余额 @@ -155,11 +152,7 @@ impl BonkInstructionBuilder { data.extend_from_slice(&minimum_amount_out.to_le_bytes()); data.extend_from_slice(&share_fee_rate.to_le_bytes()); - instructions.push(Instruction { - program_id: accounts::BONK, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::BONK, accounts, data }); if protocol_params.auto_handle_wsol { // 关闭wSOL ATA账户,回收租金 @@ -262,11 +255,7 @@ impl BonkInstructionBuilder { data.extend_from_slice(&minimum_amount_out.to_le_bytes()); data.extend_from_slice(&share_fee_rate.to_le_bytes()); - instructions.push(Instruction { - program_id: accounts::BONK, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::BONK, accounts, data }); let protocol_params = params .protocol_params diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index 8a08fce..9ddc71b 100755 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -1,5 +1,5 @@ use anyhow::{anyhow, Result}; -use solana_sdk::{instruction::Instruction, native_token::sol_to_lamports}; +use solana_sdk::{instruction::Instruction, native_token::sol_str_to_lamports}; use spl_associated_token_account::{ get_associated_token_address, instruction::create_associated_token_account, }; @@ -8,7 +8,7 @@ use spl_token::instruction::close_account; use crate::{ constants, trading::pumpfun::common::{ - get_bonding_curve_pda, get_global_pda, get_global_volume_accumulator_pda, get_metadata_pda, get_mint_authority_pda, get_user_volume_accumulator_pda + get_bonding_curve_pda, get_global_volume_accumulator_pda, get_user_volume_accumulator_pda, }, }; @@ -57,7 +57,7 @@ impl InstructionBuilder for PumpFunInstructionBuilder { let mut buy_token_amount = get_buy_token_amount_from_sol_amount(&bonding_curve, params.sol_amount); if buy_token_amount <= 100 * 1_000_000_u64 { - buy_token_amount = if max_sol_cost > sol_to_lamports(0.01) { + buy_token_amount = if max_sol_cost > sol_str_to_lamports("0.01").unwrap_or(0) { 25547619 * 1_000_000_u64 } else { 255476 * 1_000_000_u64 diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index f6e7999..0f0fdb6 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signer::Signer}; +use solana_system_interface::instruction::transfer; use spl_associated_token_account::instruction::create_associated_token_account_idempotent; use spl_token::instruction::close_account; @@ -19,7 +20,9 @@ use crate::{ pumpswap::{ self, common::{ - coin_creator_vault_ata, coin_creator_vault_authority, fee_recipient_ata, find_pool, get_global_volume_accumulator_pda, get_token_amount, get_user_volume_accumulator_pda, get_wsol_amount + coin_creator_vault_ata, coin_creator_vault_authority, fee_recipient_ata, find_pool, + get_global_volume_accumulator_pda, get_token_amount, + get_user_volume_accumulator_pda, get_wsol_amount, }, }, }, @@ -273,7 +276,7 @@ impl PumpSwapInstructionBuilder { ); instructions.push( // Transfer SOL to wSOL ATA account - solana_sdk::system_instruction::transfer( + transfer( ¶ms.payer.pubkey(), if quote_mint_is_wsol { &user_quote_token_account @@ -302,11 +305,7 @@ impl PumpSwapInstructionBuilder { instructions.push(create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - if quote_mint_is_wsol { - &base_mint - } else { - "e_mint - }, + if quote_mint_is_wsol { &base_mint } else { "e_mint }, &accounts::TOKEN_PROGRAM, )); @@ -362,11 +361,7 @@ impl PumpSwapInstructionBuilder { data.extend_from_slice(&token_amount.to_le_bytes()); } - instructions.push(Instruction { - program_id: accounts::AMM_PROGRAM, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::AMM_PROGRAM, accounts, data }); if auto_handle_wsol { // Close wSOL ATA account, reclaim rent instructions.push( @@ -465,11 +460,7 @@ impl PumpSwapInstructionBuilder { instructions.push(create_associated_token_account_idempotent( ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), - if quote_mint_is_wsol { - &base_mint - } else { - "e_mint - }, + if quote_mint_is_wsol { &base_mint } else { "e_mint }, &accounts::TOKEN_PROGRAM, )); @@ -521,11 +512,7 @@ impl PumpSwapInstructionBuilder { data.extend_from_slice(&token_amount.to_le_bytes()); } - instructions.push(Instruction { - program_id: accounts::AMM_PROGRAM, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::AMM_PROGRAM, accounts, data }); if auto_handle_wsol { instructions.push( diff --git a/src/instruction/raydium_cpmm.rs b/src/instruction/raydium_cpmm.rs index e65610f..12679d8 100755 --- a/src/instruction/raydium_cpmm.rs +++ b/src/instruction/raydium_cpmm.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use solana_sdk::{instruction::Instruction, signer::Signer}; +use solana_system_interface::instruction::transfer; use spl_associated_token_account::instruction::create_associated_token_account_idempotent; use spl_token::instruction::close_account; @@ -49,9 +50,8 @@ impl RaydiumCpmmInstructionBuilder { let pool_state = if protocol_params.pool_state.is_some() { protocol_params.pool_state.unwrap() } else { - let mint_token_in_pool_state_index = protocol_params - .mint_token_in_pool_state_index - .unwrap_or(1); + let mint_token_in_pool_state_index = + protocol_params.mint_token_in_pool_state_index.unwrap_or(1); get_pool_pda( &accounts::AMM_CONFIG, if mint_token_in_pool_state_index == 1 { @@ -116,11 +116,7 @@ impl RaydiumCpmmInstructionBuilder { ); instructions.push( // 将SOL转入wSOL ATA账户 - solana_sdk::system_instruction::transfer( - ¶ms.payer.pubkey(), - &wsol_token_account, - amount_in, - ), + transfer(¶ms.payer.pubkey(), &wsol_token_account, amount_in), ); // 同步wSOL余额 @@ -135,9 +131,7 @@ impl RaydiumCpmmInstructionBuilder { ¶ms.payer.pubkey(), ¶ms.payer.pubkey(), ¶ms.mint, - &protocol_params - .mint_token_program - .unwrap_or(accounts::TOKEN_PROGRAM), + &protocol_params.mint_token_program.unwrap_or(accounts::TOKEN_PROGRAM), )); // 创建买入指令 @@ -152,9 +146,7 @@ impl RaydiumCpmmInstructionBuilder { solana_sdk::instruction::AccountMeta::new(mint_vault_account, false), // Output Vault Account solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Input Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly( - protocol_params - .mint_token_program - .unwrap_or(accounts::TOKEN_PROGRAM), + protocol_params.mint_token_program.unwrap_or(accounts::TOKEN_PROGRAM), false, ), // Output Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(accounts::WSOL_TOKEN_ACCOUNT, false), // Input token mint (readonly) @@ -167,11 +159,7 @@ impl RaydiumCpmmInstructionBuilder { data.extend_from_slice(&amount_in.to_le_bytes()); data.extend_from_slice(&minimum_amount_out.to_le_bytes()); - instructions.push(Instruction { - program_id: accounts::RAYDIUM_CPMM, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::RAYDIUM_CPMM, accounts, data }); if protocol_params.auto_handle_wsol { // 关闭wSOL ATA账户,回收租金 @@ -239,9 +227,8 @@ impl RaydiumCpmmInstructionBuilder { let pool_state = if protocol_params.pool_state.is_some() { protocol_params.pool_state.unwrap() } else { - let mint_token_in_pool_state_index = protocol_params - .mint_token_in_pool_state_index - .unwrap_or(1); + let mint_token_in_pool_state_index = + protocol_params.mint_token_in_pool_state_index.unwrap_or(1); get_pool_pda( &accounts::AMM_CONFIG, if mint_token_in_pool_state_index == 1 { @@ -297,9 +284,7 @@ impl RaydiumCpmmInstructionBuilder { solana_sdk::instruction::AccountMeta::new(mint_vault_account, false), // Input Vault Account solana_sdk::instruction::AccountMeta::new(wsol_vault_account, false), // Output Vault Account solana_sdk::instruction::AccountMeta::new_readonly( - protocol_params - .mint_token_program - .unwrap_or(accounts::TOKEN_PROGRAM), + protocol_params.mint_token_program.unwrap_or(accounts::TOKEN_PROGRAM), false, ), // Input Token Program (readonly) solana_sdk::instruction::AccountMeta::new_readonly(accounts::TOKEN_PROGRAM, false), // Output Token Program (readonly) @@ -313,11 +298,7 @@ impl RaydiumCpmmInstructionBuilder { data.extend_from_slice(&amount.to_le_bytes()); data.extend_from_slice(&minimum_amount_out.to_le_bytes()); - instructions.push(Instruction { - program_id: accounts::RAYDIUM_CPMM, - accounts, - data, - }); + instructions.push(Instruction { program_id: accounts::RAYDIUM_CPMM, accounts, data }); if protocol_params.auto_handle_wsol { instructions.push( diff --git a/src/trading/common/nonce_manager.rs b/src/trading/common/nonce_manager.rs index 2a83ce5..e5a5edc 100755 --- a/src/trading/common/nonce_manager.rs +++ b/src/trading/common/nonce_manager.rs @@ -1,11 +1,7 @@ use anyhow::anyhow; -use solana_sdk::{ - instruction::Instruction, - signature::Keypair, - signer::Signer, - system_instruction, -}; use solana_hash::Hash; +use solana_sdk::{instruction::Instruction, signature::Keypair, signer::Signer}; +use solana_system_interface::instruction::advance_nonce_account; use crate::common::nonce_cache::NonceCache; @@ -15,8 +11,8 @@ use crate::common::nonce_cache::NonceCache; /// 如果nonce被锁定、已使用或未准备好,将返回错误 /// 成功时会锁定并标记nonce为已使用 pub fn add_nonce_instruction( - instructions: &mut Vec, - payer: &Keypair + instructions: &mut Vec, + payer: &Keypair, ) -> Result<(), anyhow::Error> { let nonce_cache = NonceCache::get_instance(); let nonce_info = nonce_cache.get_nonce_info(); @@ -40,10 +36,7 @@ pub fn add_nonce_instruction( // nonce_cache.lock(); // 创建Solana系统nonce推进指令 - 使用系统程序ID - let nonce_advance_ix = system_instruction::advance_nonce_account( - &nonce_pubkey, - &payer.pubkey(), - ); + let nonce_advance_ix = advance_nonce_account(&nonce_pubkey, &payer.pubkey()); instructions.push(nonce_advance_ix); } @@ -69,4 +62,4 @@ pub fn is_using_nonce() -> bool { let nonce_cache = NonceCache::get_instance(); let nonce_info = nonce_cache.get_nonce_info(); nonce_info.nonce_account.is_some() -} \ No newline at end of file +} diff --git a/src/trading/common/transaction_builder.rs b/src/trading/common/transaction_builder.rs index 1c454df..178c77e 100755 --- a/src/trading/common/transaction_builder.rs +++ b/src/trading/common/transaction_builder.rs @@ -2,13 +2,13 @@ use solana_hash::Hash; use solana_sdk::{ instruction::Instruction, message::{v0, VersionedMessage}, - native_token::sol_to_lamports, + native_token::sol_str_to_lamports, pubkey::Pubkey, signature::Keypair, signer::Signer, - system_instruction, transaction::VersionedTransaction, }; +use solana_system_interface::instruction::transfer; use std::sync::Arc; use super::{ @@ -54,13 +54,7 @@ pub async fn build_rpc_transaction( let address_lookup_table_accounts = get_address_lookup_table_accounts(lookup_table_key).await; // 构建交易 - build_versioned_transaction( - payer, - instructions, - address_lookup_table_accounts, - blockhash, - ) - .await + build_versioned_transaction(payer, instructions, address_lookup_table_accounts, blockhash).await } /// 构建带小费的交易 @@ -88,10 +82,10 @@ pub async fn build_tip_transaction( instructions.extend(business_instructions); // 添加小费转账指令 - instructions.push(system_instruction::transfer( + instructions.push(transfer( &payer.pubkey(), tip_account, - sol_to_lamports(tip_amount), + sol_str_to_lamports(tip_amount.to_string().as_str()).unwrap_or(0), )); // 获取交易使用的blockhash @@ -101,13 +95,7 @@ pub async fn build_tip_transaction( let address_lookup_table_accounts = get_address_lookup_table_accounts(lookup_table_key).await; // 构建交易 - build_versioned_transaction( - payer, - instructions, - address_lookup_table_accounts, - blockhash, - ) - .await + build_versioned_transaction(payer, instructions, address_lookup_table_accounts, blockhash).await } /// 构建版本化交易的底层函数 @@ -200,10 +188,10 @@ pub async fn build_sell_tip_transaction( instructions.extend(business_instructions); // 添加小费转账指令 - instructions.push(system_instruction::transfer( + instructions.push(transfer( &payer.pubkey(), tip_account, - sol_to_lamports(tip_amount), + sol_str_to_lamports(tip_amount.to_string().as_str()).unwrap_or(0), )); // 获取地址查找表账户 diff --git a/src/trading/common/utils.rs b/src/trading/common/utils.rs index f7c9f99..548f950 100644 --- a/src/trading/common/utils.rs +++ b/src/trading/common/utils.rs @@ -1,7 +1,5 @@ -use solana_sdk::{ - pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction, - transaction::Transaction, -}; +use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction}; +use solana_system_interface::instruction::transfer; use spl_associated_token_account::get_associated_token_address; use spl_token::instruction::close_account; @@ -16,10 +14,8 @@ pub async fn get_token_balance( ) -> Result { let ata = get_associated_token_address(payer, mint); let balance = rpc.get_token_account_balance(&ata).await?; - let balance_u64 = balance - .amount - .parse::() - .map_err(|_| anyhow!("Failed to parse token balance"))?; + let balance_u64 = + balance.amount.parse::().map_err(|_| anyhow!("Failed to parse token balance"))?; Ok(balance_u64) } @@ -63,8 +59,7 @@ pub async fn transfer_sol( return Err(anyhow!("Insufficient balance")); } - let transfer_instruction = - system_instruction::transfer(&payer.pubkey(), receive_wallet, amount); + let transfer_instruction = transfer(&payer.pubkey(), receive_wallet, amount); let recent_blockhash = rpc.get_latest_blockhash().await?; @@ -108,13 +103,8 @@ pub async fn close_token_account( } // 构建关闭账户指令 - let close_account_ix = close_account( - &spl_token::ID, - &ata, - &payer.pubkey(), - &payer.pubkey(), - &[&payer.pubkey()], - )?; + let close_account_ix = + close_account(&spl_token::ID, &ata, &payer.pubkey(), &payer.pubkey(), &[&payer.pubkey()])?; // 构建交易 let recent_blockhash = rpc.get_latest_blockhash().await?;