feat: optimize WSOL wrap/unwrap with seed account reuse check
- Add account existence check before creating seed account - Implement wrap_wsol_to_sol_without_create for reusing existing seed accounts - Prevent transaction failures when temporary seed account already exists - Improve WSOL conversion efficiency by avoiding redundant account creation
This commit is contained in:
+19
-3
@@ -688,12 +688,28 @@ impl SolanaTrade {
|
||||
/// - 交易执行或确认失败
|
||||
/// - 网络或 RPC 错误
|
||||
pub async fn wrap_wsol_to_sol(&self, amount: u64) -> Result<String, anyhow::Error> {
|
||||
use crate::trading::common::wsol_manager::wrap_wsol_to_sol as wrap_wsol_to_sol_internal;
|
||||
use crate::trading::common::wsol_manager::{wrap_wsol_to_sol as wrap_wsol_to_sol_internal, wrap_wsol_to_sol_without_create};
|
||||
use crate::common::seed::get_associated_token_address_with_program_id_use_seed;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
|
||||
let recent_blockhash = self.rpc.get_latest_blockhash().await?;
|
||||
let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?;
|
||||
// 检查临时seed账户是否已存在
|
||||
let seed_ata_address = get_associated_token_address_with_program_id_use_seed(
|
||||
&self.payer.pubkey(),
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
)?;
|
||||
|
||||
let account_exists = self.rpc.get_account(&seed_ata_address).await.is_ok();
|
||||
|
||||
let instructions = if account_exists {
|
||||
// 如果账户已存在,使用不创建账户的版本
|
||||
wrap_wsol_to_sol_without_create(&self.payer.pubkey(), amount)?
|
||||
} else {
|
||||
// 如果账户不存在,使用创建账户的版本
|
||||
wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?
|
||||
};
|
||||
|
||||
let recent_blockhash = self.rpc.get_latest_blockhash().await?;
|
||||
let mut transaction = Transaction::new_with_payer(&instructions, Some(&self.payer.pubkey()));
|
||||
transaction.sign(&[&*self.payer], recent_blockhash);
|
||||
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
||||
|
||||
@@ -96,17 +96,22 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2
|
||||
}
|
||||
|
||||
/// 将 WSOL 转换为 SOL,使用 seed 账户
|
||||
/// 1. 使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号
|
||||
/// 2. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址
|
||||
/// 3. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令
|
||||
/// 4. 添加关闭 WSOL seed 账号的指令
|
||||
/// 1. 检查 seed 账户是否已存在
|
||||
/// 2. 如果不存在,使用 super::seed::create_associated_token_account_use_seed 创建 WSOL seed 账号
|
||||
/// 3. 使用 get_associated_token_address_with_program_id_use_seed 获取该账号的 ATA 地址
|
||||
/// 4. 添加从用户 WSOL ATA 转账到该 seed ATA 账号的指令
|
||||
/// 5. 添加关闭 WSOL seed 账号的指令
|
||||
///
|
||||
/// 注意:此函数只生成指令,不检查账户是否存在(需要调用方在发送交易前检查)
|
||||
/// 如果临时账户已存在,可以安全地跳过创建步骤,直接转账并关闭
|
||||
pub fn wrap_wsol_to_sol(
|
||||
payer: &Pubkey,
|
||||
amount: u64,
|
||||
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||
let mut instructions = Vec::new();
|
||||
|
||||
// 1. 创建 WSOL seed 账户
|
||||
// 1. 创建 WSOL seed 账户(注意:如果账户已存在会失败)
|
||||
// 调用方应该先检查账户是否存在,如果存在则跳过此步骤
|
||||
let seed_account_instructions = create_associated_token_account_use_seed(
|
||||
payer,
|
||||
payer,
|
||||
@@ -152,3 +157,49 @@ pub fn wrap_wsol_to_sol(
|
||||
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
/// 将 WSOL 转换为 SOL(仅转账和关闭,不创建账户)
|
||||
/// 用于当临时seed账户已存在的情况
|
||||
pub fn wrap_wsol_to_sol_without_create(
|
||||
payer: &Pubkey,
|
||||
amount: u64,
|
||||
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||
let mut instructions = Vec::new();
|
||||
|
||||
// 1. 获取 seed 账户的 ATA 地址
|
||||
let seed_ata_address = get_associated_token_address_with_program_id_use_seed(
|
||||
payer,
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
)?;
|
||||
|
||||
// 2. 获取用户的 WSOL ATA 地址
|
||||
let user_wsol_ata = crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
payer,
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
);
|
||||
|
||||
// 3. 添加从用户 WSOL ATA 转账到 seed ATA 的指令
|
||||
let transfer_instruction = crate::common::spl_token::transfer(
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
&user_wsol_ata,
|
||||
&seed_ata_address,
|
||||
payer,
|
||||
amount,
|
||||
&[],
|
||||
)?;
|
||||
instructions.push(transfer_instruction);
|
||||
|
||||
// 4. 添加关闭 WSOL seed 账户的指令
|
||||
let close_instruction = close_account(
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
&seed_ata_address,
|
||||
payer,
|
||||
payer,
|
||||
&[],
|
||||
)?;
|
||||
instructions.push(close_instruction);
|
||||
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user