2024-12-31 16:51:58 +08:00
|
|
|
pub mod accounts;
|
|
|
|
|
pub mod constants;
|
|
|
|
|
pub mod error;
|
|
|
|
|
pub mod instruction;
|
2025-01-03 14:43:26 +08:00
|
|
|
pub mod jito;
|
2025-01-23 17:48:10 +08:00
|
|
|
pub mod grpc;
|
2025-01-23 21:15:55 +08:00
|
|
|
pub mod common;
|
2025-02-21 20:47:28 +08:00
|
|
|
pub mod ipfs;
|
|
|
|
|
pub mod trade;
|
|
|
|
|
|
|
|
|
|
use std::sync::Arc;
|
2025-01-23 17:48:10 +08:00
|
|
|
|
2025-02-12 20:12:14 +08:00
|
|
|
use anyhow::anyhow;
|
2025-02-21 20:47:28 +08:00
|
|
|
use solana_client::rpc_client::RpcClient;
|
2025-01-23 17:48:10 +08:00
|
|
|
use solana_sdk::{
|
2025-02-21 20:47:28 +08:00
|
|
|
commitment_config::CommitmentConfig,
|
|
|
|
|
pubkey::Pubkey,
|
|
|
|
|
signature::{Keypair, Signer, Signature},
|
2024-12-31 16:51:58 +08:00
|
|
|
};
|
2025-01-14 19:18:48 +08:00
|
|
|
|
2025-01-25 17:16:52 +08:00
|
|
|
use common::{logs_data::TradeInfo, logs_events::PumpfunEvent, logs_subscribe};
|
2025-01-23 21:15:55 +08:00
|
|
|
use common::logs_subscribe::SubscriptionHandle;
|
2025-02-21 20:47:28 +08:00
|
|
|
use ipfs::TokenMetadataIPFS;
|
2025-01-03 14:43:26 +08:00
|
|
|
|
|
|
|
|
use crate::jito::JitoClient;
|
2025-02-21 20:47:28 +08:00
|
|
|
use crate::trade::common::PriorityFee;
|
2025-01-09 16:59:05 +08:00
|
|
|
|
2024-12-31 16:51:58 +08:00
|
|
|
pub struct PumpFun {
|
|
|
|
|
pub payer: Arc<Keypair>,
|
2025-02-21 20:47:28 +08:00
|
|
|
pub rpc: RpcClient,
|
2025-01-08 16:33:43 +08:00
|
|
|
pub jito_client: Option<JitoClient>,
|
2025-01-09 00:12:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Clone for PumpFun {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self {
|
2025-02-21 20:47:28 +08:00
|
|
|
payer: self.payer.clone(),
|
2025-01-09 00:12:43 +08:00
|
|
|
rpc: RpcClient::new_with_commitment(
|
|
|
|
|
self.rpc.url().to_string(),
|
|
|
|
|
self.rpc.commitment()
|
|
|
|
|
),
|
|
|
|
|
jito_client: self.jito_client.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PumpFun {
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2024-12-31 16:51:58 +08:00
|
|
|
pub fn new(
|
2025-02-21 20:47:28 +08:00
|
|
|
payer: Arc<Keypair>,
|
2025-01-23 17:48:10 +08:00
|
|
|
rpc_url: String,
|
2025-01-09 00:12:43 +08:00
|
|
|
commitment: Option<CommitmentConfig>,
|
|
|
|
|
jito_url: Option<String>,
|
2024-12-31 16:51:58 +08:00
|
|
|
) -> Self {
|
2025-01-09 00:12:43 +08:00
|
|
|
let rpc = RpcClient::new_with_commitment(
|
2025-01-23 17:48:10 +08:00
|
|
|
rpc_url,
|
2025-01-25 16:31:11 +08:00
|
|
|
commitment.unwrap_or(CommitmentConfig::processed())
|
2025-01-09 15:43:21 +08:00
|
|
|
);
|
2024-12-31 16:51:58 +08:00
|
|
|
|
2025-01-14 19:18:48 +08:00
|
|
|
let jito_client = jito_url.map(|url| JitoClient::new(&url, None));
|
2025-01-03 14:43:26 +08:00
|
|
|
|
2024-12-31 16:51:58 +08:00
|
|
|
Self {
|
|
|
|
|
payer,
|
2025-02-21 20:47:28 +08:00
|
|
|
rpc,
|
2025-01-03 14:43:26 +08:00
|
|
|
jito_client,
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Create a new token
|
2024-12-31 16:51:58 +08:00
|
|
|
pub async fn create(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Keypair,
|
2025-02-21 20:47:28 +08:00
|
|
|
ipfs: TokenMetadataIPFS,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<Signature, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::create::create(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
2024-12-31 16:51:58 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
ipfs,
|
|
|
|
|
priority_fee,
|
|
|
|
|
).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn create_and_buy(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Keypair,
|
2025-02-21 20:47:28 +08:00
|
|
|
ipfs: TokenMetadataIPFS,
|
2024-12-31 16:51:58 +08:00
|
|
|
amount_sol: u64,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<Signature, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::create::create_and_buy(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
2024-12-31 16:51:58 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
ipfs,
|
|
|
|
|
amount_sol,
|
|
|
|
|
slippage_basis_points,
|
|
|
|
|
priority_fee,
|
|
|
|
|
).await
|
|
|
|
|
}
|
2024-12-31 16:51:58 +08:00
|
|
|
|
2025-02-21 20:47:28 +08:00
|
|
|
pub async fn create_and_buy_list_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
payers: Vec<&Keypair>,
|
|
|
|
|
mint: &Keypair,
|
|
|
|
|
ipfs: TokenMetadataIPFS,
|
|
|
|
|
amount_sols: Vec<u64>,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-21 20:47:28 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
|
|
|
|
trade::create::create_and_buy_list_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.jito_client.as_ref().unwrap(),
|
|
|
|
|
payers,
|
|
|
|
|
mint,
|
|
|
|
|
ipfs,
|
|
|
|
|
amount_sols,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
2025-02-21 20:47:28 +08:00
|
|
|
).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
|
2025-02-21 20:47:28 +08:00
|
|
|
pub async fn create_and_buy_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
payer: &Keypair,
|
|
|
|
|
mint: &Keypair,
|
|
|
|
|
ipfs: TokenMetadataIPFS,
|
|
|
|
|
amount_sol: u64,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-21 20:47:28 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
|
|
|
|
trade::create::create_and_buy_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.jito_client.as_ref().unwrap(),
|
|
|
|
|
payer,
|
|
|
|
|
mint,
|
|
|
|
|
ipfs,
|
|
|
|
|
amount_sol,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
2025-02-21 20:47:28 +08:00
|
|
|
).await
|
|
|
|
|
}
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Buy tokens
|
2024-12-31 16:51:58 +08:00
|
|
|
pub async fn buy(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
amount_sol: u64,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<Signature, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::buy::buy(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
2024-12-31 16:51:58 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
amount_sol,
|
|
|
|
|
slippage_basis_points,
|
|
|
|
|
priority_fee,
|
|
|
|
|
).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Buy tokens using Jito
|
2025-01-03 14:43:26 +08:00
|
|
|
pub async fn buy_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
2025-02-21 20:47:28 +08:00
|
|
|
amount_sol: u64,
|
2025-01-03 14:43:26 +08:00
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::buy::buy_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.jito_client.as_ref().unwrap(),
|
|
|
|
|
&self.payer,
|
2025-01-03 14:43:26 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
amount_sol,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
2025-02-21 20:47:28 +08:00
|
|
|
).await
|
|
|
|
|
}
|
2025-01-03 14:43:26 +08:00
|
|
|
|
2025-02-21 20:47:28 +08:00
|
|
|
pub async fn buy_list_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
payers: Vec<&Keypair>,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
amount_sols: Vec<u64>,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-21 20:47:28 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
|
|
|
|
trade::buy::buy_list_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.jito_client.as_ref().unwrap(),
|
|
|
|
|
payers,
|
|
|
|
|
mint,
|
|
|
|
|
amount_sols,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
2025-02-21 20:47:28 +08:00
|
|
|
).await
|
2025-01-03 14:43:26 +08:00
|
|
|
}
|
|
|
|
|
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Sell tokens
|
2024-12-31 16:51:58 +08:00
|
|
|
pub async fn sell(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
amount_token: Option<u64>,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-21 20:47:28 +08:00
|
|
|
) -> Result<Signature, anyhow::Error> {
|
|
|
|
|
trade::sell::sell(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
2025-01-07 13:18:31 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
amount_token,
|
|
|
|
|
slippage_basis_points,
|
|
|
|
|
priority_fee,
|
|
|
|
|
).await
|
2025-01-07 13:18:31 +08:00
|
|
|
}
|
|
|
|
|
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Sell tokens by percentage
|
2025-01-07 13:18:31 +08:00
|
|
|
pub async fn sell_by_percent(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
percent: u64,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-21 20:47:28 +08:00
|
|
|
) -> Result<Signature, anyhow::Error> {
|
|
|
|
|
trade::sell::sell_by_percent(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
|
|
|
|
mint,
|
|
|
|
|
percent,
|
|
|
|
|
slippage_basis_points,
|
|
|
|
|
priority_fee,
|
|
|
|
|
).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
|
2025-01-14 19:18:48 +08:00
|
|
|
pub async fn sell_by_percent_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
percent: u64,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::sell::sell_by_percent_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
|
|
|
|
self.jito_client.as_ref().unwrap(),
|
|
|
|
|
mint,
|
|
|
|
|
percent,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
|
|
|
|
).await
|
2025-01-14 19:18:48 +08:00
|
|
|
}
|
|
|
|
|
|
2025-01-09 00:12:43 +08:00
|
|
|
/// Sell tokens using Jito
|
2025-01-03 14:43:26 +08:00
|
|
|
pub async fn sell_with_jito(
|
|
|
|
|
&self,
|
|
|
|
|
mint: &Pubkey,
|
|
|
|
|
amount_token: Option<u64>,
|
|
|
|
|
slippage_basis_points: Option<u64>,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee: PriorityFee,
|
2025-02-12 22:46:09 +08:00
|
|
|
) -> Result<String, anyhow::Error> {
|
2025-01-09 00:12:43 +08:00
|
|
|
let jito_client = self.jito_client.as_ref()
|
2025-02-12 22:46:09 +08:00
|
|
|
.ok_or_else(|| anyhow!("Jito client not found"))?;
|
2025-01-08 16:33:43 +08:00
|
|
|
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::sell::sell_with_jito(
|
|
|
|
|
&self.rpc,
|
|
|
|
|
&self.payer,
|
|
|
|
|
jito_client,
|
2025-01-03 14:43:26 +08:00
|
|
|
mint,
|
2025-02-21 20:47:28 +08:00
|
|
|
amount_token,
|
|
|
|
|
slippage_basis_points,
|
2025-02-21 22:32:43 +08:00
|
|
|
priority_fee,
|
2025-02-21 20:47:28 +08:00
|
|
|
).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
2025-01-07 13:18:31 +08:00
|
|
|
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2025-01-07 13:18:31 +08:00
|
|
|
pub async fn tokens_subscription<F>(
|
|
|
|
|
&self,
|
|
|
|
|
ws_url: &str,
|
|
|
|
|
commitment: CommitmentConfig,
|
|
|
|
|
callback: F,
|
|
|
|
|
bot_wallet: Option<Pubkey>,
|
|
|
|
|
) -> Result<SubscriptionHandle, Box<dyn std::error::Error>>
|
|
|
|
|
where
|
2025-01-25 16:01:16 +08:00
|
|
|
F: Fn(PumpfunEvent) + Send + Sync + 'static,
|
2025-01-07 13:18:31 +08:00
|
|
|
{
|
|
|
|
|
logs_subscribe::tokens_subscription(ws_url, commitment, callback, bot_wallet).await
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2025-01-07 13:18:31 +08:00
|
|
|
pub async fn stop_subscription(&self, subscription_handle: SubscriptionHandle) {
|
|
|
|
|
subscription_handle.shutdown().await;
|
|
|
|
|
}
|
2025-01-09 01:21:20 +08:00
|
|
|
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2025-02-21 21:15:10 +08:00
|
|
|
pub fn get_sol_balance(&self, payer: &Pubkey) -> Result<u64, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::common::get_sol_balance(&self.rpc, payer)
|
2025-01-09 01:21:20 +08:00
|
|
|
}
|
2025-01-13 18:42:21 +08:00
|
|
|
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2025-02-21 21:15:10 +08:00
|
|
|
pub fn get_payer_sol_balance(&self) -> Result<u64, anyhow::Error> {
|
|
|
|
|
trade::common::get_sol_balance(&self.rpc, &self.payer.pubkey())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn get_token_balance(&self, payer: &Pubkey, mint: &Pubkey) -> Result<u64, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::common::get_token_balance(&self.rpc, payer, mint)
|
2025-01-13 18:42:21 +08:00
|
|
|
}
|
|
|
|
|
|
2025-02-15 18:53:17 +08:00
|
|
|
#[inline]
|
2025-02-21 21:15:10 +08:00
|
|
|
pub fn get_payer_token_balance(&self, mint: &Pubkey) -> Result<u64, anyhow::Error> {
|
2025-02-21 20:47:28 +08:00
|
|
|
trade::common::get_token_balance(&self.rpc, &self.payer.pubkey(), mint)
|
|
|
|
|
}
|
2025-01-25 17:16:52 +08:00
|
|
|
|
2025-02-21 21:15:10 +08:00
|
|
|
#[inline]
|
|
|
|
|
pub fn get_payer_pubkey(&self) -> Pubkey {
|
|
|
|
|
self.payer.pubkey()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn get_payer(&self) -> &Keypair {
|
|
|
|
|
self.payer.as_ref()
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-21 20:47:28 +08:00
|
|
|
#[inline]
|
|
|
|
|
pub fn get_token_price(&self,virtual_sol_reserves: u64, virtual_token_reserves: u64) -> f64 {
|
|
|
|
|
trade::common::get_token_price(virtual_sol_reserves, virtual_token_reserves)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn get_buy_price(&self, amount: u64, trade_info: &TradeInfo) -> u64 {
|
|
|
|
|
trade::common::get_buy_price(amount, trade_info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub async fn transfer_sol(&self, payer: &Keypair, receive_wallet: &Pubkey, amount: u64) -> Result<(), anyhow::Error> {
|
|
|
|
|
trade::common::transfer_sol(&self.rpc, payer, receive_wallet, amount).await
|
2024-12-31 16:51:58 +08:00
|
|
|
}
|
|
|
|
|
}
|