Better code
This commit is contained in:
+81
-59
@@ -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),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user