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))
29 | (PumpFunTrade(b), PumpFunBuy(i))
30 | (PumpFunTrade(b), PumpFunSell(i))
31 | (PumpFunTrade(b), PumpFunBuyExactSolIn(i))
32 | (PumpFunBuy(b), PumpFunTrade(i))
33 | (PumpFunBuy(b), PumpFunBuy(i))
34 | (PumpFunSell(b), PumpFunTrade(i))
35 | (PumpFunSell(b), PumpFunSell(i))
36 | (PumpFunBuyExactSolIn(b), PumpFunTrade(i))
37 | (PumpFunBuyExactSolIn(b), PumpFunBuyExactSolIn(i)) => merge_pumpfun_trade(b, i),
38
39 (PumpFunCreate(b), PumpFunCreate(i)) => merge_pumpfun_create(b, i),
40 (PumpFunCreateV2(b), PumpFunCreateV2(i)) => merge_generic(b, i),
41 (PumpFunMigrate(b), PumpFunMigrate(i)) => merge_pumpfun_migrate(b, i),
42
43 (PumpSwapBuy(b), PumpSwapBuy(i)) => merge_generic(b, i),
45 (PumpSwapSell(b), PumpSwapSell(i)) => merge_generic(b, i),
46 (PumpSwapCreatePool(b), PumpSwapCreatePool(i)) => merge_generic(b, i),
47 (PumpSwapLiquidityAdded(b), PumpSwapLiquidityAdded(i)) => merge_generic(b, i),
48 (PumpSwapLiquidityRemoved(b), PumpSwapLiquidityRemoved(i)) => merge_generic(b, i),
49
50 (RaydiumClmmSwap(b), RaydiumClmmSwap(i)) => merge_generic(b, i),
52 (RaydiumClmmIncreaseLiquidity(b), RaydiumClmmIncreaseLiquidity(i)) => merge_generic(b, i),
53 (RaydiumClmmDecreaseLiquidity(b), RaydiumClmmDecreaseLiquidity(i)) => merge_generic(b, i),
54 (RaydiumClmmCreatePool(b), RaydiumClmmCreatePool(i)) => merge_generic(b, i),
55 (RaydiumClmmCollectFee(b), RaydiumClmmCollectFee(i)) => merge_generic(b, i),
56
57 (RaydiumCpmmSwap(b), RaydiumCpmmSwap(i)) => merge_generic(b, i),
59 (RaydiumCpmmDeposit(b), RaydiumCpmmDeposit(i)) => merge_generic(b, i),
60 (RaydiumCpmmWithdraw(b), RaydiumCpmmWithdraw(i)) => merge_generic(b, i),
61
62 (RaydiumAmmV4Swap(b), RaydiumAmmV4Swap(i)) => merge_generic(b, i),
64 (RaydiumAmmV4Deposit(b), RaydiumAmmV4Deposit(i)) => merge_generic(b, i),
65 (RaydiumAmmV4Withdraw(b), RaydiumAmmV4Withdraw(i)) => merge_generic(b, i),
66
67 (OrcaWhirlpoolSwap(b), OrcaWhirlpoolSwap(i)) => merge_generic(b, i),
69 (OrcaWhirlpoolLiquidityIncreased(b), OrcaWhirlpoolLiquidityIncreased(i)) => {
70 merge_generic(b, i)
71 }
72 (OrcaWhirlpoolLiquidityDecreased(b), OrcaWhirlpoolLiquidityDecreased(i)) => {
73 merge_generic(b, i)
74 }
75
76 (MeteoraPoolsSwap(b), MeteoraPoolsSwap(i)) => merge_generic(b, i),
78 (MeteoraPoolsAddLiquidity(b), MeteoraPoolsAddLiquidity(i)) => merge_generic(b, i),
79 (MeteoraPoolsRemoveLiquidity(b), MeteoraPoolsRemoveLiquidity(i)) => merge_generic(b, i),
80
81 (MeteoraDammV2Swap(b), MeteoraDammV2Swap(i)) => merge_generic(b, i),
83 (MeteoraDammV2AddLiquidity(b), MeteoraDammV2AddLiquidity(i)) => merge_generic(b, i),
84 (MeteoraDammV2RemoveLiquidity(b), MeteoraDammV2RemoveLiquidity(i)) => merge_generic(b, i),
85 (MeteoraDammV2CreatePosition(b), MeteoraDammV2CreatePosition(i)) => merge_generic(b, i),
86 (MeteoraDammV2ClosePosition(b), MeteoraDammV2ClosePosition(i)) => merge_generic(b, i),
87
88 (BonkTrade(b), BonkTrade(i)) => merge_generic(b, i),
90
91 _ => {}
93 }
94}
95
96#[inline(always)]
103fn merge_generic<T>(base: &mut T, inner: T) {
104 *base = inner;
105}
106
107#[inline(always)]
118fn merge_pumpfun_trade(base: &mut PumpFunTradeEvent, inner: PumpFunTradeEvent) {
119 base.mint = inner.mint;
121 base.sol_amount = inner.sol_amount;
122 base.token_amount = inner.token_amount;
123 base.is_buy = inner.is_buy;
124 base.user = inner.user;
125 base.timestamp = inner.timestamp;
126 base.virtual_sol_reserves = inner.virtual_sol_reserves;
127 base.virtual_token_reserves = inner.virtual_token_reserves;
128 base.real_sol_reserves = inner.real_sol_reserves;
129 base.real_token_reserves = inner.real_token_reserves;
130 base.fee_recipient = inner.fee_recipient;
131 base.fee_basis_points = inner.fee_basis_points;
132 base.fee = inner.fee;
133 base.creator = inner.creator;
134 base.creator_fee_basis_points = inner.creator_fee_basis_points;
135 base.creator_fee = inner.creator_fee;
136
137 base.track_volume = inner.track_volume;
139 base.total_unclaimed_tokens = inner.total_unclaimed_tokens;
140 base.total_claimed_tokens = inner.total_claimed_tokens;
141 base.current_sol_volume = inner.current_sol_volume;
142 base.last_update_timestamp = inner.last_update_timestamp;
143 base.ix_name = inner.ix_name;
144 base.is_created_buy = inner.is_created_buy;
145 base.mayhem_mode = inner.mayhem_mode;
146 base.cashback_fee_basis_points = inner.cashback_fee_basis_points;
147 base.cashback = inner.cashback;
148 base.is_cashback_coin = inner.is_cashback_coin;
149
150 }
153
154#[inline(always)]
156fn merge_pumpfun_create(base: &mut PumpFunCreateTokenEvent, inner: PumpFunCreateTokenEvent) {
157 base.name = inner.name;
159 base.symbol = inner.symbol;
160 base.uri = inner.uri;
161 base.mint = inner.mint;
162 base.bonding_curve = inner.bonding_curve;
163 base.user = inner.user;
164 base.creator = inner.creator;
165 base.timestamp = inner.timestamp;
166 base.virtual_token_reserves = inner.virtual_token_reserves;
167 base.virtual_sol_reserves = inner.virtual_sol_reserves;
168 base.real_token_reserves = inner.real_token_reserves;
169 base.token_total_supply = inner.token_total_supply;
170 base.token_program = inner.token_program;
171 base.is_mayhem_mode = inner.is_mayhem_mode;
172}
173
174#[inline(always)]
176fn merge_pumpfun_migrate(base: &mut PumpFunMigrateEvent, inner: PumpFunMigrateEvent) {
177 base.user = inner.user;
179 base.mint = inner.mint;
180 base.mint_amount = inner.mint_amount;
181 base.sol_amount = inner.sol_amount;
182 base.pool_migration_fee = inner.pool_migration_fee;
183 base.bonding_curve = inner.bonding_curve;
184 base.timestamp = inner.timestamp;
185 base.pool = inner.pool;
186}
187
188#[inline(always)]
199pub fn can_merge(base: &DexEvent, inner: &DexEvent) -> bool {
200 if base.metadata().signature != inner.metadata().signature {
202 return false;
203 }
204
205 match (base, inner) {
207 (DexEvent::PumpFunTrade(_), DexEvent::PumpFunTrade(_))
209 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuy(_))
210 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunSell(_))
211 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuyExactSolIn(_))
212 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunTrade(_))
213 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunBuy(_))
214 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunTrade(_))
215 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunSell(_))
216 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunTrade(_))
217 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunBuyExactSolIn(_)) => true,
218
219 (DexEvent::PumpFunCreate(_), DexEvent::PumpFunCreate(_)) => true,
221 (DexEvent::PumpFunCreateV2(_), DexEvent::PumpFunCreateV2(_)) => true,
222
223 (DexEvent::PumpFunMigrate(_), DexEvent::PumpFunMigrate(_)) => true,
225
226 _ => false,
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use solana_sdk::{pubkey::Pubkey, signature::Signature};
235
236 #[test]
237 fn test_merge_pumpfun_trade() {
238 let metadata = EventMetadata {
239 signature: Signature::default(),
240 slot: 100,
241 tx_index: 1,
242 block_time_us: 1000,
243 grpc_recv_us: 2000,
244 recent_blockhash: None,
245 };
246
247 let mut base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
249 metadata: metadata.clone(),
250 bonding_curve: Pubkey::new_unique(),
251 associated_bonding_curve: Pubkey::new_unique(),
252 ..Default::default()
253 });
254
255 let inner = DexEvent::PumpFunTrade(PumpFunTradeEvent {
257 metadata: metadata.clone(),
258 mint: Pubkey::new_unique(),
259 sol_amount: 1000,
260 token_amount: 2000,
261 is_buy: true,
262 user: Pubkey::new_unique(),
263 ..Default::default()
264 });
265
266 merge_events(&mut base, inner);
268
269 if let DexEvent::PumpFunTrade(trade) = base {
271 assert_eq!(trade.sol_amount, 1000);
272 assert_eq!(trade.token_amount, 2000);
273 assert!(trade.is_buy);
274 assert_ne!(trade.bonding_curve, Pubkey::default());
276 assert_ne!(trade.associated_bonding_curve, Pubkey::default());
277 } else {
278 panic!("Expected PumpFunTrade event");
279 }
280 }
281
282 #[test]
283 fn test_can_merge() {
284 let metadata = EventMetadata {
285 signature: Signature::default(),
286 slot: 100,
287 tx_index: 1,
288 block_time_us: 1000,
289 grpc_recv_us: 2000,
290 recent_blockhash: None,
291 };
292
293 let base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
294 metadata: metadata.clone(),
295 ..Default::default()
296 });
297
298 let inner = DexEvent::PumpFunBuy(PumpFunTradeEvent {
299 metadata: metadata.clone(),
300 ..Default::default()
301 });
302
303 assert!(can_merge(&base, &inner));
305
306 let different_sig = DexEvent::PumpFunTrade(PumpFunTradeEvent {
308 metadata: EventMetadata { signature: Signature::new_unique(), ..metadata },
309 ..Default::default()
310 });
311
312 assert!(!can_merge(&base, &different_sig));
313 }
314}