1use crate::core::events::*;
10
11#[inline(always)]
23pub fn merge_events(base: &mut DexEvent, inner: DexEvent) {
24 use DexEvent::*;
25
26 match (base, inner) {
27 (PumpFunTrade(b), PumpFunTrade(i)) | (PumpFunTrade(b), PumpFunBuy(i))
29 | (PumpFunTrade(b), PumpFunSell(i)) | (PumpFunTrade(b), PumpFunBuyExactSolIn(i))
30 | (PumpFunBuy(b), PumpFunTrade(i)) | (PumpFunBuy(b), PumpFunBuy(i))
31 | (PumpFunSell(b), PumpFunTrade(i)) | (PumpFunSell(b), PumpFunSell(i))
32 | (PumpFunBuyExactSolIn(b), PumpFunTrade(i)) | (PumpFunBuyExactSolIn(b), PumpFunBuyExactSolIn(i))
33 => merge_pumpfun_trade(b, i),
34
35 (PumpFunCreate(b), PumpFunCreate(i)) => merge_pumpfun_create(b, i),
36 (PumpFunCreateV2(b), PumpFunCreateV2(i)) => merge_generic(b, i),
37 (PumpFunMigrate(b), PumpFunMigrate(i)) => merge_pumpfun_migrate(b, i),
38
39 (PumpSwapBuy(b), PumpSwapBuy(i)) => merge_generic(b, i),
41 (PumpSwapSell(b), PumpSwapSell(i)) => merge_generic(b, i),
42 (PumpSwapCreatePool(b), PumpSwapCreatePool(i)) => merge_generic(b, i),
43 (PumpSwapLiquidityAdded(b), PumpSwapLiquidityAdded(i)) => merge_generic(b, i),
44 (PumpSwapLiquidityRemoved(b), PumpSwapLiquidityRemoved(i)) => merge_generic(b, i),
45
46 (RaydiumClmmSwap(b), RaydiumClmmSwap(i)) => merge_generic(b, i),
48 (RaydiumClmmIncreaseLiquidity(b), RaydiumClmmIncreaseLiquidity(i)) => merge_generic(b, i),
49 (RaydiumClmmDecreaseLiquidity(b), RaydiumClmmDecreaseLiquidity(i)) => merge_generic(b, i),
50 (RaydiumClmmCreatePool(b), RaydiumClmmCreatePool(i)) => merge_generic(b, i),
51 (RaydiumClmmCollectFee(b), RaydiumClmmCollectFee(i)) => merge_generic(b, i),
52
53 (RaydiumCpmmSwap(b), RaydiumCpmmSwap(i)) => merge_generic(b, i),
55 (RaydiumCpmmDeposit(b), RaydiumCpmmDeposit(i)) => merge_generic(b, i),
56 (RaydiumCpmmWithdraw(b), RaydiumCpmmWithdraw(i)) => merge_generic(b, i),
57
58 (RaydiumAmmV4Swap(b), RaydiumAmmV4Swap(i)) => merge_generic(b, i),
60 (RaydiumAmmV4Deposit(b), RaydiumAmmV4Deposit(i)) => merge_generic(b, i),
61 (RaydiumAmmV4Withdraw(b), RaydiumAmmV4Withdraw(i)) => merge_generic(b, i),
62
63 (OrcaWhirlpoolSwap(b), OrcaWhirlpoolSwap(i)) => merge_generic(b, i),
65 (OrcaWhirlpoolLiquidityIncreased(b), OrcaWhirlpoolLiquidityIncreased(i)) => merge_generic(b, i),
66 (OrcaWhirlpoolLiquidityDecreased(b), OrcaWhirlpoolLiquidityDecreased(i)) => merge_generic(b, i),
67
68 (MeteoraPoolsSwap(b), MeteoraPoolsSwap(i)) => merge_generic(b, i),
70 (MeteoraPoolsAddLiquidity(b), MeteoraPoolsAddLiquidity(i)) => merge_generic(b, i),
71 (MeteoraPoolsRemoveLiquidity(b), MeteoraPoolsRemoveLiquidity(i)) => merge_generic(b, i),
72
73 (MeteoraDammV2Swap(b), MeteoraDammV2Swap(i)) => merge_generic(b, i),
75 (MeteoraDammV2AddLiquidity(b), MeteoraDammV2AddLiquidity(i)) => merge_generic(b, i),
76 (MeteoraDammV2RemoveLiquidity(b), MeteoraDammV2RemoveLiquidity(i)) => merge_generic(b, i),
77 (MeteoraDammV2CreatePosition(b), MeteoraDammV2CreatePosition(i)) => merge_generic(b, i),
78 (MeteoraDammV2ClosePosition(b), MeteoraDammV2ClosePosition(i)) => merge_generic(b, i),
79
80 (BonkTrade(b), BonkTrade(i)) => merge_generic(b, i),
82
83 _ => {}
85 }
86}
87
88#[inline(always)]
95fn merge_generic<T>(base: &mut T, inner: T) {
96 *base = inner;
97}
98
99#[inline(always)]
110fn merge_pumpfun_trade(base: &mut PumpFunTradeEvent, inner: PumpFunTradeEvent) {
111 base.mint = inner.mint;
113 base.sol_amount = inner.sol_amount;
114 base.token_amount = inner.token_amount;
115 base.is_buy = inner.is_buy;
116 base.user = inner.user;
117 base.timestamp = inner.timestamp;
118 base.virtual_sol_reserves = inner.virtual_sol_reserves;
119 base.virtual_token_reserves = inner.virtual_token_reserves;
120 base.real_sol_reserves = inner.real_sol_reserves;
121 base.real_token_reserves = inner.real_token_reserves;
122 base.fee_recipient = inner.fee_recipient;
123 base.fee_basis_points = inner.fee_basis_points;
124 base.fee = inner.fee;
125 base.creator = inner.creator;
126 base.creator_fee_basis_points = inner.creator_fee_basis_points;
127 base.creator_fee = inner.creator_fee;
128
129 base.track_volume = inner.track_volume;
131 base.total_unclaimed_tokens = inner.total_unclaimed_tokens;
132 base.total_claimed_tokens = inner.total_claimed_tokens;
133 base.current_sol_volume = inner.current_sol_volume;
134 base.last_update_timestamp = inner.last_update_timestamp;
135 base.ix_name = inner.ix_name;
136 base.is_created_buy = inner.is_created_buy;
137 base.mayhem_mode = inner.mayhem_mode;
138 base.cashback_fee_basis_points = inner.cashback_fee_basis_points;
139 base.cashback = inner.cashback;
140 base.is_cashback_coin = inner.is_cashback_coin;
141
142 }
145
146#[inline(always)]
148fn merge_pumpfun_create(base: &mut PumpFunCreateTokenEvent, inner: PumpFunCreateTokenEvent) {
149 base.name = inner.name;
151 base.symbol = inner.symbol;
152 base.uri = inner.uri;
153 base.mint = inner.mint;
154 base.bonding_curve = inner.bonding_curve;
155 base.user = inner.user;
156 base.creator = inner.creator;
157 base.timestamp = inner.timestamp;
158 base.virtual_token_reserves = inner.virtual_token_reserves;
159 base.virtual_sol_reserves = inner.virtual_sol_reserves;
160 base.real_token_reserves = inner.real_token_reserves;
161 base.token_total_supply = inner.token_total_supply;
162 base.token_program = inner.token_program;
163 base.is_mayhem_mode = inner.is_mayhem_mode;
164}
165
166#[inline(always)]
168fn merge_pumpfun_migrate(base: &mut PumpFunMigrateEvent, inner: PumpFunMigrateEvent) {
169 base.user = inner.user;
171 base.mint = inner.mint;
172 base.mint_amount = inner.mint_amount;
173 base.sol_amount = inner.sol_amount;
174 base.pool_migration_fee = inner.pool_migration_fee;
175 base.bonding_curve = inner.bonding_curve;
176 base.timestamp = inner.timestamp;
177 base.pool = inner.pool;
178}
179
180#[inline(always)]
191pub fn can_merge(base: &DexEvent, inner: &DexEvent) -> bool {
192 if base.metadata().signature != inner.metadata().signature {
194 return false;
195 }
196
197 match (base, inner) {
199 (DexEvent::PumpFunTrade(_), DexEvent::PumpFunTrade(_))
201 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuy(_))
202 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunSell(_))
203 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuyExactSolIn(_))
204 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunTrade(_))
205 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunBuy(_))
206 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunTrade(_))
207 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunSell(_))
208 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunTrade(_))
209 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunBuyExactSolIn(_)) => true,
210
211 (DexEvent::PumpFunCreate(_), DexEvent::PumpFunCreate(_)) => true,
213 (DexEvent::PumpFunCreateV2(_), DexEvent::PumpFunCreateV2(_)) => true,
214
215 (DexEvent::PumpFunMigrate(_), DexEvent::PumpFunMigrate(_)) => true,
217
218 _ => false,
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226 use solana_sdk::{pubkey::Pubkey, signature::Signature};
227
228 #[test]
229 fn test_merge_pumpfun_trade() {
230 let metadata = EventMetadata {
231 signature: Signature::default(),
232 slot: 100,
233 tx_index: 1,
234 block_time_us: 1000,
235 grpc_recv_us: 2000,
236 recent_blockhash: None,
237 };
238
239 let mut base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
241 metadata: metadata.clone(),
242 bonding_curve: Pubkey::new_unique(),
243 associated_bonding_curve: Pubkey::new_unique(),
244 ..Default::default()
245 });
246
247 let inner = DexEvent::PumpFunTrade(PumpFunTradeEvent {
249 metadata: metadata.clone(),
250 mint: Pubkey::new_unique(),
251 sol_amount: 1000,
252 token_amount: 2000,
253 is_buy: true,
254 user: Pubkey::new_unique(),
255 ..Default::default()
256 });
257
258 merge_events(&mut base, inner);
260
261 if let DexEvent::PumpFunTrade(trade) = base {
263 assert_eq!(trade.sol_amount, 1000);
264 assert_eq!(trade.token_amount, 2000);
265 assert!(trade.is_buy);
266 assert_ne!(trade.bonding_curve, Pubkey::default());
268 assert_ne!(trade.associated_bonding_curve, Pubkey::default());
269 } else {
270 panic!("Expected PumpFunTrade event");
271 }
272 }
273
274 #[test]
275 fn test_can_merge() {
276 let metadata = EventMetadata {
277 signature: Signature::default(),
278 slot: 100,
279 tx_index: 1,
280 block_time_us: 1000,
281 grpc_recv_us: 2000,
282 recent_blockhash: None,
283 };
284
285 let base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
286 metadata: metadata.clone(),
287 ..Default::default()
288 });
289
290 let inner = DexEvent::PumpFunBuy(PumpFunTradeEvent {
291 metadata: metadata.clone(),
292 ..Default::default()
293 });
294
295 assert!(can_merge(&base, &inner));
297
298 let different_sig = DexEvent::PumpFunTrade(PumpFunTradeEvent {
300 metadata: EventMetadata {
301 signature: Signature::new_unique(),
302 ..metadata
303 },
304 ..Default::default()
305 });
306
307 assert!(!can_merge(&base, &different_sig));
308 }
309}