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,1750 @@
1
+ """强类型事件定义
2
+
3
+ 提供所有 DEX 事件的强类型 dataclass 定义。
4
+ 用户可以使用这些类型获得 IDE 自动补全和类型检查。
5
+
6
+ 使用示例:
7
+ from sol_parser.event_types import PumpFunTradeEvent, DexEvent
8
+
9
+ # 解析事件
10
+ event = parse_trade_from_data(data, meta, False)
11
+
12
+ # 直接访问强类型数据
13
+ if event.type == EventType.PUMP_FUN_TRADE:
14
+ trade = event.data # 类型为 PumpFunTradeEvent
15
+ print(f"User: {trade.user}")
16
+ print(f"Amount: {trade.sol_amount}")
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass, field
22
+ from typing import Union, List, Optional, Any, Generic, TypeVar, Dict, Tuple
23
+
24
+ from .grpc_types import EventMetadata, EventType
25
+
26
+ T = TypeVar('T')
27
+
28
+
29
+ @dataclass
30
+ class DexEvent:
31
+ """强类型 DEX 事件容器
32
+
33
+ Attributes:
34
+ type: 事件类型
35
+ data: 具体的事件数据(如 PumpFunTradeEvent 等)
36
+
37
+ 控制台可读输出请用 :func:`sol_parser.format_dex_event_json`(缩进 JSON),
38
+ 默认 ``repr``/``print(ev)`` 为单行 dataclass 表示,并非 JSON。
39
+ """
40
+ type: EventType = field(default=EventType.BLOCK_META)
41
+ data: Any = None # 具体的事件类型,如 PumpFunTradeEvent
42
+
43
+ def is_valid(self) -> bool:
44
+ """检查事件是否有效"""
45
+ return self.data is not None
46
+
47
+ def is_trade(self) -> bool:
48
+ """判断是否为交易事件"""
49
+ return self.type in (
50
+ EventType.PUMP_FUN_TRADE, EventType.PUMP_FUN_BUY, EventType.PUMP_FUN_SELL,
51
+ EventType.PUMP_FUN_BUY_EXACT_SOL_IN, EventType.PUMP_SWAP_BUY, EventType.PUMP_SWAP_SELL,
52
+ EventType.RAYDIUM_AMM_V4_SWAP, EventType.RAYDIUM_CLMM_SWAP, EventType.RAYDIUM_CPMM_SWAP,
53
+ EventType.ORCA_WHIRLPOOL_SWAP, EventType.METEORA_DLMM_SWAP,
54
+ EventType.METEORA_POOLS_SWAP, EventType.METEORA_DAMM_V2_SWAP,
55
+ EventType.BONK_TRADE,
56
+ )
57
+
58
+ def as_pumpfun_trade(self) -> Optional['PumpFunTradeEvent']:
59
+ """转换为 PumpFunTradeEvent"""
60
+ if isinstance(self.data, PumpFunTradeEvent):
61
+ return self.data
62
+ return None
63
+
64
+ def as_pumpswap_buy(self) -> Optional['PumpSwapBuyEvent']:
65
+ """转换为 PumpSwapBuyEvent"""
66
+ if isinstance(self.data, PumpSwapBuyEvent):
67
+ return self.data
68
+ return None
69
+
70
+ def as_pumpswap_sell(self) -> Optional['PumpSwapSellEvent']:
71
+ """转换为 PumpSwapSellEvent"""
72
+ if isinstance(self.data, PumpSwapSellEvent):
73
+ return self.data
74
+ return None
75
+
76
+
77
+ def event_key_and_payload(ev: Union["DexEvent", Dict[str, Any]]) -> Tuple[str, Any]:
78
+ """从强类型 :class:`DexEvent` 或历史「单键 dict」形态取出事件名与 payload。"""
79
+ if isinstance(ev, DexEvent):
80
+ if ev.data is None:
81
+ return "", None
82
+ return str(ev.type.value), ev.data
83
+ if isinstance(ev, dict) and ev:
84
+ k = next(iter(ev))
85
+ return k, ev.get(k)
86
+ return "", None
87
+
88
+
89
+ def grpc_recv_us_from_payload(data: Any) -> int:
90
+ """读取 metadata.grpc_recv_us(兼容 dict 与 dataclass payload)。"""
91
+ if data is None:
92
+ return 0
93
+ if isinstance(data, dict):
94
+ m = data.get("metadata") or {}
95
+ if isinstance(m, dict):
96
+ return int(m.get("grpc_recv_us", 0) or 0)
97
+ return int(getattr(m, "grpc_recv_us", 0) or 0)
98
+ meta = getattr(data, "metadata", None)
99
+ if meta is None:
100
+ return 0
101
+ return int(getattr(meta, "grpc_recv_us", 0) or 0)
102
+
103
+
104
+ # ============================================================
105
+ # 基础类型
106
+ # ============================================================
107
+
108
+ @dataclass
109
+ class DexEventBase:
110
+ """所有事件的基类"""
111
+ metadata: EventMetadata = field(default_factory=EventMetadata)
112
+
113
+
114
+ # ============================================================
115
+ # PumpFun 事件
116
+ # ============================================================
117
+
118
+ @dataclass
119
+ class PumpFunTradeEvent(DexEventBase):
120
+ """PumpFun 交易事件"""
121
+ mint: str = ""
122
+ sol_amount: int = 0
123
+ token_amount: int = 0
124
+ is_buy: bool = False
125
+ is_created_buy: bool = False
126
+ user: str = ""
127
+ timestamp: int = 0
128
+ virtual_sol_reserves: int = 0
129
+ virtual_token_reserves: int = 0
130
+ real_sol_reserves: int = 0
131
+ real_token_reserves: int = 0
132
+ fee_recipient: str = ""
133
+ fee_basis_points: int = 0
134
+ fee: int = 0
135
+ creator: str = ""
136
+ creator_fee_basis_points: int = 0
137
+ creator_fee: int = 0
138
+ track_volume: bool = False
139
+ total_unclaimed_tokens: int = 0
140
+ total_claimed_tokens: int = 0
141
+ current_sol_volume: int = 0
142
+ last_update_timestamp: int = 0
143
+ ix_name: str = ""
144
+ mayhem_mode: bool = False
145
+ cashback_fee_basis_points: int = 0
146
+ cashback: int = 0
147
+ is_cashback_coin: bool = False
148
+ bonding_curve: str = ""
149
+ associated_bonding_curve: str = ""
150
+ token_program: str = ""
151
+ creator_vault: str = ""
152
+ #: 第 17 个账户(索引 16),部分交易存在(Creator Rewards / fee 等);由 ``fill_trade_accounts`` 从指令账户填充。
153
+ extra_instruction_account: str = ""
154
+
155
+
156
+ @dataclass
157
+ class PumpFunCreateEvent(DexEventBase):
158
+ """PumpFun 创建代币事件"""
159
+ name: str = ""
160
+ symbol: str = ""
161
+ uri: str = ""
162
+ mint: str = ""
163
+ bonding_curve: str = ""
164
+ user: str = ""
165
+ creator: str = ""
166
+ timestamp: int = 0
167
+ virtual_token_reserves: int = 0
168
+ virtual_sol_reserves: int = 0
169
+ real_token_reserves: int = 0
170
+ token_total_supply: int = 0
171
+ token_program: str = ""
172
+ is_mayhem_mode: bool = False
173
+ is_cashback_enabled: bool = False
174
+
175
+
176
+ @dataclass
177
+ class PumpFunCreateV2TokenEvent(DexEventBase):
178
+ """PumpFun CreateV2(SPL-22 / Mayhem);指令解析时从 accounts 填充。
179
+
180
+ ``observed_fee_recipient`` 由同笔交易中后续 Buy 的 fee recipient 回填(见 ``pumpfun_fee_enrich``)。
181
+ """
182
+
183
+ name: str = ""
184
+ symbol: str = ""
185
+ uri: str = ""
186
+ mint: str = ""
187
+ bonding_curve: str = ""
188
+ user: str = ""
189
+ creator: str = ""
190
+ timestamp: int = 0
191
+ virtual_token_reserves: int = 0
192
+ virtual_sol_reserves: int = 0
193
+ real_token_reserves: int = 0
194
+ token_total_supply: int = 0
195
+ token_program: str = ""
196
+ is_mayhem_mode: bool = False
197
+ is_cashback_enabled: bool = False
198
+ mint_authority: str = ""
199
+ associated_bonding_curve: str = ""
200
+ global_account: str = "" # Rust `global` PumpFun global config
201
+ system_program: str = ""
202
+ associated_token_program: str = ""
203
+ mayhem_program_id: str = ""
204
+ global_params: str = ""
205
+ sol_vault: str = ""
206
+ mayhem_state: str = ""
207
+ mayhem_token_vault: str = ""
208
+ event_authority: str = ""
209
+ program: str = ""
210
+ observed_fee_recipient: str = ""
211
+
212
+
213
+ @dataclass
214
+ class PumpFunMigrateEvent(DexEventBase):
215
+ """PumpFun 迁移事件"""
216
+ user: str = ""
217
+ mint: str = ""
218
+ mint_amount: int = 0
219
+ sol_amount: int = 0
220
+ pool_migration_fee: int = 0
221
+ bonding_curve: str = ""
222
+ timestamp: int = 0
223
+ pool: str = ""
224
+
225
+
226
+ @dataclass
227
+ class PumpFeesShareholder:
228
+ address: str = ""
229
+ share_bps: int = 0
230
+
231
+
232
+ @dataclass
233
+ class PumpFeesFees:
234
+ lp_fee_bps: int = 0
235
+ protocol_fee_bps: int = 0
236
+ creator_fee_bps: int = 0
237
+
238
+
239
+ @dataclass
240
+ class PumpFeesFeeTier:
241
+ market_cap_lamports_threshold: int = 0
242
+ fees: PumpFeesFees = field(default_factory=PumpFeesFees)
243
+
244
+
245
+ @dataclass
246
+ class PumpFeesCreateFeeSharingConfigEvent(DexEventBase):
247
+ timestamp: int = 0
248
+ mint: str = ""
249
+ bonding_curve: str = ""
250
+ pool: str = ""
251
+ sharing_config: str = ""
252
+ admin: str = ""
253
+ initial_shareholders: List[PumpFeesShareholder] = field(default_factory=list)
254
+ status: str = "Active"
255
+
256
+
257
+ @dataclass
258
+ class PumpFeesInitializeFeeConfigEvent(DexEventBase):
259
+ timestamp: int = 0
260
+ admin: str = ""
261
+ fee_config: str = ""
262
+
263
+
264
+ @dataclass
265
+ class PumpFeesResetFeeSharingConfigEvent(DexEventBase):
266
+ timestamp: int = 0
267
+ mint: str = ""
268
+ sharing_config: str = ""
269
+ old_admin: str = ""
270
+ old_shareholders: List[PumpFeesShareholder] = field(default_factory=list)
271
+ new_admin: str = ""
272
+ new_shareholders: List[PumpFeesShareholder] = field(default_factory=list)
273
+
274
+
275
+ @dataclass
276
+ class PumpFeesRevokeFeeSharingAuthorityEvent(DexEventBase):
277
+ timestamp: int = 0
278
+ mint: str = ""
279
+ sharing_config: str = ""
280
+ admin: str = ""
281
+
282
+
283
+ @dataclass
284
+ class PumpFeesTransferFeeSharingAuthorityEvent(DexEventBase):
285
+ timestamp: int = 0
286
+ mint: str = ""
287
+ sharing_config: str = ""
288
+ old_admin: str = ""
289
+ new_admin: str = ""
290
+
291
+
292
+ @dataclass
293
+ class PumpFeesUpdateAdminEvent(DexEventBase):
294
+ timestamp: int = 0
295
+ old_admin: str = ""
296
+ new_admin: str = ""
297
+
298
+
299
+ @dataclass
300
+ class PumpFeesUpdateFeeConfigEvent(DexEventBase):
301
+ timestamp: int = 0
302
+ admin: str = ""
303
+ fee_config: str = ""
304
+ fee_tiers: List[PumpFeesFeeTier] = field(default_factory=list)
305
+ flat_fees: PumpFeesFees = field(default_factory=PumpFeesFees)
306
+
307
+
308
+ @dataclass
309
+ class PumpFeesUpdateFeeSharesEvent(DexEventBase):
310
+ timestamp: int = 0
311
+ mint: str = ""
312
+ sharing_config: str = ""
313
+ admin: str = ""
314
+ bonding_curve: str = ""
315
+ pump_creator_vault: str = ""
316
+ new_shareholders: List[PumpFeesShareholder] = field(default_factory=list)
317
+
318
+
319
+ @dataclass
320
+ class PumpFeesUpsertFeeTiersEvent(DexEventBase):
321
+ timestamp: int = 0
322
+ admin: str = ""
323
+ fee_config: str = ""
324
+ fee_tiers: List[PumpFeesFeeTier] = field(default_factory=list)
325
+ offset: int = 0
326
+
327
+
328
+ @dataclass
329
+ class PumpFunMigrateBondingCurveCreatorEvent(DexEventBase):
330
+ timestamp: int = 0
331
+ mint: str = ""
332
+ bonding_curve: str = ""
333
+ sharing_config: str = ""
334
+ old_creator: str = ""
335
+ new_creator: str = ""
336
+
337
+
338
+ # ============================================================
339
+ # PumpSwap 事件
340
+ # ============================================================
341
+
342
+ @dataclass
343
+ class PumpSwapBuyEvent(DexEventBase):
344
+ """PumpSwap 买入事件"""
345
+ timestamp: int = 0
346
+ base_amount_out: int = 0
347
+ max_quote_amount_in: int = 0
348
+ user_base_token_reserves: int = 0
349
+ user_quote_token_reserves: int = 0
350
+ pool_base_token_reserves: int = 0
351
+ pool_quote_token_reserves: int = 0
352
+ quote_amount_in: int = 0
353
+ lp_fee_basis_points: int = 0
354
+ lp_fee: int = 0
355
+ protocol_fee_basis_points: int = 0
356
+ protocol_fee: int = 0
357
+ quote_amount_in_with_lp_fee: int = 0
358
+ user_quote_amount_in: int = 0
359
+ pool: str = ""
360
+ user: str = ""
361
+ user_base_token_account: str = ""
362
+ user_quote_token_account: str = ""
363
+ protocol_fee_recipient: str = ""
364
+ protocol_fee_recipient_token_account: str = ""
365
+ coin_creator: str = ""
366
+ coin_creator_fee_basis_points: int = 0
367
+ coin_creator_fee: int = 0
368
+ track_volume: bool = False
369
+ total_unclaimed_tokens: int = 0
370
+ total_claimed_tokens: int = 0
371
+ current_sol_volume: int = 0
372
+ last_update_timestamp: int = 0
373
+ min_base_amount_out: int = 0
374
+ ix_name: str = ""
375
+ mayhem_mode: bool = False
376
+ cashback_fee_basis_points: int = 0
377
+ cashback: int = 0
378
+ is_cashback_coin: bool = False
379
+ base_mint: str = ""
380
+ quote_mint: str = ""
381
+ pool_base_token_account: str = ""
382
+ pool_quote_token_account: str = ""
383
+ coin_creator_vault_ata: str = ""
384
+ coin_creator_vault_authority: str = ""
385
+ base_token_program: str = ""
386
+ quote_token_program: str = ""
387
+ is_pump_pool: bool = False
388
+
389
+
390
+ @dataclass
391
+ class PumpSwapSellEvent(DexEventBase):
392
+ """PumpSwap 卖出事件"""
393
+ timestamp: int = 0
394
+ base_amount_in: int = 0
395
+ min_quote_amount_out: int = 0
396
+ user_base_token_reserves: int = 0
397
+ user_quote_token_reserves: int = 0
398
+ pool_base_token_reserves: int = 0
399
+ pool_quote_token_reserves: int = 0
400
+ quote_amount_out: int = 0
401
+ lp_fee_basis_points: int = 0
402
+ lp_fee: int = 0
403
+ protocol_fee_basis_points: int = 0
404
+ protocol_fee: int = 0
405
+ quote_amount_out_without_lp_fee: int = 0
406
+ user_quote_amount_out: int = 0
407
+ pool: str = ""
408
+ user: str = ""
409
+ user_base_token_account: str = ""
410
+ user_quote_token_account: str = ""
411
+ protocol_fee_recipient: str = ""
412
+ protocol_fee_recipient_token_account: str = ""
413
+ coin_creator: str = ""
414
+ coin_creator_fee_basis_points: int = 0
415
+ coin_creator_fee: int = 0
416
+ cashback_fee_basis_points: int = 0
417
+ cashback: int = 0
418
+ base_mint: str = ""
419
+ quote_mint: str = ""
420
+ pool_base_token_account: str = ""
421
+ pool_quote_token_account: str = ""
422
+ coin_creator_vault_ata: str = ""
423
+ coin_creator_vault_authority: str = ""
424
+ base_token_program: str = ""
425
+ quote_token_program: str = ""
426
+ is_pump_pool: bool = False
427
+
428
+
429
+ @dataclass
430
+ class PumpSwapCreatePoolEvent(DexEventBase):
431
+ """PumpSwap 创建池子事件"""
432
+ timestamp: int = 0
433
+ index: int = 0
434
+ creator: str = ""
435
+ base_mint: str = ""
436
+ quote_mint: str = ""
437
+ base_mint_decimals: int = 0
438
+ quote_mint_decimals: int = 0
439
+ base_amount_in: int = 0
440
+ quote_amount_in: int = 0
441
+ pool_base_amount: int = 0
442
+ pool_quote_amount: int = 0
443
+ minimum_liquidity: int = 0
444
+ initial_liquidity: int = 0
445
+ lp_token_amount_out: int = 0
446
+ pool_bump: int = 0
447
+ pool: str = ""
448
+ lp_mint: str = ""
449
+ user_base_token_account: str = ""
450
+ user_quote_token_account: str = ""
451
+ coin_creator: str = ""
452
+ is_mayhem_mode: bool = False
453
+
454
+
455
+ @dataclass
456
+ class PumpSwapLiquidityAddedEvent(DexEventBase):
457
+ """PumpSwap 添加流动性事件"""
458
+ timestamp: int = 0
459
+ lp_token_amount_out: int = 0
460
+ max_base_amount_in: int = 0
461
+ max_quote_amount_in: int = 0
462
+ user_base_token_reserves: int = 0
463
+ user_quote_token_reserves: int = 0
464
+ pool_base_token_reserves: int = 0
465
+ pool_quote_token_reserves: int = 0
466
+ base_amount_in: int = 0
467
+ quote_amount_in: int = 0
468
+ lp_mint_supply: int = 0
469
+ pool: str = ""
470
+ user: str = ""
471
+ user_base_token_account: str = ""
472
+ user_quote_token_account: str = ""
473
+ user_pool_token_account: str = ""
474
+
475
+
476
+ @dataclass
477
+ class PumpSwapLiquidityRemovedEvent(DexEventBase):
478
+ """PumpSwap 移除流动性事件"""
479
+ timestamp: int = 0
480
+ lp_token_amount_in: int = 0
481
+ min_base_amount_out: int = 0
482
+ min_quote_amount_out: int = 0
483
+ user_base_token_reserves: int = 0
484
+ user_quote_token_reserves: int = 0
485
+ pool_base_token_reserves: int = 0
486
+ pool_quote_token_reserves: int = 0
487
+ base_amount_out: int = 0
488
+ quote_amount_out: int = 0
489
+ lp_mint_supply: int = 0
490
+ pool: str = ""
491
+ user: str = ""
492
+ user_base_token_account: str = ""
493
+ user_quote_token_account: str = ""
494
+ user_pool_token_account: str = ""
495
+
496
+
497
+ # ============================================================
498
+ # Raydium AMM V4(legacy AMM)事件 — 与 dex_parsers Program data 布局一致
499
+ # ============================================================
500
+
501
+ _PLACEHOLDER_PK = "11111111111111111111111111111111"
502
+
503
+
504
+ @dataclass
505
+ class RaydiumAmmV4SwapEvent(DexEventBase):
506
+ """Raydium AMM V4 交换(swap_base_in / swap_base_out)"""
507
+ amm: str = ""
508
+ user_source_owner: str = ""
509
+ amount_in: int = 0
510
+ minimum_amount_out: int = 0
511
+ max_amount_in: int = 0
512
+ amount_out: int = 0
513
+ token_program: str = _PLACEHOLDER_PK
514
+ amm_authority: str = _PLACEHOLDER_PK
515
+ amm_open_orders: str = _PLACEHOLDER_PK
516
+ pool_coin_token_account: str = _PLACEHOLDER_PK
517
+ pool_pc_token_account: str = _PLACEHOLDER_PK
518
+ serum_program: str = _PLACEHOLDER_PK
519
+ serum_market: str = _PLACEHOLDER_PK
520
+ serum_bids: str = _PLACEHOLDER_PK
521
+ serum_asks: str = _PLACEHOLDER_PK
522
+ serum_event_queue: str = _PLACEHOLDER_PK
523
+ serum_coin_vault_account: str = _PLACEHOLDER_PK
524
+ serum_pc_vault_account: str = _PLACEHOLDER_PK
525
+ serum_vault_signer: str = _PLACEHOLDER_PK
526
+ user_source_token_account: str = _PLACEHOLDER_PK
527
+ user_destination_token_account: str = _PLACEHOLDER_PK
528
+
529
+
530
+ @dataclass
531
+ class RaydiumAmmV4DepositEvent(DexEventBase):
532
+ amm: str = ""
533
+ user_owner: str = ""
534
+ max_coin_amount: int = 0
535
+ max_pc_amount: int = 0
536
+ base_side: int = 0
537
+ token_program: str = _PLACEHOLDER_PK
538
+ amm_authority: str = _PLACEHOLDER_PK
539
+ amm_open_orders: str = _PLACEHOLDER_PK
540
+ amm_target_orders: str = _PLACEHOLDER_PK
541
+ lp_mint_address: str = _PLACEHOLDER_PK
542
+ pool_coin_token_account: str = _PLACEHOLDER_PK
543
+ pool_pc_token_account: str = _PLACEHOLDER_PK
544
+ serum_market: str = _PLACEHOLDER_PK
545
+ user_coin_token_account: str = _PLACEHOLDER_PK
546
+ user_pc_token_account: str = _PLACEHOLDER_PK
547
+ user_lp_token_account: str = _PLACEHOLDER_PK
548
+ serum_event_queue: str = _PLACEHOLDER_PK
549
+
550
+
551
+ @dataclass
552
+ class RaydiumAmmV4WithdrawEvent(DexEventBase):
553
+ amm: str = ""
554
+ user_owner: str = ""
555
+ amount: int = 0
556
+ token_program: str = _PLACEHOLDER_PK
557
+ amm_authority: str = _PLACEHOLDER_PK
558
+ amm_open_orders: str = _PLACEHOLDER_PK
559
+ amm_target_orders: str = _PLACEHOLDER_PK
560
+ lp_mint_address: str = _PLACEHOLDER_PK
561
+ pool_coin_token_account: str = _PLACEHOLDER_PK
562
+ pool_pc_token_account: str = _PLACEHOLDER_PK
563
+ pool_withdraw_queue: str = _PLACEHOLDER_PK
564
+ pool_temp_lp_token_account: str = _PLACEHOLDER_PK
565
+ serum_program: str = _PLACEHOLDER_PK
566
+ serum_market: str = _PLACEHOLDER_PK
567
+ serum_coin_vault_account: str = _PLACEHOLDER_PK
568
+ serum_pc_vault_account: str = _PLACEHOLDER_PK
569
+ serum_vault_signer: str = _PLACEHOLDER_PK
570
+ user_lp_token_account: str = _PLACEHOLDER_PK
571
+ user_coin_token_account: str = _PLACEHOLDER_PK
572
+ user_pc_token_account: str = _PLACEHOLDER_PK
573
+ serum_event_queue: str = _PLACEHOLDER_PK
574
+ serum_bids: str = _PLACEHOLDER_PK
575
+ serum_asks: str = _PLACEHOLDER_PK
576
+
577
+
578
+ @dataclass
579
+ class RaydiumAmmV4WithdrawPnlEvent(DexEventBase):
580
+ token_program: str = _PLACEHOLDER_PK
581
+ amm: str = ""
582
+ amm_config: str = _PLACEHOLDER_PK
583
+ amm_authority: str = _PLACEHOLDER_PK
584
+ amm_open_orders: str = _PLACEHOLDER_PK
585
+ pool_coin_token_account: str = _PLACEHOLDER_PK
586
+ pool_pc_token_account: str = _PLACEHOLDER_PK
587
+ coin_pnl_token_account: str = _PLACEHOLDER_PK
588
+ pc_pnl_token_account: str = _PLACEHOLDER_PK
589
+ pnl_owner: str = ""
590
+ amm_target_orders: str = _PLACEHOLDER_PK
591
+ serum_program: str = _PLACEHOLDER_PK
592
+ serum_market: str = _PLACEHOLDER_PK
593
+ serum_event_queue: str = _PLACEHOLDER_PK
594
+ serum_coin_vault_account: str = _PLACEHOLDER_PK
595
+ serum_pc_vault_account: str = _PLACEHOLDER_PK
596
+ serum_vault_signer: str = _PLACEHOLDER_PK
597
+
598
+
599
+ @dataclass
600
+ class RaydiumAmmV4Initialize2Event(DexEventBase):
601
+ nonce: int = 0
602
+ open_time: int = 0
603
+ init_pc_amount: int = 0
604
+ init_coin_amount: int = 0
605
+ token_program: str = _PLACEHOLDER_PK
606
+ spl_associated_token_account: str = _PLACEHOLDER_PK
607
+ system_program: str = _PLACEHOLDER_PK
608
+ rent: str = _PLACEHOLDER_PK
609
+ amm: str = ""
610
+ amm_authority: str = _PLACEHOLDER_PK
611
+ amm_open_orders: str = _PLACEHOLDER_PK
612
+ lp_mint: str = _PLACEHOLDER_PK
613
+ coin_mint: str = _PLACEHOLDER_PK
614
+ pc_mint: str = _PLACEHOLDER_PK
615
+ pool_coin_token_account: str = _PLACEHOLDER_PK
616
+ pool_pc_token_account: str = _PLACEHOLDER_PK
617
+ pool_withdraw_queue: str = _PLACEHOLDER_PK
618
+ amm_target_orders: str = _PLACEHOLDER_PK
619
+ pool_temp_lp: str = _PLACEHOLDER_PK
620
+ serum_program: str = _PLACEHOLDER_PK
621
+ serum_market: str = _PLACEHOLDER_PK
622
+ user_wallet: str = ""
623
+ user_token_coin: str = _PLACEHOLDER_PK
624
+ user_token_pc: str = _PLACEHOLDER_PK
625
+ user_lp_token_account: str = _PLACEHOLDER_PK
626
+
627
+
628
+ # ============================================================
629
+ # Raydium CLMM 事件
630
+ # ============================================================
631
+
632
+ @dataclass
633
+ class RaydiumClmmSwapEvent(DexEventBase):
634
+ """Raydium CLMM 交换事件"""
635
+ pool_state: str = ""
636
+ sender: str = ""
637
+ token_account_0: str = ""
638
+ token_account_1: str = ""
639
+ amount_0: int = 0
640
+ amount_1: int = 0
641
+ zero_for_one: bool = False
642
+ sqrt_price_x64: str = ""
643
+ liquidity: str = ""
644
+ transfer_fee_0: int = 0
645
+ transfer_fee_1: int = 0
646
+ tick: int = 0
647
+
648
+
649
+ @dataclass
650
+ class RaydiumClmmIncreaseLiquidityEvent(DexEventBase):
651
+ """Raydium CLMM 增加流动性事件"""
652
+ pool: str = ""
653
+ position_nft_mint: str = ""
654
+ user: str = ""
655
+ liquidity: str = ""
656
+ amount0_max: int = 0
657
+ amount1_max: int = 0
658
+
659
+
660
+ @dataclass
661
+ class RaydiumClmmDecreaseLiquidityEvent(DexEventBase):
662
+ """Raydium CLMM 减少流动性事件"""
663
+ pool: str = ""
664
+ position_nft_mint: str = ""
665
+ user: str = ""
666
+ liquidity: str = ""
667
+ amount0_min: int = 0
668
+ amount1_min: int = 0
669
+
670
+
671
+ @dataclass
672
+ class RaydiumClmmOpenPositionEvent(DexEventBase):
673
+ """Raydium CLMM 开启仓位事件"""
674
+ pool: str = ""
675
+ user: str = ""
676
+ position_nft_mint: str = ""
677
+ tick_lower_index: int = 0
678
+ tick_upper_index: int = 0
679
+ liquidity: str = ""
680
+
681
+
682
+ @dataclass
683
+ class RaydiumClmmOpenPositionWithTokenExtNftEvent(DexEventBase):
684
+ """Raydium CLMM Token-2022 NFT 开启仓位事件"""
685
+ pool: str = ""
686
+ user: str = ""
687
+ position_nft_mint: str = ""
688
+ tick_lower_index: int = 0
689
+ tick_upper_index: int = 0
690
+ liquidity: str = ""
691
+
692
+
693
+ @dataclass
694
+ class RaydiumClmmClosePositionEvent(DexEventBase):
695
+ """Raydium CLMM 关闭仓位事件"""
696
+ pool: str = ""
697
+ user: str = ""
698
+ position_nft_mint: str = ""
699
+
700
+
701
+ @dataclass
702
+ class RaydiumClmmCreatePoolEvent(DexEventBase):
703
+ """Raydium CLMM 创建池子事件"""
704
+ pool: str = ""
705
+ creator: str = ""
706
+ token_0_mint: str = ""
707
+ token_1_mint: str = ""
708
+ tick_spacing: int = 0
709
+ fee_rate: int = 0
710
+ sqrt_price_x64: str = ""
711
+ open_time: int = 0
712
+
713
+
714
+ @dataclass
715
+ class RaydiumClmmCollectFeeEvent(DexEventBase):
716
+ """Raydium CLMM 收取费用事件"""
717
+ pool_state: str = ""
718
+ position_nft_mint: str = ""
719
+ amount_0: int = 0
720
+ amount_1: int = 0
721
+
722
+
723
+ # ============================================================
724
+ # Raydium CPMM 事件
725
+ # ============================================================
726
+
727
+ @dataclass
728
+ class RaydiumCpmmSwapEvent(DexEventBase):
729
+ """Raydium CPMM 交换事件"""
730
+ pool_id: str = ""
731
+ input_amount: int = 0
732
+ output_amount: int = 0
733
+ input_vault_before: int = 0
734
+ output_vault_before: int = 0
735
+ input_transfer_fee: int = 0
736
+ output_transfer_fee: int = 0
737
+ base_input: bool = False
738
+
739
+
740
+ @dataclass
741
+ class RaydiumCpmmDepositEvent(DexEventBase):
742
+ """Raydium CPMM 存款事件"""
743
+ pool: str = ""
744
+ user: str = ""
745
+ lp_token_amount: int = 0
746
+ token0_amount: int = 0
747
+ token1_amount: int = 0
748
+
749
+
750
+ @dataclass
751
+ class RaydiumCpmmWithdrawEvent(DexEventBase):
752
+ """Raydium CPMM 取款事件"""
753
+ pool: str = ""
754
+ user: str = ""
755
+ lp_token_amount: int = 0
756
+ token0_amount: int = 0
757
+ token1_amount: int = 0
758
+
759
+
760
+ @dataclass
761
+ class RaydiumCpmmInitializeEvent(DexEventBase):
762
+ """Raydium CPMM 初始化事件"""
763
+ pool: str = ""
764
+ creator: str = ""
765
+ init_amount0: int = 0
766
+ init_amount1: int = 0
767
+
768
+
769
+ # ============================================================
770
+ # Orca Whirlpool 事件
771
+ # ============================================================
772
+
773
+ @dataclass
774
+ class OrcaWhirlpoolSwapEvent(DexEventBase):
775
+ """Orca Whirlpool 交换事件"""
776
+ whirlpool: str = ""
777
+ a_to_b: bool = False
778
+ pre_sqrt_price: str = ""
779
+ post_sqrt_price: str = ""
780
+ input_amount: int = 0
781
+ output_amount: int = 0
782
+ input_transfer_fee: int = 0
783
+ output_transfer_fee: int = 0
784
+ lp_fee: int = 0
785
+ protocol_fee: int = 0
786
+
787
+
788
+ @dataclass
789
+ class OrcaWhirlpoolLiquidityIncreasedEvent(DexEventBase):
790
+ """Orca Whirlpool 增加流动性事件"""
791
+ whirlpool: str = ""
792
+ position: str = ""
793
+ tick_lower_index: int = 0
794
+ tick_upper_index: int = 0
795
+ liquidity: str = ""
796
+ token_a_amount: int = 0
797
+ token_b_amount: int = 0
798
+ token_a_transfer_fee: int = 0
799
+ token_b_transfer_fee: int = 0
800
+
801
+
802
+ @dataclass
803
+ class OrcaWhirlpoolLiquidityDecreasedEvent(DexEventBase):
804
+ """Orca Whirlpool 减少流动性事件"""
805
+ whirlpool: str = ""
806
+ position: str = ""
807
+ tick_lower_index: int = 0
808
+ tick_upper_index: int = 0
809
+ liquidity: str = ""
810
+ token_a_amount: int = 0
811
+ token_b_amount: int = 0
812
+ token_a_transfer_fee: int = 0
813
+ token_b_transfer_fee: int = 0
814
+
815
+
816
+ @dataclass
817
+ class OrcaWhirlpoolPoolInitializedEvent(DexEventBase):
818
+ """Orca Whirlpool 池子初始化事件"""
819
+ whirlpool: str = ""
820
+ whirlpools_config: str = ""
821
+ token_mint_a: str = ""
822
+ token_mint_b: str = ""
823
+ tick_spacing: int = 0
824
+ token_program_a: str = ""
825
+ token_program_b: str = ""
826
+ decimals_a: int = 0
827
+ decimals_b: int = 0
828
+ initial_sqrt_price: str = ""
829
+
830
+
831
+ # ============================================================
832
+ # Meteora DLMM 事件
833
+ # ============================================================
834
+
835
+ @dataclass
836
+ class MeteoraDlmmSwapEvent(DexEventBase):
837
+ """Meteora DLMM 交换事件"""
838
+ pool: str = ""
839
+ from_addr: str = ""
840
+ start_bin_id: int = 0
841
+ end_bin_id: int = 0
842
+ amount_in: int = 0
843
+ amount_out: int = 0
844
+ swap_for_y: bool = False
845
+ fee: int = 0
846
+ protocol_fee: int = 0
847
+ fee_bps: str = ""
848
+ host_fee: int = 0
849
+
850
+
851
+ @dataclass
852
+ class MeteoraDlmmAddLiquidityEvent(DexEventBase):
853
+ """Meteora DLMM 添加流动性事件"""
854
+ pool: str = ""
855
+ from_addr: str = ""
856
+ position: str = ""
857
+ amounts: List[int] = field(default_factory=list)
858
+ active_bin_id: int = 0
859
+
860
+
861
+ @dataclass
862
+ class MeteoraDlmmRemoveLiquidityEvent(DexEventBase):
863
+ """Meteora DLMM 移除流动性事件"""
864
+ pool: str = ""
865
+ from_addr: str = ""
866
+ position: str = ""
867
+ amounts: List[int] = field(default_factory=list)
868
+ active_bin_id: int = 0
869
+
870
+
871
+ @dataclass
872
+ class MeteoraDlmmInitializePoolEvent(DexEventBase):
873
+ """Meteora DLMM 初始化池子事件"""
874
+ pool: str = ""
875
+ creator: str = ""
876
+ active_bin_id: int = 0
877
+ bin_step: int = 0
878
+
879
+
880
+ @dataclass
881
+ class MeteoraDlmmInitializeBinArrayEvent(DexEventBase):
882
+ """Meteora DLMM 初始化 Bin Array 事件"""
883
+ pool: str = ""
884
+ bin_array: str = ""
885
+ index: int = 0
886
+
887
+
888
+ @dataclass
889
+ class MeteoraDlmmCreatePositionEvent(DexEventBase):
890
+ """Meteora DLMM 创建仓位事件"""
891
+ pool: str = ""
892
+ position: str = ""
893
+ owner: str = ""
894
+ lower_bin_id: int = 0
895
+ width: int = 0
896
+
897
+
898
+ @dataclass
899
+ class MeteoraDlmmClosePositionEvent(DexEventBase):
900
+ """Meteora DLMM 关闭仓位事件"""
901
+ pool: str = ""
902
+ position: str = ""
903
+ owner: str = ""
904
+
905
+
906
+ @dataclass
907
+ class MeteoraDlmmClaimFeeEvent(DexEventBase):
908
+ """Meteora DLMM 收取费用事件"""
909
+ pool: str = ""
910
+ position: str = ""
911
+ owner: str = ""
912
+ fee_x: int = 0
913
+ fee_y: int = 0
914
+
915
+
916
+ # ============================================================
917
+ # Meteora Pools 事件
918
+ # ============================================================
919
+
920
+
921
+ @dataclass
922
+ class MeteoraPoolsSetPoolFeesEvent(DexEventBase):
923
+ """Meteora Pools 设置池子费率"""
924
+ trade_fee_numerator: int = 0
925
+ trade_fee_denominator: int = 0
926
+ owner_trade_fee_numerator: int = 0
927
+ owner_trade_fee_denominator: int = 0
928
+ pool: str = ""
929
+
930
+
931
+ @dataclass
932
+ class MeteoraPoolsSwapEvent(DexEventBase):
933
+ """Meteora Pools 交换事件"""
934
+ in_amount: int = 0
935
+ out_amount: int = 0
936
+ trade_fee: int = 0
937
+ admin_fee: int = 0
938
+ host_fee: int = 0
939
+
940
+
941
+ @dataclass
942
+ class MeteoraPoolsAddLiquidityEvent(DexEventBase):
943
+ """Meteora Pools 添加流动性事件"""
944
+ lp_mint_amount: int = 0
945
+ token_a_amount: int = 0
946
+ token_b_amount: int = 0
947
+
948
+
949
+ @dataclass
950
+ class MeteoraPoolsRemoveLiquidityEvent(DexEventBase):
951
+ """Meteora Pools 移除流动性事件"""
952
+ lp_unmint_amount: int = 0
953
+ token_a_out_amount: int = 0
954
+ token_b_out_amount: int = 0
955
+
956
+
957
+ @dataclass
958
+ class MeteoraPoolsBootstrapLiquidityEvent(DexEventBase):
959
+ """Meteora Pools 引导流动性事件"""
960
+ lp_mint_amount: int = 0
961
+ token_a_amount: int = 0
962
+ token_b_amount: int = 0
963
+ pool: str = ""
964
+
965
+
966
+ @dataclass
967
+ class MeteoraPoolsPoolCreatedEvent(DexEventBase):
968
+ """Meteora Pools 创建池子事件"""
969
+ lp_mint: str = ""
970
+ token_a_mint: str = ""
971
+ token_b_mint: str = ""
972
+ pool_type: int = 0
973
+ pool: str = ""
974
+
975
+
976
+ # ============================================================
977
+ # Meteora DAMM v2 事件
978
+ # ============================================================
979
+
980
+ @dataclass
981
+ class MeteoraDammV2SwapEvent(DexEventBase):
982
+ """Meteora DAMM v2 交换事件"""
983
+ pool: str = ""
984
+ trade_direction: int = 0
985
+ has_referral: bool = False
986
+ amount_in: int = 0
987
+ minimum_amount_out: int = 0
988
+ output_amount: int = 0
989
+ next_sqrt_price: str = ""
990
+ lp_fee: int = 0
991
+ protocol_fee: int = 0
992
+ partner_fee: int = 0
993
+ referral_fee: int = 0
994
+ actual_amount_in: int = 0
995
+ current_timestamp: int = 0
996
+ token_a_vault: str = ""
997
+ token_b_vault: str = ""
998
+ token_a_mint: str = ""
999
+ token_b_mint: str = ""
1000
+ token_a_program: str = ""
1001
+ token_b_program: str = ""
1002
+
1003
+
1004
+ @dataclass
1005
+ class MeteoraDammV2CreatePositionEvent(DexEventBase):
1006
+ """Meteora DAMM v2 创建仓位事件"""
1007
+ pool: str = ""
1008
+ owner: str = ""
1009
+ position: str = ""
1010
+ position_nft_mint: str = ""
1011
+
1012
+
1013
+ @dataclass
1014
+ class MeteoraDammV2ClosePositionEvent(DexEventBase):
1015
+ """Meteora DAMM v2 关闭仓位事件"""
1016
+ pool: str = ""
1017
+ owner: str = ""
1018
+ position: str = ""
1019
+ position_nft_mint: str = ""
1020
+
1021
+
1022
+ @dataclass
1023
+ class MeteoraDammV2AddLiquidityEvent(DexEventBase):
1024
+ """Meteora DAMM v2 添加流动性事件"""
1025
+ pool: str = ""
1026
+ position: str = ""
1027
+ owner: str = ""
1028
+ liquidity_delta: str = ""
1029
+ token_a_amount_threshold: int = 0
1030
+ token_b_amount_threshold: int = 0
1031
+ token_a_amount: int = 0
1032
+ token_b_amount: int = 0
1033
+ total_amount_a: int = 0
1034
+ total_amount_b: int = 0
1035
+
1036
+
1037
+ @dataclass
1038
+ class MeteoraDammV2RemoveLiquidityEvent(DexEventBase):
1039
+ """Meteora DAMM v2 移除流动性事件"""
1040
+ pool: str = ""
1041
+ position: str = ""
1042
+ owner: str = ""
1043
+ liquidity_delta: str = ""
1044
+ token_a_amount_threshold: int = 0
1045
+ token_b_amount_threshold: int = 0
1046
+ token_a_amount: int = 0
1047
+ token_b_amount: int = 0
1048
+
1049
+
1050
+ @dataclass
1051
+ class MeteoraDammV2InitializePoolEvent(DexEventBase):
1052
+ """Meteora DAMM v2 初始化池子事件"""
1053
+ pool: str = ""
1054
+ token_a_mint: str = ""
1055
+ token_b_mint: str = ""
1056
+ creator: str = ""
1057
+ payer: str = ""
1058
+ alpha_vault: str = ""
1059
+ pool_fees: Any = None
1060
+ sqrt_min_price: str = ""
1061
+ sqrt_max_price: str = ""
1062
+ activation_type: int = 0
1063
+ collect_fee_mode: int = 0
1064
+ liquidity: str = ""
1065
+ sqrt_price: str = ""
1066
+ activation_point: int = 0
1067
+ token_a_flag: int = 0
1068
+ token_b_flag: int = 0
1069
+ token_a_amount: int = 0
1070
+ token_b_amount: int = 0
1071
+ total_amount_a: int = 0
1072
+ total_amount_b: int = 0
1073
+ pool_type: int = 0
1074
+
1075
+
1076
+ # ============================================================
1077
+ # Bonk 事件
1078
+ # ============================================================
1079
+
1080
+ @dataclass
1081
+ class BonkTradeEvent(DexEventBase):
1082
+ """Bonk 交易事件"""
1083
+ pool_state: str = ""
1084
+ user: str = ""
1085
+ amount_in: int = 0
1086
+ amount_out: int = 0
1087
+ is_buy: bool = False
1088
+ trade_direction: str = ""
1089
+ exact_in: bool = False
1090
+
1091
+
1092
+ @dataclass
1093
+ class BonkPoolCreateEvent(DexEventBase):
1094
+ """Bonk 创建池子事件"""
1095
+ pool_state: str = ""
1096
+ creator: str = ""
1097
+ base_mint_param: Optional[Dict[str, Any]] = None
1098
+
1099
+
1100
+ @dataclass
1101
+ class BonkMigrateAmmEvent(DexEventBase):
1102
+ """Bonk 迁移 AMM 事件"""
1103
+ old_pool: str = ""
1104
+ new_pool: str = ""
1105
+ user: str = ""
1106
+ liquidity_amount: int = 0
1107
+
1108
+
1109
+ # ============================================================
1110
+ # 类型联合
1111
+ # ============================================================
1112
+
1113
+ TypedDexEvent = Union[
1114
+ PumpFunTradeEvent,
1115
+ PumpFunCreateEvent,
1116
+ PumpFunCreateV2TokenEvent,
1117
+ PumpFunMigrateEvent,
1118
+ PumpFeesCreateFeeSharingConfigEvent,
1119
+ PumpFeesInitializeFeeConfigEvent,
1120
+ PumpFeesResetFeeSharingConfigEvent,
1121
+ PumpFeesRevokeFeeSharingAuthorityEvent,
1122
+ PumpFeesTransferFeeSharingAuthorityEvent,
1123
+ PumpFeesUpdateAdminEvent,
1124
+ PumpFeesUpdateFeeConfigEvent,
1125
+ PumpFeesUpdateFeeSharesEvent,
1126
+ PumpFeesUpsertFeeTiersEvent,
1127
+ PumpFunMigrateBondingCurveCreatorEvent,
1128
+ PumpSwapBuyEvent,
1129
+ PumpSwapSellEvent,
1130
+ PumpSwapCreatePoolEvent,
1131
+ PumpSwapLiquidityAddedEvent,
1132
+ PumpSwapLiquidityRemovedEvent,
1133
+ RaydiumAmmV4SwapEvent,
1134
+ RaydiumAmmV4DepositEvent,
1135
+ RaydiumAmmV4WithdrawEvent,
1136
+ RaydiumAmmV4WithdrawPnlEvent,
1137
+ RaydiumAmmV4Initialize2Event,
1138
+ RaydiumClmmSwapEvent,
1139
+ RaydiumClmmIncreaseLiquidityEvent,
1140
+ RaydiumClmmDecreaseLiquidityEvent,
1141
+ RaydiumClmmCreatePoolEvent,
1142
+ RaydiumClmmOpenPositionEvent,
1143
+ RaydiumClmmOpenPositionWithTokenExtNftEvent,
1144
+ RaydiumClmmClosePositionEvent,
1145
+ RaydiumClmmCollectFeeEvent,
1146
+ RaydiumCpmmSwapEvent,
1147
+ RaydiumCpmmDepositEvent,
1148
+ RaydiumCpmmWithdrawEvent,
1149
+ RaydiumCpmmInitializeEvent,
1150
+ OrcaWhirlpoolSwapEvent,
1151
+ OrcaWhirlpoolLiquidityIncreasedEvent,
1152
+ OrcaWhirlpoolLiquidityDecreasedEvent,
1153
+ OrcaWhirlpoolPoolInitializedEvent,
1154
+ MeteoraDlmmSwapEvent,
1155
+ MeteoraDlmmAddLiquidityEvent,
1156
+ MeteoraDlmmRemoveLiquidityEvent,
1157
+ MeteoraDlmmInitializePoolEvent,
1158
+ MeteoraDlmmInitializeBinArrayEvent,
1159
+ MeteoraDlmmCreatePositionEvent,
1160
+ MeteoraDlmmClosePositionEvent,
1161
+ MeteoraDlmmClaimFeeEvent,
1162
+ MeteoraPoolsSetPoolFeesEvent,
1163
+ MeteoraPoolsSwapEvent,
1164
+ MeteoraPoolsAddLiquidityEvent,
1165
+ MeteoraPoolsRemoveLiquidityEvent,
1166
+ MeteoraPoolsBootstrapLiquidityEvent,
1167
+ MeteoraPoolsPoolCreatedEvent,
1168
+ MeteoraDammV2SwapEvent,
1169
+ MeteoraDammV2CreatePositionEvent,
1170
+ MeteoraDammV2ClosePositionEvent,
1171
+ MeteoraDammV2AddLiquidityEvent,
1172
+ MeteoraDammV2RemoveLiquidityEvent,
1173
+ MeteoraDammV2InitializePoolEvent,
1174
+ BonkTradeEvent,
1175
+ BonkPoolCreateEvent,
1176
+ BonkMigrateAmmEvent,
1177
+ ]
1178
+
1179
+
1180
+ # ============================================================
1181
+ # 辅助函数
1182
+ # ============================================================
1183
+
1184
+ def _get_metadata(m: dict) -> EventMetadata:
1185
+ """从 dict 中提取 metadata"""
1186
+ v = m.get("metadata")
1187
+ if isinstance(v, EventMetadata):
1188
+ return v
1189
+ if isinstance(v, dict):
1190
+ return EventMetadata(
1191
+ signature=v.get("signature", ""),
1192
+ slot=v.get("slot", 0),
1193
+ tx_index=v.get("tx_index", 0),
1194
+ block_time_us=v.get("block_time_us", 0),
1195
+ grpc_recv_us=v.get("grpc_recv_us", 0),
1196
+ recent_blockhash=v.get("recent_blockhash", ""),
1197
+ )
1198
+ return EventMetadata()
1199
+
1200
+
1201
+ def _get_str(m: dict, key: str) -> str:
1202
+ v = m.get(key, "")
1203
+ return str(v) if v is not None else ""
1204
+
1205
+
1206
+ def _get_int(m: dict, key: str) -> int:
1207
+ v = m.get(key, 0)
1208
+ if isinstance(v, int):
1209
+ return v
1210
+ if isinstance(v, str) and v.isdigit():
1211
+ return int(v)
1212
+ return 0
1213
+
1214
+
1215
+ def _get_bool(m: dict, key: str) -> bool:
1216
+ v = m.get(key, False)
1217
+ return bool(v)
1218
+
1219
+
1220
+ def _get_list(m: dict, key: str) -> List[int]:
1221
+ v = m.get(key, [])
1222
+ if isinstance(v, (list, tuple)):
1223
+ return [int(x) for x in v]
1224
+ return []
1225
+
1226
+
1227
+ def _get_dict_any(m: dict, key: str) -> Optional[Dict[str, Any]]:
1228
+ v = m.get(key)
1229
+ return v if isinstance(v, dict) else None
1230
+
1231
+
1232
+ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
1233
+ """将旧版 DexEvent dict 转换为强类型事件
1234
+
1235
+ Args:
1236
+ event: 旧版 DexEvent dict,格式为 { "EventType": { ... } }
1237
+
1238
+ Returns:
1239
+ 强类型事件对象,如果无法识别则返回 None
1240
+ """
1241
+ if not event:
1242
+ return None
1243
+
1244
+ # 获取事件类型和数据
1245
+ event_type_str = None
1246
+ data = None
1247
+ for k, v in event.items():
1248
+ event_type_str = k
1249
+ data = v if isinstance(v, dict) else {}
1250
+ break
1251
+
1252
+ if not event_type_str or not data:
1253
+ return None
1254
+
1255
+ try:
1256
+ event_type = EventType(event_type_str)
1257
+ except ValueError:
1258
+ return None
1259
+
1260
+ meta = _get_metadata(data)
1261
+
1262
+ # PumpFun events
1263
+ if event_type in (EventType.PUMP_FUN_TRADE, EventType.PUMP_FUN_BUY,
1264
+ EventType.PUMP_FUN_SELL, EventType.PUMP_FUN_BUY_EXACT_SOL_IN):
1265
+ return PumpFunTradeEvent(
1266
+ metadata=meta,
1267
+ mint=_get_str(data, "mint"),
1268
+ sol_amount=_get_int(data, "sol_amount"),
1269
+ token_amount=_get_int(data, "token_amount"),
1270
+ is_buy=_get_bool(data, "is_buy"),
1271
+ is_created_buy=_get_bool(data, "is_created_buy"),
1272
+ user=_get_str(data, "user"),
1273
+ timestamp=_get_int(data, "timestamp"),
1274
+ virtual_sol_reserves=_get_int(data, "virtual_sol_reserves"),
1275
+ virtual_token_reserves=_get_int(data, "virtual_token_reserves"),
1276
+ real_sol_reserves=_get_int(data, "real_sol_reserves"),
1277
+ real_token_reserves=_get_int(data, "real_token_reserves"),
1278
+ fee_recipient=_get_str(data, "fee_recipient"),
1279
+ fee_basis_points=_get_int(data, "fee_basis_points"),
1280
+ fee=_get_int(data, "fee"),
1281
+ creator=_get_str(data, "creator"),
1282
+ creator_fee_basis_points=_get_int(data, "creator_fee_basis_points"),
1283
+ creator_fee=_get_int(data, "creator_fee"),
1284
+ track_volume=_get_bool(data, "track_volume"),
1285
+ total_unclaimed_tokens=_get_int(data, "total_unclaimed_tokens"),
1286
+ total_claimed_tokens=_get_int(data, "total_claimed_tokens"),
1287
+ current_sol_volume=_get_int(data, "current_sol_volume"),
1288
+ last_update_timestamp=_get_int(data, "last_update_timestamp"),
1289
+ ix_name=_get_str(data, "ix_name"),
1290
+ mayhem_mode=_get_bool(data, "mayhem_mode"),
1291
+ cashback_fee_basis_points=_get_int(data, "cashback_fee_basis_points"),
1292
+ cashback=_get_int(data, "cashback"),
1293
+ is_cashback_coin=_get_bool(data, "is_cashback_coin"),
1294
+ bonding_curve=_get_str(data, "bonding_curve"),
1295
+ associated_bonding_curve=_get_str(data, "associated_bonding_curve"),
1296
+ token_program=_get_str(data, "token_program"),
1297
+ creator_vault=_get_str(data, "creator_vault"),
1298
+ )
1299
+
1300
+ if event_type == EventType.PUMP_FUN_CREATE:
1301
+ return PumpFunCreateEvent(
1302
+ metadata=meta,
1303
+ name=_get_str(data, "name"),
1304
+ symbol=_get_str(data, "symbol"),
1305
+ uri=_get_str(data, "uri"),
1306
+ mint=_get_str(data, "mint"),
1307
+ bonding_curve=_get_str(data, "bonding_curve"),
1308
+ user=_get_str(data, "user"),
1309
+ creator=_get_str(data, "creator"),
1310
+ timestamp=_get_int(data, "timestamp"),
1311
+ virtual_token_reserves=_get_int(data, "virtual_token_reserves"),
1312
+ virtual_sol_reserves=_get_int(data, "virtual_sol_reserves"),
1313
+ real_token_reserves=_get_int(data, "real_token_reserves"),
1314
+ token_total_supply=_get_int(data, "token_total_supply"),
1315
+ token_program=_get_str(data, "token_program"),
1316
+ is_mayhem_mode=_get_bool(data, "is_mayhem_mode"),
1317
+ is_cashback_enabled=_get_bool(data, "is_cashback_enabled"),
1318
+ )
1319
+
1320
+ if event_type == EventType.PUMP_FUN_CREATE_V2:
1321
+ g = _get_str(data, "global") or _get_str(data, "global_account")
1322
+ return PumpFunCreateV2TokenEvent(
1323
+ metadata=meta,
1324
+ name=_get_str(data, "name"),
1325
+ symbol=_get_str(data, "symbol"),
1326
+ uri=_get_str(data, "uri"),
1327
+ mint=_get_str(data, "mint"),
1328
+ bonding_curve=_get_str(data, "bonding_curve"),
1329
+ user=_get_str(data, "user"),
1330
+ creator=_get_str(data, "creator"),
1331
+ timestamp=_get_int(data, "timestamp"),
1332
+ virtual_token_reserves=_get_int(data, "virtual_token_reserves"),
1333
+ virtual_sol_reserves=_get_int(data, "virtual_sol_reserves"),
1334
+ real_token_reserves=_get_int(data, "real_token_reserves"),
1335
+ token_total_supply=_get_int(data, "token_total_supply"),
1336
+ token_program=_get_str(data, "token_program"),
1337
+ is_mayhem_mode=_get_bool(data, "is_mayhem_mode"),
1338
+ is_cashback_enabled=_get_bool(data, "is_cashback_enabled"),
1339
+ mint_authority=_get_str(data, "mint_authority"),
1340
+ associated_bonding_curve=_get_str(data, "associated_bonding_curve"),
1341
+ global_account=g,
1342
+ system_program=_get_str(data, "system_program"),
1343
+ associated_token_program=_get_str(data, "associated_token_program"),
1344
+ mayhem_program_id=_get_str(data, "mayhem_program_id"),
1345
+ global_params=_get_str(data, "global_params"),
1346
+ sol_vault=_get_str(data, "sol_vault"),
1347
+ mayhem_state=_get_str(data, "mayhem_state"),
1348
+ mayhem_token_vault=_get_str(data, "mayhem_token_vault"),
1349
+ event_authority=_get_str(data, "event_authority"),
1350
+ program=_get_str(data, "program"),
1351
+ observed_fee_recipient=_get_str(data, "observed_fee_recipient"),
1352
+ )
1353
+
1354
+ if event_type == EventType.PUMP_FUN_MIGRATE:
1355
+ return PumpFunMigrateEvent(
1356
+ metadata=meta,
1357
+ user=_get_str(data, "user"),
1358
+ mint=_get_str(data, "mint"),
1359
+ mint_amount=_get_int(data, "mint_amount"),
1360
+ sol_amount=_get_int(data, "sol_amount"),
1361
+ pool_migration_fee=_get_int(data, "pool_migration_fee"),
1362
+ bonding_curve=_get_str(data, "bonding_curve"),
1363
+ timestamp=_get_int(data, "timestamp"),
1364
+ pool=_get_str(data, "pool"),
1365
+ )
1366
+
1367
+ # PumpSwap events
1368
+ if event_type == EventType.PUMP_SWAP_BUY:
1369
+ return PumpSwapBuyEvent(
1370
+ metadata=meta,
1371
+ timestamp=_get_int(data, "timestamp"),
1372
+ base_amount_out=_get_int(data, "base_amount_out"),
1373
+ max_quote_amount_in=_get_int(data, "max_quote_amount_in"),
1374
+ user_base_token_reserves=_get_int(data, "user_base_token_reserves"),
1375
+ user_quote_token_reserves=_get_int(data, "user_quote_token_reserves"),
1376
+ pool_base_token_reserves=_get_int(data, "pool_base_token_reserves"),
1377
+ pool_quote_token_reserves=_get_int(data, "pool_quote_token_reserves"),
1378
+ quote_amount_in=_get_int(data, "quote_amount_in"),
1379
+ lp_fee_basis_points=_get_int(data, "lp_fee_basis_points"),
1380
+ lp_fee=_get_int(data, "lp_fee"),
1381
+ protocol_fee_basis_points=_get_int(data, "protocol_fee_basis_points"),
1382
+ protocol_fee=_get_int(data, "protocol_fee"),
1383
+ quote_amount_in_with_lp_fee=_get_int(data, "quote_amount_in_with_lp_fee"),
1384
+ user_quote_amount_in=_get_int(data, "user_quote_amount_in"),
1385
+ pool=_get_str(data, "pool"),
1386
+ user=_get_str(data, "user"),
1387
+ user_base_token_account=_get_str(data, "user_base_token_account"),
1388
+ user_quote_token_account=_get_str(data, "user_quote_token_account"),
1389
+ protocol_fee_recipient=_get_str(data, "protocol_fee_recipient"),
1390
+ protocol_fee_recipient_token_account=_get_str(data, "protocol_fee_recipient_token_account"),
1391
+ coin_creator=_get_str(data, "coin_creator"),
1392
+ coin_creator_fee_basis_points=_get_int(data, "coin_creator_fee_basis_points"),
1393
+ coin_creator_fee=_get_int(data, "coin_creator_fee"),
1394
+ track_volume=_get_bool(data, "track_volume"),
1395
+ total_unclaimed_tokens=_get_int(data, "total_unclaimed_tokens"),
1396
+ total_claimed_tokens=_get_int(data, "total_claimed_tokens"),
1397
+ current_sol_volume=_get_int(data, "current_sol_volume"),
1398
+ last_update_timestamp=_get_int(data, "last_update_timestamp"),
1399
+ min_base_amount_out=_get_int(data, "min_base_amount_out"),
1400
+ ix_name=_get_str(data, "ix_name"),
1401
+ mayhem_mode=_get_bool(data, "mayhem_mode"),
1402
+ cashback_fee_basis_points=_get_int(data, "cashback_fee_basis_points"),
1403
+ cashback=_get_int(data, "cashback"),
1404
+ is_cashback_coin=_get_bool(data, "is_cashback_coin"),
1405
+ is_pump_pool=_get_bool(data, "is_pump_pool"),
1406
+ )
1407
+
1408
+ if event_type == EventType.PUMP_SWAP_SELL:
1409
+ return PumpSwapSellEvent(
1410
+ metadata=meta,
1411
+ timestamp=_get_int(data, "timestamp"),
1412
+ base_amount_in=_get_int(data, "base_amount_in"),
1413
+ min_quote_amount_out=_get_int(data, "min_quote_amount_out"),
1414
+ user_base_token_reserves=_get_int(data, "user_base_token_reserves"),
1415
+ user_quote_token_reserves=_get_int(data, "user_quote_token_reserves"),
1416
+ pool_base_token_reserves=_get_int(data, "pool_base_token_reserves"),
1417
+ pool_quote_token_reserves=_get_int(data, "pool_quote_token_reserves"),
1418
+ quote_amount_out=_get_int(data, "quote_amount_out"),
1419
+ lp_fee_basis_points=_get_int(data, "lp_fee_basis_points"),
1420
+ lp_fee=_get_int(data, "lp_fee"),
1421
+ protocol_fee_basis_points=_get_int(data, "protocol_fee_basis_points"),
1422
+ protocol_fee=_get_int(data, "protocol_fee"),
1423
+ quote_amount_out_without_lp_fee=_get_int(data, "quote_amount_out_without_lp_fee"),
1424
+ user_quote_amount_out=_get_int(data, "user_quote_amount_out"),
1425
+ pool=_get_str(data, "pool"),
1426
+ user=_get_str(data, "user"),
1427
+ user_base_token_account=_get_str(data, "user_base_token_account"),
1428
+ user_quote_token_account=_get_str(data, "user_quote_token_account"),
1429
+ protocol_fee_recipient=_get_str(data, "protocol_fee_recipient"),
1430
+ protocol_fee_recipient_token_account=_get_str(data, "protocol_fee_recipient_token_account"),
1431
+ coin_creator=_get_str(data, "coin_creator"),
1432
+ coin_creator_fee_basis_points=_get_int(data, "coin_creator_fee_basis_points"),
1433
+ coin_creator_fee=_get_int(data, "coin_creator_fee"),
1434
+ cashback_fee_basis_points=_get_int(data, "cashback_fee_basis_points"),
1435
+ cashback=_get_int(data, "cashback"),
1436
+ is_pump_pool=_get_bool(data, "is_pump_pool"),
1437
+ )
1438
+
1439
+ if event_type == EventType.PUMP_SWAP_CREATE_POOL:
1440
+ return PumpSwapCreatePoolEvent(
1441
+ metadata=meta,
1442
+ timestamp=_get_int(data, "timestamp"),
1443
+ index=_get_int(data, "index"),
1444
+ creator=_get_str(data, "creator"),
1445
+ base_mint=_get_str(data, "base_mint"),
1446
+ quote_mint=_get_str(data, "quote_mint"),
1447
+ base_mint_decimals=_get_int(data, "base_mint_decimals"),
1448
+ quote_mint_decimals=_get_int(data, "quote_mint_decimals"),
1449
+ base_amount_in=_get_int(data, "base_amount_in"),
1450
+ quote_amount_in=_get_int(data, "quote_amount_in"),
1451
+ pool_base_amount=_get_int(data, "pool_base_amount"),
1452
+ pool_quote_amount=_get_int(data, "pool_quote_amount"),
1453
+ minimum_liquidity=_get_int(data, "minimum_liquidity"),
1454
+ initial_liquidity=_get_int(data, "initial_liquidity"),
1455
+ lp_token_amount_out=_get_int(data, "lp_token_amount_out"),
1456
+ pool_bump=_get_int(data, "pool_bump"),
1457
+ pool=_get_str(data, "pool"),
1458
+ lp_mint=_get_str(data, "lp_mint"),
1459
+ user_base_token_account=_get_str(data, "user_base_token_account"),
1460
+ user_quote_token_account=_get_str(data, "user_quote_token_account"),
1461
+ coin_creator=_get_str(data, "coin_creator"),
1462
+ is_mayhem_mode=_get_bool(data, "is_mayhem_mode"),
1463
+ )
1464
+
1465
+ if event_type == EventType.PUMP_SWAP_LIQUIDITY_ADDED:
1466
+ return PumpSwapLiquidityAddedEvent(
1467
+ metadata=meta,
1468
+ timestamp=_get_int(data, "timestamp"),
1469
+ lp_token_amount_out=_get_int(data, "lp_token_amount_out"),
1470
+ max_base_amount_in=_get_int(data, "max_base_amount_in"),
1471
+ max_quote_amount_in=_get_int(data, "max_quote_amount_in"),
1472
+ user_base_token_reserves=_get_int(data, "user_base_token_reserves"),
1473
+ user_quote_token_reserves=_get_int(data, "user_quote_token_reserves"),
1474
+ pool_base_token_reserves=_get_int(data, "pool_base_token_reserves"),
1475
+ pool_quote_token_reserves=_get_int(data, "pool_quote_token_reserves"),
1476
+ base_amount_in=_get_int(data, "base_amount_in"),
1477
+ quote_amount_in=_get_int(data, "quote_amount_in"),
1478
+ lp_mint_supply=_get_int(data, "lp_mint_supply"),
1479
+ pool=_get_str(data, "pool"),
1480
+ user=_get_str(data, "user"),
1481
+ user_base_token_account=_get_str(data, "user_base_token_account"),
1482
+ user_quote_token_account=_get_str(data, "user_quote_token_account"),
1483
+ user_pool_token_account=_get_str(data, "user_pool_token_account"),
1484
+ )
1485
+
1486
+ if event_type == EventType.PUMP_SWAP_LIQUIDITY_REMOVED:
1487
+ return PumpSwapLiquidityRemovedEvent(
1488
+ metadata=meta,
1489
+ timestamp=_get_int(data, "timestamp"),
1490
+ lp_token_amount_in=_get_int(data, "lp_token_amount_in"),
1491
+ min_base_amount_out=_get_int(data, "min_base_amount_out"),
1492
+ min_quote_amount_out=_get_int(data, "min_quote_amount_out"),
1493
+ user_base_token_reserves=_get_int(data, "user_base_token_reserves"),
1494
+ user_quote_token_reserves=_get_int(data, "user_quote_token_reserves"),
1495
+ pool_base_token_reserves=_get_int(data, "pool_base_token_reserves"),
1496
+ pool_quote_token_reserves=_get_int(data, "pool_quote_token_reserves"),
1497
+ base_amount_out=_get_int(data, "base_amount_out"),
1498
+ quote_amount_out=_get_int(data, "quote_amount_out"),
1499
+ lp_mint_supply=_get_int(data, "lp_mint_supply"),
1500
+ pool=_get_str(data, "pool"),
1501
+ user=_get_str(data, "user"),
1502
+ user_base_token_account=_get_str(data, "user_base_token_account"),
1503
+ user_quote_token_account=_get_str(data, "user_quote_token_account"),
1504
+ user_pool_token_account=_get_str(data, "user_pool_token_account"),
1505
+ )
1506
+
1507
+ # Meteora DAMM v2 / Raydium / Orca — 指令级占位(与 instructions.py 一致)
1508
+ if event_type == EventType.METEORA_DAMM_V2_SWAP:
1509
+ return MeteoraDammV2SwapEvent(metadata=meta, pool=_get_str(data, "pool"))
1510
+ if event_type == EventType.METEORA_DAMM_V2_ADD_LIQUIDITY:
1511
+ return MeteoraDammV2AddLiquidityEvent(metadata=meta, pool=_get_str(data, "pool"))
1512
+ if event_type == EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY:
1513
+ return MeteoraDammV2RemoveLiquidityEvent(metadata=meta, pool=_get_str(data, "pool"))
1514
+ if event_type == EventType.METEORA_DAMM_V2_CREATE_POSITION:
1515
+ return MeteoraDammV2CreatePositionEvent(metadata=meta, pool=_get_str(data, "pool"))
1516
+ if event_type == EventType.METEORA_DAMM_V2_CLOSE_POSITION:
1517
+ return MeteoraDammV2ClosePositionEvent(metadata=meta, pool=_get_str(data, "pool"))
1518
+ if event_type == EventType.METEORA_DAMM_V2_INITIALIZE_POOL:
1519
+ return MeteoraDammV2InitializePoolEvent(metadata=meta, pool=_get_str(data, "pool"))
1520
+
1521
+ if event_type == EventType.RAYDIUM_CLMM_SWAP:
1522
+ return RaydiumClmmSwapEvent(
1523
+ metadata=meta,
1524
+ pool_state=_get_str(data, "pool_state"),
1525
+ sender=_get_str(data, "sender"),
1526
+ token_account_0=_get_str(data, "token_account_0"),
1527
+ token_account_1=_get_str(data, "token_account_1"),
1528
+ amount_0=_get_int(data, "amount_0"),
1529
+ amount_1=_get_int(data, "amount_1"),
1530
+ zero_for_one=_get_bool(data, "zero_for_one"),
1531
+ sqrt_price_x64=_get_str(data, "sqrt_price_x64"),
1532
+ liquidity=_get_str(data, "liquidity"),
1533
+ transfer_fee_0=_get_int(data, "transfer_fee_0"),
1534
+ transfer_fee_1=_get_int(data, "transfer_fee_1"),
1535
+ tick=_get_int(data, "tick"),
1536
+ )
1537
+ if event_type == EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY:
1538
+ return RaydiumClmmIncreaseLiquidityEvent(
1539
+ metadata=meta,
1540
+ pool=_get_str(data, "pool"),
1541
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1542
+ user=_get_str(data, "user"),
1543
+ liquidity=_get_str(data, "liquidity"),
1544
+ amount0_max=_get_int(data, "amount0_max"),
1545
+ amount1_max=_get_int(data, "amount1_max"),
1546
+ )
1547
+ if event_type == EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY:
1548
+ return RaydiumClmmDecreaseLiquidityEvent(
1549
+ metadata=meta,
1550
+ pool=_get_str(data, "pool"),
1551
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1552
+ user=_get_str(data, "user"),
1553
+ liquidity=_get_str(data, "liquidity"),
1554
+ amount0_min=_get_int(data, "amount0_min"),
1555
+ amount1_min=_get_int(data, "amount1_min"),
1556
+ )
1557
+ if event_type == EventType.RAYDIUM_CLMM_CREATE_POOL:
1558
+ return RaydiumClmmCreatePoolEvent(
1559
+ metadata=meta,
1560
+ pool=_get_str(data, "pool"),
1561
+ creator=_get_str(data, "creator"),
1562
+ token_0_mint=_get_str(data, "token_0_mint"),
1563
+ token_1_mint=_get_str(data, "token_1_mint"),
1564
+ tick_spacing=_get_int(data, "tick_spacing"),
1565
+ fee_rate=_get_int(data, "fee_rate"),
1566
+ sqrt_price_x64=_get_str(data, "sqrt_price_x64"),
1567
+ open_time=_get_int(data, "open_time"),
1568
+ )
1569
+ if event_type == EventType.RAYDIUM_CLMM_OPEN_POSITION:
1570
+ return RaydiumClmmOpenPositionEvent(
1571
+ metadata=meta,
1572
+ pool=_get_str(data, "pool"),
1573
+ user=_get_str(data, "user"),
1574
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1575
+ tick_lower_index=_get_int(data, "tick_lower_index"),
1576
+ tick_upper_index=_get_int(data, "tick_upper_index"),
1577
+ liquidity=_get_str(data, "liquidity"),
1578
+ )
1579
+ if event_type == EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT:
1580
+ return RaydiumClmmOpenPositionWithTokenExtNftEvent(
1581
+ metadata=meta,
1582
+ pool=_get_str(data, "pool"),
1583
+ user=_get_str(data, "user"),
1584
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1585
+ tick_lower_index=_get_int(data, "tick_lower_index"),
1586
+ tick_upper_index=_get_int(data, "tick_upper_index"),
1587
+ liquidity=_get_str(data, "liquidity"),
1588
+ )
1589
+ if event_type == EventType.RAYDIUM_CLMM_CLOSE_POSITION:
1590
+ return RaydiumClmmClosePositionEvent(
1591
+ metadata=meta,
1592
+ pool=_get_str(data, "pool"),
1593
+ user=_get_str(data, "user"),
1594
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1595
+ )
1596
+ if event_type == EventType.RAYDIUM_CLMM_COLLECT_FEE:
1597
+ return RaydiumClmmCollectFeeEvent(
1598
+ metadata=meta,
1599
+ pool_state=_get_str(data, "pool_state"),
1600
+ position_nft_mint=_get_str(data, "position_nft_mint"),
1601
+ amount_0=_get_int(data, "amount_0"),
1602
+ amount_1=_get_int(data, "amount_1"),
1603
+ )
1604
+
1605
+ if event_type == EventType.RAYDIUM_CPMM_SWAP:
1606
+ return RaydiumCpmmSwapEvent(
1607
+ metadata=meta,
1608
+ pool_id=_get_str(data, "pool_id"),
1609
+ input_amount=_get_int(data, "input_amount"),
1610
+ output_amount=_get_int(data, "output_amount"),
1611
+ input_vault_before=_get_int(data, "input_vault_before"),
1612
+ output_vault_before=_get_int(data, "output_vault_before"),
1613
+ input_transfer_fee=_get_int(data, "input_transfer_fee"),
1614
+ output_transfer_fee=_get_int(data, "output_transfer_fee"),
1615
+ base_input=_get_bool(data, "base_input"),
1616
+ )
1617
+ if event_type == EventType.RAYDIUM_CPMM_DEPOSIT:
1618
+ return RaydiumCpmmDepositEvent(
1619
+ metadata=meta,
1620
+ pool=_get_str(data, "pool"),
1621
+ user=_get_str(data, "user"),
1622
+ lp_token_amount=_get_int(data, "lp_token_amount"),
1623
+ token0_amount=_get_int(data, "token0_amount"),
1624
+ token1_amount=_get_int(data, "token1_amount"),
1625
+ )
1626
+ if event_type == EventType.RAYDIUM_CPMM_WITHDRAW:
1627
+ return RaydiumCpmmWithdrawEvent(
1628
+ metadata=meta,
1629
+ pool=_get_str(data, "pool"),
1630
+ user=_get_str(data, "user"),
1631
+ lp_token_amount=_get_int(data, "lp_token_amount"),
1632
+ token0_amount=_get_int(data, "token0_amount"),
1633
+ token1_amount=_get_int(data, "token1_amount"),
1634
+ )
1635
+
1636
+ if event_type == EventType.RAYDIUM_AMM_V4_SWAP:
1637
+ return RaydiumAmmV4SwapEvent(
1638
+ metadata=meta,
1639
+ amm=_get_str(data, "amm"),
1640
+ user_source_owner=_get_str(data, "user_source_owner"),
1641
+ amount_in=_get_int(data, "amount_in"),
1642
+ minimum_amount_out=_get_int(data, "minimum_amount_out"),
1643
+ max_amount_in=_get_int(data, "max_amount_in"),
1644
+ amount_out=_get_int(data, "amount_out"),
1645
+ token_program=_get_str(data, "token_program"),
1646
+ amm_authority=_get_str(data, "amm_authority"),
1647
+ amm_open_orders=_get_str(data, "amm_open_orders"),
1648
+ pool_coin_token_account=_get_str(data, "pool_coin_token_account"),
1649
+ pool_pc_token_account=_get_str(data, "pool_pc_token_account"),
1650
+ serum_program=_get_str(data, "serum_program"),
1651
+ serum_market=_get_str(data, "serum_market"),
1652
+ serum_bids=_get_str(data, "serum_bids"),
1653
+ serum_asks=_get_str(data, "serum_asks"),
1654
+ serum_event_queue=_get_str(data, "serum_event_queue"),
1655
+ serum_coin_vault_account=_get_str(data, "serum_coin_vault_account"),
1656
+ serum_pc_vault_account=_get_str(data, "serum_pc_vault_account"),
1657
+ serum_vault_signer=_get_str(data, "serum_vault_signer"),
1658
+ user_source_token_account=_get_str(data, "user_source_token_account"),
1659
+ user_destination_token_account=_get_str(data, "user_destination_token_account"),
1660
+ )
1661
+
1662
+ if event_type == EventType.ORCA_WHIRLPOOL_SWAP:
1663
+ return OrcaWhirlpoolSwapEvent(
1664
+ metadata=meta,
1665
+ whirlpool=_get_str(data, "whirlpool"),
1666
+ a_to_b=_get_bool(data, "a_to_b"),
1667
+ pre_sqrt_price=_get_str(data, "pre_sqrt_price"),
1668
+ post_sqrt_price=_get_str(data, "post_sqrt_price"),
1669
+ input_amount=_get_int(data, "input_amount"),
1670
+ output_amount=_get_int(data, "output_amount"),
1671
+ input_transfer_fee=_get_int(data, "input_transfer_fee"),
1672
+ output_transfer_fee=_get_int(data, "output_transfer_fee"),
1673
+ lp_fee=_get_int(data, "lp_fee"),
1674
+ protocol_fee=_get_int(data, "protocol_fee"),
1675
+ )
1676
+ if event_type == EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED:
1677
+ return OrcaWhirlpoolLiquidityIncreasedEvent(
1678
+ metadata=meta,
1679
+ whirlpool=_get_str(data, "whirlpool"),
1680
+ position=_get_str(data, "position"),
1681
+ tick_lower_index=_get_int(data, "tick_lower_index"),
1682
+ tick_upper_index=_get_int(data, "tick_upper_index"),
1683
+ liquidity=_get_str(data, "liquidity"),
1684
+ token_a_amount=_get_int(data, "token_a_amount"),
1685
+ token_b_amount=_get_int(data, "token_b_amount"),
1686
+ token_a_transfer_fee=_get_int(data, "token_a_transfer_fee"),
1687
+ token_b_transfer_fee=_get_int(data, "token_b_transfer_fee"),
1688
+ )
1689
+ if event_type == EventType.ORCA_WHIRLPOOL_LIQUIDITY_DECREASED:
1690
+ return OrcaWhirlpoolLiquidityDecreasedEvent(
1691
+ metadata=meta,
1692
+ whirlpool=_get_str(data, "whirlpool"),
1693
+ position=_get_str(data, "position"),
1694
+ tick_lower_index=_get_int(data, "tick_lower_index"),
1695
+ tick_upper_index=_get_int(data, "tick_upper_index"),
1696
+ liquidity=_get_str(data, "liquidity"),
1697
+ token_a_amount=_get_int(data, "token_a_amount"),
1698
+ token_b_amount=_get_int(data, "token_b_amount"),
1699
+ token_a_transfer_fee=_get_int(data, "token_a_transfer_fee"),
1700
+ token_b_transfer_fee=_get_int(data, "token_b_transfer_fee"),
1701
+ )
1702
+
1703
+ # Bonk events
1704
+ if event_type == EventType.BONK_TRADE:
1705
+ return BonkTradeEvent(
1706
+ metadata=meta,
1707
+ pool_state=_get_str(data, "pool_state"),
1708
+ user=_get_str(data, "user"),
1709
+ amount_in=_get_int(data, "amount_in"),
1710
+ amount_out=_get_int(data, "amount_out"),
1711
+ is_buy=_get_bool(data, "is_buy"),
1712
+ trade_direction=_get_str(data, "trade_direction"),
1713
+ exact_in=_get_bool(data, "exact_in"),
1714
+ )
1715
+
1716
+ if event_type == EventType.BONK_POOL_CREATE:
1717
+ return BonkPoolCreateEvent(
1718
+ metadata=meta,
1719
+ pool_state=_get_str(data, "pool_state"),
1720
+ creator=_get_str(data, "creator"),
1721
+ base_mint_param=_get_dict_any(data, "base_mint_param"),
1722
+ )
1723
+
1724
+ if event_type == EventType.BONK_MIGRATE_AMM:
1725
+ return BonkMigrateAmmEvent(
1726
+ metadata=meta,
1727
+ old_pool=_get_str(data, "old_pool"),
1728
+ new_pool=_get_str(data, "new_pool"),
1729
+ user=_get_str(data, "user"),
1730
+ liquidity_amount=_get_int(data, "liquidity_amount"),
1731
+ )
1732
+
1733
+ # Add more event type conversions as needed...
1734
+
1735
+ return None
1736
+
1737
+
1738
+ def legacy_dict_to_dex_event(d: dict) -> Optional[DexEvent]:
1739
+ """将单键 legacy dict ``{ EventType.value: payload }`` 转为 :class:`DexEvent`(供指令解析等路径)。"""
1740
+ if not d:
1741
+ return None
1742
+ typed = to_typed_event(d)
1743
+ if typed is None:
1744
+ return None
1745
+ key = next(iter(d))
1746
+ try:
1747
+ et = EventType(key)
1748
+ except ValueError:
1749
+ return None
1750
+ return DexEvent(type=et, data=typed)