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 (PumpFunMigrate(b), PumpFunMigrate(i)) => merge_pumpfun_migrate(b, i),
37
38 (PumpSwapBuy(b), PumpSwapBuy(i)) => merge_generic(b, i),
40 (PumpSwapSell(b), PumpSwapSell(i)) => merge_generic(b, i),
41 (PumpSwapCreatePool(b), PumpSwapCreatePool(i)) => merge_generic(b, i),
42 (PumpSwapLiquidityAdded(b), PumpSwapLiquidityAdded(i)) => merge_generic(b, i),
43 (PumpSwapLiquidityRemoved(b), PumpSwapLiquidityRemoved(i)) => merge_generic(b, i),
44
45 (RaydiumClmmSwap(b), RaydiumClmmSwap(i)) => merge_generic(b, i),
47 (RaydiumClmmIncreaseLiquidity(b), RaydiumClmmIncreaseLiquidity(i)) => merge_generic(b, i),
48 (RaydiumClmmDecreaseLiquidity(b), RaydiumClmmDecreaseLiquidity(i)) => merge_generic(b, i),
49 (RaydiumClmmCreatePool(b), RaydiumClmmCreatePool(i)) => merge_generic(b, i),
50 (RaydiumClmmCollectFee(b), RaydiumClmmCollectFee(i)) => merge_generic(b, i),
51
52 (RaydiumCpmmSwap(b), RaydiumCpmmSwap(i)) => merge_generic(b, i),
54 (RaydiumCpmmDeposit(b), RaydiumCpmmDeposit(i)) => merge_generic(b, i),
55 (RaydiumCpmmWithdraw(b), RaydiumCpmmWithdraw(i)) => merge_generic(b, i),
56
57 (RaydiumAmmV4Swap(b), RaydiumAmmV4Swap(i)) => merge_generic(b, i),
59 (RaydiumAmmV4Deposit(b), RaydiumAmmV4Deposit(i)) => merge_generic(b, i),
60 (RaydiumAmmV4Withdraw(b), RaydiumAmmV4Withdraw(i)) => merge_generic(b, i),
61
62 (OrcaWhirlpoolSwap(b), OrcaWhirlpoolSwap(i)) => merge_generic(b, i),
64 (OrcaWhirlpoolLiquidityIncreased(b), OrcaWhirlpoolLiquidityIncreased(i)) => merge_generic(b, i),
65 (OrcaWhirlpoolLiquidityDecreased(b), OrcaWhirlpoolLiquidityDecreased(i)) => merge_generic(b, i),
66
67 (MeteoraPoolsSwap(b), MeteoraPoolsSwap(i)) => merge_generic(b, i),
69 (MeteoraPoolsAddLiquidity(b), MeteoraPoolsAddLiquidity(i)) => merge_generic(b, i),
70 (MeteoraPoolsRemoveLiquidity(b), MeteoraPoolsRemoveLiquidity(i)) => merge_generic(b, i),
71
72 (MeteoraDammV2Swap(b), MeteoraDammV2Swap(i)) => merge_generic(b, i),
74 (MeteoraDammV2AddLiquidity(b), MeteoraDammV2AddLiquidity(i)) => merge_generic(b, i),
75 (MeteoraDammV2RemoveLiquidity(b), MeteoraDammV2RemoveLiquidity(i)) => merge_generic(b, i),
76 (MeteoraDammV2CreatePosition(b), MeteoraDammV2CreatePosition(i)) => merge_generic(b, i),
77 (MeteoraDammV2ClosePosition(b), MeteoraDammV2ClosePosition(i)) => merge_generic(b, i),
78
79 (BonkTrade(b), BonkTrade(i)) => merge_generic(b, i),
81
82 _ => {}
84 }
85}
86
87#[inline(always)]
94fn merge_generic<T>(base: &mut T, inner: T) {
95 *base = inner;
96}
97
98#[inline(always)]
109fn merge_pumpfun_trade(base: &mut PumpFunTradeEvent, inner: PumpFunTradeEvent) {
110 base.mint = inner.mint;
112 base.sol_amount = inner.sol_amount;
113 base.token_amount = inner.token_amount;
114 base.is_buy = inner.is_buy;
115 base.user = inner.user;
116 base.timestamp = inner.timestamp;
117 base.virtual_sol_reserves = inner.virtual_sol_reserves;
118 base.virtual_token_reserves = inner.virtual_token_reserves;
119 base.real_sol_reserves = inner.real_sol_reserves;
120 base.real_token_reserves = inner.real_token_reserves;
121 base.fee_recipient = inner.fee_recipient;
122 base.fee_basis_points = inner.fee_basis_points;
123 base.fee = inner.fee;
124 base.creator = inner.creator;
125 base.creator_fee_basis_points = inner.creator_fee_basis_points;
126 base.creator_fee = inner.creator_fee;
127
128 base.track_volume = inner.track_volume;
130 base.total_unclaimed_tokens = inner.total_unclaimed_tokens;
131 base.total_claimed_tokens = inner.total_claimed_tokens;
132 base.current_sol_volume = inner.current_sol_volume;
133 base.last_update_timestamp = inner.last_update_timestamp;
134 base.ix_name = inner.ix_name;
135 base.is_created_buy = inner.is_created_buy;
136 base.mayhem_mode = inner.mayhem_mode;
137 base.cashback_fee_basis_points = inner.cashback_fee_basis_points;
138 base.cashback = inner.cashback;
139 base.is_cashback_coin = inner.is_cashback_coin;
140
141 }
144
145#[inline(always)]
147fn merge_pumpfun_create(base: &mut PumpFunCreateTokenEvent, inner: PumpFunCreateTokenEvent) {
148 base.name = inner.name;
150 base.symbol = inner.symbol;
151 base.uri = inner.uri;
152 base.mint = inner.mint;
153 base.bonding_curve = inner.bonding_curve;
154 base.user = inner.user;
155 base.creator = inner.creator;
156 base.timestamp = inner.timestamp;
157 base.virtual_token_reserves = inner.virtual_token_reserves;
158 base.virtual_sol_reserves = inner.virtual_sol_reserves;
159 base.real_token_reserves = inner.real_token_reserves;
160 base.token_total_supply = inner.token_total_supply;
161 base.token_program = inner.token_program;
162 base.is_mayhem_mode = inner.is_mayhem_mode;
163}
164
165#[inline(always)]
167fn merge_pumpfun_migrate(base: &mut PumpFunMigrateEvent, inner: PumpFunMigrateEvent) {
168 base.user = inner.user;
170 base.mint = inner.mint;
171 base.mint_amount = inner.mint_amount;
172 base.sol_amount = inner.sol_amount;
173 base.pool_migration_fee = inner.pool_migration_fee;
174 base.bonding_curve = inner.bonding_curve;
175 base.timestamp = inner.timestamp;
176 base.pool = inner.pool;
177}
178
179#[inline(always)]
190pub fn can_merge(base: &DexEvent, inner: &DexEvent) -> bool {
191 if base.metadata().signature != inner.metadata().signature {
193 return false;
194 }
195
196 match (base, inner) {
198 (DexEvent::PumpFunTrade(_), DexEvent::PumpFunTrade(_))
200 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuy(_))
201 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunSell(_))
202 | (DexEvent::PumpFunTrade(_), DexEvent::PumpFunBuyExactSolIn(_))
203 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunTrade(_))
204 | (DexEvent::PumpFunBuy(_), DexEvent::PumpFunBuy(_))
205 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunTrade(_))
206 | (DexEvent::PumpFunSell(_), DexEvent::PumpFunSell(_))
207 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunTrade(_))
208 | (DexEvent::PumpFunBuyExactSolIn(_), DexEvent::PumpFunBuyExactSolIn(_)) => true,
209
210 (DexEvent::PumpFunCreate(_), DexEvent::PumpFunCreate(_)) => true,
212
213 (DexEvent::PumpFunMigrate(_), DexEvent::PumpFunMigrate(_)) => true,
215
216 _ => false,
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use solana_sdk::{pubkey::Pubkey, signature::Signature};
225
226 #[test]
227 fn test_merge_pumpfun_trade() {
228 let metadata = EventMetadata {
229 signature: Signature::default(),
230 slot: 100,
231 tx_index: 1,
232 block_time_us: 1000,
233 grpc_recv_us: 2000,
234 };
235
236 let mut base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
238 metadata: metadata.clone(),
239 bonding_curve: Pubkey::new_unique(),
240 associated_bonding_curve: Pubkey::new_unique(),
241 ..Default::default()
242 });
243
244 let inner = DexEvent::PumpFunTrade(PumpFunTradeEvent {
246 metadata: metadata.clone(),
247 mint: Pubkey::new_unique(),
248 sol_amount: 1000,
249 token_amount: 2000,
250 is_buy: true,
251 user: Pubkey::new_unique(),
252 ..Default::default()
253 });
254
255 merge_events(&mut base, inner);
257
258 if let DexEvent::PumpFunTrade(trade) = base {
260 assert_eq!(trade.sol_amount, 1000);
261 assert_eq!(trade.token_amount, 2000);
262 assert!(trade.is_buy);
263 assert_ne!(trade.bonding_curve, Pubkey::default());
265 assert_ne!(trade.associated_bonding_curve, Pubkey::default());
266 } else {
267 panic!("Expected PumpFunTrade event");
268 }
269 }
270
271 #[test]
272 fn test_can_merge() {
273 let metadata = EventMetadata {
274 signature: Signature::default(),
275 slot: 100,
276 tx_index: 1,
277 block_time_us: 1000,
278 grpc_recv_us: 2000,
279 };
280
281 let base = DexEvent::PumpFunTrade(PumpFunTradeEvent {
282 metadata: metadata.clone(),
283 ..Default::default()
284 });
285
286 let inner = DexEvent::PumpFunBuy(PumpFunTradeEvent {
287 metadata: metadata.clone(),
288 ..Default::default()
289 });
290
291 assert!(can_merge(&base, &inner));
293
294 let different_sig = DexEvent::PumpFunTrade(PumpFunTradeEvent {
296 metadata: EventMetadata {
297 signature: Signature::new_unique(),
298 ..metadata
299 },
300 ..Default::default()
301 });
302
303 assert!(!can_merge(&base, &different_sig));
304 }
305}