use solana_sdk::pubkey::Pubkey;
use crate::core::events::*;
#[inline(always)]
pub fn merge_events(base: &mut DexEvent, inner: DexEvent) {
use DexEvent::*;
match (base, inner) {
(PumpFunTrade(b), PumpFunTrade(i))
| (PumpFunTrade(b), PumpFunBuy(i))
| (PumpFunTrade(b), PumpFunSell(i))
| (PumpFunTrade(b), PumpFunBuyExactSolIn(i))
| (PumpFunBuy(b), PumpFunTrade(i))
| (PumpFunBuy(b), PumpFunBuy(i))
| (PumpFunSell(b), PumpFunTrade(i))
| (PumpFunSell(b), PumpFunSell(i))
| (PumpFunBuyExactSolIn(b), PumpFunTrade(i))
| (PumpFunBuyExactSolIn(b), PumpFunBuyExactSolIn(i)) => merge_pumpfun_trade(b, i),
(PumpFunCreate(b), PumpFunCreate(i)) => merge_pumpfun_create(b, i),
(PumpFunCreateV2(b), PumpFunCreateV2(i)) => merge_generic(b, i),
(PumpFunMigrate(b), PumpFunMigrate(i)) => merge_pumpfun_migrate(b, i),
(PumpSwapBuy(b), PumpSwapBuy(i)) => merge_generic(b, i),
(PumpSwapSell(b), PumpSwapSell(i)) => merge_generic(b, i),
(PumpSwapCreatePool(b), PumpSwapCreatePool(i)) => merge_generic(b, i),
(PumpSwapLiquidityAdded(b), PumpSwapLiquidityAdded(i)) => merge_generic(b, i),
(PumpSwapLiquidityRemoved(b), PumpSwapLiquidityRemoved(i)) => merge_generic(b, i),
(RaydiumClmmSwap(b), RaydiumClmmSwap(i)) => merge_generic(b, i),
(RaydiumClmmIncreaseLiquidity(b), RaydiumClmmIncreaseLiquidity(i)) => merge_generic(b, i),
(RaydiumClmmDecreaseLiquidity(b), RaydiumClmmDecreaseLiquidity(i)) => merge_generic(b, i),
(RaydiumClmmCreatePool(b), RaydiumClmmCreatePool(i)) => merge_generic(b, i),
(RaydiumClmmCollectFee(b), RaydiumClmmCollectFee(i)) => merge_generic(b, i),
(RaydiumCpmmSwap(b), RaydiumCpmmSwap(i)) => merge_generic(b, i),
(RaydiumCpmmDeposit(b), RaydiumCpmmDeposit(i)) => merge_generic(b, i),
(RaydiumCpmmWithdraw(b), RaydiumCpmmWithdraw(i)) => merge_generic(b, i),
(RaydiumAmmV4Swap(b), RaydiumAmmV4Swap(i)) => merge_generic(b, i),
(RaydiumAmmV4Deposit(b), RaydiumAmmV4Deposit(i)) => merge_generic(b, i),
(RaydiumAmmV4Withdraw(b), RaydiumAmmV4Withdraw(i)) => merge_generic(b, i),
(OrcaWhirlpoolSwap(b), OrcaWhirlpoolSwap(i)) => merge_generic(b, i),
(OrcaWhirlpoolLiquidityIncreased(b), OrcaWhirlpoolLiquidityIncreased(i)) => {
merge_generic(b, i)
}
(OrcaWhirlpoolLiquidityDecreased(b), OrcaWhirlpoolLiquidityDecreased(i)) => {
merge_generic(b, i)
}
(MeteoraPoolsSwap(b), MeteoraPoolsSwap(i)) => merge_generic(b, i),
(MeteoraPoolsAddLiquidity(b), MeteoraPoolsAddLiquidity(i)) => merge_generic(b, i),
(MeteoraPoolsRemoveLiquidity(b), MeteoraPoolsRemoveLiquidity(i)) => merge_generic(b, i),
(MeteoraDammV2Swap(b), MeteoraDammV2Swap(i)) => merge_generic(b, i),
(MeteoraDammV2AddLiquidity(b), MeteoraDammV2AddLiquidity(i)) => merge_generic(b, i),
(MeteoraDammV2RemoveLiquidity(b), MeteoraDammV2RemoveLiquidity(i)) => merge_generic(b, i),
(MeteoraDammV2CreatePosition(b), MeteoraDammV2CreatePosition(i)) => merge_generic(b, i),
(MeteoraDammV2ClosePosition(b), MeteoraDammV2ClosePosition(i)) => merge_generic(b, i),
(BonkTrade(b), BonkTrade(i)) => merge_generic(b, i),
_ => {}
}
}
#[inline(always)]
fn merge_generic<T>(base: &mut T, inner: T) {
*base = inner;
}
#[inline(always)]
fn put_pk_if_set(to: &mut Pubkey, from: Pubkey) {
if from != Pubkey::default() {
*to = from;
}
}
#[inline(always)]
fn put_u64_if_nonzero(to: &mut u64, from: u64) {
if from != 0 {
*to = from;
}
}
#[inline(always)]
fn put_i64_if_nonzero(to: &mut i64, from: i64) {
if from != 0 {
*to = from;
}
}
#[inline(always)]
fn merge_pumpfun_trade(base: &mut PumpFunTradeEvent, inner: PumpFunTradeEvent) {
let leg = inner.sol_amount != 0 || inner.token_amount != 0;
put_pk_if_set(&mut base.mint, inner.mint);
put_pk_if_set(&mut base.user, inner.user);
put_pk_if_set(&mut base.fee_recipient, inner.fee_recipient);
put_pk_if_set(&mut base.creator, inner.creator);
if leg {
base.sol_amount = inner.sol_amount;
base.token_amount = inner.token_amount;
base.is_buy = inner.is_buy;
base.timestamp = inner.timestamp;
base.virtual_sol_reserves = inner.virtual_sol_reserves;
base.virtual_token_reserves = inner.virtual_token_reserves;
base.real_sol_reserves = inner.real_sol_reserves;
base.real_token_reserves = inner.real_token_reserves;
base.fee_basis_points = inner.fee_basis_points;
base.fee = inner.fee;
base.creator_fee_basis_points = inner.creator_fee_basis_points;
base.creator_fee = inner.creator_fee;
base.track_volume |= inner.track_volume;
base.total_unclaimed_tokens = inner.total_unclaimed_tokens;
base.total_claimed_tokens = inner.total_claimed_tokens;
base.current_sol_volume = inner.current_sol_volume;
base.last_update_timestamp = inner.last_update_timestamp;
base.ix_name = inner.ix_name;
base.mayhem_mode |= inner.mayhem_mode;
base.cashback_fee_basis_points = inner.cashback_fee_basis_points;
base.cashback = inner.cashback;
base.is_cashback_coin |= inner.is_cashback_coin;
} else {
put_u64_if_nonzero(&mut base.fee, inner.fee);
put_u64_if_nonzero(&mut base.creator_fee, inner.creator_fee);
put_u64_if_nonzero(&mut base.fee_basis_points, inner.fee_basis_points);
put_u64_if_nonzero(&mut base.creator_fee_basis_points, inner.creator_fee_basis_points);
put_u64_if_nonzero(&mut base.virtual_sol_reserves, inner.virtual_sol_reserves);
put_u64_if_nonzero(&mut base.virtual_token_reserves, inner.virtual_token_reserves);
put_u64_if_nonzero(&mut base.real_sol_reserves, inner.real_sol_reserves);
put_u64_if_nonzero(&mut base.real_token_reserves, inner.real_token_reserves);
put_u64_if_nonzero(&mut base.total_unclaimed_tokens, inner.total_unclaimed_tokens);
put_u64_if_nonzero(&mut base.total_claimed_tokens, inner.total_claimed_tokens);
put_u64_if_nonzero(&mut base.current_sol_volume, inner.current_sol_volume);
put_u64_if_nonzero(&mut base.cashback_fee_basis_points, inner.cashback_fee_basis_points);
put_u64_if_nonzero(&mut base.cashback, inner.cashback);
put_i64_if_nonzero(&mut base.timestamp, inner.timestamp);
put_i64_if_nonzero(&mut base.last_update_timestamp, inner.last_update_timestamp);
if !inner.ix_name.is_empty() {
base.ix_name = inner.ix_name;
}
base.track_volume |= inner.track_volume;
base.mayhem_mode |= inner.mayhem_mode;
base.is_cashback_coin |= inner.is_cashback_coin;
}
base.is_created_buy |= inner.is_created_buy;
}
#[inline(always)]
fn merge_pumpfun_create(base: &mut PumpFunCreateTokenEvent, inner: PumpFunCreateTokenEvent) {
base.name = inner.name;
base.symbol = inner.symbol;
base.uri = inner.uri;
base.mint = inner.mint;
base.bonding_curve = inner.bonding_curve;
base.user = inner.user;
base.creator = inner.creator;
base.timestamp = inner.timestamp;
base.virtual_token_reserves = inner.virtual_token_reserves;
base.virtual_sol_reserves = inner.virtual_sol_reserves;
base.real_token_reserves = inner.real_token_reserves;
base.token_total_supply = inner.token_total_supply;
base.token_program = inner.token_program;
base.is_mayhem_mode = inner.is_mayhem_mode;
}
#[inline(always)]
fn merge_pumpfun_migrate(base: &mut PumpFunMigrateEvent, inner: PumpFunMigrateEvent) {
base.user = inner.user;
base.mint = inner.mint;
base.mint_amount = inner.mint_amount;
base.sol_amount = inner.sol_amount;
base.pool_migration_fee = inner.pool_migration_fee;
base.bonding_curve = inner.bonding_curve;
base.timestamp = inner.timestamp;
base.pool = inner.pool;
}
#[inline(always)]
pub fn can_merge(base: &DexEvent, inner: &DexEvent) -> bool {
if base.metadata().signature != inner.metadata().signature {
return false;
}
match (base, inner) {
(DexEvent::PumpFunTrade(_), DexEvent::PumpFunTrade(_))
| (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuy(_))
| (DexEvent::PumpFunTrade(_), DexEvent::PumpFunSell(_))
| (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuyExactSolIn(_))
| (DexEvent::PumpFunBuy(_), DexEvent::PumpFunTrade(_))
| (DexEvent::PumpFunBuy(_), DexEvent::PumpFunBuy(_))
| (DexEvent::PumpFunSell(_), DexEvent::PumpFunTrade(_))
| (DexEvent::PumpFunSell(_), DexEvent::PumpFunSell(_))
| (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunTrade(_))
| (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunBuyExactSolIn(_)) => true,
(DexEvent::PumpFunCreate(_), DexEvent::PumpFunCreate(_)) => true,
(DexEvent::PumpFunCreateV2(_), DexEvent::PumpFunCreateV2(_)) => true,
(DexEvent::PumpFunMigrate(_), DexEvent::PumpFunMigrate(_)) => true,
_ => false,
}
}
#[inline(always)]
fn fill_pk(to: &mut Pubkey, from: Pubkey) {
if *to == Pubkey::default() && from != Pubkey::default() {
*to = from;
}
}
#[inline(always)]
fn fill_str_if_empty(to: &mut String, from: &str) {
if to.is_empty() && !from.is_empty() {
to.push_str(from);
}
}
#[inline]
fn merge_pumpfun_trade_log_preferred(log: &mut PumpFunTradeEvent, ix: PumpFunTradeEvent) {
fill_pk(&mut log.bonding_curve, ix.bonding_curve);
fill_pk(&mut log.associated_bonding_curve, ix.associated_bonding_curve);
fill_pk(&mut log.token_program, ix.token_program);
fill_pk(&mut log.creator_vault, ix.creator_vault);
fill_pk(&mut log.fee_recipient, ix.fee_recipient);
fill_pk(&mut log.creator, ix.creator);
if log.account.is_none() {
log.account = ix.account;
}
if log.ix_name.is_empty() && !ix.ix_name.is_empty() {
log.ix_name = ix.ix_name;
}
if !log.is_created_buy && ix.is_created_buy {
log.is_created_buy = true;
}
}
#[inline]
fn merge_pumpfun_create_log_preferred(log: &mut PumpFunCreateTokenEvent, ix: PumpFunCreateTokenEvent) {
fill_str_if_empty(&mut log.name, &ix.name);
fill_str_if_empty(&mut log.symbol, &ix.symbol);
fill_str_if_empty(&mut log.uri, &ix.uri);
fill_pk(&mut log.bonding_curve, ix.bonding_curve);
fill_pk(&mut log.user, ix.user);
fill_pk(&mut log.creator, ix.creator);
fill_pk(&mut log.token_program, ix.token_program);
}
#[inline]
fn merge_pumpfun_create_v2_log_preferred(
log: &mut PumpFunCreateV2TokenEvent,
ix: PumpFunCreateV2TokenEvent,
) {
fill_str_if_empty(&mut log.name, &ix.name);
fill_str_if_empty(&mut log.symbol, &ix.symbol);
fill_str_if_empty(&mut log.uri, &ix.uri);
fill_pk(&mut log.bonding_curve, ix.bonding_curve);
fill_pk(&mut log.user, ix.user);
fill_pk(&mut log.creator, ix.creator);
fill_pk(&mut log.token_program, ix.token_program);
fill_pk(&mut log.mint_authority, ix.mint_authority);
fill_pk(&mut log.associated_bonding_curve, ix.associated_bonding_curve);
fill_pk(&mut log.global, ix.global);
fill_pk(&mut log.system_program, ix.system_program);
fill_pk(&mut log.associated_token_program, ix.associated_token_program);
fill_pk(&mut log.mayhem_program_id, ix.mayhem_program_id);
fill_pk(&mut log.global_params, ix.global_params);
fill_pk(&mut log.sol_vault, ix.sol_vault);
fill_pk(&mut log.mayhem_state, ix.mayhem_state);
fill_pk(&mut log.mayhem_token_vault, ix.mayhem_token_vault);
fill_pk(&mut log.event_authority, ix.event_authority);
fill_pk(&mut log.program, ix.program);
fill_pk(&mut log.observed_fee_recipient, ix.observed_fee_recipient);
}
#[inline]
fn merge_pumpfun_migrate_log_preferred(log: &mut PumpFunMigrateEvent, ix: PumpFunMigrateEvent) {
fill_pk(&mut log.bonding_curve, ix.bonding_curve);
fill_pk(&mut log.pool, ix.pool);
fill_pk(&mut log.user, ix.user);
}
#[inline]
fn merge_pumpswap_trade_log_preferred(log: &mut PumpSwapTradeEvent, ix: PumpSwapTradeEvent) {
if log.ix_name.is_empty() && !ix.ix_name.is_empty() {
log.ix_name = ix.ix_name;
}
}
#[inline]
fn merge_pumpswap_buy_log_preferred(log: &mut PumpSwapBuyEvent, ix: PumpSwapBuyEvent) {
fill_pk(&mut log.user_base_token_account, ix.user_base_token_account);
fill_pk(&mut log.user_quote_token_account, ix.user_quote_token_account);
fill_pk(&mut log.protocol_fee_recipient, ix.protocol_fee_recipient);
fill_pk(
&mut log.protocol_fee_recipient_token_account,
ix.protocol_fee_recipient_token_account,
);
fill_pk(&mut log.coin_creator, ix.coin_creator);
fill_pk(&mut log.base_mint, ix.base_mint);
fill_pk(&mut log.quote_mint, ix.quote_mint);
fill_pk(&mut log.pool_base_token_account, ix.pool_base_token_account);
fill_pk(&mut log.pool_quote_token_account, ix.pool_quote_token_account);
fill_pk(&mut log.coin_creator_vault_ata, ix.coin_creator_vault_ata);
fill_pk(
&mut log.coin_creator_vault_authority,
ix.coin_creator_vault_authority,
);
fill_pk(&mut log.base_token_program, ix.base_token_program);
fill_pk(&mut log.quote_token_program, ix.quote_token_program);
if log.ix_name.is_empty() && !ix.ix_name.is_empty() {
log.ix_name = ix.ix_name;
}
}
#[inline]
fn merge_pumpswap_sell_log_preferred(log: &mut PumpSwapSellEvent, ix: PumpSwapSellEvent) {
fill_pk(&mut log.user_base_token_account, ix.user_base_token_account);
fill_pk(&mut log.user_quote_token_account, ix.user_quote_token_account);
fill_pk(&mut log.protocol_fee_recipient, ix.protocol_fee_recipient);
fill_pk(
&mut log.protocol_fee_recipient_token_account,
ix.protocol_fee_recipient_token_account,
);
fill_pk(&mut log.coin_creator, ix.coin_creator);
fill_pk(&mut log.base_mint, ix.base_mint);
fill_pk(&mut log.quote_mint, ix.quote_mint);
fill_pk(&mut log.pool_base_token_account, ix.pool_base_token_account);
fill_pk(&mut log.pool_quote_token_account, ix.pool_quote_token_account);
fill_pk(&mut log.coin_creator_vault_ata, ix.coin_creator_vault_ata);
fill_pk(
&mut log.coin_creator_vault_authority,
ix.coin_creator_vault_authority,
);
fill_pk(&mut log.base_token_program, ix.base_token_program);
fill_pk(&mut log.quote_token_program, ix.quote_token_program);
}
#[inline]
fn merge_raydium_clmm_swap_log_preferred(log: &mut RaydiumClmmSwapEvent, ix: RaydiumClmmSwapEvent) {
fill_pk(&mut log.token_account_0, ix.token_account_0);
fill_pk(&mut log.token_account_1, ix.token_account_1);
fill_pk(&mut log.sender, ix.sender);
}
#[inline]
fn merge_raydium_amm_v4_swap_log_preferred(log: &mut RaydiumAmmV4SwapEvent, ix: RaydiumAmmV4SwapEvent) {
fill_pk(&mut log.token_program, ix.token_program);
fill_pk(&mut log.amm_authority, ix.amm_authority);
fill_pk(&mut log.amm_open_orders, ix.amm_open_orders);
if let Some(ref o) = ix.amm_target_orders {
if log.amm_target_orders.is_none() {
log.amm_target_orders = Some(*o);
}
}
fill_pk(&mut log.pool_coin_token_account, ix.pool_coin_token_account);
fill_pk(&mut log.pool_pc_token_account, ix.pool_pc_token_account);
fill_pk(&mut log.serum_program, ix.serum_program);
fill_pk(&mut log.serum_market, ix.serum_market);
fill_pk(&mut log.serum_bids, ix.serum_bids);
fill_pk(&mut log.serum_asks, ix.serum_asks);
fill_pk(&mut log.serum_event_queue, ix.serum_event_queue);
fill_pk(
&mut log.serum_coin_vault_account,
ix.serum_coin_vault_account,
);
fill_pk(&mut log.serum_pc_vault_account, ix.serum_pc_vault_account);
fill_pk(&mut log.serum_vault_signer, ix.serum_vault_signer);
fill_pk(
&mut log.user_source_token_account,
ix.user_source_token_account,
);
fill_pk(
&mut log.user_destination_token_account,
ix.user_destination_token_account,
);
}
#[inline]
fn merge_pumpswap_create_pool_log_preferred(
log: &mut PumpSwapCreatePoolEvent,
ix: PumpSwapCreatePoolEvent,
) {
fill_pk(&mut log.creator, ix.creator);
fill_pk(&mut log.pool, ix.pool);
fill_pk(&mut log.lp_mint, ix.lp_mint);
fill_pk(&mut log.user_base_token_account, ix.user_base_token_account);
fill_pk(&mut log.user_quote_token_account, ix.user_quote_token_account);
fill_pk(&mut log.coin_creator, ix.coin_creator);
}
#[inline]
fn merge_pumpswap_liquidity_added_log_preferred(
log: &mut PumpSwapLiquidityAdded,
ix: PumpSwapLiquidityAdded,
) {
fill_pk(&mut log.user_base_token_account, ix.user_base_token_account);
fill_pk(&mut log.user_quote_token_account, ix.user_quote_token_account);
fill_pk(&mut log.user_pool_token_account, ix.user_pool_token_account);
}
#[inline]
fn merge_pumpswap_liquidity_removed_log_preferred(
log: &mut PumpSwapLiquidityRemoved,
ix: PumpSwapLiquidityRemoved,
) {
fill_pk(&mut log.user_base_token_account, ix.user_base_token_account);
fill_pk(&mut log.user_quote_token_account, ix.user_quote_token_account);
fill_pk(&mut log.user_pool_token_account, ix.user_pool_token_account);
}
#[inline]
fn merge_bonk_pool_create_log_preferred(log: &mut BonkPoolCreateEvent, ix: BonkPoolCreateEvent) {
fill_pk(&mut log.creator, ix.creator);
fill_str_if_empty(&mut log.base_mint_param.name, &ix.base_mint_param.name);
fill_str_if_empty(&mut log.base_mint_param.symbol, &ix.base_mint_param.symbol);
fill_str_if_empty(&mut log.base_mint_param.uri, &ix.base_mint_param.uri);
}
#[inline]
fn merge_bonk_migrate_amm_log_preferred(log: &mut BonkMigrateAmmEvent, ix: BonkMigrateAmmEvent) {
fill_pk(&mut log.old_pool, ix.old_pool);
fill_pk(&mut log.new_pool, ix.new_pool);
fill_pk(&mut log.user, ix.user);
}
#[inline]
fn merge_bonk_trade_log_preferred(_log: &mut BonkTradeEvent, _ix: BonkTradeEvent) {}
#[inline]
fn merge_meteora_dlmm_swap_log_preferred(_log: &mut MeteoraDlmmSwapEvent, _ix: MeteoraDlmmSwapEvent) {}
pub fn merge_grpc_instruction_into_log(log: &mut DexEvent, ix: DexEvent) {
use DexEvent::*;
match log {
PumpFunTrade(l) => {
if let Some(i) = pumpfun_trade_from_ix_variant(ix) {
merge_pumpfun_trade_log_preferred(l, i);
}
}
PumpFunBuy(l) => {
if let Some(i) = pumpfun_trade_from_ix_variant(ix) {
merge_pumpfun_trade_log_preferred(l, i);
}
}
PumpFunSell(l) => {
if let Some(i) = pumpfun_trade_from_ix_variant(ix) {
merge_pumpfun_trade_log_preferred(l, i);
}
}
PumpFunBuyExactSolIn(l) => {
if let Some(i) = pumpfun_trade_from_ix_variant(ix) {
merge_pumpfun_trade_log_preferred(l, i);
}
}
PumpFunCreate(l) => {
if let DexEvent::PumpFunCreate(i) = ix {
merge_pumpfun_create_log_preferred(l, i);
}
}
PumpFunCreateV2(l) => {
if let DexEvent::PumpFunCreateV2(i) = ix {
merge_pumpfun_create_v2_log_preferred(l, i);
}
}
PumpFunMigrate(l) => {
if let DexEvent::PumpFunMigrate(i) = ix {
merge_pumpfun_migrate_log_preferred(l, i);
}
}
PumpSwapTrade(l) => {
if let PumpSwapTrade(i) = ix {
merge_pumpswap_trade_log_preferred(l, i);
}
}
PumpSwapBuy(l) => {
if let PumpSwapBuy(i) = ix {
merge_pumpswap_buy_log_preferred(l, i);
}
}
PumpSwapSell(l) => {
if let PumpSwapSell(i) = ix {
merge_pumpswap_sell_log_preferred(l, i);
}
}
RaydiumClmmSwap(l) => {
if let RaydiumClmmSwap(i) = ix {
merge_raydium_clmm_swap_log_preferred(l, i);
}
}
RaydiumAmmV4Swap(l) => {
if let RaydiumAmmV4Swap(i) = ix {
merge_raydium_amm_v4_swap_log_preferred(l, i);
}
}
BonkTrade(l) => {
if let BonkTrade(i) = ix {
merge_bonk_trade_log_preferred(l, i);
}
}
BonkPoolCreate(l) => {
if let BonkPoolCreate(i) = ix {
merge_bonk_pool_create_log_preferred(l, i);
}
}
BonkMigrateAmm(l) => {
if let BonkMigrateAmm(i) = ix {
merge_bonk_migrate_amm_log_preferred(l, i);
}
}
PumpSwapCreatePool(l) => {
if let PumpSwapCreatePool(i) = ix {
merge_pumpswap_create_pool_log_preferred(l, i);
}
}
PumpSwapLiquidityAdded(l) => {
if let PumpSwapLiquidityAdded(i) = ix {
merge_pumpswap_liquidity_added_log_preferred(l, i);
}
}
PumpSwapLiquidityRemoved(l) => {
if let PumpSwapLiquidityRemoved(i) = ix {
merge_pumpswap_liquidity_removed_log_preferred(l, i);
}
}
MeteoraDlmmSwap(l) => {
if let MeteoraDlmmSwap(i) = ix {
merge_meteora_dlmm_swap_log_preferred(l, i);
}
}
_ => {}
}
}
#[inline]
fn pumpfun_trade_from_ix_variant(ix: DexEvent) -> Option<PumpFunTradeEvent> {
match ix {
DexEvent::PumpFunTrade(t)
| DexEvent::PumpFunBuy(t)
| DexEvent::PumpFunSell(t)
| DexEvent::PumpFunBuyExactSolIn(t) => Some(t),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
#[test]
fn test_merge_pumpfun_trade() {
let metadata = EventMetadata {
signature: Signature::default(),
slot: 100,
tx_index: 1,
block_time_us: 1000,
grpc_recv_us: 2000,
recent_blockhash: None,
};
let mut base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
metadata: metadata.clone(),
bonding_curve: Pubkey::new_unique(),
associated_bonding_curve: Pubkey::new_unique(),
..Default::default()
});
let inner = DexEvent::PumpFunTrade(PumpFunTradeEvent {
metadata: metadata.clone(),
mint: Pubkey::new_unique(),
sol_amount: 1000,
token_amount: 2000,
is_buy: true,
user: Pubkey::new_unique(),
..Default::default()
});
merge_events(&mut base, inner);
if let DexEvent::PumpFunTrade(trade) = base {
assert_eq!(trade.sol_amount, 1000);
assert_eq!(trade.token_amount, 2000);
assert!(trade.is_buy);
assert_ne!(trade.bonding_curve, Pubkey::default());
assert_ne!(trade.associated_bonding_curve, Pubkey::default());
} else {
panic!("Expected PumpFunTrade event");
}
}
#[test]
fn test_can_merge() {
let metadata = EventMetadata {
signature: Signature::default(),
slot: 100,
tx_index: 1,
block_time_us: 1000,
grpc_recv_us: 2000,
recent_blockhash: None,
};
let base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
metadata: metadata.clone(),
..Default::default()
});
let inner = DexEvent::PumpFunBuy(PumpFunTradeEvent {
metadata: metadata.clone(),
..Default::default()
});
assert!(can_merge(&base, &inner));
let different_sig = DexEvent::PumpFunTrade(PumpFunTradeEvent {
metadata: EventMetadata { signature: Signature::new_unique(), ..metadata },
..Default::default()
});
assert!(!can_merge(&base, &different_sig));
}
#[test]
fn grpc_merge_fills_fee_recipient_from_ix_when_log_default() {
let metadata = EventMetadata {
signature: Signature::default(),
slot: 1,
tx_index: 0,
block_time_us: 0,
grpc_recv_us: 0,
recent_blockhash: None,
};
let fr = Pubkey::new_unique();
let log_t = PumpFunTradeEvent {
metadata: metadata.clone(),
sol_amount: 50,
..Default::default()
};
let mut ix_t = log_t.clone();
ix_t.fee_recipient = fr;
ix_t.sol_amount = 777;
let mut log_ev = DexEvent::PumpFunTrade(log_t);
merge_grpc_instruction_into_log(&mut log_ev, DexEvent::PumpFunBuy(ix_t));
match log_ev {
DexEvent::PumpFunTrade(t) => {
assert_eq!(t.fee_recipient, fr);
assert_eq!(t.sol_amount, 50);
}
_ => panic!("expected trade"),
}
}
#[test]
fn grpc_merge_keeps_log_trade_fields() {
let metadata = EventMetadata {
signature: Signature::default(),
slot: 1,
tx_index: 0,
block_time_us: 0,
grpc_recv_us: 0,
recent_blockhash: None,
};
let log_t = PumpFunTradeEvent {
metadata: metadata.clone(),
mayhem_mode: true,
sol_amount: 100,
..Default::default()
};
let mut ix_t = log_t.clone();
ix_t.mayhem_mode = false;
ix_t.sol_amount = 999;
let mut log_ev = DexEvent::PumpFunTrade(log_t);
merge_grpc_instruction_into_log(&mut log_ev, DexEvent::PumpFunBuy(ix_t));
match log_ev {
DexEvent::PumpFunTrade(t) => {
assert!(t.mayhem_mode);
assert_eq!(t.sol_amount, 100);
}
_ => panic!("variant preserved"),
}
}
}