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 merge_pumpfun_trade(base: &mut PumpFunTradeEvent, inner: PumpFunTradeEvent) {
base.mint = inner.mint;
base.sol_amount = inner.sol_amount;
base.token_amount = inner.token_amount;
base.is_buy = inner.is_buy;
base.user = inner.user;
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_recipient = inner.fee_recipient;
base.fee_basis_points = inner.fee_basis_points;
base.fee = inner.fee;
base.creator = inner.creator;
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.is_created_buy = inner.is_created_buy;
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;
}
#[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,
}
}
#[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));
}
}