Better code
This commit is contained in:
+79
-57
@@ -2,76 +2,98 @@ use solana_sdk::{
|
||||
instruction::{AccountMeta, Instruction},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod system_program {
|
||||
use solana_sdk::declare_id;
|
||||
use spl_associated_token_account::ID as ASSOCIATED_TOKEN_PROGRAM_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.
|
||||
pub fn derive_bonding_curve_pdas(mint: &Pubkey, program_id: &Pubkey) -> (Pubkey, Pubkey) {
|
||||
let (bonding_curve, _) =
|
||||
Pubkey::find_program_address(&[b"bonding-curve", mint.as_ref()], program_id);
|
||||
declare_id!(PUMP_FUN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5AMX787Nz");
|
||||
declare_id!(GLOBAL_ACCOUNT = "4wTV1YmiEkRvAtN4S7mJP2bXax2p18e4LK8LCHWwEQ2F");
|
||||
declare_id!(FEE_RECIPIENT = "CebN5WG3QfR6EPEDZgbu6wN6sfg92v7S759DcGTR8b61");
|
||||
declare_id!(EVENT_AUTHORITY = "Ce6TQqeHC9p8KBAayQr27Pyy6wJaCdE7wXw8msu3vA8Q");
|
||||
declare_id!(SYS_PROGRAM_ID = "11111111111111111111111111111111");
|
||||
|
||||
let (associated_bonding_curve, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
bonding_curve.as_ref(),
|
||||
spl_token::ID.as_ref(),
|
||||
mint.as_ref(),
|
||||
],
|
||||
&spl_associated_token_account::ID,
|
||||
const BUY_DISCRIMINATOR: [u8; 8] = [102, 139, 25, 211, 85, 210, 149, 228];
|
||||
|
||||
pub struct PumpFun;
|
||||
|
||||
impl PumpFun {
|
||||
pub fn bonding_curve(mint: &Pubkey) -> (Pubkey, Pubkey) {
|
||||
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 create_pump_buy_instruction(
|
||||
pub fn buy(
|
||||
payer: Pubkey,
|
||||
mint: Pubkey,
|
||||
ata_token_account: Pubkey, // User's associated token account for this mint
|
||||
token_amount: u64, // Amount of tokens to purchase
|
||||
max_sol_cost: u64, // Max lamports to spend (Slippage protection)
|
||||
user_token_account: Pubkey,
|
||||
amount: u64,
|
||||
max_sol_cost: u64,
|
||||
) -> Instruction {
|
||||
let program_id = Pubkey::from_str("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5AMX787Nz").unwrap();
|
||||
|
||||
// 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),
|
||||
];
|
||||
let (bonding_curve, bonding_curve_token) = Self::bonding_curve(&mint);
|
||||
|
||||
Instruction {
|
||||
program_id,
|
||||
accounts,
|
||||
data: instruction_data,
|
||||
program_id: PUMP_FUN_PROGRAM_ID,
|
||||
accounts: Self::buy_accounts(
|
||||
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),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user