Buy and sell according to the trading platform
This commit is contained in:
+14
-1
@@ -1,2 +1,15 @@
|
||||
pub mod pumpfun;
|
||||
pub mod pumpswap;
|
||||
pub mod pumpswap;
|
||||
|
||||
pub mod trade_type {
|
||||
pub const COPY_BUY: &'static str = "copy_buy";
|
||||
pub const COPY_SELL: &'static str = "copy_sell";
|
||||
pub const SNIPER_BUY: &'static str = "sniper_buy";
|
||||
pub const SNIPER_SELL: &'static str = "sniper_sell";
|
||||
}
|
||||
|
||||
pub mod trade_platform {
|
||||
pub const PUMPFUN: &'static str = "pumpfun";
|
||||
pub const PUMPFUN_SWAP: &'static str = "pumpswap";
|
||||
pub const RAYDIUM: &'static str = "raydium";
|
||||
}
|
||||
@@ -173,10 +173,3 @@ impl Symbol {
|
||||
pub const SOLANA: &'static str = "solana";
|
||||
}
|
||||
|
||||
pub mod trade_type {
|
||||
pub const COPY_BUY: &'static str = "copy_buy";
|
||||
pub const COPY_SELL: &'static str = "copy_sell";
|
||||
pub const SNIPER_BUY: &'static str = "sniper_buy";
|
||||
pub const SNIPER_SELL: &'static str = "sniper_sell";
|
||||
}
|
||||
|
||||
|
||||
+166
-71
@@ -7,6 +7,7 @@ pub mod common;
|
||||
pub mod ipfs;
|
||||
pub mod swqos;
|
||||
pub mod pumpfun;
|
||||
pub mod pumpswap;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
@@ -24,7 +25,8 @@ use common::{pumpfun::logs_data::TradeInfo, pumpfun::logs_events::PumpfunEvent,
|
||||
use common::pumpfun::logs_subscribe::SubscriptionHandle;
|
||||
use ipfs::TokenMetadataIPFS;
|
||||
|
||||
use constants::pumpfun::trade_type::{COPY_BUY, SNIPER_BUY};
|
||||
use constants::trade_type::{COPY_BUY, SNIPER_BUY};
|
||||
use constants::trade_platform::{PUMPFUN, PUMPFUN_SWAP, RAYDIUM};
|
||||
|
||||
pub struct PumpFun {
|
||||
pub payer: Arc<Keypair>,
|
||||
@@ -228,21 +230,36 @@ impl PumpFun {
|
||||
buy_sol_cost: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::buy::buy(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
dev_buy_token,
|
||||
dev_sol_cost,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
COPY_BUY.to_string(),
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::buy::buy(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
dev_buy_token,
|
||||
dev_sol_cost,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
COPY_BUY.to_string(),
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::buy::buy(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
/// Buy tokens using Jito
|
||||
@@ -281,21 +298,37 @@ impl PumpFun {
|
||||
buy_sol_cost: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::buy::buy_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
dev_buy_token,
|
||||
dev_sol_cost,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
COPY_BUY.to_string(),
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::buy::buy_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
dev_buy_token,
|
||||
dev_sol_cost,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
COPY_BUY.to_string(),
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::buy::buy_with_tip(
|
||||
self.rpc.clone(),
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
buy_sol_cost,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sell tokens
|
||||
@@ -326,18 +359,33 @@ impl PumpFun {
|
||||
percent: u64,
|
||||
amount_token: u64,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::sell::sell_by_percent(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
creator,
|
||||
percent,
|
||||
amount_token,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::sell::sell_by_percent(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
creator,
|
||||
percent,
|
||||
amount_token,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::sell::sell_by_percent(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
percent,
|
||||
None,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sell tokens by amount
|
||||
@@ -347,17 +395,32 @@ impl PumpFun {
|
||||
creator: Pubkey,
|
||||
amount: u64,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::sell::sell_by_amount(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
creator,
|
||||
amount,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::sell::sell_by_amount(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
creator,
|
||||
amount,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::sell::sell_by_amount(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint.clone(),
|
||||
amount,
|
||||
None,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sell_by_percent_with_tip(
|
||||
@@ -367,18 +430,34 @@ impl PumpFun {
|
||||
percent: u64,
|
||||
amount_token: u64,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::sell::sell_by_percent_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
percent,
|
||||
amount_token,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::sell::sell_by_percent_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
percent,
|
||||
amount_token,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::sell::sell_by_percent_with_tip(
|
||||
self.rpc.clone(),
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
percent,
|
||||
None,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sell_by_amount_with_tip(
|
||||
@@ -387,17 +466,33 @@ impl PumpFun {
|
||||
creator: Pubkey,
|
||||
amount: u64,
|
||||
recent_blockhash: Hash,
|
||||
trade_platform: String,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::sell::sell_by_amount_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
amount,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
if trade_platform == PUMPFUN {
|
||||
pumpfun::sell::sell_by_amount_with_tip(
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
creator,
|
||||
amount,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
recent_blockhash,
|
||||
).await
|
||||
} else if trade_platform == PUMPFUN_SWAP {
|
||||
pumpswap::sell::sell_by_amount_with_tip(
|
||||
self.rpc.clone(),
|
||||
self.fee_clients.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
amount,
|
||||
None,
|
||||
self.priority_fee.clone(),
|
||||
self.cluster.clone().lookup_table_key,
|
||||
).await
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Unsupported trade platform: {}", trade_platform))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sell tokens using Jito
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ use crate::{
|
||||
const MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT: u32 = 250000;
|
||||
|
||||
use super::common::{calculate_with_slippage_buy, get_buy_token_amount_from_sol_amount, init_bonding_curve_account, get_bonding_curve_account_v2, get_bonding_curve_pda};
|
||||
use crate::constants::pumpfun::trade_type::{SNIPER_BUY};
|
||||
use crate::constants::trade_type::{SNIPER_BUY};
|
||||
use crate::PumpFun;
|
||||
|
||||
/// 添加nonce消费指令到指令集合中
|
||||
|
||||
+6
-5
@@ -11,12 +11,13 @@ use solana_sdk::{
|
||||
signature::{Keypair, Signer},
|
||||
system_instruction,
|
||||
transaction::VersionedTransaction,
|
||||
native_token::sol_to_lamports,
|
||||
};
|
||||
use spl_associated_token_account::instruction::create_associated_token_account_idempotent;
|
||||
|
||||
use crate::common::{address_lookup_cache::get_address_lookup_table_account, nonce_cache::{self, NonceCache}, PriorityFee, SolanaRpcClient};
|
||||
use crate::pumpswap::common::{calculate_with_slippage_buy, find_pool, get_buy_token_amount};
|
||||
use crate::constants::{accounts, trade::DEFAULT_SLIPPAGE, BUY_DISCRIMINATOR};
|
||||
use crate::constants::pumpswap::{accounts, trade::DEFAULT_SLIPPAGE, BUY_DISCRIMINATOR};
|
||||
use crate::swqos::FeeClient;
|
||||
|
||||
// Constants for compute budget
|
||||
@@ -31,7 +32,7 @@ const MAX_LOADED_ACCOUNTS_DATA_SIZE_LIMIT: u32 = 256 * 1024;
|
||||
fn add_nonce_instruction(instructions: &mut Vec<Instruction>, payer: &Keypair) -> Result<(), anyhow::Error> {
|
||||
let nonce_cache = NonceCache::get_instance();
|
||||
let nonce_info = nonce_cache.get_nonce_info();
|
||||
if let (Some(nonce_pubkey), Some(program_id)) = (nonce_info.nonce_account, nonce_info.program_id) {
|
||||
if let Some(nonce_pubkey) = nonce_info.nonce_account {
|
||||
let nonce_value = nonce_info.current_nonce;
|
||||
// 暂不加锁
|
||||
// if nonce_info.lock {
|
||||
@@ -47,7 +48,7 @@ fn add_nonce_instruction(instructions: &mut Vec<Instruction>, payer: &Keypair) -
|
||||
// nonce_cache.lock();
|
||||
// 创建自定义nonce消费指令
|
||||
let nonce_consume_ix = Instruction {
|
||||
program_id,
|
||||
program_id: crate::constants::pumpswap::accounts::AMM_PROGRAM,
|
||||
accounts: vec![
|
||||
AccountMeta::new(nonce_pubkey, false),
|
||||
AccountMeta::new_readonly(payer.pubkey(), true),
|
||||
@@ -55,7 +56,7 @@ fn add_nonce_instruction(instructions: &mut Vec<Instruction>, payer: &Keypair) -
|
||||
// INSTR_CONSUME = 1, 使用传入的nonce值
|
||||
data: {
|
||||
let mut data = vec![1]; // INSTR_CONSUME = 1
|
||||
data.extend_from_slice(&nonce_value.to_le_bytes()); // 添加nonce值
|
||||
data.extend_from_slice(&nonce_value.to_bytes()); // 添加nonce值
|
||||
data
|
||||
},
|
||||
};
|
||||
@@ -248,7 +249,7 @@ pub async fn build_buy_transaction_with_tip(
|
||||
system_instruction::transfer(
|
||||
&payer.pubkey(),
|
||||
&tip_account,
|
||||
priority_fee.buy_tip_fee,
|
||||
sol_to_lamports(priority_fee.buy_tip_fee),
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use anyhow::anyhow;
|
||||
use solana_account_decoder::UiAccountEncoding;
|
||||
use crate::{common::SolanaRpcClient, constants::accounts};
|
||||
use crate::{common::SolanaRpcClient, constants::pumpswap::accounts};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -91,7 +91,7 @@ impl Pool {
|
||||
sort_results: None,
|
||||
};
|
||||
|
||||
let program_id = crate::constants::accounts::AMM_PROGRAM;
|
||||
let program_id = crate::constants::pumpswap::accounts::AMM_PROGRAM;
|
||||
println!("program_id: {:?}", program_id);
|
||||
let accounts = rpc.get_program_accounts_with_config(&program_id, config).await?;
|
||||
|
||||
|
||||
+38
-3
@@ -5,17 +5,17 @@ use anyhow::anyhow;
|
||||
use solana_sdk::{
|
||||
compute_budget::ComputeBudgetInstruction,
|
||||
instruction::Instruction,
|
||||
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
system_instruction,
|
||||
transaction::VersionedTransaction,
|
||||
native_token::sol_to_lamports,
|
||||
};
|
||||
use spl_associated_token_account::instruction::create_associated_token_account_idempotent;
|
||||
|
||||
use crate::common::{address_lookup_cache::get_address_lookup_table_account, PriorityFee, SolanaRpcClient};
|
||||
use crate::pumpswap::common::{calculate_with_slippage_sell, find_pool, get_sell_sol_amount, get_token_balance};
|
||||
use crate::constants::{accounts, trade::DEFAULT_SLIPPAGE, SELL_DISCRIMINATOR};
|
||||
use crate::constants::pumpswap::{accounts, trade::DEFAULT_SLIPPAGE, SELL_DISCRIMINATOR};
|
||||
use crate::swqos::FeeClient;
|
||||
|
||||
// Constants for compute budget
|
||||
@@ -73,6 +73,23 @@ pub async fn sell_by_percent(
|
||||
sell(rpc, payer, mint, Some(amount), slippage_basis_points, priority_fee, lookup_table_key).await
|
||||
}
|
||||
|
||||
/// Sell tokens by amount
|
||||
pub async fn sell_by_amount(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Pubkey,
|
||||
amount: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
lookup_table_key: Option<Pubkey>
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if amount == 0 {
|
||||
return Err(anyhow!("Amount must be greater than 0"));
|
||||
}
|
||||
|
||||
sell(rpc, payer, mint, Some(amount), slippage_basis_points, priority_fee, lookup_table_key).await
|
||||
}
|
||||
|
||||
// Sell tokens using a MEV service
|
||||
pub async fn sell_with_tip(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
@@ -144,6 +161,24 @@ pub async fn sell_by_percent_with_tip(
|
||||
sell_with_tip(rpc, fee_clients, payer, mint, Some(amount), slippage_basis_points, priority_fee, lookup_table_key).await
|
||||
}
|
||||
|
||||
// Sell tokens by amount using a MEV service
|
||||
pub async fn sell_by_amount_with_tip(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
fee_clients: Vec<Arc<FeeClient>>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Pubkey,
|
||||
amount: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
lookup_table_key: Option<Pubkey>
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if amount == 0 {
|
||||
return Err(anyhow!("Amount must be greater than 0"));
|
||||
}
|
||||
|
||||
sell_with_tip(rpc, fee_clients, payer, mint, Some(amount), slippage_basis_points, priority_fee, lookup_table_key).await
|
||||
}
|
||||
|
||||
// Build a transaction for selling tokens
|
||||
pub async fn build_sell_transaction(
|
||||
_rpc: Arc<SolanaRpcClient>,
|
||||
@@ -206,7 +241,7 @@ pub async fn build_sell_transaction_with_tip(
|
||||
system_instruction::transfer(
|
||||
&payer.pubkey(),
|
||||
&tip_account,
|
||||
priority_fee.sell_tip_fee,
|
||||
sol_to_lamports(priority_fee.sell_tip_fee),
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user