feat: optimize PumpSwap instruction builder performance and caching
- Add PumpSwapUserVolume PDA cache key support - Refactor PumpSwap instruction builder to simplify code logic - Optimize memory allocation with pre-allocated Vec capacity - Integrate fast_fn caching mechanism to replace redundant PDA calculations - Standardize account metadata construction and data serialization - Simplify wSOL handling logic by reusing common functions - Optimize import statements and remove unused dependencies - Add pool token account parameters to PumpSwapParams structure
This commit is contained in:
@@ -110,6 +110,7 @@ pub enum PdaCacheKey {
|
||||
PumpFunCreatorVault(Pubkey),
|
||||
BonkPool(Pubkey, Pubkey),
|
||||
BonkVault(Pubkey, Pubkey),
|
||||
PumpSwapUserVolume(Pubkey),
|
||||
}
|
||||
|
||||
/// 全局 PDA 缓存,用于存储计算结果
|
||||
@@ -196,6 +197,8 @@ pub fn get_associated_token_address_with_program_id_fast(
|
||||
pub fn fast_init(payer: &Pubkey) {
|
||||
// 获取 PumpFun 用户量累加器 PDA
|
||||
crate::instruction::utils::pumpfun::get_user_volume_accumulator_pda(payer);
|
||||
// 获取 PumpSwap 用户量累加器 PDA
|
||||
crate::instruction::utils::pumpswap::get_user_volume_accumulator_pda(payer);
|
||||
// 获取 wSOL ATA 地址
|
||||
let wsol_token_account = get_associated_token_address_with_program_id_fast(
|
||||
payer,
|
||||
|
||||
+97
-190
@@ -1,14 +1,8 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use solana_sdk::{instruction::Instruction, pubkey::Pubkey, signer::Signer};
|
||||
use solana_system_interface::instruction::transfer;
|
||||
use spl_associated_token_account::instruction::create_associated_token_account_idempotent;
|
||||
use spl_token::instruction::close_account;
|
||||
|
||||
use crate::{
|
||||
constants::trade::trade::DEFAULT_SLIPPAGE,
|
||||
instruction::utils::pumpswap::{
|
||||
accounts, coin_creator_vault_ata, fee_recipient_ata, get_user_volume_accumulator_pda,
|
||||
BUY_DISCRIMINATOR, SELL_DISCRIMINATOR,
|
||||
accounts, fee_recipient_ata, get_user_volume_accumulator_pda, BUY_DISCRIMINATOR,
|
||||
SELL_DISCRIMINATOR,
|
||||
},
|
||||
trading::core::{
|
||||
params::{BuyParams, PumpSwapParams, SellParams},
|
||||
@@ -16,6 +10,12 @@ use crate::{
|
||||
},
|
||||
utils::calc::pumpswap::{buy_quote_input_internal, sell_base_input_internal},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use solana_sdk::{
|
||||
instruction::{AccountMeta, Instruction},
|
||||
pubkey::Pubkey,
|
||||
signer::Signer,
|
||||
};
|
||||
|
||||
/// Instruction builder for PumpSwap protocol
|
||||
pub struct PumpSwapInstructionBuilder;
|
||||
@@ -45,24 +45,23 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
let auto_handle_wsol = protocol_params.auto_handle_wsol;
|
||||
let base_token_program = protocol_params.base_token_program;
|
||||
let quote_token_program = protocol_params.quote_token_program;
|
||||
let pool_base_token_account = protocol_params.pool_base_token_account;
|
||||
let pool_quote_token_account = protocol_params.pool_quote_token_account;
|
||||
|
||||
if base_mint != crate::constants::WSOL_TOKEN_ACCOUNT
|
||||
&& quote_mint != crate::constants::WSOL_TOKEN_ACCOUNT
|
||||
{
|
||||
return Err(anyhow!("Invalid base mint and quote mint"));
|
||||
}
|
||||
if params.rpc.is_none() {
|
||||
return Err(anyhow!("RPC is not set"));
|
||||
}
|
||||
|
||||
let quote_mint_is_wsol = quote_mint == crate::constants::WSOL_TOKEN_ACCOUNT;
|
||||
|
||||
let mut token_amount = 0;
|
||||
let mut sol_amount = 0;
|
||||
|
||||
let mut creator = Pubkey::default();
|
||||
let default_creator_ata = coin_creator_vault_ata(creator, quote_mint);
|
||||
if default_creator_ata != params_coin_creator_vault_ata {
|
||||
creator = params_coin_creator_vault_ata;
|
||||
if params_coin_creator_vault_authority != accounts::DEFAULT_COIN_CREATOR_VAULT_AUTHORITY {
|
||||
creator = params_coin_creator_vault_authority;
|
||||
}
|
||||
if quote_mint_is_wsol {
|
||||
let result = buy_quote_input_internal(
|
||||
@@ -94,75 +93,27 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
|
||||
// Create user token accounts
|
||||
let user_base_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
&base_mint,
|
||||
&base_token_program,
|
||||
);
|
||||
let user_quote_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
"e_mint,
|
||||
"e_token_program,
|
||||
);
|
||||
|
||||
// Get pool token accounts
|
||||
let pool_base_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
&pool,
|
||||
&base_mint,
|
||||
&base_token_program,
|
||||
);
|
||||
|
||||
let pool_quote_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
&pool,
|
||||
"e_mint,
|
||||
"e_token_program,
|
||||
);
|
||||
|
||||
let mut instructions = vec![];
|
||||
let mut instructions = Vec::with_capacity(6);
|
||||
|
||||
if auto_handle_wsol {
|
||||
// Handle wSOL
|
||||
instructions.push(
|
||||
// Create wSOL ATA account if it doesn't exist
|
||||
create_associated_token_account_idempotent(
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
),
|
||||
);
|
||||
instructions.push(
|
||||
// Transfer SOL to wSOL ATA account
|
||||
transfer(
|
||||
¶ms.payer.pubkey(),
|
||||
if quote_mint_is_wsol {
|
||||
&user_quote_token_account
|
||||
} else {
|
||||
&user_base_token_account
|
||||
},
|
||||
sol_amount,
|
||||
),
|
||||
);
|
||||
|
||||
// Sync wSOL balance
|
||||
instructions.push(
|
||||
spl_token::instruction::sync_native(
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
if quote_mint_is_wsol {
|
||||
&user_quote_token_account
|
||||
} else {
|
||||
&user_base_token_account
|
||||
},
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
instructions
|
||||
.extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount));
|
||||
}
|
||||
|
||||
// Create user's base token account
|
||||
instructions.push(create_associated_token_account_idempotent(
|
||||
instructions.push(crate::common::fast_fn::create_associated_token_account_idempotent_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
if quote_mint_is_wsol { &base_mint } else { "e_mint },
|
||||
@@ -172,33 +123,31 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
let fee_recipient_ata = fee_recipient_ata(accounts::FEE_RECIPIENT, quote_mint);
|
||||
|
||||
// Create buy instruction
|
||||
let mut accounts = vec![
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(pool, false), // pool_id (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // user (signer)
|
||||
accounts::GLOBAL_ACCOUNT_META, // global (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(base_mint, false), // base_mint (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(quote_mint, false), // quote_mint (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(user_base_token_account, false), // user_base_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(user_quote_token_account, false), // user_quote_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(pool_base_token_account, false), // pool_base_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account
|
||||
accounts::FEE_RECIPIENT_META, // fee_recipient (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS)
|
||||
crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly)
|
||||
let mut accounts = Vec::with_capacity(23);
|
||||
accounts.extend([
|
||||
AccountMeta::new_readonly(pool, false), // pool_id (readonly)
|
||||
AccountMeta::new(params.payer.pubkey(), true), // user (signer)
|
||||
accounts::GLOBAL_ACCOUNT_META, // global (readonly)
|
||||
AccountMeta::new_readonly(base_mint, false), // base_mint (readonly)
|
||||
AccountMeta::new_readonly(quote_mint, false), // quote_mint (readonly)
|
||||
AccountMeta::new(user_base_token_account, false), // user_base_token_account
|
||||
AccountMeta::new(user_quote_token_account, false), // user_quote_token_account
|
||||
AccountMeta::new(pool_base_token_account, false), // pool_base_token_account
|
||||
AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account
|
||||
accounts::FEE_RECIPIENT_META, // fee_recipient (readonly)
|
||||
AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata
|
||||
AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly)
|
||||
AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS)
|
||||
crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly)
|
||||
accounts::ASSOCIATED_TOKEN_PROGRAM_META, // ASSOCIATED_TOKEN_PROGRAM_ID (readonly)
|
||||
accounts::EVENT_AUTHORITY_META, // event_authority (readonly)
|
||||
accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(
|
||||
params_coin_creator_vault_authority,
|
||||
false,
|
||||
), // coin_creator_vault_authority (readonly)
|
||||
];
|
||||
accounts::EVENT_AUTHORITY_META, // event_authority (readonly)
|
||||
accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly)
|
||||
AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata
|
||||
AccountMeta::new_readonly(params_coin_creator_vault_authority, false), // coin_creator_vault_authority (readonly)
|
||||
]);
|
||||
if quote_mint_is_wsol {
|
||||
accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META);
|
||||
accounts.push(solana_sdk::instruction::AccountMeta::new(
|
||||
accounts.push(AccountMeta::new(
|
||||
get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(),
|
||||
false,
|
||||
));
|
||||
@@ -207,38 +156,29 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
accounts.push(accounts::FEE_PROGRAM_META);
|
||||
|
||||
// Create instruction data
|
||||
let mut data = vec![];
|
||||
let mut data = [0u8; 24];
|
||||
if quote_mint_is_wsol {
|
||||
data.extend_from_slice(&BUY_DISCRIMINATOR);
|
||||
data[..8].copy_from_slice(&BUY_DISCRIMINATOR);
|
||||
// base_amount_out
|
||||
data.extend_from_slice(&token_amount.to_le_bytes());
|
||||
data[8..16].copy_from_slice(&token_amount.to_le_bytes());
|
||||
// max_quote_amount_in
|
||||
data.extend_from_slice(&sol_amount.to_le_bytes());
|
||||
data[16..24].copy_from_slice(&sol_amount.to_le_bytes());
|
||||
} else {
|
||||
data.extend_from_slice(&SELL_DISCRIMINATOR);
|
||||
data[..8].copy_from_slice(&SELL_DISCRIMINATOR);
|
||||
// base_amount_in
|
||||
data.extend_from_slice(&sol_amount.to_le_bytes());
|
||||
data[8..16].copy_from_slice(&sol_amount.to_le_bytes());
|
||||
// min_quote_amount_out
|
||||
data.extend_from_slice(&token_amount.to_le_bytes());
|
||||
data[16..24].copy_from_slice(&token_amount.to_le_bytes());
|
||||
}
|
||||
|
||||
instructions.push(Instruction { program_id: accounts::AMM_PROGRAM, accounts, data });
|
||||
instructions.push(Instruction {
|
||||
program_id: accounts::AMM_PROGRAM,
|
||||
accounts,
|
||||
data: data.to_vec(),
|
||||
});
|
||||
if auto_handle_wsol {
|
||||
// Close wSOL ATA account, reclaim rent
|
||||
instructions.push(
|
||||
spl_token::instruction::close_account(
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
if quote_mint_is_wsol {
|
||||
&user_quote_token_account
|
||||
} else {
|
||||
&user_base_token_account
|
||||
},
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
&[¶ms.payer.pubkey()],
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
instructions.push(crate::trading::common::close_wsol(¶ms.payer.pubkey()));
|
||||
}
|
||||
Ok(instructions)
|
||||
}
|
||||
@@ -257,6 +197,8 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
let quote_mint = protocol_params.quote_mint;
|
||||
let pool_base_token_reserves = protocol_params.pool_base_token_reserves;
|
||||
let pool_quote_token_reserves = protocol_params.pool_quote_token_reserves;
|
||||
let pool_base_token_account = protocol_params.pool_base_token_account;
|
||||
let pool_quote_token_account = protocol_params.pool_quote_token_account;
|
||||
let params_coin_creator_vault_ata = protocol_params.coin_creator_vault_ata;
|
||||
let params_coin_creator_vault_authority = protocol_params.coin_creator_vault_authority;
|
||||
let auto_handle_wsol = protocol_params.auto_handle_wsol;
|
||||
@@ -268,9 +210,6 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
{
|
||||
return Err(anyhow!("Invalid base mint and quote mint"));
|
||||
}
|
||||
if params.rpc.is_none() {
|
||||
return Err(anyhow!("RPC is not set"));
|
||||
}
|
||||
if params.token_amount.is_none() {
|
||||
return Err(anyhow!("Token amount is not set"));
|
||||
}
|
||||
@@ -281,9 +220,8 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
let mut sol_amount = 0;
|
||||
|
||||
let mut creator = Pubkey::default();
|
||||
let default_creator_ata = coin_creator_vault_ata(creator, quote_mint);
|
||||
if default_creator_ata != params_coin_creator_vault_ata {
|
||||
creator = params_coin_creator_vault_ata;
|
||||
if params_coin_creator_vault_authority != accounts::DEFAULT_COIN_CREATOR_VAULT_AUTHORITY {
|
||||
creator = params_coin_creator_vault_authority;
|
||||
}
|
||||
|
||||
if quote_mint_is_wsol {
|
||||
@@ -317,36 +255,24 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
let fee_recipient_ata = fee_recipient_ata(accounts::FEE_RECIPIENT, quote_mint);
|
||||
|
||||
let user_base_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
&base_mint,
|
||||
&base_token_program,
|
||||
);
|
||||
let user_quote_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
"e_mint,
|
||||
"e_token_program,
|
||||
);
|
||||
let pool_base_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
&pool,
|
||||
&base_mint,
|
||||
&base_token_program,
|
||||
);
|
||||
let pool_quote_token_account =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
&pool,
|
||||
"e_mint,
|
||||
"e_token_program,
|
||||
);
|
||||
|
||||
let mut instructions = vec![];
|
||||
let mut instructions = Vec::with_capacity(3);
|
||||
|
||||
// Insert wSOL
|
||||
instructions.push(
|
||||
// Create wSOL ATA account if it doesn't exist
|
||||
create_associated_token_account_idempotent(
|
||||
crate::common::fast_fn::create_associated_token_account_idempotent_fast(
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
&crate::constants::WSOL_TOKEN_ACCOUNT,
|
||||
@@ -354,42 +280,32 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
),
|
||||
);
|
||||
|
||||
// Create user's token account
|
||||
instructions.push(create_associated_token_account_idempotent(
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
if quote_mint_is_wsol { &base_mint } else { "e_mint },
|
||||
if quote_mint_is_wsol { &base_token_program } else { "e_token_program },
|
||||
));
|
||||
|
||||
// Create sell instruction
|
||||
let mut accounts = vec![
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(pool, false), // pool_id (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(params.payer.pubkey(), true), // user (signer)
|
||||
accounts::GLOBAL_ACCOUNT_META, // global (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(base_mint, false), // mint (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(quote_mint, false), // WSOL_TOKEN_ACCOUNT (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(user_base_token_account, false), // user_base_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(user_quote_token_account, false), // user_quote_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(pool_base_token_account, false), // pool_base_token_account
|
||||
solana_sdk::instruction::AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account
|
||||
accounts::FEE_RECIPIENT_META, // fee_recipient (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS)
|
||||
crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly)
|
||||
let mut accounts = Vec::with_capacity(23);
|
||||
accounts.extend([
|
||||
AccountMeta::new_readonly(pool, false), // pool_id (readonly)
|
||||
AccountMeta::new(params.payer.pubkey(), true), // user (signer)
|
||||
accounts::GLOBAL_ACCOUNT_META, // global (readonly)
|
||||
AccountMeta::new_readonly(base_mint, false), // mint (readonly)
|
||||
AccountMeta::new_readonly(quote_mint, false), // WSOL_TOKEN_ACCOUNT (readonly)
|
||||
AccountMeta::new(user_base_token_account, false), // user_base_token_account
|
||||
AccountMeta::new(user_quote_token_account, false), // user_quote_token_account
|
||||
AccountMeta::new(pool_base_token_account, false), // pool_base_token_account
|
||||
AccountMeta::new(pool_quote_token_account, false), // pool_quote_token_account
|
||||
accounts::FEE_RECIPIENT_META, // fee_recipient (readonly)
|
||||
AccountMeta::new(fee_recipient_ata, false), // fee_recipient_ata
|
||||
AccountMeta::new_readonly(base_token_program, false), // TOKEN_PROGRAM_ID (readonly)
|
||||
AccountMeta::new_readonly(quote_token_program, false), // TOKEN_PROGRAM_ID (readonly, duplicated as in JS)
|
||||
crate::constants::SYSTEM_PROGRAM_META, // System Program (readonly)
|
||||
accounts::ASSOCIATED_TOKEN_PROGRAM_META, // ASSOCIATED_TOKEN_PROGRAM_ID (readonly)
|
||||
accounts::EVENT_AUTHORITY_META, // event_authority (readonly)
|
||||
accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly)
|
||||
solana_sdk::instruction::AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata
|
||||
solana_sdk::instruction::AccountMeta::new_readonly(
|
||||
params_coin_creator_vault_authority,
|
||||
false,
|
||||
), // coin_creator_vault_authority (readonly)
|
||||
];
|
||||
accounts::EVENT_AUTHORITY_META, // event_authority (readonly)
|
||||
accounts::AMM_PROGRAM_META, // PUMP_AMM_PROGRAM_ID (readonly)
|
||||
AccountMeta::new(params_coin_creator_vault_ata, false), // coin_creator_vault_ata
|
||||
AccountMeta::new_readonly(params_coin_creator_vault_authority, false), // coin_creator_vault_authority (readonly)
|
||||
]);
|
||||
if !quote_mint_is_wsol {
|
||||
accounts.push(accounts::GLOBAL_VOLUME_ACCUMULATOR_META);
|
||||
accounts.push(solana_sdk::instruction::AccountMeta::new(
|
||||
accounts.push(AccountMeta::new(
|
||||
get_user_volume_accumulator_pda(¶ms.payer.pubkey()).unwrap(),
|
||||
false,
|
||||
));
|
||||
@@ -399,38 +315,29 @@ impl InstructionBuilder for PumpSwapInstructionBuilder {
|
||||
accounts.push(accounts::FEE_PROGRAM_META);
|
||||
|
||||
// Create instruction data
|
||||
let mut data = vec![];
|
||||
let mut data = [0u8; 24];
|
||||
if quote_mint_is_wsol {
|
||||
data.extend_from_slice(&SELL_DISCRIMINATOR);
|
||||
data[..8].copy_from_slice(&SELL_DISCRIMINATOR);
|
||||
// base_amount_in
|
||||
data.extend_from_slice(&token_amount.to_le_bytes());
|
||||
data[8..16].copy_from_slice(&token_amount.to_le_bytes());
|
||||
// min_quote_amount_out
|
||||
data.extend_from_slice(&sol_amount.to_le_bytes());
|
||||
data[16..24].copy_from_slice(&sol_amount.to_le_bytes());
|
||||
} else {
|
||||
data.extend_from_slice(&BUY_DISCRIMINATOR);
|
||||
data[..8].copy_from_slice(&BUY_DISCRIMINATOR);
|
||||
// base_amount_out
|
||||
data.extend_from_slice(&sol_amount.to_le_bytes());
|
||||
data[8..16].copy_from_slice(&sol_amount.to_le_bytes());
|
||||
// max_quote_amount_in
|
||||
data.extend_from_slice(&token_amount.to_le_bytes());
|
||||
data[16..24].copy_from_slice(&token_amount.to_le_bytes());
|
||||
}
|
||||
|
||||
instructions.push(Instruction { program_id: accounts::AMM_PROGRAM, accounts, data });
|
||||
instructions.push(Instruction {
|
||||
program_id: accounts::AMM_PROGRAM,
|
||||
accounts,
|
||||
data: data.to_vec(),
|
||||
});
|
||||
|
||||
if auto_handle_wsol {
|
||||
instructions.push(
|
||||
close_account(
|
||||
&crate::constants::TOKEN_PROGRAM,
|
||||
if quote_mint_is_wsol {
|
||||
&user_quote_token_account
|
||||
} else {
|
||||
&user_base_token_account
|
||||
},
|
||||
¶ms.payer.pubkey(),
|
||||
¶ms.payer.pubkey(),
|
||||
&[¶ms.payer.pubkey()],
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
instructions.push(crate::trading::common::close_wsol(¶ms.payer.pubkey()));
|
||||
}
|
||||
Ok(instructions)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use crate::{
|
||||
common::SolanaRpcClient,
|
||||
constants::{self, TOKEN_PROGRAM},
|
||||
};
|
||||
use crate::{common::SolanaRpcClient, constants::TOKEN_PROGRAM};
|
||||
use anyhow::anyhow;
|
||||
use solana_account_decoder::UiAccountEncoding;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
@@ -60,6 +57,9 @@ pub mod accounts {
|
||||
|
||||
pub const FEE_CONFIG: Pubkey = pubkey!("5PHirr8joyTMp9JMm6nW7hNDVyEYdkzDqazxPD7RaTjx"); // get_fee_config_pda().unwrap();
|
||||
|
||||
pub const DEFAULT_COIN_CREATOR_VAULT_AUTHORITY: Pubkey =
|
||||
pubkey!("8N3GDaZ2iwN65oxVatKTLPNooAVUJTbfiVJ1ahyqwjSk");
|
||||
|
||||
// META
|
||||
|
||||
pub const GLOBAL_ACCOUNT_META: solana_sdk::instruction::AccountMeta =
|
||||
@@ -149,7 +149,7 @@ pub(crate) fn coin_creator_vault_ata(coin_creator: Pubkey, quote_mint: Pubkey) -
|
||||
|
||||
pub(crate) fn fee_recipient_ata(fee_recipient: Pubkey, quote_mint: Pubkey) -> Pubkey {
|
||||
let associated_token_fee_recipient =
|
||||
spl_associated_token_account::get_associated_token_address_with_program_id(
|
||||
crate::common::fast_fn::get_associated_token_address_with_program_id_fast(
|
||||
&fee_recipient,
|
||||
"e_mint,
|
||||
&TOKEN_PROGRAM,
|
||||
@@ -158,10 +158,15 @@ pub(crate) fn fee_recipient_ata(fee_recipient: Pubkey, quote_mint: Pubkey) -> Pu
|
||||
}
|
||||
|
||||
pub fn get_user_volume_accumulator_pda(user: &Pubkey) -> Option<Pubkey> {
|
||||
let seeds: &[&[u8]; 2] = &[&seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()];
|
||||
let program_id: &Pubkey = &&accounts::AMM_PROGRAM;
|
||||
let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id);
|
||||
pda.map(|pubkey| pubkey.0)
|
||||
crate::common::fast_fn::get_cached_pda(
|
||||
crate::common::fast_fn::PdaCacheKey::PumpSwapUserVolume(*user),
|
||||
|| {
|
||||
let seeds: &[&[u8]; 2] = &[&seeds::USER_VOLUME_ACCUMULATOR_SEED, user.as_ref()];
|
||||
let program_id: &Pubkey = &&accounts::AMM_PROGRAM;
|
||||
let pda: Option<(Pubkey, u8)> = Pubkey::try_find_program_address(seeds, program_id);
|
||||
pda.map(|pubkey| pubkey.0)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_global_volume_accumulator_pda() -> Option<Pubkey> {
|
||||
|
||||
@@ -126,6 +126,10 @@ pub struct PumpSwapParams {
|
||||
/// Quote token mint address
|
||||
/// The mint account address of the quote token in the trading pair, usually SOL or USDC
|
||||
pub quote_mint: Pubkey,
|
||||
/// Pool base token account
|
||||
pub pool_base_token_account: Pubkey,
|
||||
/// Pool quote token account
|
||||
pub pool_quote_token_account: Pubkey,
|
||||
/// Base token reserves in the pool
|
||||
pub pool_base_token_reserves: u64,
|
||||
/// Quote token reserves in the pool
|
||||
@@ -149,6 +153,8 @@ impl PumpSwapParams {
|
||||
pool: event.pool,
|
||||
base_mint: event.base_mint,
|
||||
quote_mint: event.quote_mint,
|
||||
pool_base_token_account: event.pool_base_token_account,
|
||||
pool_quote_token_account: event.pool_quote_token_account,
|
||||
pool_base_token_reserves: event.pool_base_token_reserves,
|
||||
pool_quote_token_reserves: event.pool_quote_token_reserves,
|
||||
coin_creator_vault_ata: event.coin_creator_vault_ata,
|
||||
@@ -164,6 +170,8 @@ impl PumpSwapParams {
|
||||
pool: event.pool,
|
||||
base_mint: event.base_mint,
|
||||
quote_mint: event.quote_mint,
|
||||
pool_base_token_account: event.pool_base_token_account,
|
||||
pool_quote_token_account: event.pool_quote_token_account,
|
||||
pool_base_token_reserves: event.pool_base_token_reserves,
|
||||
pool_quote_token_reserves: event.pool_quote_token_reserves,
|
||||
coin_creator_vault_ata: event.coin_creator_vault_ata,
|
||||
@@ -206,6 +214,8 @@ impl PumpSwapParams {
|
||||
pool: pool_address.clone(),
|
||||
base_mint: pool_data.base_mint,
|
||||
quote_mint: pool_data.quote_mint,
|
||||
pool_base_token_account: pool_data.pool_base_token_account,
|
||||
pool_quote_token_account: pool_data.pool_quote_token_account,
|
||||
pool_base_token_reserves: pool_base_token_reserves,
|
||||
pool_quote_token_reserves: pool_quote_token_reserves,
|
||||
coin_creator_vault_ata: coin_creator_vault_ata,
|
||||
|
||||
Reference in New Issue
Block a user