fix(meteora-damm-v2): use correct token program for output ATA creation

- Pass token_a/token_b program based on swap direction (is_a_in) when
  creating the output mint ATA in buy flow, matching ATA address derivation
  for SPL Token vs Token-2022 mints.
- Resolve token_a_program and token_b_program from on-chain mint account
  owners in MeteoraDammV2Params::from_pool_address_by_rpc instead of
  hardcoding the classic SPL Token program.

Fixes incorrect ATA creation for Token-2022 output mints (issue #99).

Made-with: Cursor
This commit is contained in:
0xfnzero
2026-04-14 13:04:01 +08:00
parent 06ef2fed84
commit d711346c55
2 changed files with 20 additions and 4 deletions
+5 -1
View File
@@ -87,7 +87,11 @@ impl InstructionBuilder for MeteoraDammV2InstructionBuilder {
&params.payer.pubkey(),
&params.payer.pubkey(),
&params.output_mint,
&crate::constants::TOKEN_PROGRAM,
if is_a_in {
&protocol_params.token_b_program
} else {
&protocol_params.token_a_program
},
params.open_seed_optimize,
),
);
+15 -3
View File
@@ -2,7 +2,6 @@ use crate::common::bonding_curve::BondingCurveAccount;
use crate::common::nonce_cache::DurableNonceInfo;
use crate::common::spl_associated_token_account::get_associated_token_address_with_program_id;
use crate::common::{GasFeeStrategy, SolanaRpcClient};
use crate::constants::TOKEN_PROGRAM;
use core_affinity::CoreId;
use crate::instruction::utils::pumpfun::is_mayhem_fee_recipient;
@@ -854,14 +853,27 @@ impl MeteoraDammV2Params {
) -> Result<Self, anyhow::Error> {
let pool_data =
crate::instruction::utils::meteora_damm_v2::fetch_pool(rpc, pool_address).await?;
let mint_accounts = rpc
.get_multiple_accounts(&[pool_data.token_a_mint, pool_data.token_b_mint])
.await?;
let token_a_program = mint_accounts
.get(0)
.and_then(|a| a.as_ref())
.map(|a| a.owner)
.ok_or_else(|| anyhow::anyhow!("Token A mint account not found"))?;
let token_b_program = mint_accounts
.get(1)
.and_then(|a| a.as_ref())
.map(|a| a.owner)
.ok_or_else(|| anyhow::anyhow!("Token B mint account not found"))?;
Ok(Self {
pool: *pool_address,
token_a_vault: pool_data.token_a_vault,
token_b_vault: pool_data.token_b_vault,
token_a_mint: pool_data.token_a_mint,
token_b_mint: pool_data.token_b_mint,
token_a_program: TOKEN_PROGRAM,
token_b_program: TOKEN_PROGRAM,
token_a_program,
token_b_program,
})
}
}