sol-parser-sdk-python 0.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. sol_parser/__init__.py +400 -0
  2. sol_parser/account_dispatcher.py +209 -0
  3. sol_parser/account_fillers/__init__.py +5 -0
  4. sol_parser/account_fillers/bonk.py +30 -0
  5. sol_parser/account_fillers/meteora.py +51 -0
  6. sol_parser/account_fillers/orca.py +40 -0
  7. sol_parser/account_fillers/pumpfun.py +97 -0
  8. sol_parser/account_fillers/pumpswap.py +93 -0
  9. sol_parser/account_fillers/raydium.py +119 -0
  10. sol_parser/accounts/__init__.py +461 -0
  11. sol_parser/accounts/rpc_wallet.py +64 -0
  12. sol_parser/accounts/utils.py +71 -0
  13. sol_parser/check_migration.py +18 -0
  14. sol_parser/clock.py +10 -0
  15. sol_parser/common/__init__.py +27 -0
  16. sol_parser/dex_parsers.py +2576 -0
  17. sol_parser/entries_decode.py +186 -0
  18. sol_parser/env_config.py +215 -0
  19. sol_parser/event_types.py +1750 -0
  20. sol_parser/geyser_pb2.py +148 -0
  21. sol_parser/geyser_pb2_grpc.py +398 -0
  22. sol_parser/grpc/__init__.py +61 -0
  23. sol_parser/grpc/geyser_connect.py +42 -0
  24. sol_parser/grpc/subscribe_builder.py +133 -0
  25. sol_parser/grpc/transaction_meta.py +183 -0
  26. sol_parser/grpc_client.py +870 -0
  27. sol_parser/grpc_instruction_parser.py +318 -0
  28. sol_parser/grpc_types.py +919 -0
  29. sol_parser/inner_instruction_parser.py +281 -0
  30. sol_parser/instr/__init__.py +15 -0
  31. sol_parser/instr_account_utils.py +58 -0
  32. sol_parser/instructions.py +1026 -0
  33. sol_parser/json_util.py +41 -0
  34. sol_parser/log_instr_dedup.py +284 -0
  35. sol_parser/logs/__init__.py +15 -0
  36. sol_parser/merger.py +233 -0
  37. sol_parser/order_buffer.py +171 -0
  38. sol_parser/parser.py +300 -0
  39. sol_parser/pumpfun_fee_enrich.py +75 -0
  40. sol_parser/rpc_parser.py +655 -0
  41. sol_parser/rust_api_inventory.py +42 -0
  42. sol_parser/rust_event_json.py +50 -0
  43. sol_parser/shredstream_client.py +191 -0
  44. sol_parser/shredstream_pb2.py +40 -0
  45. sol_parser/shredstream_pb2_grpc.py +81 -0
  46. sol_parser/shredstream_pumpfun.py +296 -0
  47. sol_parser/solana_storage_pb2.py +75 -0
  48. sol_parser/solana_storage_pb2_grpc.py +24 -0
  49. sol_parser/u128_parity.py +115 -0
  50. sol_parser/verify_discriminators.py +85 -0
  51. sol_parser_sdk_python-0.4.4.dist-info/METADATA +14 -0
  52. sol_parser_sdk_python-0.4.4.dist-info/RECORD +54 -0
  53. sol_parser_sdk_python-0.4.4.dist-info/WHEEL +4 -0
  54. sol_parser_sdk_python-0.4.4.dist-info/entry_points.txt +4 -0
@@ -0,0 +1,2576 @@
1
+ """与 `sol-parser-sdk-golang/solparser` matcher 对齐的程序数据解析(Program data 行)。
2
+
3
+ 由小端 u128 承载的语义字段(Meteora DAMM v2、Raydium CLMM、Orca Whirlpool、Meteora DLMM Swap 的 `fee_bps` 等)
4
+ 在 Python 结果里为 **十进制字符串**,与 TS `bigint` 十进制及 Go `u128LEDecimalString` 一致。
5
+ `python3 -m sol_parser.check_migration` 会额外跑 `u128_parity`(标量 + Orca 合成用例)。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import struct
11
+ from typing import Any, Dict, List, Optional
12
+
13
+ import base58
14
+
15
+ from .grpc_types import EventType, EventMetadata
16
+ from .event_types import (
17
+ DexEvent, PumpFunTradeEvent, PumpFunCreateEvent, PumpFunMigrateEvent,
18
+ PumpFeesShareholder, PumpFeesFees, PumpFeesFeeTier,
19
+ PumpFeesCreateFeeSharingConfigEvent, PumpFeesInitializeFeeConfigEvent,
20
+ PumpFeesResetFeeSharingConfigEvent, PumpFeesRevokeFeeSharingAuthorityEvent,
21
+ PumpFeesTransferFeeSharingAuthorityEvent, PumpFeesUpdateAdminEvent,
22
+ PumpFeesUpdateFeeConfigEvent, PumpFeesUpdateFeeSharesEvent, PumpFeesUpsertFeeTiersEvent,
23
+ PumpFunMigrateBondingCurveCreatorEvent,
24
+ PumpSwapBuyEvent, PumpSwapSellEvent, PumpSwapCreatePoolEvent,
25
+ PumpSwapLiquidityAddedEvent, PumpSwapLiquidityRemovedEvent,
26
+ RaydiumAmmV4SwapEvent, RaydiumAmmV4DepositEvent, RaydiumAmmV4WithdrawEvent,
27
+ RaydiumAmmV4WithdrawPnlEvent, RaydiumAmmV4Initialize2Event,
28
+ RaydiumClmmSwapEvent, RaydiumClmmIncreaseLiquidityEvent,
29
+ RaydiumClmmDecreaseLiquidityEvent, RaydiumClmmCreatePoolEvent,
30
+ RaydiumClmmCollectFeeEvent, RaydiumCpmmSwapEvent, RaydiumCpmmDepositEvent,
31
+ RaydiumCpmmWithdrawEvent, OrcaWhirlpoolSwapEvent, OrcaWhirlpoolLiquidityIncreasedEvent,
32
+ OrcaWhirlpoolLiquidityDecreasedEvent, OrcaWhirlpoolPoolInitializedEvent,
33
+ MeteoraDlmmSwapEvent, MeteoraDlmmAddLiquidityEvent, MeteoraDlmmRemoveLiquidityEvent,
34
+ MeteoraDlmmInitializePoolEvent, MeteoraDlmmInitializeBinArrayEvent,
35
+ MeteoraDlmmCreatePositionEvent, MeteoraDlmmClosePositionEvent,
36
+ MeteoraDlmmClaimFeeEvent, MeteoraPoolsSetPoolFeesEvent, MeteoraPoolsSwapEvent,
37
+ MeteoraPoolsAddLiquidityEvent, MeteoraPoolsRemoveLiquidityEvent,
38
+ MeteoraPoolsBootstrapLiquidityEvent, MeteoraPoolsPoolCreatedEvent, MeteoraDammV2SwapEvent,
39
+ MeteoraDammV2CreatePositionEvent, MeteoraDammV2ClosePositionEvent,
40
+ MeteoraDammV2AddLiquidityEvent, MeteoraDammV2RemoveLiquidityEvent,
41
+ MeteoraDammV2InitializePoolEvent,
42
+ BonkTradeEvent, BonkPoolCreateEvent, BonkMigrateAmmEvent,
43
+ )
44
+
45
+ Z = "11111111111111111111111111111111"
46
+
47
+
48
+ def _u64le(b: bytes, o: int) -> int:
49
+ return struct.unpack_from("<Q", b, o)[0]
50
+
51
+
52
+ def _i64le(b: bytes, o: int) -> int:
53
+ return struct.unpack_from("<q", b, o)[0]
54
+
55
+
56
+ def _i32le(b: bytes, o: int) -> int:
57
+ return struct.unpack_from("<i", b, o)[0]
58
+
59
+
60
+ def _u32le(b: bytes, o: int) -> int:
61
+ return struct.unpack_from("<I", b, o)[0]
62
+
63
+
64
+ def _u16le(b: bytes, o: int) -> int:
65
+ return struct.unpack_from("<H", b, o)[0]
66
+
67
+
68
+ def _u8(b: bytes, o: int) -> int:
69
+ return b[o]
70
+
71
+
72
+ def _pub(b: bytes, o: int) -> str:
73
+ return base58.b58encode(b[o : o + 32]).decode()
74
+
75
+
76
+ def _bool(b: bytes, o: int) -> bool:
77
+ return b[o] == 1
78
+
79
+
80
+ def _u128le_int(b: bytes, o: int) -> int:
81
+ return int.from_bytes(b[o : o + 16], "little")
82
+
83
+
84
+ def _borsh_str(b: bytes, o: int) -> tuple[str, int]:
85
+ (n,) = struct.unpack_from("<I", b, o)
86
+ o += 4
87
+ return b[o : o + n].decode("utf-8", errors="replace"), o + n
88
+
89
+
90
+ def _disc8(bs: bytes) -> int:
91
+ return struct.unpack("<Q", bs)[0]
92
+
93
+
94
+ def _d(*xs: int) -> int:
95
+ return struct.unpack("<Q", bytes(xs))[0]
96
+
97
+
98
+ def _u64_at(b: bytes, o: List[int]) -> int:
99
+ v = _u64le(b, o[0])
100
+ o[0] += 8
101
+ return v
102
+
103
+
104
+ # --- PumpFun ---
105
+
106
+ PUMP_TRADE = _d(189, 219, 127, 211, 78, 230, 97, 238)
107
+ PUMP_CREATE = _d(27, 114, 169, 77, 222, 235, 99, 118)
108
+ PUMP_MIGRATE = _d(189, 233, 93, 185, 92, 148, 234, 148)
109
+ PUMP_MIGRATE_BONDING_CURVE_CREATOR = _d(155, 167, 104, 220, 213, 108, 243, 3)
110
+ PUMP_FEES_CREATE_FEE_SHARING_CONFIG = _d(133, 105, 170, 200, 184, 116, 251, 88)
111
+ PUMP_FEES_INITIALIZE_FEE_CONFIG = _d(89, 138, 244, 230, 10, 56, 226, 126)
112
+ PUMP_FEES_RESET_FEE_SHARING_CONFIG = _d(203, 204, 151, 226, 120, 55, 214, 243)
113
+ PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY = _d(114, 23, 101, 60, 14, 190, 153, 62)
114
+ PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY = _d(124, 143, 198, 245, 77, 184, 8, 236)
115
+ PUMP_FEES_UPDATE_ADMIN = _d(225, 152, 171, 87, 246, 63, 66, 234)
116
+ PUMP_FEES_UPDATE_FEE_CONFIG = _d(90, 23, 65, 35, 62, 244, 188, 208)
117
+ PUMP_FEES_UPDATE_FEE_SHARES = _d(21, 186, 196, 184, 91, 228, 225, 203)
118
+ PUMP_FEES_UPSERT_FEE_TIERS = _d(171, 89, 169, 187, 122, 186, 33, 204)
119
+
120
+
121
+ def _make_meta(meta: dict) -> EventMetadata:
122
+ """从 dict 构造 EventMetadata"""
123
+ if isinstance(meta, EventMetadata):
124
+ return meta
125
+ if isinstance(meta, dict):
126
+ return EventMetadata(
127
+ signature=meta.get("signature", ""),
128
+ slot=meta.get("slot", 0),
129
+ tx_index=meta.get("tx_index", 0),
130
+ block_time_us=meta.get("block_time_us", 0),
131
+ grpc_recv_us=meta.get("grpc_recv_us", 0),
132
+ recent_blockhash=meta.get("recent_blockhash", ""),
133
+ )
134
+ return EventMetadata()
135
+
136
+
137
+ def parse_trade_from_data(data: bytes, meta: dict, is_created_buy: bool) -> DexEvent:
138
+ if len(data) < 200:
139
+ return DexEvent()
140
+ o = 0
141
+ mint = _pub(data, o)
142
+ o += 32
143
+ sol_amount = _u64le(data, o)
144
+ o += 8
145
+ token_amount = _u64le(data, o)
146
+ o += 8
147
+ is_buy = _bool(data, o)
148
+ o += 1
149
+ user = _pub(data, o)
150
+ o += 32
151
+ ts = _i64le(data, o)
152
+ o += 8
153
+ vsol = _u64le(data, o)
154
+ o += 8
155
+ vtok = _u64le(data, o)
156
+ o += 8
157
+ rsol = _u64le(data, o)
158
+ o += 8
159
+ rtok = _u64le(data, o)
160
+ o += 8
161
+ fee_rec = _pub(data, o)
162
+ o += 32
163
+ fee_bps = _u64le(data, o)
164
+ o += 8
165
+ fee = _u64le(data, o)
166
+ o += 8
167
+ creator = _pub(data, o)
168
+ o += 32
169
+ cfbps = _u64le(data, o)
170
+ o += 8
171
+ cfee = _u64le(data, o)
172
+ o += 8
173
+ tv = _bool(data, o) if o < len(data) else False
174
+ o += 1
175
+ tuc = _u64le(data, o) if o + 8 <= len(data) else 0
176
+ o += 8
177
+ tcc = _u64le(data, o) if o + 8 <= len(data) else 0
178
+ o += 8
179
+ csv = _u64le(data, o) if o + 8 <= len(data) else 0
180
+ o += 8
181
+ lut = _i64le(data, o) if o + 8 <= len(data) else 0
182
+ o += 8
183
+ ix_name = ""
184
+ if o + 4 <= len(data):
185
+ ix_name, o = _borsh_str(data, o)
186
+ mm = _bool(data, o) if o < len(data) else False
187
+ o += 1
188
+ cb_bps = _u64le(data, o) if o + 8 <= len(data) else 0
189
+ o += 8
190
+ cb = _u64le(data, o) if o + 8 <= len(data) else 0
191
+
192
+ event_data = PumpFunTradeEvent(
193
+ metadata=_make_meta(meta),
194
+ mint=mint,
195
+ sol_amount=sol_amount,
196
+ token_amount=token_amount,
197
+ is_buy=is_buy,
198
+ is_created_buy=is_created_buy,
199
+ user=user,
200
+ timestamp=ts,
201
+ virtual_sol_reserves=vsol,
202
+ virtual_token_reserves=vtok,
203
+ real_sol_reserves=rsol,
204
+ real_token_reserves=rtok,
205
+ fee_recipient=fee_rec,
206
+ fee_basis_points=fee_bps,
207
+ fee=fee,
208
+ creator=creator,
209
+ creator_fee_basis_points=cfbps,
210
+ creator_fee=cfee,
211
+ track_volume=tv,
212
+ total_unclaimed_tokens=tuc,
213
+ total_claimed_tokens=tcc,
214
+ current_sol_volume=csv,
215
+ last_update_timestamp=lut,
216
+ ix_name=ix_name,
217
+ mayhem_mode=mm,
218
+ cashback_fee_basis_points=cb_bps,
219
+ cashback=cb,
220
+ is_cashback_coin=cb_bps > 0,
221
+ bonding_curve=Z,
222
+ associated_bonding_curve=Z,
223
+ token_program=Z,
224
+ creator_vault=Z,
225
+ )
226
+
227
+ if ix_name in ("buy", "buy_v2"):
228
+ return DexEvent(type=EventType.PUMP_FUN_BUY, data=event_data)
229
+ if ix_name in ("sell", "sell_v2"):
230
+ return DexEvent(type=EventType.PUMP_FUN_SELL, data=event_data)
231
+ if ix_name in ("buy_exact_sol_in", "buy_exact_quote_in_v2"):
232
+ return DexEvent(type=EventType.PUMP_FUN_BUY_EXACT_SOL_IN, data=event_data)
233
+ return DexEvent(type=EventType.PUMP_FUN_TRADE, data=event_data)
234
+
235
+
236
+ def parse_create_from_data(data: bytes, meta: dict) -> DexEvent:
237
+ o = 0
238
+ try:
239
+ name, o = _borsh_str(data, o)
240
+ sym, o = _borsh_str(data, o)
241
+ uri, o = _borsh_str(data, o)
242
+ except Exception:
243
+ return DexEvent()
244
+ if len(data) < o + 32 * 4 + 8 * 5 + 32 + 1:
245
+ return DexEvent()
246
+ mint = _pub(data, o)
247
+ o += 32
248
+ bc = _pub(data, o)
249
+ o += 32
250
+ user = _pub(data, o)
251
+ o += 32
252
+ creator = _pub(data, o)
253
+ o += 32
254
+ ts = _i64le(data, o)
255
+ o += 8
256
+ vtr = _u64le(data, o)
257
+ o += 8
258
+ vsol = _u64le(data, o)
259
+ o += 8
260
+ rtr = _u64le(data, o)
261
+ o += 8
262
+ tts = _u64le(data, o)
263
+ o += 8
264
+ tp = _pub(data, o) if o + 32 <= len(data) else Z
265
+ o += 32
266
+ mm = _bool(data, o) if o < len(data) else False
267
+ o += 1
268
+ ice = _bool(data, o) if o < len(data) else False
269
+
270
+ return DexEvent(
271
+ type=EventType.PUMP_FUN_CREATE,
272
+ data=PumpFunCreateEvent(
273
+ metadata=_make_meta(meta),
274
+ name=name,
275
+ symbol=sym,
276
+ uri=uri,
277
+ mint=mint,
278
+ bonding_curve=bc,
279
+ user=user,
280
+ creator=creator,
281
+ timestamp=ts,
282
+ virtual_token_reserves=vtr,
283
+ virtual_sol_reserves=vsol,
284
+ real_token_reserves=rtr,
285
+ token_total_supply=tts,
286
+ token_program=tp,
287
+ is_mayhem_mode=mm,
288
+ is_cashback_enabled=ice,
289
+ ),
290
+ )
291
+
292
+
293
+ def parse_migrate_from_data(data: bytes, meta: dict) -> DexEvent:
294
+ if len(data) < 32 + 32 + 8 + 8 + 8 + 32 + 8 + 32:
295
+ return DexEvent()
296
+ o = 0
297
+ user = _pub(data, o)
298
+ o += 32
299
+ mint = _pub(data, o)
300
+ o += 32
301
+ ma = _u64le(data, o)
302
+ o += 8
303
+ sa = _u64le(data, o)
304
+ o += 8
305
+ pmf = _u64le(data, o)
306
+ o += 8
307
+ bc = _pub(data, o)
308
+ o += 32
309
+ ts = _i64le(data, o)
310
+ o += 8
311
+ pool = _pub(data, o)
312
+
313
+ return DexEvent(
314
+ type=EventType.PUMP_FUN_MIGRATE,
315
+ data=PumpFunMigrateEvent(
316
+ metadata=_make_meta(meta),
317
+ user=user,
318
+ mint=mint,
319
+ mint_amount=ma,
320
+ sol_amount=sa,
321
+ pool_migration_fee=pmf,
322
+ bonding_curve=bc,
323
+ timestamp=ts,
324
+ pool=pool,
325
+ ),
326
+ )
327
+
328
+
329
+ def _read_fees_at(data: bytes, o: List[int]) -> Optional[PumpFeesFees]:
330
+ if o[0] + 24 > len(data):
331
+ return None
332
+ lp_fee_bps = _u64_at(data, o)
333
+ protocol_fee_bps = _u64_at(data, o)
334
+ creator_fee_bps = _u64_at(data, o)
335
+ return PumpFeesFees(
336
+ lp_fee_bps=lp_fee_bps,
337
+ protocol_fee_bps=protocol_fee_bps,
338
+ creator_fee_bps=creator_fee_bps,
339
+ )
340
+
341
+
342
+ def read_pump_fees_shareholders_vec(data: bytes, o: List[int]) -> Optional[List[PumpFeesShareholder]]:
343
+ if o[0] + 4 > len(data):
344
+ return None
345
+ n = _u32le(data, o[0])
346
+ o[0] += 4
347
+ if n > 64:
348
+ return None
349
+ out: List[PumpFeesShareholder] = []
350
+ for _ in range(n):
351
+ if o[0] + 34 > len(data):
352
+ return None
353
+ address = _pub(data, o[0])
354
+ o[0] += 32
355
+ share_bps = _u16le(data, o[0])
356
+ o[0] += 2
357
+ out.append(PumpFeesShareholder(address=address, share_bps=share_bps))
358
+ return out
359
+
360
+
361
+ def read_pump_fees_fee_tiers_vec(data: bytes, o: List[int]) -> Optional[List[PumpFeesFeeTier]]:
362
+ if o[0] + 4 > len(data):
363
+ return None
364
+ n = _u32le(data, o[0])
365
+ o[0] += 4
366
+ if n > 64:
367
+ return None
368
+ out: List[PumpFeesFeeTier] = []
369
+ for _ in range(n):
370
+ if o[0] + 16 > len(data):
371
+ return None
372
+ threshold = _u128le_int(data, o[0])
373
+ o[0] += 16
374
+ fees = _read_fees_at(data, o)
375
+ if fees is None:
376
+ return None
377
+ out.append(PumpFeesFeeTier(market_cap_lamports_threshold=threshold, fees=fees))
378
+ return out
379
+
380
+
381
+ def _read_option_pubkey_at(data: bytes, o: List[int]) -> Optional[str]:
382
+ if o[0] >= len(data):
383
+ return None
384
+ tag = _u8(data, o[0])
385
+ o[0] += 1
386
+ if tag == 0:
387
+ return ""
388
+ if tag != 1 or o[0] + 32 > len(data):
389
+ return None
390
+ v = _pub(data, o[0])
391
+ o[0] += 32
392
+ return v
393
+
394
+
395
+ def _read_config_status_at(data: bytes, o: List[int]) -> Optional[str]:
396
+ if o[0] >= len(data):
397
+ return None
398
+ tag = _u8(data, o[0])
399
+ o[0] += 1
400
+ if tag == 0:
401
+ return "Paused"
402
+ if tag == 1:
403
+ return "Active"
404
+ return None
405
+
406
+
407
+ def parse_migrate_bonding_curve_creator_from_data(data: bytes, meta: dict) -> DexEvent:
408
+ if len(data) < 8 + 32 * 5:
409
+ return DexEvent()
410
+ o = 0
411
+ ts = _i64le(data, o)
412
+ o += 8
413
+ mint = _pub(data, o)
414
+ o += 32
415
+ bonding_curve = _pub(data, o)
416
+ o += 32
417
+ sharing_config = _pub(data, o)
418
+ o += 32
419
+ old_creator = _pub(data, o)
420
+ o += 32
421
+ new_creator = _pub(data, o)
422
+ return DexEvent(
423
+ type=EventType.PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR,
424
+ data=PumpFunMigrateBondingCurveCreatorEvent(
425
+ metadata=_make_meta(meta),
426
+ timestamp=ts,
427
+ mint=mint,
428
+ bonding_curve=bonding_curve,
429
+ sharing_config=sharing_config,
430
+ old_creator=old_creator,
431
+ new_creator=new_creator,
432
+ ),
433
+ )
434
+
435
+
436
+ def parse_pump_fees_create_fee_sharing_config_from_data(data: bytes, meta: dict) -> DexEvent:
437
+ o = [0]
438
+ if len(data) < 8 + 32 * 4 + 1 + 4 + 1:
439
+ return DexEvent()
440
+ ts = _i64le(data, o[0])
441
+ o[0] += 8
442
+ mint = _pub(data, o[0])
443
+ o[0] += 32
444
+ bonding_curve = _pub(data, o[0])
445
+ o[0] += 32
446
+ pool = _read_option_pubkey_at(data, o)
447
+ if pool is None:
448
+ return DexEvent()
449
+ sharing_config = _pub(data, o[0])
450
+ o[0] += 32
451
+ admin = _pub(data, o[0])
452
+ o[0] += 32
453
+ shareholders = read_pump_fees_shareholders_vec(data, o)
454
+ if shareholders is None:
455
+ return DexEvent()
456
+ status = _read_config_status_at(data, o)
457
+ if status is None or o[0] != len(data):
458
+ return DexEvent()
459
+ return DexEvent(
460
+ type=EventType.PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
461
+ data=PumpFeesCreateFeeSharingConfigEvent(
462
+ metadata=_make_meta(meta),
463
+ timestamp=ts,
464
+ mint=mint,
465
+ bonding_curve=bonding_curve,
466
+ pool=pool,
467
+ sharing_config=sharing_config,
468
+ admin=admin,
469
+ initial_shareholders=shareholders,
470
+ status=status,
471
+ ),
472
+ )
473
+
474
+
475
+ def parse_pump_fees_initialize_fee_config_from_data(data: bytes, meta: dict) -> DexEvent:
476
+ if len(data) != 8 + 32 + 32:
477
+ return DexEvent()
478
+ o = 0
479
+ ts = _i64le(data, o)
480
+ o += 8
481
+ admin = _pub(data, o)
482
+ o += 32
483
+ fee_config = _pub(data, o)
484
+ return DexEvent(
485
+ type=EventType.PUMP_FEES_INITIALIZE_FEE_CONFIG,
486
+ data=PumpFeesInitializeFeeConfigEvent(
487
+ metadata=_make_meta(meta), timestamp=ts, admin=admin, fee_config=fee_config
488
+ ),
489
+ )
490
+
491
+
492
+ def parse_pump_fees_reset_fee_sharing_config_from_data(data: bytes, meta: dict) -> DexEvent:
493
+ o = [0]
494
+ if len(data) < 8 + 32 * 4 + 4 + 4:
495
+ return DexEvent()
496
+ ts = _i64le(data, o[0])
497
+ o[0] += 8
498
+ mint = _pub(data, o[0])
499
+ o[0] += 32
500
+ sharing_config = _pub(data, o[0])
501
+ o[0] += 32
502
+ old_admin = _pub(data, o[0])
503
+ o[0] += 32
504
+ old_shareholders = read_pump_fees_shareholders_vec(data, o)
505
+ if old_shareholders is None:
506
+ return DexEvent()
507
+ new_admin = _pub(data, o[0])
508
+ o[0] += 32
509
+ new_shareholders = read_pump_fees_shareholders_vec(data, o)
510
+ if new_shareholders is None or o[0] != len(data):
511
+ return DexEvent()
512
+ return DexEvent(
513
+ type=EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
514
+ data=PumpFeesResetFeeSharingConfigEvent(
515
+ metadata=_make_meta(meta),
516
+ timestamp=ts,
517
+ mint=mint,
518
+ sharing_config=sharing_config,
519
+ old_admin=old_admin,
520
+ old_shareholders=old_shareholders,
521
+ new_admin=new_admin,
522
+ new_shareholders=new_shareholders,
523
+ ),
524
+ )
525
+
526
+
527
+ def parse_pump_fees_revoke_fee_sharing_authority_from_data(data: bytes, meta: dict) -> DexEvent:
528
+ if len(data) != 8 + 32 * 3:
529
+ return DexEvent()
530
+ o = 0
531
+ ts = _i64le(data, o)
532
+ o += 8
533
+ mint = _pub(data, o)
534
+ o += 32
535
+ sharing_config = _pub(data, o)
536
+ o += 32
537
+ admin = _pub(data, o)
538
+ return DexEvent(
539
+ type=EventType.PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
540
+ data=PumpFeesRevokeFeeSharingAuthorityEvent(
541
+ metadata=_make_meta(meta), timestamp=ts, mint=mint, sharing_config=sharing_config, admin=admin
542
+ ),
543
+ )
544
+
545
+
546
+ def parse_pump_fees_transfer_fee_sharing_authority_from_data(data: bytes, meta: dict) -> DexEvent:
547
+ if len(data) != 8 + 32 * 4:
548
+ return DexEvent()
549
+ o = 0
550
+ ts = _i64le(data, o)
551
+ o += 8
552
+ mint = _pub(data, o)
553
+ o += 32
554
+ sharing_config = _pub(data, o)
555
+ o += 32
556
+ old_admin = _pub(data, o)
557
+ o += 32
558
+ new_admin = _pub(data, o)
559
+ return DexEvent(
560
+ type=EventType.PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
561
+ data=PumpFeesTransferFeeSharingAuthorityEvent(
562
+ metadata=_make_meta(meta),
563
+ timestamp=ts,
564
+ mint=mint,
565
+ sharing_config=sharing_config,
566
+ old_admin=old_admin,
567
+ new_admin=new_admin,
568
+ ),
569
+ )
570
+
571
+
572
+ def parse_pump_fees_update_admin_from_data(data: bytes, meta: dict) -> DexEvent:
573
+ if len(data) != 8 + 32 + 32:
574
+ return DexEvent()
575
+ o = 0
576
+ ts = _i64le(data, o)
577
+ o += 8
578
+ old_admin = _pub(data, o)
579
+ o += 32
580
+ new_admin = _pub(data, o)
581
+ return DexEvent(
582
+ type=EventType.PUMP_FEES_UPDATE_ADMIN,
583
+ data=PumpFeesUpdateAdminEvent(
584
+ metadata=_make_meta(meta), timestamp=ts, old_admin=old_admin, new_admin=new_admin
585
+ ),
586
+ )
587
+
588
+
589
+ def parse_pump_fees_update_fee_config_from_data(data: bytes, meta: dict) -> DexEvent:
590
+ o = [0]
591
+ if len(data) < 8 + 32 + 32 + 4 + 24:
592
+ return DexEvent()
593
+ ts = _i64le(data, o[0])
594
+ o[0] += 8
595
+ admin = _pub(data, o[0])
596
+ o[0] += 32
597
+ fee_config = _pub(data, o[0])
598
+ o[0] += 32
599
+ fee_tiers = read_pump_fees_fee_tiers_vec(data, o)
600
+ if fee_tiers is None:
601
+ return DexEvent()
602
+ flat_fees = _read_fees_at(data, o)
603
+ if flat_fees is None or o[0] != len(data):
604
+ return DexEvent()
605
+ return DexEvent(
606
+ type=EventType.PUMP_FEES_UPDATE_FEE_CONFIG,
607
+ data=PumpFeesUpdateFeeConfigEvent(
608
+ metadata=_make_meta(meta),
609
+ timestamp=ts,
610
+ admin=admin,
611
+ fee_config=fee_config,
612
+ fee_tiers=fee_tiers,
613
+ flat_fees=flat_fees,
614
+ ),
615
+ )
616
+
617
+
618
+ def parse_pump_fees_update_fee_shares_from_data(data: bytes, meta: dict) -> DexEvent:
619
+ o = [0]
620
+ if len(data) < 8 + 32 * 3 + 4:
621
+ return DexEvent()
622
+ ts = _i64le(data, o[0])
623
+ o[0] += 8
624
+ mint = _pub(data, o[0])
625
+ o[0] += 32
626
+ sharing_config = _pub(data, o[0])
627
+ o[0] += 32
628
+ admin = _pub(data, o[0])
629
+ o[0] += 32
630
+ shareholders = read_pump_fees_shareholders_vec(data, o)
631
+ if shareholders is None or o[0] != len(data):
632
+ return DexEvent()
633
+ return DexEvent(
634
+ type=EventType.PUMP_FEES_UPDATE_FEE_SHARES,
635
+ data=PumpFeesUpdateFeeSharesEvent(
636
+ metadata=_make_meta(meta),
637
+ timestamp=ts,
638
+ mint=mint,
639
+ sharing_config=sharing_config,
640
+ admin=admin,
641
+ bonding_curve=Z,
642
+ pump_creator_vault=Z,
643
+ new_shareholders=shareholders,
644
+ ),
645
+ )
646
+
647
+
648
+ def parse_pump_fees_upsert_fee_tiers_from_data(data: bytes, meta: dict) -> DexEvent:
649
+ o = [0]
650
+ if len(data) < 8 + 32 + 32 + 4 + 1:
651
+ return DexEvent()
652
+ ts = _i64le(data, o[0])
653
+ o[0] += 8
654
+ admin = _pub(data, o[0])
655
+ o[0] += 32
656
+ fee_config = _pub(data, o[0])
657
+ o[0] += 32
658
+ fee_tiers = read_pump_fees_fee_tiers_vec(data, o)
659
+ if fee_tiers is None or o[0] >= len(data):
660
+ return DexEvent()
661
+ offset = _u8(data, o[0])
662
+ o[0] += 1
663
+ if o[0] != len(data):
664
+ return DexEvent()
665
+ return DexEvent(
666
+ type=EventType.PUMP_FEES_UPSERT_FEE_TIERS,
667
+ data=PumpFeesUpsertFeeTiersEvent(
668
+ metadata=_make_meta(meta),
669
+ timestamp=ts,
670
+ admin=admin,
671
+ fee_config=fee_config,
672
+ fee_tiers=fee_tiers,
673
+ offset=offset,
674
+ ),
675
+ )
676
+
677
+
678
+ # --- Raydium CLMM ---
679
+
680
+
681
+ def parse_clmm_swap_from_data(data: bytes, meta: dict) -> DexEvent:
682
+ if len(data) < 32 + 32 + 8 + 8 + 16 + 1:
683
+ return DexEvent()
684
+ o = 0
685
+ ps = _pub(data, o)
686
+ o += 32
687
+ user = _pub(data, o)
688
+ o += 32 + 8 + 8
689
+ sqrt = str(_u128le_int(data, o))
690
+ o += 16
691
+ zfo = _bool(data, o)
692
+
693
+ return DexEvent(
694
+ type=EventType.RAYDIUM_CLMM_SWAP,
695
+ data=RaydiumClmmSwapEvent(
696
+ metadata=_make_meta(meta),
697
+ pool_state=ps,
698
+ sender=user,
699
+ token_account_0=Z,
700
+ token_account_1=Z,
701
+ amount_0=0,
702
+ amount_1=0,
703
+ zero_for_one=zfo,
704
+ sqrt_price_x64=sqrt,
705
+ liquidity="0",
706
+ transfer_fee_0=0,
707
+ transfer_fee_1=0,
708
+ tick=0,
709
+ ),
710
+ )
711
+
712
+
713
+ def parse_clmm_inc_from_data(data: bytes, meta: dict) -> DexEvent:
714
+ if len(data) < 32 + 32 + 16 + 8 + 8:
715
+ return DexEvent()
716
+ o = 0
717
+ pool = _pub(data, o)
718
+ o += 32
719
+ user = _pub(data, o)
720
+ o += 32
721
+ liq = str(_u128le_int(data, o))
722
+ o += 16
723
+ a0 = _u64le(data, o)
724
+ o += 8
725
+ a1 = _u64le(data, o)
726
+
727
+ return DexEvent(
728
+ type=EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
729
+ data=RaydiumClmmIncreaseLiquidityEvent(
730
+ metadata=_make_meta(meta),
731
+ pool=pool,
732
+ position_nft_mint=Z,
733
+ user=user,
734
+ liquidity=liq,
735
+ amount0_max=a0,
736
+ amount1_max=a1,
737
+ ),
738
+ )
739
+
740
+
741
+ def parse_clmm_dec_from_data(data: bytes, meta: dict) -> DexEvent:
742
+ if len(data) < 32 + 32 + 16 + 8 + 8:
743
+ return DexEvent()
744
+ o = 0
745
+ pool = _pub(data, o)
746
+ o += 32
747
+ user = _pub(data, o)
748
+ o += 32
749
+ liq = str(_u128le_int(data, o))
750
+ o += 16
751
+ a0 = _u64le(data, o)
752
+ o += 8
753
+ a1 = _u64le(data, o)
754
+
755
+ return DexEvent(
756
+ type=EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
757
+ data=RaydiumClmmDecreaseLiquidityEvent(
758
+ metadata=_make_meta(meta),
759
+ pool=pool,
760
+ position_nft_mint=Z,
761
+ user=user,
762
+ liquidity=liq,
763
+ amount0_min=a0,
764
+ amount1_min=a1,
765
+ ),
766
+ )
767
+
768
+
769
+ def parse_clmm_create_from_data(data: bytes, meta: dict) -> DexEvent:
770
+ if len(data) < 32 + 32 + 16 + 8:
771
+ return DexEvent()
772
+ o = 0
773
+ pool = _pub(data, o)
774
+ o += 32
775
+ cr = _pub(data, o)
776
+ o += 32
777
+ sqrt = str(_u128le_int(data, o))
778
+ o += 16
779
+ ot = _u64le(data, o)
780
+
781
+ return DexEvent(
782
+ type=EventType.RAYDIUM_CLMM_CREATE_POOL,
783
+ data=RaydiumClmmCreatePoolEvent(
784
+ metadata=_make_meta(meta),
785
+ pool=pool,
786
+ creator=cr,
787
+ token_0_mint=Z,
788
+ token_1_mint=Z,
789
+ tick_spacing=0,
790
+ fee_rate=0,
791
+ sqrt_price_x64=sqrt,
792
+ open_time=ot,
793
+ ),
794
+ )
795
+
796
+
797
+ def parse_clmm_collect_from_data(data: bytes, meta: dict) -> DexEvent:
798
+ if len(data) < 32 + 32 + 8 + 8:
799
+ return DexEvent()
800
+ o = 0
801
+ ps = _pub(data, o)
802
+ o += 32
803
+ pn = _pub(data, o)
804
+ o += 32
805
+ a0 = _u64le(data, o)
806
+ o += 8
807
+ a1 = _u64le(data, o)
808
+
809
+ return DexEvent(
810
+ type=EventType.RAYDIUM_CLMM_COLLECT_FEE,
811
+ data=RaydiumClmmCollectFeeEvent(
812
+ metadata=_make_meta(meta),
813
+ pool_state=ps,
814
+ position_nft_mint=pn,
815
+ amount_0=a0,
816
+ amount_1=a1,
817
+ ),
818
+ )
819
+
820
+
821
+ # --- Raydium AMM ---
822
+
823
+
824
+ def _amm_swap_event(
825
+ meta: dict, amm: str, user: str, ai: int, mo: int, mai: int, ao: int
826
+ ) -> RaydiumAmmV4SwapEvent:
827
+ return RaydiumAmmV4SwapEvent(
828
+ metadata=_make_meta(meta),
829
+ amm=amm,
830
+ user_source_owner=user,
831
+ amount_in=ai,
832
+ minimum_amount_out=mo,
833
+ max_amount_in=mai,
834
+ amount_out=ao,
835
+ )
836
+
837
+
838
+ def parse_amm_swap_in_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
839
+ if len(data) < 32 + 32 + 8 + 8:
840
+ return None
841
+ o = 0
842
+ amm = _pub(data, o)
843
+ o += 32
844
+ user = _pub(data, o)
845
+ o += 32
846
+ ai = _u64le(data, o)
847
+ o += 8
848
+ mo = _u64le(data, o)
849
+ return DexEvent(
850
+ type=EventType.RAYDIUM_AMM_V4_SWAP,
851
+ data=_amm_swap_event(meta, amm, user, ai, mo, 0, 0),
852
+ )
853
+
854
+
855
+ def parse_amm_swap_out_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
856
+ if len(data) < 32 + 32 + 8 + 8:
857
+ return None
858
+ o = 0
859
+ amm = _pub(data, o)
860
+ o += 32
861
+ user = _pub(data, o)
862
+ o += 32
863
+ mai = _u64le(data, o)
864
+ o += 8
865
+ ao = _u64le(data, o)
866
+ return DexEvent(
867
+ type=EventType.RAYDIUM_AMM_V4_SWAP,
868
+ data=_amm_swap_event(meta, amm, user, 0, 0, mai, ao),
869
+ )
870
+
871
+
872
+ def parse_amm_deposit_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
873
+ if len(data) < 32 + 32 + 8 + 8 + 8:
874
+ return None
875
+ o = 0
876
+ amm = _pub(data, o)
877
+ o += 32
878
+ user = _pub(data, o)
879
+ o += 32
880
+ mc = _u64le(data, o)
881
+ o += 8
882
+ mp = _u64le(data, o)
883
+ o += 8
884
+ bs = _u64le(data, o)
885
+ return DexEvent(
886
+ type=EventType.RAYDIUM_AMM_V4_DEPOSIT,
887
+ data=RaydiumAmmV4DepositEvent(
888
+ metadata=_make_meta(meta),
889
+ amm=amm,
890
+ user_owner=user,
891
+ max_coin_amount=mc,
892
+ max_pc_amount=mp,
893
+ base_side=bs,
894
+ ),
895
+ )
896
+
897
+
898
+ def parse_amm_withdraw_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
899
+ if len(data) < 32 + 32 + 8:
900
+ return None
901
+ o = 0
902
+ amm = _pub(data, o)
903
+ o += 32
904
+ user = _pub(data, o)
905
+ o += 32
906
+ amt = _u64le(data, o)
907
+ return DexEvent(
908
+ type=EventType.RAYDIUM_AMM_V4_WITHDRAW,
909
+ data=RaydiumAmmV4WithdrawEvent(
910
+ metadata=_make_meta(meta),
911
+ amm=amm,
912
+ user_owner=user,
913
+ amount=amt,
914
+ ),
915
+ )
916
+
917
+
918
+ def parse_amm_withdraw_pnl_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
919
+ if len(data) < 64:
920
+ return None
921
+ o = 0
922
+ amm = _pub(data, o)
923
+ o += 32
924
+ pnl_owner = _pub(data, o)
925
+ return DexEvent(
926
+ type=EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
927
+ data=RaydiumAmmV4WithdrawPnlEvent(
928
+ metadata=_make_meta(meta),
929
+ amm=amm,
930
+ pnl_owner=pnl_owner,
931
+ ),
932
+ )
933
+
934
+
935
+ def parse_amm_init2_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
936
+ if len(data) < 32 + 32 + 1 + 8 + 8 + 8:
937
+ return None
938
+ o = 0
939
+ amm = _pub(data, o)
940
+ o += 32
941
+ user = _pub(data, o)
942
+ o += 32
943
+ nonce = _u8(data, o)
944
+ o += 1
945
+ ot = _u64le(data, o)
946
+ o += 8
947
+ ipc = _u64le(data, o)
948
+ o += 8
949
+ ic = _u64le(data, o)
950
+ return DexEvent(
951
+ type=EventType.RAYDIUM_AMM_V4_INITIALIZE2,
952
+ data=RaydiumAmmV4Initialize2Event(
953
+ metadata=_make_meta(meta),
954
+ nonce=nonce,
955
+ open_time=ot,
956
+ init_pc_amount=ipc,
957
+ init_coin_amount=ic,
958
+ amm=amm,
959
+ user_wallet=user,
960
+ ),
961
+ )
962
+
963
+
964
+ # --- Raydium CPMM ---
965
+
966
+
967
+ def parse_cpmm_swap_in_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
968
+ if len(data) < 32 + 32 + 8 + 8 + 8 + 1:
969
+ return None
970
+ o = 0
971
+ pool = _pub(data, o)
972
+ o += 64
973
+ ai = _u64le(data, o)
974
+ o += 16
975
+ ao = _u64le(data, o)
976
+ o += 8
977
+ bi = _bool(data, o)
978
+ return DexEvent(
979
+ type=EventType.RAYDIUM_CPMM_SWAP,
980
+ data=RaydiumCpmmSwapEvent(
981
+ metadata=_make_meta(meta),
982
+ pool_id=pool,
983
+ input_amount=ai,
984
+ output_amount=ao,
985
+ base_input=bi,
986
+ ),
987
+ )
988
+
989
+
990
+ def parse_cpmm_swap_out_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
991
+ if len(data) < 32 + 32 + 8 + 8 + 8 + 1:
992
+ return None
993
+ o = 0
994
+ pool = _pub(data, o)
995
+ o += 64
996
+ o += 8
997
+ ao = _u64le(data, o)
998
+ o += 8
999
+ ai = _u64le(data, o)
1000
+ o += 8
1001
+ bo = _bool(data, o)
1002
+ return DexEvent(
1003
+ type=EventType.RAYDIUM_CPMM_SWAP,
1004
+ data=RaydiumCpmmSwapEvent(
1005
+ metadata=_make_meta(meta),
1006
+ pool_id=pool,
1007
+ input_amount=ai,
1008
+ output_amount=ao,
1009
+ base_input=not bo,
1010
+ ),
1011
+ )
1012
+
1013
+
1014
+ def parse_cpmm_deposit_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1015
+ if len(data) < 32 + 32 + 8 + 8 + 8:
1016
+ return None
1017
+ o = 0
1018
+ pool = _pub(data, o)
1019
+ o += 32
1020
+ user = _pub(data, o)
1021
+ o += 32
1022
+ lp = _u64le(data, o)
1023
+ o += 8
1024
+ t0 = _u64le(data, o)
1025
+ o += 8
1026
+ t1 = _u64le(data, o)
1027
+ return DexEvent(
1028
+ type=EventType.RAYDIUM_CPMM_DEPOSIT,
1029
+ data=RaydiumCpmmDepositEvent(
1030
+ metadata=_make_meta(meta),
1031
+ pool=pool,
1032
+ user=user,
1033
+ lp_token_amount=lp,
1034
+ token0_amount=t0,
1035
+ token1_amount=t1,
1036
+ ),
1037
+ )
1038
+
1039
+
1040
+ def parse_cpmm_withdraw_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1041
+ if len(data) < 32 + 32 + 8 + 8 + 8:
1042
+ return None
1043
+ o = 0
1044
+ pool = _pub(data, o)
1045
+ o += 32
1046
+ user = _pub(data, o)
1047
+ o += 32
1048
+ lp = _u64le(data, o)
1049
+ o += 8
1050
+ t0 = _u64le(data, o)
1051
+ o += 8
1052
+ t1 = _u64le(data, o)
1053
+ return DexEvent(
1054
+ type=EventType.RAYDIUM_CPMM_WITHDRAW,
1055
+ data=RaydiumCpmmWithdrawEvent(
1056
+ metadata=_make_meta(meta),
1057
+ pool=pool,
1058
+ user=user,
1059
+ lp_token_amount=lp,
1060
+ token0_amount=t0,
1061
+ token1_amount=t1,
1062
+ ),
1063
+ )
1064
+
1065
+
1066
+ # --- Orca ---
1067
+
1068
+
1069
+ def parse_orca_traded_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1070
+ if len(data) < 32 + 1 + 16 + 16 + 8 * 6:
1071
+ return None
1072
+ o = 0
1073
+ w = _pub(data, o)
1074
+ o += 32
1075
+ atb = _bool(data, o)
1076
+ o += 1
1077
+ pre = str(_u128le_int(data, o))
1078
+ o += 16
1079
+ post = str(_u128le_int(data, o))
1080
+ o += 16
1081
+ ia = _u64le(data, o)
1082
+ o += 8
1083
+ oa = _u64le(data, o)
1084
+ o += 8
1085
+ itf = _u64le(data, o)
1086
+ o += 8
1087
+ otf = _u64le(data, o)
1088
+ o += 8
1089
+ lpf = _u64le(data, o)
1090
+ o += 8
1091
+ pf = _u64le(data, o)
1092
+ return DexEvent(
1093
+ type=EventType.ORCA_WHIRLPOOL_SWAP,
1094
+ data=OrcaWhirlpoolSwapEvent(
1095
+ metadata=_make_meta(meta),
1096
+ whirlpool=w,
1097
+ a_to_b=atb,
1098
+ pre_sqrt_price=pre,
1099
+ post_sqrt_price=post,
1100
+ input_amount=ia,
1101
+ output_amount=oa,
1102
+ input_transfer_fee=itf,
1103
+ output_transfer_fee=otf,
1104
+ lp_fee=lpf,
1105
+ protocol_fee=pf,
1106
+ ),
1107
+ )
1108
+
1109
+
1110
+ def parse_orca_liq_inc_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1111
+ if len(data) < 32 + 32 + 4 + 4 + 16 + 8 * 4:
1112
+ return None
1113
+ o = 0
1114
+ w = _pub(data, o)
1115
+ o += 32
1116
+ p = _pub(data, o)
1117
+ o += 32
1118
+ tl = _i32le(data, o)
1119
+ o += 4
1120
+ tu = _i32le(data, o)
1121
+ o += 4
1122
+ liq = str(_u128le_int(data, o))
1123
+ o += 16
1124
+ ta = _u64le(data, o)
1125
+ o += 8
1126
+ tb = _u64le(data, o)
1127
+ o += 8
1128
+ taf = _u64le(data, o)
1129
+ o += 8
1130
+ tbf = _u64le(data, o)
1131
+ return DexEvent(
1132
+ type=EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED,
1133
+ data=OrcaWhirlpoolLiquidityIncreasedEvent(
1134
+ metadata=_make_meta(meta),
1135
+ whirlpool=w,
1136
+ position=p,
1137
+ tick_lower_index=tl,
1138
+ tick_upper_index=tu,
1139
+ liquidity=liq,
1140
+ token_a_amount=ta,
1141
+ token_b_amount=tb,
1142
+ token_a_transfer_fee=taf,
1143
+ token_b_transfer_fee=tbf,
1144
+ ),
1145
+ )
1146
+
1147
+
1148
+ def parse_orca_liq_dec_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1149
+ if len(data) < 32 + 32 + 4 + 4 + 16 + 8 * 4:
1150
+ return None
1151
+ o = 0
1152
+ w = _pub(data, o)
1153
+ o += 32
1154
+ p = _pub(data, o)
1155
+ o += 32
1156
+ tl = _i32le(data, o)
1157
+ o += 4
1158
+ tu = _i32le(data, o)
1159
+ o += 4
1160
+ liq = str(_u128le_int(data, o))
1161
+ o += 16
1162
+ ta = _u64le(data, o)
1163
+ o += 8
1164
+ tb = _u64le(data, o)
1165
+ o += 8
1166
+ taf = _u64le(data, o)
1167
+ o += 8
1168
+ tbf = _u64le(data, o)
1169
+ return DexEvent(
1170
+ type=EventType.ORCA_WHIRLPOOL_LIQUIDITY_DECREASED,
1171
+ data=OrcaWhirlpoolLiquidityDecreasedEvent(
1172
+ metadata=_make_meta(meta),
1173
+ whirlpool=w,
1174
+ position=p,
1175
+ tick_lower_index=tl,
1176
+ tick_upper_index=tu,
1177
+ liquidity=liq,
1178
+ token_a_amount=ta,
1179
+ token_b_amount=tb,
1180
+ token_a_transfer_fee=taf,
1181
+ token_b_transfer_fee=tbf,
1182
+ ),
1183
+ )
1184
+
1185
+
1186
+ def parse_orca_pool_init_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1187
+ if len(data) < 32 * 5 + 2 + 1 + 1 + 16:
1188
+ return None
1189
+ o = 0
1190
+ w = _pub(data, o)
1191
+ o += 32
1192
+ cfg = _pub(data, o)
1193
+ o += 32
1194
+ ma = _pub(data, o)
1195
+ o += 32
1196
+ mb = _pub(data, o)
1197
+ o += 32
1198
+ ts = _u16le(data, o)
1199
+ o += 2
1200
+ tpa = _pub(data, o)
1201
+ o += 32
1202
+ tpb = _pub(data, o)
1203
+ o += 32
1204
+ da = _u8(data, o)
1205
+ o += 1
1206
+ db = _u8(data, o)
1207
+ o += 1
1208
+ isp = str(_u128le_int(data, o))
1209
+ return DexEvent(
1210
+ type=EventType.ORCA_WHIRLPOOL_POOL_INITIALIZED,
1211
+ data=OrcaWhirlpoolPoolInitializedEvent(
1212
+ metadata=_make_meta(meta),
1213
+ whirlpool=w,
1214
+ whirlpools_config=cfg,
1215
+ token_mint_a=ma,
1216
+ token_mint_b=mb,
1217
+ tick_spacing=ts,
1218
+ token_program_a=tpa,
1219
+ token_program_b=tpb,
1220
+ decimals_a=da,
1221
+ decimals_b=db,
1222
+ initial_sqrt_price=isp,
1223
+ ),
1224
+ )
1225
+
1226
+
1227
+ # --- Meteora Pools ---
1228
+
1229
+
1230
+ def parse_meteora_swap_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1231
+ if len(data) < 8 * 5:
1232
+ return None
1233
+ ox = [0]
1234
+ return DexEvent(
1235
+ type=EventType.METEORA_POOLS_SWAP,
1236
+ data=MeteoraPoolsSwapEvent(
1237
+ metadata=_make_meta(meta),
1238
+ in_amount=_u64_at(data, ox),
1239
+ out_amount=_u64_at(data, ox),
1240
+ trade_fee=_u64_at(data, ox),
1241
+ admin_fee=_u64_at(data, ox),
1242
+ host_fee=_u64_at(data, ox),
1243
+ ),
1244
+ )
1245
+
1246
+
1247
+ def parse_meteora_add_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1248
+ if len(data) < 24:
1249
+ return None
1250
+ ox = [0]
1251
+ return DexEvent(
1252
+ type=EventType.METEORA_POOLS_ADD_LIQUIDITY,
1253
+ data=MeteoraPoolsAddLiquidityEvent(
1254
+ metadata=_make_meta(meta),
1255
+ lp_mint_amount=_u64_at(data, ox),
1256
+ token_a_amount=_u64_at(data, ox),
1257
+ token_b_amount=_u64_at(data, ox),
1258
+ ),
1259
+ )
1260
+
1261
+
1262
+ def parse_meteora_remove_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1263
+ if len(data) < 24:
1264
+ return None
1265
+ ox = [0]
1266
+ return DexEvent(
1267
+ type=EventType.METEORA_POOLS_REMOVE_LIQUIDITY,
1268
+ data=MeteoraPoolsRemoveLiquidityEvent(
1269
+ metadata=_make_meta(meta),
1270
+ lp_unmint_amount=_u64_at(data, ox),
1271
+ token_a_out_amount=_u64_at(data, ox),
1272
+ token_b_out_amount=_u64_at(data, ox),
1273
+ ),
1274
+ )
1275
+
1276
+
1277
+ def parse_meteora_bootstrap_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1278
+ if len(data) < 24 + 32:
1279
+ return None
1280
+ ox = [0]
1281
+ lp = _u64_at(data, ox)
1282
+ ta = _u64_at(data, ox)
1283
+ tb = _u64_at(data, ox)
1284
+ pl = _pub(data, ox[0])
1285
+ return DexEvent(
1286
+ type=EventType.METEORA_POOLS_BOOTSTRAP_LIQUIDITY,
1287
+ data=MeteoraPoolsBootstrapLiquidityEvent(
1288
+ metadata=_make_meta(meta),
1289
+ lp_mint_amount=lp,
1290
+ token_a_amount=ta,
1291
+ token_b_amount=tb,
1292
+ pool=pl,
1293
+ ),
1294
+ )
1295
+
1296
+
1297
+ def parse_meteora_pool_created_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1298
+ if len(data) < 32 * 4 + 1:
1299
+ return None
1300
+ o = 0
1301
+ lm = _pub(data, o)
1302
+ o += 32
1303
+ ta = _pub(data, o)
1304
+ o += 32
1305
+ tb = _pub(data, o)
1306
+ o += 32
1307
+ pt = _u8(data, o)
1308
+ o += 1
1309
+ pl = _pub(data, o)
1310
+ return DexEvent(
1311
+ type=EventType.METEORA_POOLS_POOL_CREATED,
1312
+ data=MeteoraPoolsPoolCreatedEvent(
1313
+ metadata=_make_meta(meta),
1314
+ lp_mint=lm,
1315
+ token_a_mint=ta,
1316
+ token_b_mint=tb,
1317
+ pool_type=pt,
1318
+ pool=pl,
1319
+ ),
1320
+ )
1321
+
1322
+
1323
+ def parse_meteora_pools_set_pool_fees_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1324
+ if len(data) < 8 + 8 + 8 + 8 + 32:
1325
+ return None
1326
+ o = 0
1327
+ tfn = _u64le(data, o)
1328
+ o += 8
1329
+ tfd = _u64le(data, o)
1330
+ o += 8
1331
+ ofn = _u64le(data, o)
1332
+ o += 8
1333
+ ofd = _u64le(data, o)
1334
+ o += 8
1335
+ pool = _pub(data, o)
1336
+ return DexEvent(
1337
+ type=EventType.METEORA_POOLS_SET_POOL_FEES,
1338
+ data=MeteoraPoolsSetPoolFeesEvent(
1339
+ metadata=_make_meta(meta),
1340
+ trade_fee_numerator=tfn,
1341
+ trade_fee_denominator=tfd,
1342
+ owner_trade_fee_numerator=ofn,
1343
+ owner_trade_fee_denominator=ofd,
1344
+ pool=pool,
1345
+ ),
1346
+ )
1347
+
1348
+
1349
+ # --- Meteora DAMM (Swap / Swap2 only,与 Go/TS 一致) ---
1350
+
1351
+ DAMM_SWAP = _d(27, 60, 21, 213, 138, 170, 187, 147)
1352
+ DAMM_SWAP2 = _d(189, 66, 51, 168, 38, 80, 117, 153)
1353
+ DAMM_CREATE_POSITION = _d(156, 15, 119, 198, 29, 181, 221, 55)
1354
+ DAMM_CLOSE_POSITION = _d(20, 145, 144, 68, 143, 142, 214, 178)
1355
+ DAMM_ADD_LIQUIDITY = _d(175, 242, 8, 157, 30, 247, 185, 169)
1356
+ DAMM_REMOVE_LIQUIDITY = _d(87, 46, 88, 98, 175, 96, 34, 91)
1357
+ DAMM_INIT_POOL = _d(228, 50, 246, 85, 203, 66, 134, 37)
1358
+
1359
+
1360
+ def parse_meteora_damm_from_buf(buf: bytes, meta: dict) -> Optional[DexEvent]:
1361
+ if len(buf) < 8:
1362
+ return None
1363
+ d = _disc8(buf[:8])
1364
+ data = buf[8:]
1365
+ if d == DAMM_SWAP:
1366
+ return _parse_damm_swap(data, meta)
1367
+ if d == DAMM_SWAP2:
1368
+ return _parse_damm_swap2(data, meta)
1369
+ if d == DAMM_CREATE_POSITION:
1370
+ return _parse_damm_create_position(data, meta)
1371
+ if d == DAMM_CLOSE_POSITION:
1372
+ return _parse_damm_close_position(data, meta)
1373
+ if d == DAMM_ADD_LIQUIDITY:
1374
+ return _parse_damm_add_liquidity(data, meta)
1375
+ if d == DAMM_REMOVE_LIQUIDITY:
1376
+ return _parse_damm_remove_liquidity(data, meta)
1377
+ if d == DAMM_INIT_POOL:
1378
+ return _parse_damm_initialize_pool(data, meta)
1379
+ return None
1380
+
1381
+
1382
+ def _parse_damm_swap(data: bytes, meta: dict) -> Optional[DexEvent]:
1383
+ if len(data) < 32 + 32 + 1 + 1 + 8 * 8 + 16 + 8 * 4:
1384
+ return None
1385
+ o = 0
1386
+ pool = _pub(data, o)
1387
+ o += 32 + 32
1388
+ td = _u8(data, o)
1389
+ o += 1
1390
+ hr = _bool(data, o)
1391
+ o += 1
1392
+ ai = _u64le(data, o)
1393
+ o += 8
1394
+ mo = _u64le(data, o)
1395
+ o += 8
1396
+ aai = _u64le(data, o)
1397
+ o += 8
1398
+ oa = _u64le(data, o)
1399
+ o += 8
1400
+ nsp = str(_u128le_int(data, o))
1401
+ o += 16
1402
+ lpf = _u64le(data, o)
1403
+ o += 8
1404
+ pf = _u64le(data, o)
1405
+ o += 8
1406
+ rf = _u64le(data, o)
1407
+ o += 8
1408
+ o += 8
1409
+ ct = _u64le(data, o)
1410
+ return DexEvent(
1411
+ type=EventType.METEORA_DAMM_V2_SWAP,
1412
+ data=MeteoraDammV2SwapEvent(
1413
+ metadata=_make_meta(meta),
1414
+ pool=pool,
1415
+ trade_direction=td,
1416
+ has_referral=hr,
1417
+ amount_in=ai,
1418
+ minimum_amount_out=mo,
1419
+ output_amount=oa,
1420
+ next_sqrt_price=nsp,
1421
+ lp_fee=lpf,
1422
+ protocol_fee=pf,
1423
+ partner_fee=0,
1424
+ referral_fee=rf,
1425
+ actual_amount_in=aai,
1426
+ current_timestamp=ct,
1427
+ token_a_vault=Z,
1428
+ token_b_vault=Z,
1429
+ token_a_mint=Z,
1430
+ token_b_mint=Z,
1431
+ token_a_program=Z,
1432
+ token_b_program=Z,
1433
+ ),
1434
+ )
1435
+
1436
+
1437
+ def _parse_damm_swap2(data: bytes, meta: dict) -> Optional[DexEvent]:
1438
+ if len(data) < 32 + 1 + 1 + 1 + 8 * 2 + 1 + 8 * 6 + 16 + 8 * 4 + 8 * 3:
1439
+ return None
1440
+ o = 0
1441
+ pool = _pub(data, o)
1442
+ o += 32
1443
+ td = _u8(data, o)
1444
+ o += 1
1445
+ o += 1
1446
+ hr = _bool(data, o)
1447
+ o += 1
1448
+ a0 = _u64le(data, o)
1449
+ o += 8
1450
+ a1 = _u64le(data, o)
1451
+ o += 8
1452
+ sm = _u8(data, o)
1453
+ o += 1
1454
+ ifi = _u64le(data, o)
1455
+ o += 8
1456
+ o += 16
1457
+ oa = _u64le(data, o)
1458
+ o += 8
1459
+ nsp = str(_u128le_int(data, o))
1460
+ o += 16
1461
+ lpf = _u64le(data, o)
1462
+ o += 8
1463
+ pf = _u64le(data, o)
1464
+ o += 8
1465
+ rf = _u64le(data, o)
1466
+ o += 8
1467
+ o += 8
1468
+ o += 8
1469
+ ct = _u64le(data, o)
1470
+ ai, mo = (a0, a1) if sm == 0 else (a1, a0)
1471
+ return DexEvent(
1472
+ type=EventType.METEORA_DAMM_V2_SWAP,
1473
+ data=MeteoraDammV2SwapEvent(
1474
+ metadata=_make_meta(meta),
1475
+ pool=pool,
1476
+ trade_direction=td,
1477
+ has_referral=hr,
1478
+ amount_in=ai,
1479
+ minimum_amount_out=mo,
1480
+ output_amount=oa,
1481
+ next_sqrt_price=nsp,
1482
+ lp_fee=lpf,
1483
+ protocol_fee=pf,
1484
+ partner_fee=0,
1485
+ referral_fee=rf,
1486
+ actual_amount_in=ifi,
1487
+ current_timestamp=ct,
1488
+ token_a_vault=Z,
1489
+ token_b_vault=Z,
1490
+ token_a_mint=Z,
1491
+ token_b_mint=Z,
1492
+ token_a_program=Z,
1493
+ token_b_program=Z,
1494
+ ),
1495
+ )
1496
+
1497
+
1498
+ def _parse_damm_create_position(data: bytes, meta: dict) -> Optional[DexEvent]:
1499
+ if len(data) < 32 * 4:
1500
+ return None
1501
+ o = 0
1502
+ pool = _pub(data, o)
1503
+ o += 32
1504
+ owner = _pub(data, o)
1505
+ o += 32
1506
+ position = _pub(data, o)
1507
+ o += 32
1508
+ nft = _pub(data, o)
1509
+ return DexEvent(
1510
+ type=EventType.METEORA_DAMM_V2_CREATE_POSITION,
1511
+ data=MeteoraDammV2CreatePositionEvent(
1512
+ metadata=_make_meta(meta),
1513
+ pool=pool,
1514
+ owner=owner,
1515
+ position=position,
1516
+ position_nft_mint=nft,
1517
+ ),
1518
+ )
1519
+
1520
+
1521
+ def _parse_damm_close_position(data: bytes, meta: dict) -> Optional[DexEvent]:
1522
+ if len(data) < 32 * 4:
1523
+ return None
1524
+ o = 0
1525
+ pool = _pub(data, o)
1526
+ o += 32
1527
+ owner = _pub(data, o)
1528
+ o += 32
1529
+ position = _pub(data, o)
1530
+ o += 32
1531
+ nft = _pub(data, o)
1532
+ return DexEvent(
1533
+ type=EventType.METEORA_DAMM_V2_CLOSE_POSITION,
1534
+ data=MeteoraDammV2ClosePositionEvent(
1535
+ metadata=_make_meta(meta),
1536
+ pool=pool,
1537
+ owner=owner,
1538
+ position=position,
1539
+ position_nft_mint=nft,
1540
+ ),
1541
+ )
1542
+
1543
+
1544
+ def _parse_damm_add_liquidity(data: bytes, meta: dict) -> Optional[DexEvent]:
1545
+ if len(data) < 32 * 3 + 16 + 8 * 6:
1546
+ return None
1547
+ o = 0
1548
+ pool = _pub(data, o)
1549
+ o += 32
1550
+ position = _pub(data, o)
1551
+ o += 32
1552
+ owner = _pub(data, o)
1553
+ o += 32
1554
+ ld = str(_u128le_int(data, o))
1555
+ o += 16
1556
+ tat = _u64le(data, o)
1557
+ o += 8
1558
+ tbt = _u64le(data, o)
1559
+ o += 8
1560
+ ta = _u64le(data, o)
1561
+ o += 8
1562
+ tb = _u64le(data, o)
1563
+ o += 8
1564
+ tota = _u64le(data, o)
1565
+ o += 8
1566
+ totb = _u64le(data, o)
1567
+ return DexEvent(
1568
+ type=EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
1569
+ data=MeteoraDammV2AddLiquidityEvent(
1570
+ metadata=_make_meta(meta),
1571
+ pool=pool,
1572
+ position=position,
1573
+ owner=owner,
1574
+ liquidity_delta=ld,
1575
+ token_a_amount_threshold=tat,
1576
+ token_b_amount_threshold=tbt,
1577
+ token_a_amount=ta,
1578
+ token_b_amount=tb,
1579
+ total_amount_a=tota,
1580
+ total_amount_b=totb,
1581
+ ),
1582
+ )
1583
+
1584
+
1585
+ def _parse_damm_dynamic_fee(data: bytes, o: int) -> Optional[tuple[dict, int]]:
1586
+ if o + 32 > len(data):
1587
+ return None
1588
+ bs = _u16le(data, o)
1589
+ o += 2
1590
+ bu = _u128le_int(data, o)
1591
+ o += 16
1592
+ fp = _u16le(data, o)
1593
+ o += 2
1594
+ dp = _u16le(data, o)
1595
+ o += 2
1596
+ rf = _u16le(data, o)
1597
+ o += 2
1598
+ mva = _u32le(data, o)
1599
+ o += 4
1600
+ vfc = _u32le(data, o)
1601
+ o += 4
1602
+ return (
1603
+ {
1604
+ "bin_step": bs,
1605
+ "bin_step_u128": str(bu),
1606
+ "filter_period": fp,
1607
+ "decay_period": dp,
1608
+ "reduction_factor": rf,
1609
+ "max_volatility_accumulator": mva,
1610
+ "variable_fee_control": vfc,
1611
+ },
1612
+ o,
1613
+ )
1614
+
1615
+
1616
+ def _parse_damm_pool_fees(data: bytes, start: int) -> Optional[tuple[dict, int]]:
1617
+ if start + 30 > len(data):
1618
+ return None
1619
+ o = start
1620
+ base_hex = data[o : o + 27].hex()
1621
+ o += 27
1622
+ cfb = _u16le(data, o)
1623
+ o += 2
1624
+ pad = _u8(data, o)
1625
+ o += 1
1626
+ tag = _u8(data, o)
1627
+ o += 1
1628
+ dyn = None
1629
+ if tag == 1:
1630
+ inner = _parse_damm_dynamic_fee(data, o)
1631
+ if not inner:
1632
+ return None
1633
+ dyn, o = inner
1634
+ elif tag != 0:
1635
+ return None
1636
+ return (
1637
+ {
1638
+ "base_fee_data": base_hex,
1639
+ "compounding_fee_bps": cfb,
1640
+ "padding": pad,
1641
+ "dynamic_fee": dyn,
1642
+ },
1643
+ o,
1644
+ )
1645
+
1646
+
1647
+ def _parse_damm_initialize_pool(data: bytes, meta: dict) -> Optional[DexEvent]:
1648
+ min_after_pub = 31 + 109
1649
+ if len(data) < 32 * 6 + min_after_pub:
1650
+ return None
1651
+ o = 0
1652
+ pool = _pub(data, o)
1653
+ o += 32
1654
+ tam = _pub(data, o)
1655
+ o += 32
1656
+ tbm = _pub(data, o)
1657
+ o += 32
1658
+ creator = _pub(data, o)
1659
+ o += 32
1660
+ payer = _pub(data, o)
1661
+ o += 32
1662
+ av = _pub(data, o)
1663
+ o += 32
1664
+ pfp = _parse_damm_pool_fees(data, o)
1665
+ if not pfp:
1666
+ return None
1667
+ fees, o = pfp
1668
+ if o + 109 > len(data):
1669
+ return None
1670
+ smin = str(_u128le_int(data, o))
1671
+ o += 16
1672
+ smax = str(_u128le_int(data, o))
1673
+ o += 16
1674
+ act = _u8(data, o)
1675
+ o += 1
1676
+ cfm = _u8(data, o)
1677
+ o += 1
1678
+ liq = str(_u128le_int(data, o))
1679
+ o += 16
1680
+ sqrt_p = str(_u128le_int(data, o))
1681
+ o += 16
1682
+ ap = _u64le(data, o)
1683
+ o += 8
1684
+ taf = _u8(data, o)
1685
+ o += 1
1686
+ tbf = _u8(data, o)
1687
+ o += 1
1688
+ tau = _u64le(data, o)
1689
+ o += 8
1690
+ tbu = _u64le(data, o)
1691
+ o += 8
1692
+ tota = _u64le(data, o)
1693
+ o += 8
1694
+ totb = _u64le(data, o)
1695
+ o += 8
1696
+ pt = _u8(data, o)
1697
+ return DexEvent(
1698
+ type=EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
1699
+ data=MeteoraDammV2InitializePoolEvent(
1700
+ metadata=_make_meta(meta),
1701
+ pool=pool,
1702
+ token_a_mint=tam,
1703
+ token_b_mint=tbm,
1704
+ creator=creator,
1705
+ payer=payer,
1706
+ alpha_vault=av,
1707
+ pool_fees=fees,
1708
+ sqrt_min_price=smin,
1709
+ sqrt_max_price=smax,
1710
+ activation_type=act,
1711
+ collect_fee_mode=cfm,
1712
+ liquidity=liq,
1713
+ sqrt_price=sqrt_p,
1714
+ activation_point=ap,
1715
+ token_a_flag=taf,
1716
+ token_b_flag=tbf,
1717
+ token_a_amount=tau,
1718
+ token_b_amount=tbu,
1719
+ total_amount_a=tota,
1720
+ total_amount_b=totb,
1721
+ pool_type=pt,
1722
+ ),
1723
+ )
1724
+
1725
+
1726
+ def _parse_damm_remove_liquidity(data: bytes, meta: dict) -> Optional[DexEvent]:
1727
+ if len(data) < 32 * 3 + 16 + 8 * 4:
1728
+ return None
1729
+ o = 0
1730
+ pool = _pub(data, o)
1731
+ o += 32
1732
+ position = _pub(data, o)
1733
+ o += 32
1734
+ owner = _pub(data, o)
1735
+ o += 32
1736
+ ld = str(_u128le_int(data, o))
1737
+ o += 16
1738
+ tat = _u64le(data, o)
1739
+ o += 8
1740
+ tbt = _u64le(data, o)
1741
+ o += 8
1742
+ ta = _u64le(data, o)
1743
+ o += 8
1744
+ tb = _u64le(data, o)
1745
+ return DexEvent(
1746
+ type=EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
1747
+ data=MeteoraDammV2RemoveLiquidityEvent(
1748
+ metadata=_make_meta(meta),
1749
+ pool=pool,
1750
+ position=position,
1751
+ owner=owner,
1752
+ liquidity_delta=ld,
1753
+ token_a_amount_threshold=tat,
1754
+ token_b_amount_threshold=tbt,
1755
+ token_a_amount=ta,
1756
+ token_b_amount=tb,
1757
+ ),
1758
+ )
1759
+
1760
+
1761
+ # --- Bonk ---
1762
+
1763
+ DISC_BONK_TRADE = _d(2, 3, 4, 5, 6, 7, 8, 9)
1764
+ DISC_BONK_POOL_CREATE = _d(1, 2, 3, 4, 5, 6, 7, 8)
1765
+ DISC_BONK_MIGRATE_AMM = _d(3, 4, 5, 6, 7, 8, 9, 10)
1766
+
1767
+
1768
+ def parse_bonk_from_discriminator(disc: int, data: bytes, meta: dict) -> Optional[DexEvent]:
1769
+ if disc == DISC_BONK_TRADE:
1770
+ return _parse_bonk_trade(data, meta)
1771
+ if disc == DISC_BONK_POOL_CREATE:
1772
+ return _parse_bonk_pool_create(data, meta)
1773
+ if disc == DISC_BONK_MIGRATE_AMM:
1774
+ return _parse_bonk_migrate_amm(data, meta)
1775
+ return None
1776
+
1777
+
1778
+ def _parse_bonk_trade(data: bytes, meta: dict) -> Optional[DexEvent]:
1779
+ if len(data) < 32 + 32 + 8 + 8 + 1 + 1:
1780
+ return None
1781
+ o = 0
1782
+ pool = _pub(data, o)
1783
+ o += 32
1784
+ user = _pub(data, o)
1785
+ o += 32
1786
+ ai = _u64le(data, o)
1787
+ o += 8
1788
+ ao = _u64le(data, o)
1789
+ o += 8
1790
+ is_buy = _bool(data, o)
1791
+ o += 1
1792
+ ex_in = _bool(data, o)
1793
+ d = "Buy" if is_buy else "Sell"
1794
+ return DexEvent(
1795
+ type=EventType.BONK_TRADE,
1796
+ data=BonkTradeEvent(
1797
+ metadata=_make_meta(meta),
1798
+ pool_state=pool,
1799
+ user=user,
1800
+ amount_in=ai,
1801
+ amount_out=ao,
1802
+ is_buy=is_buy,
1803
+ trade_direction=d,
1804
+ exact_in=ex_in,
1805
+ ),
1806
+ )
1807
+
1808
+
1809
+ def _parse_bonk_pool_create(data: bytes, meta: dict) -> Optional[DexEvent]:
1810
+ if len(data) < 32 + 32 + 32 + 32 + 8 + 8:
1811
+ return None
1812
+ o = 0
1813
+ pool = _pub(data, o)
1814
+ o += 32 + 32 + 32
1815
+ creator = _pub(data, o)
1816
+ return DexEvent(
1817
+ type=EventType.BONK_POOL_CREATE,
1818
+ data=BonkPoolCreateEvent(
1819
+ metadata=_make_meta(meta),
1820
+ base_mint_param={"symbol": "BONK", "name": "Bonk Pool", "uri": "https://bonk.com", "decimals": 5},
1821
+ pool_state=pool,
1822
+ creator=creator,
1823
+ ),
1824
+ )
1825
+
1826
+
1827
+ def _parse_bonk_migrate_amm(data: bytes, meta: dict) -> Optional[DexEvent]:
1828
+ if len(data) < 32 + 32 + 32 + 8:
1829
+ return None
1830
+ o = 0
1831
+ old_p = _pub(data, o)
1832
+ o += 32
1833
+ new_p = _pub(data, o)
1834
+ o += 32
1835
+ user = _pub(data, o)
1836
+ o += 32
1837
+ liq = _u64le(data, o)
1838
+ return DexEvent(
1839
+ type=EventType.BONK_MIGRATE_AMM,
1840
+ data=BonkMigrateAmmEvent(
1841
+ metadata=_make_meta(meta),
1842
+ old_pool=old_p,
1843
+ new_pool=new_p,
1844
+ user=user,
1845
+ liquidity_amount=liq,
1846
+ ),
1847
+ )
1848
+
1849
+
1850
+ # --- PumpSwap ---
1851
+
1852
+
1853
+ def parse_ps_buy_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1854
+ min_len = 14 * 8 + 7 * 32 + 1 + 5 * 8 + 4
1855
+ if len(data) < min_len:
1856
+ return None
1857
+ o = 0
1858
+
1859
+ def rd() -> int:
1860
+ nonlocal o
1861
+ v = _u64le(data, o)
1862
+ o += 8
1863
+ return v
1864
+
1865
+ def ri() -> int:
1866
+ nonlocal o
1867
+ v = _i64le(data, o)
1868
+ o += 8
1869
+ return v
1870
+
1871
+ def rp() -> str:
1872
+ nonlocal o
1873
+ s = _pub(data, o)
1874
+ o += 32
1875
+ return s
1876
+
1877
+ ts = ri()
1878
+ ev: Dict[str, Any] = {
1879
+ "metadata": meta,
1880
+ "timestamp": ts,
1881
+ "base_amount_out": rd(),
1882
+ "max_quote_amount_in": rd(),
1883
+ "user_base_token_reserves": rd(),
1884
+ "user_quote_token_reserves": rd(),
1885
+ "pool_base_token_reserves": rd(),
1886
+ "pool_quote_token_reserves": rd(),
1887
+ "quote_amount_in": rd(),
1888
+ "lp_fee_basis_points": rd(),
1889
+ "lp_fee": rd(),
1890
+ "protocol_fee_basis_points": rd(),
1891
+ "protocol_fee": rd(),
1892
+ "quote_amount_in_with_lp_fee": rd(),
1893
+ "user_quote_amount_in": rd(),
1894
+ "pool": rp(),
1895
+ "user": rp(),
1896
+ "user_base_token_account": rp(),
1897
+ "user_quote_token_account": rp(),
1898
+ "protocol_fee_recipient": rp(),
1899
+ "protocol_fee_recipient_token_account": rp(),
1900
+ "coin_creator": rp(),
1901
+ "coin_creator_fee_basis_points": rd(),
1902
+ "coin_creator_fee": rd(),
1903
+ }
1904
+ tv = _bool(data, o)
1905
+ o += 1
1906
+ ev["track_volume"] = tv
1907
+ ev["total_unclaimed_tokens"] = rd()
1908
+ ev["total_claimed_tokens"] = rd()
1909
+ ev["current_sol_volume"] = rd()
1910
+ ev["last_update_timestamp"] = ri()
1911
+ ev["min_base_amount_out"] = rd()
1912
+ ix = ""
1913
+ if o + 4 <= len(data):
1914
+ ln = _u32le(data, o)
1915
+ o += 4
1916
+ if o + ln <= len(data):
1917
+ ix = data[o : o + ln].decode("utf-8", errors="replace")
1918
+ ev["ix_name"] = ix
1919
+ # Mayhem mode and cashback fields
1920
+ mm = False
1921
+ if o < len(data):
1922
+ mm = _bool(data, o)
1923
+ o += 1
1924
+ cb_bps = 0
1925
+ cb = 0
1926
+ if o + 16 <= len(data):
1927
+ cb_bps = _u64le(data, o)
1928
+ o += 8
1929
+ cb = _u64le(data, o)
1930
+ ev["mayhem_mode"] = mm
1931
+ ev["cashback_fee_basis_points"] = cb_bps
1932
+ ev["cashback"] = cb
1933
+ ev["is_cashback_coin"] = cb_bps > 0
1934
+ md = ev.pop("metadata", meta)
1935
+ return DexEvent(
1936
+ type=EventType.PUMP_SWAP_BUY,
1937
+ data=PumpSwapBuyEvent(metadata=_make_meta(md), **ev),
1938
+ )
1939
+
1940
+
1941
+ def parse_ps_sell_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
1942
+ req = 13 * 8 + 7 * 32
1943
+ if len(data) < req:
1944
+ return None
1945
+ o = 0
1946
+
1947
+ def rd() -> int:
1948
+ nonlocal o
1949
+ v = _u64le(data, o)
1950
+ o += 8
1951
+ return v
1952
+
1953
+ def ri() -> int:
1954
+ nonlocal o
1955
+ v = _i64le(data, o)
1956
+ o += 8
1957
+ return v
1958
+
1959
+ def rp() -> str:
1960
+ nonlocal o
1961
+ s = _pub(data, o)
1962
+ o += 32
1963
+ return s
1964
+
1965
+ ev: Dict[str, Any] = {
1966
+ "metadata": meta,
1967
+ "timestamp": ri(),
1968
+ "base_amount_in": rd(),
1969
+ "min_quote_amount_out": rd(),
1970
+ "user_base_token_reserves": rd(),
1971
+ "user_quote_token_reserves": rd(),
1972
+ "pool_base_token_reserves": rd(),
1973
+ "pool_quote_token_reserves": rd(),
1974
+ "quote_amount_out": rd(),
1975
+ "lp_fee_basis_points": rd(),
1976
+ "lp_fee": rd(),
1977
+ "protocol_fee_basis_points": rd(),
1978
+ "protocol_fee": rd(),
1979
+ "quote_amount_out_without_lp_fee": rd(),
1980
+ "user_quote_amount_out": rd(),
1981
+ "pool": rp(),
1982
+ "user": rp(),
1983
+ "user_base_token_account": rp(),
1984
+ "user_quote_token_account": rp(),
1985
+ "protocol_fee_recipient": rp(),
1986
+ "protocol_fee_recipient_token_account": rp(),
1987
+ "coin_creator": rp(),
1988
+ "coin_creator_fee_basis_points": rd(),
1989
+ "coin_creator_fee": rd(),
1990
+ }
1991
+ cash_bps, cash = 0, 0
1992
+ if len(data) >= 368:
1993
+ cash_bps = _u64le(data, 352)
1994
+ cash = _u64le(data, 360)
1995
+ ev["cashback_fee_basis_points"] = cash_bps
1996
+ ev["cashback"] = cash
1997
+ md = ev.pop("metadata", meta)
1998
+ return DexEvent(
1999
+ type=EventType.PUMP_SWAP_SELL,
2000
+ data=PumpSwapSellEvent(metadata=_make_meta(md), **ev),
2001
+ )
2002
+
2003
+
2004
+ def parse_ps_create_pool_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
2005
+ req = 8 + 2 + 32 * 6 + 2 + 8 * 7 + 1
2006
+ if len(data) < req:
2007
+ return None
2008
+ o = 0
2009
+ ts = _i64le(data, o)
2010
+ o += 8
2011
+ idx = _u16le(data, o)
2012
+ o += 2
2013
+ creator = _pub(data, o)
2014
+ o += 32
2015
+ bm = _pub(data, o)
2016
+ o += 32
2017
+ qm = _pub(data, o)
2018
+ o += 32
2019
+ bd = _u8(data, o)
2020
+ o += 1
2021
+ qd = _u8(data, o)
2022
+ o += 1
2023
+
2024
+ def rd() -> int:
2025
+ nonlocal o
2026
+ v = _u64le(data, o)
2027
+ o += 8
2028
+ return v
2029
+
2030
+ ev: Dict[str, Any] = {
2031
+ "metadata": meta,
2032
+ "timestamp": ts,
2033
+ "index": idx,
2034
+ "creator": creator,
2035
+ "base_mint": bm,
2036
+ "quote_mint": qm,
2037
+ "base_mint_decimals": bd,
2038
+ "quote_mint_decimals": qd,
2039
+ "base_amount_in": rd(),
2040
+ "quote_amount_in": rd(),
2041
+ "pool_base_amount": rd(),
2042
+ "pool_quote_amount": rd(),
2043
+ "minimum_liquidity": rd(),
2044
+ "initial_liquidity": rd(),
2045
+ "lp_token_amount_out": rd(),
2046
+ }
2047
+ pb = _u8(data, o)
2048
+ o += 1
2049
+ pool = _pub(data, o)
2050
+ o += 32
2051
+ lp = _pub(data, o)
2052
+ o += 32
2053
+ uba = _pub(data, o)
2054
+ o += 32
2055
+ uqa = _pub(data, o)
2056
+ o += 32
2057
+ cc = _pub(data, o)
2058
+ ev["pool_bump"] = pb
2059
+ ev["pool"] = pool
2060
+ ev["lp_mint"] = lp
2061
+ ev["user_base_token_account"] = uba
2062
+ ev["user_quote_token_account"] = uqa
2063
+ ev["coin_creator"] = cc
2064
+ ev["is_mayhem_mode"] = len(data) > 325 and _bool(data, 325)
2065
+ md = ev.pop("metadata", meta)
2066
+ return DexEvent(
2067
+ type=EventType.PUMP_SWAP_CREATE_POOL,
2068
+ data=PumpSwapCreatePoolEvent(metadata=_make_meta(md), **ev),
2069
+ )
2070
+
2071
+
2072
+ def parse_ps_add_liq_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
2073
+ if len(data) < 10 * 8 + 5 * 32:
2074
+ return None
2075
+ o = 0
2076
+
2077
+ def rd() -> int:
2078
+ nonlocal o
2079
+ v = _u64le(data, o)
2080
+ o += 8
2081
+ return v
2082
+
2083
+ def ri() -> int:
2084
+ nonlocal o
2085
+ v = _i64le(data, o)
2086
+ o += 8
2087
+ return v
2088
+
2089
+ def rp() -> str:
2090
+ nonlocal o
2091
+ s = _pub(data, o)
2092
+ o += 32
2093
+ return s
2094
+
2095
+ return DexEvent(
2096
+ type=EventType.PUMP_SWAP_LIQUIDITY_ADDED,
2097
+ data=PumpSwapLiquidityAddedEvent(
2098
+ metadata=_make_meta(meta),
2099
+ timestamp=ri(),
2100
+ lp_token_amount_out=rd(),
2101
+ max_base_amount_in=rd(),
2102
+ max_quote_amount_in=rd(),
2103
+ user_base_token_reserves=rd(),
2104
+ user_quote_token_reserves=rd(),
2105
+ pool_base_token_reserves=rd(),
2106
+ pool_quote_token_reserves=rd(),
2107
+ base_amount_in=rd(),
2108
+ quote_amount_in=rd(),
2109
+ lp_mint_supply=rd(),
2110
+ pool=rp(),
2111
+ user=rp(),
2112
+ user_base_token_account=rp(),
2113
+ user_quote_token_account=rp(),
2114
+ user_pool_token_account=rp(),
2115
+ ),
2116
+ )
2117
+
2118
+
2119
+ def parse_ps_remove_liq_from_data(data: bytes, meta: dict) -> Optional[DexEvent]:
2120
+ if len(data) < 10 * 8 + 5 * 32:
2121
+ return None
2122
+ o = 0
2123
+
2124
+ def rd() -> int:
2125
+ nonlocal o
2126
+ v = _u64le(data, o)
2127
+ o += 8
2128
+ return v
2129
+
2130
+ def ri() -> int:
2131
+ nonlocal o
2132
+ v = _i64le(data, o)
2133
+ o += 8
2134
+ return v
2135
+
2136
+ def rp() -> str:
2137
+ nonlocal o
2138
+ s = _pub(data, o)
2139
+ o += 32
2140
+ return s
2141
+
2142
+ return DexEvent(
2143
+ type=EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
2144
+ data=PumpSwapLiquidityRemovedEvent(
2145
+ metadata=_make_meta(meta),
2146
+ timestamp=ri(),
2147
+ lp_token_amount_in=rd(),
2148
+ min_base_amount_out=rd(),
2149
+ min_quote_amount_out=rd(),
2150
+ user_base_token_reserves=rd(),
2151
+ user_quote_token_reserves=rd(),
2152
+ pool_base_token_reserves=rd(),
2153
+ pool_quote_token_reserves=rd(),
2154
+ base_amount_out=rd(),
2155
+ quote_amount_out=rd(),
2156
+ lp_mint_supply=rd(),
2157
+ pool=rp(),
2158
+ user=rp(),
2159
+ user_base_token_account=rp(),
2160
+ user_quote_token_account=rp(),
2161
+ user_pool_token_account=rp(),
2162
+ ),
2163
+ )
2164
+
2165
+
2166
+ # --- Meteora DLMM ---
2167
+
2168
+ DLMM_SWAP = _d(143, 190, 90, 218, 196, 30, 51, 222)
2169
+ DLMM_ADD_LIQ = _d(181, 157, 89, 67, 143, 182, 52, 72)
2170
+ DLMM_REMOVE_LIQ = _d(80, 85, 209, 72, 24, 206, 35, 178)
2171
+ DLMM_INIT_POOL = _d(95, 180, 10, 172, 84, 174, 232, 40)
2172
+ DLMM_INIT_BIN = _d(11, 18, 155, 194, 33, 115, 238, 119)
2173
+ DLMM_CREATE_POS = _d(123, 233, 11, 43, 146, 180, 97, 119)
2174
+ DLMM_CLOSE_POS = _d(94, 168, 102, 45, 59, 122, 137, 54)
2175
+ DLMM_CLAIM_FEE = _d(152, 70, 208, 111, 104, 91, 44, 1)
2176
+
2177
+
2178
+ def parse_dlmm_from_program_data(buf: bytes, meta: dict) -> Optional[DexEvent]:
2179
+ if len(buf) < 8:
2180
+ return None
2181
+ d = _disc8(buf[:8])
2182
+ data = buf[8:]
2183
+ if d == DLMM_SWAP:
2184
+ if len(data) < 32 + 32 + 4 + 4 + 8 + 8 + 1 + 8 + 8 + 16 + 8:
2185
+ return None
2186
+ o = 0
2187
+ pool = _pub(data, o)
2188
+ o += 32
2189
+ frm = _pub(data, o)
2190
+ o += 32
2191
+ sb = _i32le(data, o)
2192
+ o += 4
2193
+ eb = _i32le(data, o)
2194
+ o += 4
2195
+ ai = _u64le(data, o)
2196
+ o += 8
2197
+ ao = _u64le(data, o)
2198
+ o += 8
2199
+ sy = _bool(data, o)
2200
+ o += 1
2201
+ fee = _u64le(data, o)
2202
+ o += 8
2203
+ pf = _u64le(data, o)
2204
+ o += 8
2205
+ fbps = str(_u128le_int(data, o))
2206
+ o += 16
2207
+ hf = _u64le(data, o)
2208
+ return DexEvent(
2209
+ type=EventType.METEORA_DLMM_SWAP,
2210
+ data=MeteoraDlmmSwapEvent(
2211
+ metadata=_make_meta(meta),
2212
+ pool=pool,
2213
+ from_addr=frm,
2214
+ start_bin_id=sb,
2215
+ end_bin_id=eb,
2216
+ amount_in=ai,
2217
+ amount_out=ao,
2218
+ swap_for_y=sy,
2219
+ fee=fee,
2220
+ protocol_fee=pf,
2221
+ fee_bps=fbps,
2222
+ host_fee=hf,
2223
+ ),
2224
+ )
2225
+ if d == DLMM_ADD_LIQ:
2226
+ if len(data) < 32 + 32 + 32 + 8 + 8 + 4:
2227
+ return None
2228
+ o = 0
2229
+ pool = _pub(data, o)
2230
+ o += 32
2231
+ frm = _pub(data, o)
2232
+ o += 32
2233
+ pos = _pub(data, o)
2234
+ o += 32
2235
+ a0 = _u64le(data, o)
2236
+ o += 8
2237
+ a1 = _u64le(data, o)
2238
+ o += 8
2239
+ ab = _i32le(data, o)
2240
+ return DexEvent(
2241
+ type=EventType.METEORA_DLMM_ADD_LIQUIDITY,
2242
+ data=MeteoraDlmmAddLiquidityEvent(
2243
+ metadata=_make_meta(meta),
2244
+ pool=pool,
2245
+ from_addr=frm,
2246
+ position=pos,
2247
+ amounts=[a0, a1],
2248
+ active_bin_id=ab,
2249
+ ),
2250
+ )
2251
+ if d == DLMM_REMOVE_LIQ:
2252
+ if len(data) < 32 + 32 + 32 + 8 + 8 + 4:
2253
+ return None
2254
+ o = 0
2255
+ pool = _pub(data, o)
2256
+ o += 32
2257
+ frm = _pub(data, o)
2258
+ o += 32
2259
+ pos = _pub(data, o)
2260
+ o += 32
2261
+ a0 = _u64le(data, o)
2262
+ o += 8
2263
+ a1 = _u64le(data, o)
2264
+ o += 8
2265
+ ab = _i32le(data, o)
2266
+ return DexEvent(
2267
+ type=EventType.METEORA_DLMM_REMOVE_LIQUIDITY,
2268
+ data=MeteoraDlmmRemoveLiquidityEvent(
2269
+ metadata=_make_meta(meta),
2270
+ pool=pool,
2271
+ from_addr=frm,
2272
+ position=pos,
2273
+ amounts=[a0, a1],
2274
+ active_bin_id=ab,
2275
+ ),
2276
+ )
2277
+ if d == DLMM_INIT_POOL:
2278
+ if len(data) < 32 + 32 + 4 + 2:
2279
+ return None
2280
+ o = 0
2281
+ pool = _pub(data, o)
2282
+ o += 32
2283
+ creator = _pub(data, o)
2284
+ o += 32
2285
+ ab = _i32le(data, o)
2286
+ o += 4
2287
+ bs = _u16le(data, o)
2288
+ return DexEvent(
2289
+ type=EventType.METEORA_DLMM_INITIALIZE_POOL,
2290
+ data=MeteoraDlmmInitializePoolEvent(
2291
+ metadata=_make_meta(meta),
2292
+ pool=pool,
2293
+ creator=creator,
2294
+ active_bin_id=ab,
2295
+ bin_step=bs,
2296
+ ),
2297
+ )
2298
+ if d == DLMM_INIT_BIN:
2299
+ if len(data) < 32 + 32 + 8:
2300
+ return None
2301
+ o = 0
2302
+ pool = _pub(data, o)
2303
+ o += 32
2304
+ ba = _pub(data, o)
2305
+ o += 32
2306
+ idx = _u64le(data, o)
2307
+ return DexEvent(
2308
+ type=EventType.METEORA_DLMM_INITIALIZE_BIN_ARRAY,
2309
+ data=MeteoraDlmmInitializeBinArrayEvent(
2310
+ metadata=_make_meta(meta),
2311
+ pool=pool,
2312
+ bin_array=ba,
2313
+ index=int(idx),
2314
+ ),
2315
+ )
2316
+ if d == DLMM_CREATE_POS:
2317
+ if len(data) < 32 + 32 + 32 + 4 + 4:
2318
+ return None
2319
+ o = 0
2320
+ pool = _pub(data, o)
2321
+ o += 32
2322
+ pos = _pub(data, o)
2323
+ o += 32
2324
+ owner = _pub(data, o)
2325
+ o += 32
2326
+ lb = _i32le(data, o)
2327
+ o += 4
2328
+ w = _u32le(data, o)
2329
+ return DexEvent(
2330
+ type=EventType.METEORA_DLMM_CREATE_POSITION,
2331
+ data=MeteoraDlmmCreatePositionEvent(
2332
+ metadata=_make_meta(meta),
2333
+ pool=pool,
2334
+ position=pos,
2335
+ owner=owner,
2336
+ lower_bin_id=lb,
2337
+ width=w,
2338
+ ),
2339
+ )
2340
+ if d == DLMM_CLOSE_POS:
2341
+ if len(data) < 32 + 32 + 32:
2342
+ return None
2343
+ o = 0
2344
+ pool = _pub(data, o)
2345
+ o += 32
2346
+ pos = _pub(data, o)
2347
+ o += 32
2348
+ owner = _pub(data, o)
2349
+ return DexEvent(
2350
+ type=EventType.METEORA_DLMM_CLOSE_POSITION,
2351
+ data=MeteoraDlmmClosePositionEvent(
2352
+ metadata=_make_meta(meta),
2353
+ pool=pool,
2354
+ position=pos,
2355
+ owner=owner,
2356
+ ),
2357
+ )
2358
+ if d == DLMM_CLAIM_FEE:
2359
+ if len(data) < 32 + 32 + 32 + 8 + 8:
2360
+ return None
2361
+ o = 0
2362
+ pool = _pub(data, o)
2363
+ o += 32
2364
+ pos = _pub(data, o)
2365
+ o += 32
2366
+ owner = _pub(data, o)
2367
+ o += 32
2368
+ fx = _u64le(data, o)
2369
+ o += 8
2370
+ fy = _u64le(data, o)
2371
+ return DexEvent(
2372
+ type=EventType.METEORA_DLMM_CLAIM_FEE,
2373
+ data=MeteoraDlmmClaimFeeEvent(
2374
+ metadata=_make_meta(meta),
2375
+ pool=pool,
2376
+ position=pos,
2377
+ owner=owner,
2378
+ fee_x=fx,
2379
+ fee_y=fy,
2380
+ ),
2381
+ )
2382
+ return None
2383
+
2384
+
2385
+ # --- 日志过滤(与优化 matcher 的 early-filter / actual-type filter 对齐) ---
2386
+
2387
+ _LOG_DISCRIMINATOR_EVENT_TYPES = {
2388
+ PUMP_CREATE: EventType.PUMP_FUN_CREATE,
2389
+ PUMP_TRADE: EventType.PUMP_FUN_TRADE,
2390
+ PUMP_MIGRATE: EventType.PUMP_FUN_MIGRATE,
2391
+ PUMP_MIGRATE_BONDING_CURVE_CREATOR: EventType.PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR,
2392
+ PUMP_FEES_CREATE_FEE_SHARING_CONFIG: EventType.PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
2393
+ PUMP_FEES_INITIALIZE_FEE_CONFIG: EventType.PUMP_FEES_INITIALIZE_FEE_CONFIG,
2394
+ PUMP_FEES_RESET_FEE_SHARING_CONFIG: EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
2395
+ PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY: EventType.PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
2396
+ PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY: EventType.PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
2397
+ PUMP_FEES_UPDATE_ADMIN: EventType.PUMP_FEES_UPDATE_ADMIN,
2398
+ PUMP_FEES_UPDATE_FEE_CONFIG: EventType.PUMP_FEES_UPDATE_FEE_CONFIG,
2399
+ PUMP_FEES_UPDATE_FEE_SHARES: EventType.PUMP_FEES_UPDATE_FEE_SHARES,
2400
+ PUMP_FEES_UPSERT_FEE_TIERS: EventType.PUMP_FEES_UPSERT_FEE_TIERS,
2401
+ _d(103, 244, 82, 31, 44, 245, 119, 119): EventType.PUMP_SWAP_BUY,
2402
+ _d(62, 47, 55, 10, 165, 3, 220, 42): EventType.PUMP_SWAP_SELL,
2403
+ _d(177, 49, 12, 210, 160, 118, 167, 116): EventType.PUMP_SWAP_CREATE_POOL,
2404
+ _d(120, 248, 61, 83, 31, 142, 107, 144): EventType.PUMP_SWAP_LIQUIDITY_ADDED,
2405
+ _d(22, 9, 133, 26, 160, 44, 71, 192): EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
2406
+ _d(248, 198, 158, 145, 225, 117, 135, 200): EventType.RAYDIUM_CLMM_SWAP,
2407
+ _d(133, 29, 89, 223, 69, 238, 176, 10): EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
2408
+ _d(160, 38, 208, 111, 104, 91, 44, 1): EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
2409
+ _d(233, 146, 209, 142, 207, 104, 64, 188): EventType.RAYDIUM_CLMM_CREATE_POOL,
2410
+ _d(164, 152, 207, 99, 187, 104, 171, 119): EventType.RAYDIUM_CLMM_COLLECT_FEE,
2411
+ _d(143, 190, 90, 218, 196, 30, 51, 222): EventType.RAYDIUM_CPMM_SWAP,
2412
+ _d(55, 217, 98, 86, 163, 74, 180, 173): EventType.RAYDIUM_CPMM_SWAP,
2413
+ _d(242, 35, 198, 137, 82, 225, 242, 182): EventType.RAYDIUM_CPMM_DEPOSIT,
2414
+ _d(183, 18, 70, 156, 148, 109, 161, 34): EventType.RAYDIUM_CPMM_WITHDRAW,
2415
+ _d(0, 0, 0, 0, 0, 0, 0, 9): EventType.RAYDIUM_AMM_V4_SWAP,
2416
+ _d(0, 0, 0, 0, 0, 0, 0, 11): EventType.RAYDIUM_AMM_V4_SWAP,
2417
+ _d(0, 0, 0, 0, 0, 0, 0, 3): EventType.RAYDIUM_AMM_V4_DEPOSIT,
2418
+ _d(0, 0, 0, 0, 0, 0, 0, 4): EventType.RAYDIUM_AMM_V4_WITHDRAW,
2419
+ _d(0, 0, 0, 0, 0, 0, 0, 7): EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
2420
+ _d(0, 0, 0, 0, 0, 0, 0, 1): EventType.RAYDIUM_AMM_V4_INITIALIZE2,
2421
+ _d(225, 202, 73, 175, 147, 43, 160, 150): EventType.ORCA_WHIRLPOOL_SWAP,
2422
+ _d(30, 7, 144, 181, 102, 254, 155, 161): EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED,
2423
+ _d(166, 1, 36, 71, 112, 202, 181, 171): EventType.ORCA_WHIRLPOOL_LIQUIDITY_DECREASED,
2424
+ _d(100, 118, 173, 87, 12, 198, 254, 229): EventType.ORCA_WHIRLPOOL_POOL_INITIALIZED,
2425
+ _d(81, 108, 227, 190, 205, 208, 10, 196): EventType.METEORA_POOLS_SWAP,
2426
+ _d(31, 94, 125, 90, 227, 52, 61, 186): EventType.METEORA_POOLS_ADD_LIQUIDITY,
2427
+ _d(116, 244, 97, 232, 103, 31, 152, 58): EventType.METEORA_POOLS_REMOVE_LIQUIDITY,
2428
+ _d(121, 127, 38, 136, 92, 55, 14, 247): EventType.METEORA_POOLS_BOOTSTRAP_LIQUIDITY,
2429
+ _d(202, 44, 41, 88, 104, 220, 157, 82): EventType.METEORA_POOLS_POOL_CREATED,
2430
+ _d(245, 26, 198, 164, 88, 18, 75, 9): EventType.METEORA_POOLS_SET_POOL_FEES,
2431
+ DAMM_SWAP: EventType.METEORA_DAMM_V2_SWAP,
2432
+ DAMM_SWAP2: EventType.METEORA_DAMM_V2_SWAP,
2433
+ _d(175, 242, 8, 157, 30, 247, 185, 169): EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
2434
+ _d(87, 46, 88, 98, 175, 96, 34, 91): EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
2435
+ _d(228, 50, 246, 85, 203, 66, 134, 37): EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
2436
+ _d(156, 15, 119, 198, 29, 181, 221, 55): EventType.METEORA_DAMM_V2_CREATE_POSITION,
2437
+ _d(20, 145, 144, 68, 143, 142, 214, 178): EventType.METEORA_DAMM_V2_CLOSE_POSITION,
2438
+ DISC_BONK_TRADE: EventType.BONK_TRADE,
2439
+ DISC_BONK_POOL_CREATE: EventType.BONK_POOL_CREATE,
2440
+ DISC_BONK_MIGRATE_AMM: EventType.BONK_MIGRATE_AMM,
2441
+ DLMM_ADD_LIQ: EventType.METEORA_DLMM_ADD_LIQUIDITY,
2442
+ DLMM_REMOVE_LIQ: EventType.METEORA_DLMM_REMOVE_LIQUIDITY,
2443
+ DLMM_INIT_POOL: EventType.METEORA_DLMM_INITIALIZE_POOL,
2444
+ DLMM_INIT_BIN: EventType.METEORA_DLMM_INITIALIZE_BIN_ARRAY,
2445
+ DLMM_CREATE_POS: EventType.METEORA_DLMM_CREATE_POSITION,
2446
+ DLMM_CLOSE_POS: EventType.METEORA_DLMM_CLOSE_POSITION,
2447
+ DLMM_CLAIM_FEE: EventType.METEORA_DLMM_CLAIM_FEE,
2448
+ }
2449
+
2450
+
2451
+ def event_type_for_discriminator(disc: int) -> Optional[EventType]:
2452
+ return _LOG_DISCRIMINATOR_EVENT_TYPES.get(disc)
2453
+
2454
+
2455
+ def filter_allows_unknown_log_event(event_type_filter: Any) -> bool:
2456
+ include_only = getattr(event_type_filter, "include_only", None)
2457
+ return include_only is None
2458
+
2459
+
2460
+ def apply_event_type_filter(ev: Optional[DexEvent], event_type_filter: Any) -> Optional[DexEvent]:
2461
+ if ev is None or not ev.is_valid():
2462
+ return None
2463
+ if event_type_filter is not None and not event_type_filter.should_include(ev.type):
2464
+ return None
2465
+ return ev
2466
+
2467
+
2468
+ # --- 主调度(与 Go matcher 分支顺序一致) ---
2469
+
2470
+ def dispatch_program_data(
2471
+ disc: int,
2472
+ data: bytes,
2473
+ buf: bytes,
2474
+ meta: dict,
2475
+ is_created_buy: bool,
2476
+ ) -> Optional[DexEvent]:
2477
+ if disc == PUMP_TRADE:
2478
+ return parse_trade_from_data(data, meta, is_created_buy)
2479
+ if disc == _d(248, 198, 158, 145, 225, 117, 135, 200):
2480
+ return parse_clmm_swap_from_data(data, meta)
2481
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 9):
2482
+ return parse_amm_swap_in_from_data(data, meta)
2483
+ if disc == _d(103, 244, 82, 31, 44, 245, 119, 119):
2484
+ return parse_ps_buy_from_data(data, meta)
2485
+ if disc == _d(62, 47, 55, 10, 165, 3, 220, 42):
2486
+ return parse_ps_sell_from_data(data, meta)
2487
+ if disc == PUMP_CREATE:
2488
+ return parse_create_from_data(data, meta)
2489
+ if disc == PUMP_MIGRATE:
2490
+ return parse_migrate_from_data(data, meta)
2491
+ if disc == PUMP_MIGRATE_BONDING_CURVE_CREATOR:
2492
+ return parse_migrate_bonding_curve_creator_from_data(data, meta)
2493
+ if disc == PUMP_FEES_CREATE_FEE_SHARING_CONFIG:
2494
+ return parse_pump_fees_create_fee_sharing_config_from_data(data, meta)
2495
+ if disc == PUMP_FEES_INITIALIZE_FEE_CONFIG:
2496
+ return parse_pump_fees_initialize_fee_config_from_data(data, meta)
2497
+ if disc == PUMP_FEES_RESET_FEE_SHARING_CONFIG:
2498
+ return parse_pump_fees_reset_fee_sharing_config_from_data(data, meta)
2499
+ if disc == PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY:
2500
+ return parse_pump_fees_revoke_fee_sharing_authority_from_data(data, meta)
2501
+ if disc == PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY:
2502
+ return parse_pump_fees_transfer_fee_sharing_authority_from_data(data, meta)
2503
+ if disc == PUMP_FEES_UPDATE_ADMIN:
2504
+ return parse_pump_fees_update_admin_from_data(data, meta)
2505
+ if disc == PUMP_FEES_UPDATE_FEE_CONFIG:
2506
+ return parse_pump_fees_update_fee_config_from_data(data, meta)
2507
+ if disc == PUMP_FEES_UPDATE_FEE_SHARES:
2508
+ return parse_pump_fees_update_fee_shares_from_data(data, meta)
2509
+ if disc == PUMP_FEES_UPSERT_FEE_TIERS:
2510
+ return parse_pump_fees_upsert_fee_tiers_from_data(data, meta)
2511
+ if disc == _d(177, 49, 12, 210, 160, 118, 167, 116):
2512
+ return parse_ps_create_pool_from_data(data, meta)
2513
+ if disc == _d(120, 248, 61, 83, 31, 142, 107, 144):
2514
+ return parse_ps_add_liq_from_data(data, meta)
2515
+ if disc == _d(22, 9, 133, 26, 160, 44, 71, 192):
2516
+ return parse_ps_remove_liq_from_data(data, meta)
2517
+ if disc == _d(133, 29, 89, 223, 69, 238, 176, 10):
2518
+ return parse_clmm_inc_from_data(data, meta)
2519
+ if disc == _d(160, 38, 208, 111, 104, 91, 44, 1):
2520
+ return parse_clmm_dec_from_data(data, meta)
2521
+ if disc == _d(233, 146, 209, 142, 207, 104, 64, 188):
2522
+ return parse_clmm_create_from_data(data, meta)
2523
+ if disc == _d(164, 152, 207, 99, 187, 104, 171, 119):
2524
+ return parse_clmm_collect_from_data(data, meta)
2525
+ if disc == _d(143, 190, 90, 218, 196, 30, 51, 222):
2526
+ return parse_cpmm_swap_in_from_data(data, meta)
2527
+ if disc == _d(55, 217, 98, 86, 163, 74, 180, 173):
2528
+ return parse_cpmm_swap_out_from_data(data, meta)
2529
+ if disc == _d(242, 35, 198, 137, 82, 225, 242, 182):
2530
+ return parse_cpmm_deposit_from_data(data, meta)
2531
+ if disc == _d(183, 18, 70, 156, 148, 109, 161, 34):
2532
+ return parse_cpmm_withdraw_from_data(data, meta)
2533
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 11):
2534
+ return parse_amm_swap_out_from_data(data, meta)
2535
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 3):
2536
+ return parse_amm_deposit_from_data(data, meta)
2537
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 4):
2538
+ return parse_amm_withdraw_from_data(data, meta)
2539
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 7):
2540
+ return parse_amm_withdraw_pnl_from_data(data, meta)
2541
+ if disc == _d(0, 0, 0, 0, 0, 0, 0, 1):
2542
+ return parse_amm_init2_from_data(data, meta)
2543
+ if disc == _d(225, 202, 73, 175, 147, 43, 160, 150):
2544
+ return parse_orca_traded_from_data(data, meta)
2545
+ if disc == _d(30, 7, 144, 181, 102, 254, 155, 161):
2546
+ return parse_orca_liq_inc_from_data(data, meta)
2547
+ if disc == _d(166, 1, 36, 71, 112, 202, 181, 171):
2548
+ return parse_orca_liq_dec_from_data(data, meta)
2549
+ if disc == _d(100, 118, 173, 87, 12, 198, 254, 229):
2550
+ return parse_orca_pool_init_from_data(data, meta)
2551
+ if disc == _d(81, 108, 227, 190, 205, 208, 10, 196):
2552
+ return parse_meteora_swap_from_data(data, meta)
2553
+ if disc == _d(31, 94, 125, 90, 227, 52, 61, 186):
2554
+ return parse_meteora_add_from_data(data, meta)
2555
+ if disc == _d(116, 244, 97, 232, 103, 31, 152, 58):
2556
+ return parse_meteora_remove_from_data(data, meta)
2557
+ if disc == _d(121, 127, 38, 136, 92, 55, 14, 247):
2558
+ return parse_meteora_bootstrap_from_data(data, meta)
2559
+ if disc == _d(202, 44, 41, 88, 104, 220, 157, 82):
2560
+ return parse_meteora_pool_created_from_data(data, meta)
2561
+ if disc == _d(245, 26, 198, 164, 88, 18, 75, 9):
2562
+ return parse_meteora_pools_set_pool_fees_from_data(data, meta)
2563
+ if disc in (
2564
+ DAMM_SWAP,
2565
+ DAMM_SWAP2,
2566
+ _d(175, 242, 8, 157, 30, 247, 185, 169),
2567
+ _d(87, 46, 88, 98, 175, 96, 34, 91),
2568
+ _d(228, 50, 246, 85, 203, 66, 134, 37),
2569
+ _d(156, 15, 119, 198, 29, 181, 221, 55),
2570
+ _d(20, 145, 144, 68, 143, 142, 214, 178),
2571
+ ):
2572
+ return parse_meteora_damm_from_buf(buf, meta)
2573
+ bonk = parse_bonk_from_discriminator(disc, data, meta)
2574
+ if bonk:
2575
+ return bonk
2576
+ return parse_dlmm_from_program_data(buf, meta)