feat: add wrap_wsol_to_sol function with seed account optimization
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "sol-trade-sdk"
|
name = "sol-trade-sdk"
|
||||||
version = "3.3.2"
|
version = "3.3.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = [
|
authors = [
|
||||||
"William <byteblock6@gmail.com>",
|
"William <byteblock6@gmail.com>",
|
||||||
|
|||||||
@@ -87,14 +87,14 @@ Add the dependency to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
# Add to your Cargo.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
|
### Use crates.io
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# Add to your Cargo.toml
|
# Add to your Cargo.toml
|
||||||
sol-trade-sdk = "3.3.2"
|
sol-trade-sdk = "3.3.3"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🛠️ Usage Examples
|
## 🛠️ Usage Examples
|
||||||
|
|||||||
+2
-2
@@ -87,14 +87,14 @@ git clone https://github.com/0xfnzero/sol-trade-sdk
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
# 添加到您的 Cargo.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
|
### 使用 crates.io
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# 添加到您的 Cargo.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]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("🔄 WSOL Wrapper Example");
|
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
|
// Initialize SolanaTrade client
|
||||||
let solana_trade = create_solana_trade_client().await?;
|
let solana_trade = create_solana_trade_client().await?;
|
||||||
@@ -24,15 +27,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("❌ Failed to wrap SOL to WSOL: {}", e);
|
println!("❌ Failed to wrap SOL to WSOL: {}", e);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait a moment before unwrapping
|
// Wait a moment before partial unwrapping
|
||||||
println!("\n⏳ Waiting 3 seconds before unwrapping...");
|
println!("\n⏳ Waiting 3 seconds before partial unwrapping...");
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
||||||
|
|
||||||
// Example 2: Close WSOL account and unwrap all remaining balance
|
// Example 2: Unwrap half of the WSOL back to SOL using seed account
|
||||||
println!("\n🔒 Example 2: Closing WSOL account and unwrapping remaining balance");
|
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...");
|
println!("Closing WSOL account and unwrapping all remaining balance to SOL...");
|
||||||
|
|
||||||
match solana_trade.close_wsol().await {
|
match solana_trade.close_wsol().await {
|
||||||
@@ -53,7 +77,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
/// Create and initialize SolanaTrade client
|
/// Create and initialize SolanaTrade client
|
||||||
async fn create_solana_trade_client() -> Result<SolanaTrade, Box<dyn std::error::Error>> {
|
async fn create_solana_trade_client() -> Result<SolanaTrade, Box<dyn std::error::Error>> {
|
||||||
println!("🚀 Initializing SolanaTrade client...");
|
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 rpc_url = "https://api.mainnet-beta.solana.com".to_string();
|
||||||
let commitment = CommitmentConfig::confirmed();
|
let commitment = CommitmentConfig::confirmed();
|
||||||
let swqos_configs: Vec<SwqosConfig> = vec![SwqosConfig::Default(rpc_url.clone())];
|
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 })
|
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(
|
pub fn initialize_account3(
|
||||||
token_program_id: &Pubkey,
|
token_program_id: &Pubkey,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
|
|||||||
+36
@@ -663,4 +663,40 @@ impl SolanaTrade {
|
|||||||
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
let signature = self.rpc.send_and_confirm_transaction(&transaction).await?;
|
||||||
Ok(signature.to_string())
|
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::{
|
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 smallvec::SmallVec;
|
||||||
use solana_sdk::{instruction::Instruction, message::AccountMeta, pubkey::Pubkey};
|
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
|
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