feat: upgrade to v1.1.0 and add universal token swap functionality
- Version bump: upgrade from 1.0.2 to 1.1.0 - Add TradeSwapParams struct for universal token-to-token swapping - Update bonk_copy_trading example to use new swap method instead of buy/sell - Expand trading parameters documentation with TradeSwapParams details - Fix SOL_TOKEN_ACCOUNT constant definition - Add USD1 token support (Bonk protocol only) - Enhance account management and optimization options for token swaps
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sol-trade-sdk"
|
||||
version = "1.0.2"
|
||||
version = "1.1.0"
|
||||
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 = "1.0.2" }
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.1.0" }
|
||||
```
|
||||
|
||||
### Use crates.io
|
||||
|
||||
```toml
|
||||
# Add to your Cargo.toml
|
||||
sol-trade-sdk = "1.0.2"
|
||||
sol-trade-sdk = "1.1.0"
|
||||
```
|
||||
|
||||
## 🛠️ 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 = "1.0.2" }
|
||||
sol-trade-sdk = { path = "./sol-trade-sdk", version = "1.1.0" }
|
||||
```
|
||||
|
||||
### 使用 crates.io
|
||||
|
||||
```toml
|
||||
# 添加到您的 Cargo.toml
|
||||
sol-trade-sdk = "1.0.2"
|
||||
sol-trade-sdk = "1.1.0"
|
||||
```
|
||||
|
||||
## 🛠️ 使用示例
|
||||
|
||||
@@ -4,11 +4,60 @@ This document provides a comprehensive reference for all trading parameters used
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
- [TradeSwapParams](#tradeswapparams)
|
||||
- [TradeBuyParams](#tradebuyparams)
|
||||
- [TradeSellParams](#tradesellparams)
|
||||
- [Parameter Categories](#parameter-categories)
|
||||
- [Important Notes](#important-notes)
|
||||
|
||||
## TradeSwapParams
|
||||
|
||||
The `TradeSwapParams` struct contains all parameters required for executing swap orders across different DEX protocols. This is the most flexible trading method that supports swapping between any supported tokens.
|
||||
|
||||
### Basic Trading Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `dex_type` | `DexType` | ✅ | The trading protocol to use (PumpFun, PumpSwap, Bonk, RaydiumCpmm, RaydiumAmmV4) |
|
||||
| `input_mint` | `Pubkey` | ✅ | The public key of the token to spend (input token) |
|
||||
| `output_mint` | `Pubkey` | ✅ | The public key of the token to receive (output token) |
|
||||
| `input_token_program` | `Pubkey` | ✅ | The token program ID for the input token |
|
||||
| `output_token_program` | `Pubkey` | ✅ | The token program ID for the output token |
|
||||
| `input_amount` | `u64` | ✅ | Amount of input token to spend (in smallest token units) |
|
||||
| `slippage_basis_points` | `Option<u64>` | ❌ | Slippage tolerance in basis points (e.g., 100 = 1%, 500 = 5%) |
|
||||
| `recent_blockhash` | `Option<Hash>` | ❌ | Recent blockhash for transaction validity |
|
||||
| `extension_params` | `Box<dyn ProtocolParams>` | ✅ | Protocol-specific parameters (PumpFunParams, PumpSwapParams, etc.) |
|
||||
|
||||
### Advanced Configuration Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `lookup_table_key` | `Option<Pubkey>` | ❌ | Address lookup table key for transaction optimization |
|
||||
| `wait_transaction_confirmed` | `bool` | ✅ | Whether to wait for transaction confirmation |
|
||||
| `create_input_mint_ata` | `bool` | ✅ | Whether to create input token Associated Token Account |
|
||||
| `close_input_mint_ata` | `bool` | ✅ | Whether to close input token ATA after transaction |
|
||||
| `create_output_mint_ata` | `bool` | ✅ | Whether to create output token ATA |
|
||||
| `close_output_mint_ata` | `bool` | ✅ | Whether to close output token ATA after transaction |
|
||||
| `open_seed_optimize` | `bool` | ✅ | Whether to use seed optimization for reduced CU consumption |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | Durable nonce information containing nonce account and current nonce value |
|
||||
| `with_tip` | `bool` | ✅ | Whether to include tip for transaction priority |
|
||||
|
||||
### Supported Token Pairs
|
||||
|
||||
The SDK currently supports swap trading between the following base tokens and other tokens:
|
||||
- **SOL** (Native Solana token)
|
||||
- **WSOL** (Wrapped SOL)
|
||||
- **USD1** (USD1 stablecoin - currently only supported on Bonk protocol)
|
||||
|
||||
**Important**: At least one token in the swap pair must be a supported base token (SOL, WSOL, or USD1).
|
||||
|
||||
### USD1 Token Support
|
||||
|
||||
USD1 token support has the following limitations:
|
||||
- **Protocol Restriction**: USD1 trading is currently only supported on the Bonk protocol
|
||||
- **Pair Requirements**: USD1 can be swapped with other tokens, but the swap must occur on Bonk DEX
|
||||
- **Token Address**: `USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB`
|
||||
|
||||
## TradeBuyParams
|
||||
|
||||
The `TradeBuyParams` struct contains all parameters required for executing buy orders across different DEX protocols.
|
||||
|
||||
@@ -4,11 +4,60 @@
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [TradeSwapParams](#tradeswapparams)
|
||||
- [TradeBuyParams](#tradebuyparams)
|
||||
- [TradeSellParams](#tradesellparams)
|
||||
- [参数分类](#参数分类)
|
||||
- [重要说明](#重要说明)
|
||||
|
||||
## TradeSwapParams
|
||||
|
||||
`TradeSwapParams` 结构体包含在不同 DEX 协议上执行代币交换订单所需的所有参数。这是最灵活的交易方法,支持在任何支持的代币之间进行交换。
|
||||
|
||||
### 基础交易参数
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
|------|------|------|------|
|
||||
| `dex_type` | `DexType` | ✅ | 要使用的交易协议 (PumpFun, PumpSwap, Bonk, RaydiumCpmm, RaydiumAmmV4) |
|
||||
| `input_mint` | `Pubkey` | ✅ | 要花费的代币公钥(输入代币) |
|
||||
| `output_mint` | `Pubkey` | ✅ | 要接收的代币公钥(输出代币) |
|
||||
| `input_token_program` | `Pubkey` | ✅ | 输入代币的代币程序 ID |
|
||||
| `output_token_program` | `Pubkey` | ✅ | 输出代币的代币程序 ID |
|
||||
| `input_amount` | `u64` | ✅ | 要花费的输入代币数量(最小代币单位) |
|
||||
| `slippage_basis_points` | `Option<u64>` | ❌ | 滑点容忍度(基点单位,例如 100 = 1%, 500 = 5%) |
|
||||
| `recent_blockhash` | `Option<Hash>` | ❌ | 用于交易有效性的最新区块哈希 |
|
||||
| `extension_params` | `Box<dyn ProtocolParams>` | ✅ | 协议特定参数 (PumpFunParams, PumpSwapParams 等) |
|
||||
|
||||
### 高级配置参数
|
||||
|
||||
| 参数 | 类型 | 必需 | 描述 |
|
||||
|------|------|------|------|
|
||||
| `lookup_table_key` | `Option<Pubkey>` | ❌ | 用于交易优化的地址查找表键 |
|
||||
| `wait_transaction_confirmed` | `bool` | ✅ | 是否等待交易确认 |
|
||||
| `create_input_mint_ata` | `bool` | ✅ | 是否创建输入代币关联代币账户 |
|
||||
| `close_input_mint_ata` | `bool` | ✅ | 交易后是否关闭输入代币 ATA |
|
||||
| `create_output_mint_ata` | `bool` | ✅ | 是否创建输出代币 ATA |
|
||||
| `close_output_mint_ata` | `bool` | ✅ | 交易后是否关闭输出代币 ATA |
|
||||
| `open_seed_optimize` | `bool` | ✅ | 是否使用 seed 优化以减少 CU 消耗 |
|
||||
| `durable_nonce` | `Option<DurableNonceInfo>` | ❌ | 持久 nonce 信息,包含 nonce 账户和当前 nonce 值 |
|
||||
| `with_tip` | `bool` | ✅ | 是否包含小费以提高交易优先级 |
|
||||
|
||||
### 支持的代币交易对
|
||||
|
||||
SDK 目前支持以下基础代币与其他代币之间的交换交易:
|
||||
- **SOL**(Solana 原生代币)
|
||||
- **WSOL**(包装 SOL)
|
||||
- **USD1**(USD1 稳定币 - 目前仅在 Bonk 协议上支持)
|
||||
|
||||
**重要提示**:交换对中至少有一个代币必须是支持的基础代币(SOL、WSOL 或 USD1)。
|
||||
|
||||
### USD1 代币支持
|
||||
|
||||
USD1 代币支持有以下限制:
|
||||
- **协议限制**:USD1 交易目前仅在 Bonk 协议上支持
|
||||
- **交易对要求**:USD1 可以与其他代币交换,但必须在 Bonk DEX 上进行
|
||||
- **代币地址**:`USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB`
|
||||
|
||||
## TradeBuyParams
|
||||
|
||||
`TradeBuyParams` 结构体包含在不同 DEX 协议上执行买入订单所需的所有参数。
|
||||
|
||||
@@ -88,9 +88,6 @@ fn create_event_callback() -> impl Fn(Box<dyn UnifiedEvent>) {
|
||||
|event: Box<dyn UnifiedEvent>| {
|
||||
match_event!(event, {
|
||||
BonkTradeEvent => |e: BonkTradeEvent| {
|
||||
if e.base_token_mint != WSOL_TOKEN_ACCOUNT && e.quote_token_mint != WSOL_TOKEN_ACCOUNT {
|
||||
return;
|
||||
}
|
||||
// Test code, only test one transaction
|
||||
if !ALREADY_EXECUTED.swap(true, Ordering::SeqCst) {
|
||||
let event_clone = e.clone();
|
||||
@@ -129,28 +126,34 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()>
|
||||
|
||||
let client = create_solana_trade_client().await?;
|
||||
let mint_pubkey = trade_info.base_token_mint;
|
||||
let quote_mint_pubkey = trade_info.quote_token_mint;
|
||||
let slippage_basis_points = Some(100);
|
||||
let recent_blockhash = client.rpc.get_latest_blockhash().await?;
|
||||
|
||||
// Buy tokens
|
||||
println!("Buying tokens from Bonk...");
|
||||
let buy_sol_amount = 100_000;
|
||||
let buy_params = sol_trade_sdk::TradeBuyParams {
|
||||
let buy_params = sol_trade_sdk::TradeSwapParams {
|
||||
dex_type: DexType::Bonk,
|
||||
mint: mint_pubkey,
|
||||
sol_amount: buy_sol_amount,
|
||||
input_mint: quote_mint_pubkey,
|
||||
output_mint: mint_pubkey,
|
||||
input_token_program: trade_info.quote_token_program,
|
||||
output_token_program: trade_info.base_token_program,
|
||||
input_amount: buy_sol_amount,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::from_trade(trade_info.clone())),
|
||||
lookup_table_key: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_wsol_ata: true,
|
||||
close_wsol_ata: true,
|
||||
create_mint_ata: true,
|
||||
create_input_mint_ata: true,
|
||||
close_input_mint_ata: false,
|
||||
create_output_mint_ata: true,
|
||||
close_output_mint_ata: true,
|
||||
open_seed_optimize: false,
|
||||
durable_nonce: None,
|
||||
with_tip: true,
|
||||
};
|
||||
client.buy(buy_params).await?;
|
||||
client.swap(buy_params).await?;
|
||||
|
||||
// Sell tokens
|
||||
println!("Selling tokens from Bonk...");
|
||||
@@ -163,22 +166,27 @@ async fn bonk_copy_trade_with_grpc(trade_info: BonkTradeEvent) -> AnyResult<()>
|
||||
let amount_token = balance.amount.parse::<u64>().unwrap();
|
||||
|
||||
println!("Selling {} tokens", amount_token);
|
||||
let sell_params = sol_trade_sdk::TradeSellParams {
|
||||
let sell_params = sol_trade_sdk::TradeSwapParams {
|
||||
dex_type: DexType::Bonk,
|
||||
mint: mint_pubkey,
|
||||
token_amount: amount_token,
|
||||
input_mint: mint_pubkey,
|
||||
output_mint: quote_mint_pubkey,
|
||||
input_token_program: trade_info.base_token_program,
|
||||
output_token_program: trade_info.quote_token_program,
|
||||
input_amount: amount_token,
|
||||
slippage_basis_points: slippage_basis_points,
|
||||
recent_blockhash: Some(recent_blockhash),
|
||||
extension_params: Box::new(BonkParams::from_trade(trade_info.clone())),
|
||||
lookup_table_key: None,
|
||||
wait_transaction_confirmed: true,
|
||||
create_wsol_ata: true,
|
||||
close_wsol_ata: true,
|
||||
open_seed_optimize: false,
|
||||
with_tip: false,
|
||||
durable_nonce: None,
|
||||
create_input_mint_ata: false,
|
||||
close_input_mint_ata: false,
|
||||
create_output_mint_ata: true,
|
||||
close_output_mint_ata: false,
|
||||
};
|
||||
client.sell(sell_params).await?;
|
||||
client.swap(sell_params).await?;
|
||||
|
||||
// Exit program
|
||||
std::process::exit(0);
|
||||
|
||||
@@ -24,7 +24,7 @@ pub const TOKEN_PROGRAM_2022_META: solana_sdk::instruction::AccountMeta =
|
||||
is_writable: false,
|
||||
};
|
||||
|
||||
pub const SOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112");
|
||||
pub const SOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111111");
|
||||
|
||||
pub const WSOL_TOKEN_ACCOUNT: Pubkey = pubkey!("So11111111111111111111111111111111111111112");
|
||||
pub const WSOL_TOKEN_ACCOUNT_META: solana_sdk::instruction::AccountMeta =
|
||||
|
||||
+148
@@ -9,6 +9,7 @@ use crate::common::nonce_cache::DurableNonceInfo;
|
||||
use crate::common::TradeConfig;
|
||||
use crate::constants::trade::trade::DEFAULT_SLIPPAGE;
|
||||
use crate::constants::SOL_TOKEN_ACCOUNT;
|
||||
use crate::constants::USD1_TOKEN_ACCOUNT;
|
||||
use crate::constants::WSOL_TOKEN_ACCOUNT;
|
||||
use crate::swqos::SwqosClient;
|
||||
use crate::swqos::SwqosConfig;
|
||||
@@ -60,6 +61,52 @@ impl Clone for SolanaTrade {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters for executing swap orders across different DEX protocols
|
||||
///
|
||||
/// Contains all necessary configuration for swapping tokens, including
|
||||
/// protocol-specific settings, account management options, and transaction preferences.
|
||||
#[derive(Clone)]
|
||||
pub struct TradeSwapParams {
|
||||
// Trading configuration
|
||||
/// The DEX protocol to use for the trade
|
||||
pub dex_type: DexType,
|
||||
/// Public key of the token to purchase
|
||||
pub input_mint: Pubkey,
|
||||
/// Public key of the token to sell
|
||||
pub output_mint: Pubkey,
|
||||
/// Public key of the token program to use for the input token
|
||||
pub input_token_program: Pubkey,
|
||||
/// Public key of the token program to use for the output token
|
||||
pub output_token_program: Pubkey,
|
||||
/// Amount of input token to spend (in lamports)
|
||||
pub input_amount: u64,
|
||||
/// Optional slippage tolerance in basis points (e.g., 100 = 1%)
|
||||
pub slippage_basis_points: Option<u64>,
|
||||
/// Recent blockhash for transaction validity
|
||||
pub recent_blockhash: Option<Hash>,
|
||||
/// Protocol-specific parameters (PumpFun, Raydium, etc.)
|
||||
pub extension_params: Box<dyn ProtocolParams>,
|
||||
// Extended configuration
|
||||
/// Optional address lookup table for transaction size optimization
|
||||
pub lookup_table_key: Option<Pubkey>,
|
||||
/// Whether to wait for transaction confirmation before returning
|
||||
pub wait_transaction_confirmed: bool,
|
||||
/// Whether to create wrapped SOL associated token account
|
||||
pub create_input_mint_ata: bool,
|
||||
/// Whether to close wrapped SOL associated token account after trade
|
||||
pub close_input_mint_ata: bool,
|
||||
/// Whether to create token mint associated token account
|
||||
pub create_output_mint_ata: bool,
|
||||
/// Whether to close token mint associated token account after trade
|
||||
pub close_output_mint_ata: bool,
|
||||
/// Whether to enable seed-based optimization for account creation
|
||||
pub open_seed_optimize: bool,
|
||||
/// Durable nonce information
|
||||
pub durable_nonce: Option<DurableNonceInfo>,
|
||||
/// Whether to include tip for transaction priority
|
||||
pub with_tip: bool,
|
||||
}
|
||||
|
||||
/// Parameters for executing buy orders across different DEX protocols
|
||||
///
|
||||
/// Contains all necessary configuration for purchasing tokens, including
|
||||
@@ -224,6 +271,107 @@ impl SolanaTrade {
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Execute a swap order for a specified token
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `params` - Swap trade parameters containing all necessary trading configuration
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `Ok(Signature)` with the transaction signature if the swap order is successfully executed,
|
||||
/// or an error if the transaction fails.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if:
|
||||
/// - Invalid protocol parameters are provided for the specified DEX type
|
||||
/// - The transaction fails to execute
|
||||
/// - Network or RPC errors occur
|
||||
/// - Insufficient token balance for the sale
|
||||
/// - Token account doesn't exist or is not properly initialized
|
||||
/// - Required accounts cannot be created or accessed
|
||||
pub async fn swap(&self, params: TradeSwapParams) -> Result<Signature, anyhow::Error> {
|
||||
if params.slippage_basis_points.is_none() {
|
||||
println!(
|
||||
"slippage_basis_points is none, use default slippage basis points: {}",
|
||||
DEFAULT_SLIPPAGE
|
||||
);
|
||||
}
|
||||
let executor = TradeFactory::create_executor(params.dex_type.clone());
|
||||
let protocol_params = params.extension_params;
|
||||
let buy_params = SwapParams {
|
||||
rpc: Some(self.rpc.clone()),
|
||||
payer: self.payer.clone(),
|
||||
input_mint: params.input_mint,
|
||||
output_mint: params.output_mint,
|
||||
input_token_program: Some(params.input_token_program),
|
||||
output_token_program: Some(params.output_token_program),
|
||||
input_amount: Some(params.input_amount),
|
||||
slippage_basis_points: params.slippage_basis_points,
|
||||
lookup_table_key: params.lookup_table_key,
|
||||
recent_blockhash: params.recent_blockhash,
|
||||
data_size_limit: 256 * 1024,
|
||||
wait_transaction_confirmed: params.wait_transaction_confirmed,
|
||||
protocol_params: protocol_params.clone(),
|
||||
open_seed_optimize: params.open_seed_optimize,
|
||||
swqos_clients: self.swqos_clients.clone(),
|
||||
middleware_manager: self.middleware_manager.clone(),
|
||||
durable_nonce: params.durable_nonce,
|
||||
with_tip: params.with_tip,
|
||||
create_input_mint_ata: params.create_input_mint_ata,
|
||||
close_input_mint_ata: params.close_input_mint_ata,
|
||||
create_output_mint_ata: params.create_output_mint_ata,
|
||||
close_output_mint_ata: params.close_output_mint_ata,
|
||||
};
|
||||
|
||||
// Validate protocol params
|
||||
let is_valid_params = match params.dex_type {
|
||||
DexType::PumpFun => protocol_params.as_any().downcast_ref::<PumpFunParams>().is_some(),
|
||||
DexType::PumpSwap => {
|
||||
protocol_params.as_any().downcast_ref::<PumpSwapParams>().is_some()
|
||||
}
|
||||
DexType::Bonk => protocol_params.as_any().downcast_ref::<BonkParams>().is_some(),
|
||||
DexType::RaydiumCpmm => {
|
||||
protocol_params.as_any().downcast_ref::<RaydiumCpmmParams>().is_some()
|
||||
}
|
||||
DexType::RaydiumAmmV4 => {
|
||||
protocol_params.as_any().downcast_ref::<RaydiumAmmV4Params>().is_some()
|
||||
}
|
||||
};
|
||||
|
||||
if !is_valid_params {
|
||||
return Err(anyhow::anyhow!("Invalid protocol params for Trade"));
|
||||
}
|
||||
|
||||
let mut no_support_mint = false;
|
||||
|
||||
// 检查是否至少有一个代币是支持的基础代币(SOL、WSOL、USD1)
|
||||
let has_supported_base_token = params.input_mint == SOL_TOKEN_ACCOUNT
|
||||
|| params.output_mint == SOL_TOKEN_ACCOUNT
|
||||
|| params.input_mint == WSOL_TOKEN_ACCOUNT
|
||||
|| params.output_mint == WSOL_TOKEN_ACCOUNT
|
||||
|| params.input_mint == USD1_TOKEN_ACCOUNT
|
||||
|| params.output_mint == USD1_TOKEN_ACCOUNT;
|
||||
|
||||
if !has_supported_base_token {
|
||||
no_support_mint = true;
|
||||
}
|
||||
|
||||
// USD1 代币暂支持在 Bonk 协议上交易
|
||||
if (params.input_mint == USD1_TOKEN_ACCOUNT || params.output_mint == USD1_TOKEN_ACCOUNT)
|
||||
&& params.dex_type != DexType::Bonk
|
||||
{
|
||||
no_support_mint = true;
|
||||
}
|
||||
|
||||
if no_support_mint {
|
||||
return Err(anyhow::anyhow!("Currently only supports swap trading between (SOL、WSOL、USD1) and other tokens. USD1 swap trading is currently only supported on the Bonk protocol."));
|
||||
}
|
||||
|
||||
executor.swap(buy_params).await
|
||||
}
|
||||
|
||||
/// Execute a buy order for a specified token
|
||||
///
|
||||
/// # Arguments
|
||||
|
||||
Reference in New Issue
Block a user