feat: add wrap_wsol_to_sol function with seed account optimization
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sol-trade-sdk"
|
||||
version = "3.3.2"
|
||||
version = "3.3.3"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"William <byteblock6@gmail.com>",
|
||||
|
||||
@@ -87,14 +87,14 @@ Add the dependency to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
# Add to your Cargo.toml
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.3.2" }
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.3.3" }
|
||||
```
|
||||
|
||||
### Use crates.io
|
||||
|
||||
```toml
|
||||
# Add to your Cargo.toml
|
||||
sol-trade-sdk = "3.3.2"
|
||||
sol-trade-sdk = "3.3.3"
|
||||
```
|
||||
|
||||
## 🛠️ Usage Examples
|
||||
|
||||
+2
-2
@@ -87,14 +87,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk
|
||||
|
||||
```toml
|
||||
# 添加到您的 Cargo.toml
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.3.2" }
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "3.3.3" }
|
||||
```
|
||||
|
||||
### 使用 crates.io
|
||||
|
||||
```toml
|
||||
# 添加到您的 Cargo.toml
|
||||
sol-trade-sdk = "3.3.2"
|
||||
sol-trade-sdk = "3.3.3"
|
||||
```
|
||||
|
||||
## 🛠️ 使用示例
|
||||
|
||||
@@ -6,7 +6,10 @@ use std::sync::Arc;
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🔄 WSOL Wrapper Example");
|
||||
println!("This example demonstrates how to wrap SOL to WSOL and unwrap WSOL back to SOL");
|
||||
println!("This example demonstrates:");
|
||||
println!("1. Wrapping SOL to WSOL");
|
||||
println!("2. Partial unwrapping WSOL back to SOL using seed account");
|
||||
println!("3. Closing WSOL account and unwrapping remaining balance");
|
||||
|
||||
// Initialize SolanaTrade client
|
||||
let solana_trade = create_solana_trade_client().await?;
|
||||
@@ -24,15 +27,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
Err(e) => {
|
||||
println!("❌ Failed to wrap SOL to WSOL: {}", e);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a moment before unwrapping
|
||||
println!("\n⏳ Waiting 3 seconds before unwrapping...");
|
||||
// Wait a moment before partial unwrapping
|
||||
println!("\n⏳ Waiting 3 seconds before partial unwrapping...");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
||||
|
||||
// Example 2: Close WSOL account and unwrap all remaining balance
|
||||
println!("\n🔒 Example 2: Closing WSOL account and unwrapping remaining balance");
|
||||
// Example 2: Unwrap half of the WSOL back to SOL using seed account
|
||||
println!("\n🔄 Example 2: Unwrapping half of WSOL back to SOL using seed account");
|
||||
let unwrap_amount = wrap_amount / 2; // Half of the wrapped amount
|
||||
println!("Unwrapping {} lamports (0.0005 SOL) back to SOL using seed account...", unwrap_amount);
|
||||
|
||||
match solana_trade.wrap_wsol_to_sol(unwrap_amount).await {
|
||||
Ok(signature) => {
|
||||
println!("✅ Successfully unwrapped half of WSOL back to SOL using seed account!");
|
||||
println!("Transaction signature: {}", signature);
|
||||
println!("Explorer: https://solscan.io/tx/{}", signature);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("❌ Failed to unwrap WSOL to SOL: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a moment before final unwrapping
|
||||
println!("\n⏳ Waiting 3 seconds before final unwrapping...");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
||||
|
||||
// Example 3: Close WSOL account and unwrap all remaining balance
|
||||
println!("\n🔒 Example 3: Closing WSOL account and unwrapping remaining balance");
|
||||
println!("Closing WSOL account and unwrapping all remaining balance to SOL...");
|
||||
|
||||
match solana_trade.close_wsol().await {
|
||||
@@ -53,7 +77,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// Create and initialize SolanaTrade client
|
||||
async fn create_solana_trade_client() -> Result<SolanaTrade, Box<dyn std::error::Error>> {
|
||||
println!("🚀 Initializing SolanaTrade client...");
|
||||
let payer = Keypair::from_base58_string("use_your_payer_keypair_here");
|
||||
let payer = Keypair::from_base58_string("R26eUYq691PC7AFh6yNyC285qr5tZfu43SAYhKGNZrpRVmrwDhR254bSS7Z1e87LWCmPNmiPvYkz9kA9hXyQD2m");
|
||||
let rpc_url = "https://api.mainnet-beta.solana.com".to_string();
|
||||
let commitment = CommitmentConfig::confirmed();
|
||||
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
|
||||
|
||||
@@ -30,6 +30,35 @@ pub fn close_account(
|
||||
Ok(Instruction { program_id: *token_program_id, accounts, data })
|
||||
}
|
||||
|
||||
pub fn transfer(
|
||||
token_program_id: &Pubkey,
|
||||
source_pubkey: &Pubkey,
|
||||
destination_pubkey: &Pubkey,
|
||||
owner_pubkey: &Pubkey,
|
||||
amount: u64,
|
||||
signers: &[&Pubkey],
|
||||
) -> Result<Instruction, ProgramError> {
|
||||
// Transfer
|
||||
let mut data = Vec::with_capacity(9);
|
||||
data.push(3); // Instruction discriminator for Transfer
|
||||
data.extend_from_slice(&amount.to_le_bytes());
|
||||
|
||||
let mut accounts = Vec::with_capacity(3 + signers.len());
|
||||
accounts.push(AccountMeta::new(*source_pubkey, false));
|
||||
accounts.push(AccountMeta::new(*destination_pubkey, false));
|
||||
accounts.push(AccountMeta::new_readonly(*owner_pubkey, signers.is_empty()));
|
||||
|
||||
for signer in signers.iter() {
|
||||
accounts.push(AccountMeta::new_readonly(**signer, true));
|
||||
}
|
||||
|
||||
Ok(Instruction {
|
||||
program_id: *token_program_id,
|
||||
accounts,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn initialize_account3(
|
||||
token_program_id: &Pubkey,
|
||||
account_pubkey: &Pubkey,
|
||||
|
||||
+36
@@ -663,4 +663,40 @@ impl SolanaTrade {
|
||||
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
||||
Ok(signature.to_string())
|
||||
}
|
||||
|
||||
/// 将 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 账号的指令
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `amount` - 要转换的 WSOL 数量(以 lamports 为单位)
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(String)` - 交易签名
|
||||
/// * `Err(anyhow::Error)` - 如果交易执行失败
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 此函数在以下情况下会返回错误:
|
||||
/// - 用户 WSOL ATA 中余额不足
|
||||
/// - seed 账户创建失败
|
||||
/// - 转账指令执行失败
|
||||
/// - 交易执行或确认失败
|
||||
/// - 网络或 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 solana_sdk::transaction::Transaction;
|
||||
|
||||
let recent_blockhash = self.rpc.get_latest_blockhash().await?;
|
||||
let instructions = wrap_wsol_to_sol_internal(&self.payer.pubkey(), amount)?;
|
||||
|
||||
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?;
|
||||
Ok(signature.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::common::{
|
||||
fast_fn::create_associated_token_account_idempotent_fast, spl_token::close_account,
|
||||
fast_fn::create_associated_token_account_idempotent_fast,
|
||||
spl_token::close_account,
|
||||
seed::{create_associated_token_account_use_seed, get_associated_token_address_with_program_id_use_seed},
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use solana_sdk::{instruction::Instruction, message::AccountMeta, pubkey::Pubkey};
|
||||
@@ -92,3 +94,61 @@ pub fn wrap_sol_only(payer: &Pubkey, amount_in: u64) -> SmallVec<[Instruction; 2
|
||||
|
||||
insts
|
||||
}
|
||||
|
||||
/// 将 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 账号的指令
|
||||
pub fn wrap_wsol_to_sol(
|
||||
payer: &Pubkey,
|
||||
amount: u64,
|
||||
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||
let mut instructions = Vec::new();
|
||||
|
||||
// 1. 创建 WSOL seed 账户
|
||||
let seed_account_instructions = create_associated_token_account_use_seed(
|
||||
payer,
|
||||
payer,
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
)?;
|
||||
instructions.extend(seed_account_instructions);
|
||||
|
||||
// 2. 获取 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,
|
||||
)?;
|
||||
|
||||
// 3. 获取用户的 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,
|
||||
);
|
||||
|
||||
// 4. 添加从用户 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);
|
||||
|
||||
// 5. 添加关闭 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