Better code

This commit is contained in:
2026-08-06 05:31:33 +02:00
parent f20bdd490a
commit 0fdb684122
+81 -59
View File
@@ -2,76 +2,98 @@ use solana_sdk::{
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
pubkey::Pubkey, pubkey::Pubkey,
}; };
use std::str::FromStr;
pub mod system_program { use spl_associated_token_account::ID as ASSOCIATED_TOKEN_PROGRAM_ID;
use solana_sdk::declare_id; use spl_token::ID as TOKEN_PROGRAM_ID;
declare_id!("11111111111111111111111111111111"); macro_rules! declare_id {
($name:ident = $l:literal) => {
#[cfg(not(target_arch = "bpf"))]
#[doc = r" The const program ID."]
pub const $name: solana_sdk::pubkey::Pubkey =
solana_sdk::pubkey::Pubkey::from_str_const($l);
#[cfg(target_arch = "bpf")]
#[doc = r" The const program ID."]
pub static $name: solana_sdk::pubkey::Pubkey =
solana_sdk::pubkey::Pubkey::from_str_const($l);
};
} }
/// Derives the bonding curve and associated bonding curve tokens for a given mint. declare_id!(PUMP_FUN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5AMX787Nz");
pub fn derive_bonding_curve_pdas(mint: &Pubkey, program_id: &Pubkey) -> (Pubkey, Pubkey) { declare_id!(GLOBAL_ACCOUNT = "4wTV1YmiEkRvAtN4S7mJP2bXax2p18e4LK8LCHWwEQ2F");
let (bonding_curve, _) = declare_id!(FEE_RECIPIENT = "CebN5WG3QfR6EPEDZgbu6wN6sfg92v7S759DcGTR8b61");
Pubkey::find_program_address(&[b"bonding-curve", mint.as_ref()], program_id); declare_id!(EVENT_AUTHORITY = "Ce6TQqeHC9p8KBAayQr27Pyy6wJaCdE7wXw8msu3vA8Q");
declare_id!(SYS_PROGRAM_ID = "11111111111111111111111111111111");
let (associated_bonding_curve, _) = Pubkey::find_program_address( const BUY_DISCRIMINATOR: [u8; 8] = [102, 139, 25, 211, 85, 210, 149, 228];
&[
bonding_curve.as_ref(), pub struct PumpFun;
spl_token::ID.as_ref(),
mint.as_ref(), impl PumpFun {
], pub fn bonding_curve(mint: &Pubkey) -> (Pubkey, Pubkey) {
&spl_associated_token_account::ID, let (curve, _) =
Pubkey::find_program_address(&[b"bonding-curve", mint.as_ref()], &PUMP_FUN_PROGRAM_ID);
let (curve_ata, _) = Pubkey::find_program_address(
&[curve.as_ref(), TOKEN_PROGRAM_ID.as_ref(), mint.as_ref()],
&ASSOCIATED_TOKEN_PROGRAM_ID,
); );
(bonding_curve, associated_bonding_curve) (curve, curve_ata)
} }
/// Constructs a raw pump.fun buy instruction pub fn buy(
pub fn create_pump_buy_instruction(
payer: Pubkey, payer: Pubkey,
mint: Pubkey, mint: Pubkey,
ata_token_account: Pubkey, // User's associated token account for this mint user_token_account: Pubkey,
token_amount: u64, // Amount of tokens to purchase amount: u64,
max_sol_cost: u64, // Max lamports to spend (Slippage protection) max_sol_cost: u64,
) -> Instruction { ) -> Instruction {
let program_id = Pubkey::from_str("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5AMX787Nz").unwrap(); let (bonding_curve, bonding_curve_token) = Self::bonding_curve(&mint);
// Constant global state accounts used by pump.fun
let global_account = Pubkey::from_str("4wTV1YmiEkRvAtN4S7mJP2bXax2p18e4LK8LCHWwEQ2F").unwrap();
let fee_recipient = Pubkey::from_str("CebN5WG3QfR6EPEDZgbu6wN6sfg92v7S759DcGTR8b61").unwrap();
// Derive the PDAs for the bonding curves
let (bonding_curve, associated_bonding_curve) = derive_bonding_curve_pdas(&mint, &program_id);
// 1. Build the data payload (Discriminator + Args)
// Anchor discriminator for 'buy': [102, 139, 25, 211, 85, 210, 149, 228]
let mut instruction_data = vec![102, 139, 25, 211, 85, 210, 149, 228];
instruction_data.extend_from_slice(&token_amount.to_le_bytes());
instruction_data.extend_from_slice(&max_sol_cost.to_le_bytes());
// 2. Map required accounts in correct order
let accounts = vec![
AccountMeta::new_readonly(global_account, false),
AccountMeta::new(fee_recipient, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new(bonding_curve, false),
AccountMeta::new(associated_bonding_curve, false),
AccountMeta::new(ata_token_account, false),
AccountMeta::new(payer, true), // Signer
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(spl_token::ID, false),
AccountMeta::new_readonly(solana_program::sysvar::rent::ID, false),
AccountMeta::new_readonly(
Pubkey::from_str("Ce6TQqeHC9p8KBAayQr27Pyy6wJaCdE7wXw8msu3vA8Q").unwrap(),
false,
), // Event Authority
AccountMeta::new_readonly(program_id, false),
];
Instruction { Instruction {
program_id, program_id: PUMP_FUN_PROGRAM_ID,
accounts, accounts: Self::buy_accounts(
data: instruction_data, payer,
mint,
user_token_account,
bonding_curve,
bonding_curve_token,
),
data: Self::buy_data(amount, max_sol_cost),
}
}
fn buy_data(token_amount: u64, max_sol_cost: u64) -> Vec<u8> {
let mut data = Vec::with_capacity(24);
data.extend_from_slice(&BUY_DISCRIMINATOR);
data.extend_from_slice(&token_amount.to_le_bytes());
data.extend_from_slice(&max_sol_cost.to_le_bytes());
data
}
fn buy_accounts(
payer: Pubkey,
mint: Pubkey,
user_token_account: Pubkey,
bonding_curve: Pubkey,
bonding_curve_token: Pubkey,
) -> Vec<AccountMeta> {
vec![
AccountMeta::new_readonly(GLOBAL_ACCOUNT, false),
AccountMeta::new(FEE_RECIPIENT, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new(bonding_curve, false),
AccountMeta::new(bonding_curve_token, false),
AccountMeta::new(user_token_account, false),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(SYS_PROGRAM_ID, false),
AccountMeta::new_readonly(TOKEN_PROGRAM_ID, false),
AccountMeta::new_readonly(solana_sdk::sysvar::rent::ID, false),
AccountMeta::new_readonly(EVENT_AUTHORITY, false),
AccountMeta::new_readonly(PUMP_FUN_PROGRAM_ID, false),
]
} }
} }