mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-09 07:07:44 +00:00
remove pumpfun create token
This commit is contained in:
@@ -54,7 +54,6 @@ let callback = |event: PumpfunEvent| {
|
||||
|
||||
let payer_keypair = Keypair::from_base58_string("your private key");
|
||||
client.subscribe_pumpfun(callback, Some(payer_keypair.pubkey())).await?;
|
||||
|
||||
```
|
||||
|
||||
### Init pumpfun instance for configs
|
||||
@@ -92,42 +91,6 @@ let pumpfun = PumpFun::new(
|
||||
).await;
|
||||
```
|
||||
|
||||
### pumpfun create Token
|
||||
```rust
|
||||
use std::sync::Arc;
|
||||
use pumpfun_sdk::{ipfs, PumpFun};
|
||||
use solana_sdk::{native_token::sol_to_lamports, signature::Keypair, signer::Signer};
|
||||
|
||||
// create pumpfun instance
|
||||
let pumpfun = PumpFun::new(Arc::new(payer), &cluster).await;
|
||||
|
||||
// Mint keypair
|
||||
let mint_pubkey: Keypair = Keypair::new();
|
||||
|
||||
let metadata = ipfs::CreateTokenMetadata {
|
||||
name: "Doge".to_string(),
|
||||
symbol: "DOGE".to_string(),
|
||||
description: "Dogecoin".to_string(),
|
||||
file: "/Users/joseph/Desktop/doge.png".to_string(),
|
||||
twitter: None,
|
||||
telegram: None,
|
||||
website: None,
|
||||
metadata_uri: None,
|
||||
};
|
||||
|
||||
// ipfs jwt_token for https://pinata.cloud
|
||||
let jwt_token = "your ipfs jwt_token";
|
||||
let ipfs_metadata = ipfs::create_token_metadata(metadata, &jwt_token).await?;
|
||||
println!("ipfs_metadata: {:?}", ipfs_metadata);
|
||||
|
||||
pumpfun.create_and_buy(
|
||||
mint,
|
||||
ipfs_metadata,
|
||||
sol_to_lamports(0.1),
|
||||
None,
|
||||
).await?;
|
||||
```
|
||||
|
||||
### pumpfun buy token
|
||||
```rust
|
||||
use pumpfun_sdk::PumpFun;
|
||||
|
||||
@@ -24,38 +24,6 @@ use solana_sdk::{
|
||||
signer::Signer,
|
||||
};
|
||||
|
||||
pub struct Create {
|
||||
pub _name: String,
|
||||
pub _symbol: String,
|
||||
pub _uri: String,
|
||||
pub _creator: Pubkey,
|
||||
}
|
||||
|
||||
impl Create {
|
||||
pub fn data(&self) -> Vec<u8> {
|
||||
let mut data = Vec::with_capacity(8 + 4 + self._name.len() + 4 + self._symbol.len() + 4 + self._uri.len() + 32);
|
||||
|
||||
// 追加 discriminator
|
||||
data.extend_from_slice(&[24, 30, 200, 40, 5, 28, 7, 119]); // discriminator
|
||||
|
||||
// 添加 name 字符串长度和内容
|
||||
data.extend_from_slice(&(self._name.len() as u32).to_le_bytes()); // 添加 name 长度
|
||||
data.extend_from_slice(self._name.as_bytes()); // 添加 name 内容
|
||||
|
||||
// 添加 symbol 字符串长度和内容
|
||||
data.extend_from_slice(&(self._symbol.len() as u32).to_le_bytes()); // 添加 symbol 长度
|
||||
data.extend_from_slice(self._symbol.as_bytes()); // 添加 symbol 内容
|
||||
|
||||
// 添加 uri 字符串长度和内容
|
||||
data.extend_from_slice(&(self._uri.len() as u32).to_le_bytes()); // 添加 uri 长度
|
||||
data.extend_from_slice(self._uri.as_bytes()); // 添加 uri 内容
|
||||
|
||||
data.extend_from_slice(&self._creator.to_bytes());
|
||||
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Buy {
|
||||
pub _amount: u64,
|
||||
pub _max_sol_cost: u64,
|
||||
@@ -86,47 +54,6 @@ impl Sell {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Creates an instruction to create a new token with bonding curve
|
||||
///
|
||||
/// Creates a new SPL token with an associated bonding curve that determines its price.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `payer` - Keypair that will pay for account creation and transaction fees
|
||||
/// * `mint` - Keypair for the new token mint account that will be created
|
||||
/// * `args` - Create instruction data containing token name, symbol and metadata URI
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns a Solana instruction that when executed will create the token and its accounts
|
||||
pub fn create(payer: &Keypair, mint: &Keypair, args: Create) -> Instruction {
|
||||
let bonding_curve: Pubkey = get_bonding_curve_pda(&mint.pubkey()).unwrap();
|
||||
Instruction::new_with_bytes(
|
||||
constants::accounts::PUMPFUN,
|
||||
&args.data(),
|
||||
vec![
|
||||
AccountMeta::new(mint.pubkey(), true),
|
||||
AccountMeta::new(get_mint_authority_pda(), false),
|
||||
AccountMeta::new(bonding_curve, false),
|
||||
AccountMeta::new(
|
||||
get_associated_token_address(&bonding_curve, &mint.pubkey()),
|
||||
false,
|
||||
),
|
||||
AccountMeta::new_readonly(get_global_pda(), false),
|
||||
AccountMeta::new_readonly(constants::accounts::MPL_TOKEN_METADATA, false),
|
||||
AccountMeta::new(get_metadata_pda(&mint.pubkey()), false),
|
||||
AccountMeta::new(payer.pubkey(), true),
|
||||
AccountMeta::new_readonly(constants::accounts::SYSTEM_PROGRAM, false),
|
||||
AccountMeta::new_readonly(constants::accounts::TOKEN_PROGRAM, false),
|
||||
AccountMeta::new_readonly(constants::accounts::ASSOCIATED_TOKEN_PROGRAM, false),
|
||||
AccountMeta::new_readonly(constants::accounts::RENT, false),
|
||||
AccountMeta::new_readonly(constants::accounts::EVENT_AUTHORITY, false),
|
||||
AccountMeta::new_readonly(constants::accounts::PUMPFUN, false),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates an instruction to buy tokens from a bonding curve
|
||||
///
|
||||
/// Buys tokens by providing SOL. The amount of tokens received is calculated based on
|
||||
|
||||
-53
@@ -97,59 +97,6 @@ impl PumpFun {
|
||||
cluster: cluster.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new token
|
||||
pub async fn create(
|
||||
&self,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::create::create(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
ipfs,
|
||||
self.priority_fee.clone(),
|
||||
).await
|
||||
}
|
||||
|
||||
pub async fn create_and_buy(
|
||||
&self,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
amount_sol: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::create::create_and_buy(
|
||||
self.rpc.clone(),
|
||||
self.payer.clone(),
|
||||
mint,
|
||||
ipfs,
|
||||
amount_sol,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
).await
|
||||
}
|
||||
|
||||
pub async fn create_and_buy_with_tip(
|
||||
&self,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
amount_sol: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
pumpfun::create::create_and_buy_with_tip(
|
||||
self.rpc.clone(),
|
||||
self.fee_clients.clone(),
|
||||
payer,
|
||||
mint,
|
||||
ipfs,
|
||||
amount_sol,
|
||||
slippage_basis_points,
|
||||
self.priority_fee.clone(),
|
||||
).await
|
||||
}
|
||||
|
||||
/// Buy tokens
|
||||
pub async fn buy(
|
||||
|
||||
-57
@@ -33,61 +33,4 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
client.subscribe_pumpfun(callback, Some(payer_keypair.pubkey())).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_and_buy() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let priority_fee = PriorityFee{
|
||||
unit_limit: 72000,
|
||||
unit_price: 1000000,
|
||||
buy_tip_fee: 0.001,
|
||||
sell_tip_fee: 0.0001,
|
||||
};
|
||||
|
||||
let cluster = Cluster {
|
||||
rpc_url: "https://api.mainnet-beta.solana.com".to_string(),
|
||||
block_engine_url: "https://block-engine.example.com".to_string(),
|
||||
nextblock_url: "https://nextblock.example.com".to_string(),
|
||||
nextblock_auth_token: "nextblock_api_token".to_string(),
|
||||
zeroslot_url: "https://zeroslot.example.com".to_string(),
|
||||
zeroslot_auth_token: "zeroslot_api_token".to_string(),
|
||||
use_jito: true,
|
||||
use_nextblock: false,
|
||||
use_zeroslot: false,
|
||||
priority_fee,
|
||||
commitment: CommitmentConfig::processed(),
|
||||
};
|
||||
|
||||
// create pumpfun instance
|
||||
let payer = Keypair::new();
|
||||
let pumpfun = PumpFun::new(
|
||||
Arc::new(payer),
|
||||
&cluster,
|
||||
).await;
|
||||
|
||||
let metadata = ipfs::CreateTokenMetadata {
|
||||
name: "Doge".to_string(),
|
||||
symbol: "DOGE".to_string(),
|
||||
description: "Dogecoin".to_string(),
|
||||
file: "/Users/joseph/Desktop/doge.png".to_string(),
|
||||
twitter: None,
|
||||
telegram: None,
|
||||
website: None,
|
||||
metadata_uri: None,
|
||||
};
|
||||
|
||||
// ipfs jwt_token for https://pinata.cloud
|
||||
let jwt_token = "your ipfs jwt_token";
|
||||
let ipfs_metadata = ipfs::create_token_metadata(metadata, &jwt_token).await?;
|
||||
println!("ipfs_metadata: {:?}", ipfs_metadata);
|
||||
|
||||
let mint = Keypair::new();
|
||||
|
||||
pumpfun.create_and_buy(
|
||||
mint,
|
||||
ipfs_metadata,
|
||||
sol_to_lamports(0.1),
|
||||
None,
|
||||
).await?;
|
||||
|
||||
Ok(()) // 添加返回值
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
use std::{str::FromStr, time::Instant, sync::Arc};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use solana_client::rpc_config::RpcSimulateTransactionConfig;
|
||||
use solana_sdk::{
|
||||
commitment_config::CommitmentConfig, compute_budget::ComputeBudgetInstruction, instruction::Instruction, message::{v0, VersionedMessage}, native_token::sol_to_lamports, pubkey::Pubkey, signature::{Keypair, Signature}, signer::Signer, system_instruction, transaction::{Transaction, VersionedTransaction}
|
||||
};
|
||||
use spl_associated_token_account::{
|
||||
instruction::create_associated_token_account,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
common::{PriorityFee, SolanaRpcClient}, constants::{self, global_constants::FEE_RECIPIENT}, instruction, ipfs::TokenMetadataIPFS, pumpfun::buy::build_buy_transaction_with_tip, swqos::FeeClient
|
||||
};
|
||||
|
||||
use crate::pumpfun::common::{
|
||||
create_priority_fee_instructions,
|
||||
get_buy_amount_with_slippage, get_global_account
|
||||
};
|
||||
|
||||
use super::common::{get_bonding_curve_account, get_buy_token_amount, get_creator_vault_pda};
|
||||
|
||||
/// Create a new token
|
||||
pub async fn create(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
priority_fee: PriorityFee,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let mut instructions = create_priority_fee_instructions(priority_fee);
|
||||
|
||||
instructions.push(instruction::create(
|
||||
payer.as_ref(),
|
||||
&mint,
|
||||
instruction::Create {
|
||||
_name: ipfs.metadata.name,
|
||||
_symbol: ipfs.metadata.symbol,
|
||||
_uri: ipfs.metadata_uri,
|
||||
_creator: payer.pubkey(),
|
||||
},
|
||||
));
|
||||
|
||||
let recent_blockhash = rpc.get_latest_blockhash().await?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&instructions,
|
||||
Some(&payer.pubkey()),
|
||||
&[payer.as_ref(), &mint],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
rpc.send_and_confirm_transaction(&transaction).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create and buy tokens in one transaction
|
||||
pub async fn create_and_buy(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
amount_sol: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if amount_sol == 0 {
|
||||
return Err(anyhow!("Amount cannot be zero"));
|
||||
}
|
||||
|
||||
let mint = Arc::new(mint);
|
||||
let transaction = build_create_and_buy_transaction(rpc.clone(), payer.clone(), mint.clone(), ipfs, amount_sol, slippage_basis_points, priority_fee.clone()).await?;
|
||||
rpc.send_and_confirm_transaction(&transaction).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn create_and_buy_with_tip(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
fee_clients: Vec<Arc<FeeClient>>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Keypair,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
amount_sol: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let start_time = Instant::now();
|
||||
let mint = Arc::new(mint);
|
||||
let build_instructions = build_create_and_buy_instructions(rpc.clone(), payer.clone(), mint.clone(), ipfs.clone(), amount_sol, slippage_basis_points, priority_fee.clone()).await?;
|
||||
let mut handles = vec![];
|
||||
for fee_client in fee_clients {
|
||||
let rpc = rpc.clone();
|
||||
let payer = payer.clone();
|
||||
let mint = mint.clone();
|
||||
let priority_fee = priority_fee.clone();
|
||||
let tip_account = fee_client.get_tip_account().await.map_err(|e| anyhow!(e.to_string()))?;
|
||||
let tip_account = Arc::new(Pubkey::from_str(&tip_account).map_err(|e| anyhow!(e))?);
|
||||
let build_instructions = build_instructions.clone();
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
let transaction = build_create_and_buy_transaction_with_tip(rpc, tip_account, payer, mint, priority_fee, build_instructions).await?;
|
||||
fee_client.send_transaction(&transaction).await.map_err(|e| anyhow!(e.to_string()))?;
|
||||
println!("Total Jito create and buy operation time: {:?}ms", start_time.elapsed().as_millis());
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
for handle in handles {
|
||||
match handle.await {
|
||||
Ok(Ok(_)) => (),
|
||||
Ok(Err(e)) => println!("Error in task: {}", e),
|
||||
Err(e) => println!("Task join error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn build_create_and_buy_transaction(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Arc<Keypair>,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
amount_sol: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
) -> Result<Transaction, anyhow::Error> {
|
||||
let mut instructions: Vec<Instruction> = vec![
|
||||
ComputeBudgetInstruction::set_compute_unit_price(priority_fee.unit_price),
|
||||
ComputeBudgetInstruction::set_compute_unit_limit(priority_fee.unit_limit),
|
||||
];
|
||||
|
||||
let build_instructions: Vec<Instruction> = build_create_and_buy_instructions(rpc.clone(), payer.clone(), mint.clone(), ipfs, amount_sol, slippage_basis_points, priority_fee.clone()).await?;
|
||||
instructions.extend(build_instructions);
|
||||
|
||||
let recent_blockhash = rpc.get_latest_blockhash().await?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&instructions,
|
||||
Some(&payer.pubkey()),
|
||||
&[payer.as_ref(), mint.as_ref()],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
Ok(transaction)
|
||||
}
|
||||
|
||||
pub async fn build_create_and_buy_transaction_with_tip(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
tip_account: Arc<Pubkey>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Arc<Keypair>,
|
||||
priority_fee: PriorityFee,
|
||||
build_instructions: Vec<Instruction>,
|
||||
) -> Result<VersionedTransaction, anyhow::Error> {
|
||||
let mut instructions: Vec<Instruction> = vec![
|
||||
ComputeBudgetInstruction::set_compute_unit_price(priority_fee.unit_price),
|
||||
ComputeBudgetInstruction::set_compute_unit_limit(priority_fee.unit_limit),
|
||||
system_instruction::transfer(
|
||||
&payer.pubkey(),
|
||||
&tip_account,
|
||||
sol_to_lamports(priority_fee.buy_tip_fee),
|
||||
),
|
||||
];
|
||||
instructions.extend(build_instructions);
|
||||
|
||||
let recent_blockhash = rpc.get_latest_blockhash().await?;
|
||||
let v0_message: v0::Message =
|
||||
v0::Message::try_compile(&payer.pubkey(), &instructions, &[], recent_blockhash)?;
|
||||
|
||||
let versioned_message: VersionedMessage = VersionedMessage::V0(v0_message);
|
||||
let transaction = VersionedTransaction::try_new(versioned_message, &[&payer])?;
|
||||
|
||||
Ok(transaction)
|
||||
}
|
||||
|
||||
pub async fn build_create_and_buy_instructions(
|
||||
rpc: Arc<SolanaRpcClient>,
|
||||
payer: Arc<Keypair>,
|
||||
mint: Arc<Keypair>,
|
||||
ipfs: TokenMetadataIPFS,
|
||||
buy_sol_cost: u64,
|
||||
slippage_basis_points: Option<u64>,
|
||||
priority_fee: PriorityFee,
|
||||
) -> Result<Vec<Instruction>, anyhow::Error> {
|
||||
if buy_sol_cost == 0 {
|
||||
return Err(anyhow!("Amount cannot be zero"));
|
||||
}
|
||||
|
||||
let (bonding_curve_account, bonding_curve_pda) = get_bonding_curve_account(&rpc, &mint.pubkey()).await?;
|
||||
|
||||
let creator_vault_pda = get_creator_vault_pda(&bonding_curve_account.creator).unwrap();
|
||||
|
||||
let (buy_token_amount, max_sol_cost) = get_buy_token_amount(&bonding_curve_account, buy_sol_cost, slippage_basis_points)?;
|
||||
|
||||
let mut instructions = vec![];
|
||||
|
||||
instructions.push(instruction::create(
|
||||
payer.as_ref(),
|
||||
mint.as_ref(),
|
||||
instruction::Create {
|
||||
_name: ipfs.metadata.name.clone(),
|
||||
_symbol: ipfs.metadata.symbol.clone(),
|
||||
_uri: ipfs.metadata_uri.clone(),
|
||||
_creator: payer.pubkey(),
|
||||
},
|
||||
));
|
||||
|
||||
instructions.push(create_associated_token_account(
|
||||
&payer.pubkey(),
|
||||
&payer.pubkey(),
|
||||
&mint.pubkey(),
|
||||
&constants::accounts::TOKEN_PROGRAM,
|
||||
));
|
||||
|
||||
instructions.push(instruction::buy(
|
||||
payer.as_ref(),
|
||||
&mint.pubkey(),
|
||||
&bonding_curve_pda,
|
||||
&creator_vault_pda,
|
||||
&FEE_RECIPIENT,
|
||||
instruction::Buy {
|
||||
_amount: buy_token_amount,
|
||||
_max_sol_cost: max_sol_cost,
|
||||
},
|
||||
));
|
||||
|
||||
Ok(instructions)
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod buy;
|
||||
pub mod create;
|
||||
pub mod sell;
|
||||
pub mod common;
|
||||
Reference in New Issue
Block a user