sol-parser-sdk-python 0.5.6__py3-none-any.whl → 0.5.8__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.
sol_parser/grpc_client.py CHANGED
@@ -449,6 +449,7 @@ class YellowstoneGrpc:
449
449
  signature = base58.b58encode(bytes(info.signature)).decode("ascii") if info.signature else ""
450
450
 
451
451
  from .grpc_instruction_parser import (
452
+ detect_pumpfun_create_from_logs,
452
453
  enrich_dex_events_with_subscribe_tx_info,
453
454
  parse_instructions_enhanced_from_subscribe_tx_info,
454
455
  )
@@ -466,7 +467,7 @@ class YellowstoneGrpc:
466
467
  )
467
468
 
468
469
  log_events = []
469
- is_created_buy = False
470
+ has_pumpfun_create_log = detect_pumpfun_create_from_logs(list(info.log_messages))
470
471
  active_program_stack = []
471
472
  for log in info.log_messages:
472
473
  invoke = parse_invoke_info(log)
@@ -483,7 +484,7 @@ class YellowstoneGrpc:
483
484
  block_time_us,
484
485
  grpc_recv_us,
485
486
  event_type_filter,
486
- is_created_buy,
487
+ has_pumpfun_create_log,
487
488
  "",
488
489
  active_program_stack[-1] if active_program_stack else None,
489
490
  )
@@ -495,8 +496,6 @@ class YellowstoneGrpc:
495
496
  del active_program_stack[i:]
496
497
  break
497
498
  continue
498
- if ev.type in (EventType.PUMP_FUN_CREATE, EventType.PUMP_FUN_CREATE_V2):
499
- is_created_buy = True
500
499
  log_events.append(ev)
501
500
  completed = parse_program_complete_info(log)
502
501
  if completed is not None:
@@ -7,17 +7,18 @@ from typing import Any, Dict, List, Optional, Tuple
7
7
 
8
8
  import base58
9
9
 
10
- from .account_dispatcher import fill_accounts_with_owned_keys, fill_data
10
+ from .account_dispatcher import fill_accounts_with_owned_keys, fill_data, fill_token_balances
11
11
  from .event_types import DexEvent
12
12
  from .grpc_types import (
13
13
  EventMetadata,
14
+ EventType,
14
15
  EventTypeFilter,
15
16
  SubscribeUpdateTransactionInfo,
16
17
  event_type_filter_allows_instruction_parsing,
17
18
  )
18
19
  from .inner_instruction_parser import parse_inner_instruction
19
- from .instructions import parse_instruction_unified
20
- from .merger import merge_dex_events
20
+ from .instructions import parse_inner_compiled_instruction_if_supported, parse_instruction_unified
21
+ from .merger import try_merge_dex_events
21
22
  from .pumpfun_fee_enrich import enrich_pumpfun_same_tx_post_merge
22
23
 
23
24
 
@@ -73,6 +74,7 @@ def apply_account_fill_to_events(
73
74
  for ev in events:
74
75
  fill_accounts_with_owned_keys(ev, meta_pb, tx_pb, invokes_raw)
75
76
  fill_data(ev, meta_pb, tx_pb, invokes_str)
77
+ fill_token_balances(ev, meta_pb, tx_pb)
76
78
  recent_bh = ""
77
79
  if msg.recent_blockhash:
78
80
  recent_bh = base58.b58encode(bytes(msg.recent_blockhash)).decode("ascii")
@@ -124,36 +126,86 @@ def should_parse_instructions(filter: Optional[EventTypeFilter]) -> bool:
124
126
  return event_type_filter_allows_instruction_parsing(list(inc))
125
127
 
126
128
 
127
- def merge_instruction_events(
128
- events: List[Tuple[int, Optional[int], DexEvent]],
129
- ) -> List[DexEvent]:
129
+ _DLMM_EVENT_TYPES = {
130
+ EventType.METEORA_DLMM_SWAP,
131
+ EventType.METEORA_DLMM_ADD_LIQUIDITY,
132
+ EventType.METEORA_DLMM_REMOVE_LIQUIDITY,
133
+ EventType.METEORA_DLMM_INITIALIZE_POOL,
134
+ EventType.METEORA_DLMM_INITIALIZE_BIN_ARRAY,
135
+ EventType.METEORA_DLMM_CREATE_POSITION,
136
+ EventType.METEORA_DLMM_CLOSE_POSITION,
137
+ EventType.METEORA_DLMM_CLAIM_FEE,
138
+ }
139
+
140
+
141
+ def _is_dlmm_event_cpi(data: bytes) -> bool:
142
+ return len(data) >= 16 and (
143
+ data[:8] == bytes((228, 69, 165, 46, 81, 203, 154, 29))
144
+ or data[8:16] == bytes((155, 167, 108, 32, 122, 76, 173, 64))
145
+ )
146
+
147
+
148
+ def merge_instruction_events(events: List[Tuple[Any, ...]]) -> List[DexEvent]:
130
149
  """对齐 Rust ``merge_instruction_events``。"""
131
150
  if not events:
132
151
  return []
133
- events = sorted(events, key=lambda x: (x[0], 0 if x[1] is None else 1 + x[1]))
152
+ normalized = events if all(len(item) == 5 for item in events) else [
153
+ (item[0], item[1], None, False, item[2]) if len(item) == 3 else item
154
+ for item in events
155
+ ]
156
+ normalized.sort(key=lambda x: (x[0], 0 if x[1] is None else 1 + x[1]))
134
157
  result: List[DexEvent] = []
135
- pending_outer: Optional[Tuple[int, DexEvent]] = None
158
+ outer_target: Optional[Tuple[int, int]] = None
159
+ dlmm_targets: List[Tuple[int, Optional[int], int]] = []
136
160
 
137
- for outer_idx, inner_idx, event in events:
161
+ for outer_idx, inner_idx, stack_height, is_dlmm_event_cpi, event in normalized:
138
162
  if inner_idx is None:
139
- if pending_outer is not None:
140
- result.append(pending_outer[1])
141
- pending_outer = (outer_idx, event)
142
- else:
143
- if pending_outer is not None:
144
- po_idx, mut_outer = pending_outer
145
- pending_outer = None
146
- if po_idx == outer_idx:
147
- merge_dex_events(mut_outer, event)
148
- result.append(mut_outer)
149
- else:
150
- result.append(mut_outer)
151
- result.append(event)
163
+ result.append(event)
164
+ target_idx = len(result) - 1
165
+ outer_target = (outer_idx, target_idx)
166
+ dlmm_targets = (
167
+ [(outer_idx, stack_height, target_idx)] if event.type in _DLMM_EVENT_TYPES else []
168
+ )
169
+ continue
170
+
171
+ if is_dlmm_event_cpi:
172
+ for candidate_idx in range(len(dlmm_targets) - 1, -1, -1):
173
+ target_outer, target_height, target_idx = dlmm_targets[candidate_idx]
174
+ direct_child = (
175
+ target_height is None
176
+ or stack_height is None
177
+ or stack_height == target_height + 1
178
+ )
179
+ if target_outer == outer_idx and direct_child:
180
+ del dlmm_targets[candidate_idx + 1:]
181
+ if try_merge_dex_events(result[target_idx], event):
182
+ break
152
183
  else:
153
184
  result.append(event)
185
+ continue
186
+
187
+ target_idx: Optional[int] = None
188
+ if outer_target is not None and outer_target[0] == outer_idx:
189
+ if try_merge_dex_events(result[outer_target[1]], event):
190
+ target_idx = outer_target[1]
191
+ if target_idx is None:
192
+ result.append(event)
193
+ target_idx = len(result) - 1
194
+
195
+ if event.type in _DLMM_EVENT_TYPES:
196
+ if stack_height is None:
197
+ dlmm_targets.clear()
198
+ else:
199
+ while dlmm_targets and (
200
+ dlmm_targets[-1][0] != outer_idx
201
+ or (
202
+ dlmm_targets[-1][1] is not None
203
+ and dlmm_targets[-1][1] >= stack_height
204
+ )
205
+ ):
206
+ dlmm_targets.pop()
207
+ dlmm_targets.append((outer_idx, stack_height, target_idx))
154
208
 
155
- if pending_outer is not None:
156
- result.append(pending_outer[1])
157
209
  return result
158
210
 
159
211
 
@@ -260,7 +312,7 @@ def parse_instructions_enhanced_from_parsed(
260
312
 
261
313
  is_created_buy = detect_pumpfun_create_from_logs(list(meta.log_messages))
262
314
 
263
- result: List[Tuple[int, Optional[int], DexEvent]] = []
315
+ result: List[Tuple[Any, ...]] = []
264
316
 
265
317
  for i, ix in enumerate(msg.instructions):
266
318
  pid_idx = ix.program_id_index
@@ -272,14 +324,25 @@ def parse_instructions_enhanced_from_parsed(
272
324
  data, accounts, signature, slot, tx_index, block_time_us, grpc_us, filter, pid
273
325
  )
274
326
  if ev:
275
- result.append((i, None, ev))
327
+ result.append((i, None, 1, False, ev))
276
328
 
277
329
  for inner in meta.inner_instructions:
278
330
  outer_idx = inner.index
279
331
  for j, inner_ix in enumerate(inner.instructions):
280
332
  pid = get_key_b58(inner_ix.program_id_index)
281
333
  data = bytes(inner_ix.data)
282
- ev = parse_inner_instruction(
334
+ accounts = [get_key_b58(b) for b in bytes(inner_ix.accounts)]
335
+ ev = parse_inner_compiled_instruction_if_supported(
336
+ data,
337
+ accounts,
338
+ signature,
339
+ slot,
340
+ tx_index,
341
+ block_time_us,
342
+ grpc_us,
343
+ filter,
344
+ pid,
345
+ ) or parse_inner_instruction(
283
346
  data,
284
347
  pid,
285
348
  _meta_dict(signature, slot, tx_index, block_time_us, grpc_us, recent_bh),
@@ -287,7 +350,13 @@ def parse_instructions_enhanced_from_parsed(
287
350
  is_created_buy,
288
351
  )
289
352
  if ev:
290
- result.append((int(outer_idx), j, ev))
353
+ result.append((
354
+ int(outer_idx),
355
+ j,
356
+ int(inner_ix.stack_height) if inner_ix.HasField("stack_height") else None,
357
+ pid == METEORA_DLMM_PROGRAM_ID and _is_dlmm_event_cpi(data),
358
+ ev,
359
+ ))
291
360
 
292
361
  merged = merge_instruction_events(result)
293
362
  enrich_pumpfun_same_tx_post_merge(merged)
@@ -299,6 +368,7 @@ def parse_instructions_enhanced_from_parsed(
299
368
  for ev in merged:
300
369
  fill_accounts_with_owned_keys(ev, meta, transaction_pb, invokes_raw)
301
370
  fill_data(ev, meta, transaction_pb, invokes_str)
371
+ fill_token_balances(ev, meta, transaction_pb)
302
372
 
303
373
  for ev in merged:
304
374
  if isinstance(ev.data, object) and hasattr(ev.data, "metadata"):
sol_parser/grpc_types.py CHANGED
@@ -37,10 +37,11 @@ class EventType(str, Enum):
37
37
  """事件类型"""
38
38
  # Block
39
39
  BLOCK_META = "BlockMeta"
40
- # PumpFun
40
+ # RaydiumLaunchlab
41
41
  RAYDIUM_LAUNCHLAB_TRADE = "RaydiumLaunchlabTrade"
42
42
  RAYDIUM_LAUNCHLAB_POOL_CREATE = "RaydiumLaunchlabPoolCreate"
43
43
  RAYDIUM_LAUNCHLAB_MIGRATE_AMM = "RaydiumLaunchlabMigrateAmm"
44
+ # PumpFun
44
45
  PUMP_FUN_TRADE = "PumpFunTrade"
45
46
  PUMP_FUN_BUY = "PumpFunBuy"
46
47
  PUMP_FUN_SELL = "PumpFunSell"
@@ -66,26 +67,35 @@ class EventType(str, Enum):
66
67
  PUMP_SWAP_CREATE_POOL = "PumpSwapCreatePool"
67
68
  PUMP_SWAP_LIQUIDITY_ADDED = "PumpSwapLiquidityAdded"
68
69
  PUMP_SWAP_LIQUIDITY_REMOVED = "PumpSwapLiquidityRemoved"
70
+ # Raydium CPMM
71
+ RAYDIUM_CPMM_SWAP = "RaydiumCpmmSwap"
72
+ RAYDIUM_CPMM_DEPOSIT = "RaydiumCpmmDeposit"
73
+ RAYDIUM_CPMM_WITHDRAW = "RaydiumCpmmWithdraw"
74
+ RAYDIUM_CPMM_INITIALIZE = "RaydiumCpmmInitialize"
69
75
  # Raydium CLMM
70
76
  RAYDIUM_CLMM_SWAP = "RaydiumClmmSwap"
71
- RAYDIUM_CLMM_INCREASE_LIQUIDITY = "RaydiumClmmIncreaseLiquidity"
72
- RAYDIUM_CLMM_DECREASE_LIQUIDITY = "RaydiumClmmDecreaseLiquidity"
73
77
  RAYDIUM_CLMM_CREATE_POOL = "RaydiumClmmCreatePool"
74
78
  RAYDIUM_CLMM_OPEN_POSITION = "RaydiumClmmOpenPosition"
75
- RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT = "RaydiumClmmOpenPositionWithTokenExtNft"
76
79
  RAYDIUM_CLMM_CLOSE_POSITION = "RaydiumClmmClosePosition"
80
+ RAYDIUM_CLMM_INCREASE_LIQUIDITY = "RaydiumClmmIncreaseLiquidity"
81
+ RAYDIUM_CLMM_DECREASE_LIQUIDITY = "RaydiumClmmDecreaseLiquidity"
82
+ RAYDIUM_CLMM_LIQUIDITY_CHANGE = "RaydiumClmmLiquidityChange"
83
+ RAYDIUM_CLMM_CONFIG_CHANGE = "RaydiumClmmConfigChange"
84
+ RAYDIUM_CLMM_CREATE_PERSONAL_POSITION = "RaydiumClmmCreatePersonalPosition"
85
+ RAYDIUM_CLMM_LIQUIDITY_CALCULATE = "RaydiumClmmLiquidityCalculate"
86
+ RAYDIUM_CLMM_OPEN_LIMIT_ORDER = "RaydiumClmmOpenLimitOrder"
87
+ RAYDIUM_CLMM_INCREASE_LIMIT_ORDER = "RaydiumClmmIncreaseLimitOrder"
88
+ RAYDIUM_CLMM_DECREASE_LIMIT_ORDER = "RaydiumClmmDecreaseLimitOrder"
89
+ RAYDIUM_CLMM_SETTLE_LIMIT_ORDER = "RaydiumClmmSettleLimitOrder"
90
+ RAYDIUM_CLMM_UPDATE_REWARD_INFOS = "RaydiumClmmUpdateRewardInfos"
91
+ RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT = "RaydiumClmmOpenPositionWithTokenExtNft"
77
92
  RAYDIUM_CLMM_COLLECT_FEE = "RaydiumClmmCollectFee"
78
- # Raydium CPMM
79
- RAYDIUM_CPMM_SWAP = "RaydiumCpmmSwap"
80
- RAYDIUM_CPMM_DEPOSIT = "RaydiumCpmmDeposit"
81
- RAYDIUM_CPMM_WITHDRAW = "RaydiumCpmmWithdraw"
82
- RAYDIUM_CPMM_INITIALIZE = "RaydiumCpmmInitialize"
83
93
  # Raydium AMM V4
84
94
  RAYDIUM_AMM_V4_SWAP = "RaydiumAmmV4Swap"
85
95
  RAYDIUM_AMM_V4_DEPOSIT = "RaydiumAmmV4Deposit"
86
96
  RAYDIUM_AMM_V4_WITHDRAW = "RaydiumAmmV4Withdraw"
87
- RAYDIUM_AMM_V4_WITHDRAW_PNL = "RaydiumAmmV4WithdrawPnl"
88
97
  RAYDIUM_AMM_V4_INITIALIZE2 = "RaydiumAmmV4Initialize2"
98
+ RAYDIUM_AMM_V4_WITHDRAW_PNL = "RaydiumAmmV4WithdrawPnl"
89
99
  # Orca Whirlpool
90
100
  ORCA_WHIRLPOOL_SWAP = "OrcaWhirlpoolSwap"
91
101
  ORCA_WHIRLPOOL_LIQUIDITY_INCREASED = "OrcaWhirlpoolLiquidityIncreased"
@@ -102,9 +112,13 @@ class EventType(str, Enum):
102
112
  METEORA_DAMM_V2_SWAP = "MeteoraDammV2Swap"
103
113
  METEORA_DAMM_V2_ADD_LIQUIDITY = "MeteoraDammV2AddLiquidity"
104
114
  METEORA_DAMM_V2_REMOVE_LIQUIDITY = "MeteoraDammV2RemoveLiquidity"
115
+ METEORA_DAMM_V2_INITIALIZE_POOL = "MeteoraDammV2InitializePool"
105
116
  METEORA_DAMM_V2_CREATE_POSITION = "MeteoraDammV2CreatePosition"
106
117
  METEORA_DAMM_V2_CLOSE_POSITION = "MeteoraDammV2ClosePosition"
107
- METEORA_DAMM_V2_INITIALIZE_POOL = "MeteoraDammV2InitializePool"
118
+ METEORA_DAMM_V2_UPDATE_DELEGATE_PERMISSION = "MeteoraDammV2UpdateDelegatePermission"
119
+ METEORA_DAMM_V2_WITHDRAW_DEAD_LIQUIDITY_REWARD = "MeteoraDammV2WithdrawDeadLiquidityReward"
120
+ METEORA_DAMM_V2_CREATE_CONFIG = "MeteoraDammV2CreateConfig"
121
+ METEORA_DAMM_V2_CREATE_DYNAMIC_CONFIG = "MeteoraDammV2CreateDynamicConfig"
108
122
  # Meteora DBC
109
123
  METEORA_DBC_SWAP = "MeteoraDbcSwap"
110
124
  METEORA_DBC_INITIALIZE_POOL = "MeteoraDbcInitializePool"
@@ -196,6 +210,10 @@ METEORA_DAMM_V2_FILTER_TYPES = (
196
210
  EventType.METEORA_DAMM_V2_CLOSE_POSITION,
197
211
  EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
198
212
  EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
213
+ EventType.METEORA_DAMM_V2_UPDATE_DELEGATE_PERMISSION,
214
+ EventType.METEORA_DAMM_V2_WITHDRAW_DEAD_LIQUIDITY_REWARD,
215
+ EventType.METEORA_DAMM_V2_CREATE_CONFIG,
216
+ EventType.METEORA_DAMM_V2_CREATE_DYNAMIC_CONFIG,
199
217
  )
200
218
  METEORA_DBC_FILTER_TYPES = (
201
219
  EventType.METEORA_DBC_SWAP,
@@ -206,6 +224,15 @@ RAYDIUM_CLMM_FILTER_TYPES = (
206
224
  EventType.RAYDIUM_CLMM_SWAP,
207
225
  EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
208
226
  EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
227
+ EventType.RAYDIUM_CLMM_LIQUIDITY_CHANGE,
228
+ EventType.RAYDIUM_CLMM_CONFIG_CHANGE,
229
+ EventType.RAYDIUM_CLMM_CREATE_PERSONAL_POSITION,
230
+ EventType.RAYDIUM_CLMM_LIQUIDITY_CALCULATE,
231
+ EventType.RAYDIUM_CLMM_OPEN_LIMIT_ORDER,
232
+ EventType.RAYDIUM_CLMM_INCREASE_LIMIT_ORDER,
233
+ EventType.RAYDIUM_CLMM_DECREASE_LIMIT_ORDER,
234
+ EventType.RAYDIUM_CLMM_SETTLE_LIMIT_ORDER,
235
+ EventType.RAYDIUM_CLMM_UPDATE_REWARD_INFOS,
209
236
  EventType.RAYDIUM_CLMM_CREATE_POOL,
210
237
  EventType.RAYDIUM_CLMM_OPEN_POSITION,
211
238
  EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT,
@@ -305,26 +332,35 @@ def all_event_types() -> List[EventType]:
305
332
  EventType.PUMP_SWAP_CREATE_POOL,
306
333
  EventType.PUMP_SWAP_LIQUIDITY_ADDED,
307
334
  EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
335
+ # Raydium CPMM
336
+ EventType.RAYDIUM_CPMM_SWAP,
337
+ EventType.RAYDIUM_CPMM_DEPOSIT,
338
+ EventType.RAYDIUM_CPMM_WITHDRAW,
339
+ EventType.RAYDIUM_CPMM_INITIALIZE,
308
340
  # Raydium CLMM
309
341
  EventType.RAYDIUM_CLMM_SWAP,
310
- EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
311
- EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
312
342
  EventType.RAYDIUM_CLMM_CREATE_POOL,
313
343
  EventType.RAYDIUM_CLMM_OPEN_POSITION,
314
- EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT,
315
344
  EventType.RAYDIUM_CLMM_CLOSE_POSITION,
345
+ EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
346
+ EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
347
+ EventType.RAYDIUM_CLMM_LIQUIDITY_CHANGE,
348
+ EventType.RAYDIUM_CLMM_CONFIG_CHANGE,
349
+ EventType.RAYDIUM_CLMM_CREATE_PERSONAL_POSITION,
350
+ EventType.RAYDIUM_CLMM_LIQUIDITY_CALCULATE,
351
+ EventType.RAYDIUM_CLMM_OPEN_LIMIT_ORDER,
352
+ EventType.RAYDIUM_CLMM_INCREASE_LIMIT_ORDER,
353
+ EventType.RAYDIUM_CLMM_DECREASE_LIMIT_ORDER,
354
+ EventType.RAYDIUM_CLMM_SETTLE_LIMIT_ORDER,
355
+ EventType.RAYDIUM_CLMM_UPDATE_REWARD_INFOS,
356
+ EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT,
316
357
  EventType.RAYDIUM_CLMM_COLLECT_FEE,
317
- # Raydium CPMM
318
- EventType.RAYDIUM_CPMM_SWAP,
319
- EventType.RAYDIUM_CPMM_DEPOSIT,
320
- EventType.RAYDIUM_CPMM_WITHDRAW,
321
- EventType.RAYDIUM_CPMM_INITIALIZE,
322
358
  # Raydium AMM V4
323
359
  EventType.RAYDIUM_AMM_V4_SWAP,
324
360
  EventType.RAYDIUM_AMM_V4_DEPOSIT,
325
361
  EventType.RAYDIUM_AMM_V4_WITHDRAW,
326
- EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
327
362
  EventType.RAYDIUM_AMM_V4_INITIALIZE2,
363
+ EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
328
364
  # Orca Whirlpool
329
365
  EventType.ORCA_WHIRLPOOL_SWAP,
330
366
  EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED,
@@ -341,9 +377,13 @@ def all_event_types() -> List[EventType]:
341
377
  EventType.METEORA_DAMM_V2_SWAP,
342
378
  EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
343
379
  EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
380
+ EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
344
381
  EventType.METEORA_DAMM_V2_CREATE_POSITION,
345
382
  EventType.METEORA_DAMM_V2_CLOSE_POSITION,
346
- EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
383
+ EventType.METEORA_DAMM_V2_UPDATE_DELEGATE_PERMISSION,
384
+ EventType.METEORA_DAMM_V2_WITHDRAW_DEAD_LIQUIDITY_REWARD,
385
+ EventType.METEORA_DAMM_V2_CREATE_CONFIG,
386
+ EventType.METEORA_DAMM_V2_CREATE_DYNAMIC_CONFIG,
347
387
  # Meteora DBC
348
388
  EventType.METEORA_DBC_SWAP,
349
389
  EventType.METEORA_DBC_INITIALIZE_POOL,
@@ -8,24 +8,62 @@ from typing import Optional
8
8
  from .dex_parsers import (
9
9
  _parse_raydium_launchlab_trade,
10
10
  _parse_raydium_launchlab_pool_create,
11
+ PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
12
+ PUMP_FEES_INITIALIZE_FEE_CONFIG,
13
+ PUMP_FEES_RESET_FEE_SHARING_CONFIG,
14
+ PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
15
+ PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
16
+ PUMP_FEES_UPDATE_ADMIN,
17
+ PUMP_FEES_UPDATE_FEE_CONFIG,
18
+ PUMP_FEES_UPDATE_FEE_SHARES,
19
+ PUMP_FEES_UPSERT_FEE_TIERS,
11
20
  parse_amm_deposit_from_data,
21
+ parse_amm_init2_from_data,
12
22
  parse_amm_swap_in_from_data,
13
23
  parse_amm_swap_out_from_data,
14
24
  parse_amm_withdraw_from_data,
15
- parse_clmm_collect_from_data,
25
+ parse_amm_withdraw_pnl_from_data,
26
+ parse_clmm_collect_personal_from_data,
27
+ parse_clmm_collect_protocol_from_data,
28
+ parse_clmm_config_change_from_data,
16
29
  parse_clmm_create_from_data,
30
+ parse_clmm_create_personal_position_from_data,
17
31
  parse_clmm_dec_from_data,
32
+ parse_clmm_decrease_limit_order_from_data,
18
33
  parse_clmm_inc_from_data,
34
+ parse_clmm_increase_limit_order_from_data,
35
+ parse_clmm_liquidity_calculate_from_data,
36
+ parse_clmm_liquidity_change_from_data,
37
+ parse_clmm_open_limit_order_from_data,
38
+ parse_clmm_settle_limit_order_from_data,
19
39
  parse_clmm_swap_from_data,
40
+ parse_clmm_update_reward_infos_from_data,
41
+ parse_cpmm_create_from_data,
20
42
  parse_cpmm_deposit_from_data,
21
43
  parse_cpmm_swap_in_from_data,
22
44
  parse_cpmm_swap_out_from_data,
23
45
  parse_cpmm_withdraw_from_data,
24
- parse_dlmm_from_program_data,
46
+ parse_dlmm_event_from_data,
25
47
  parse_meteora_damm_from_buf,
48
+ parse_meteora_add_from_data,
49
+ parse_meteora_bootstrap_from_data,
50
+ parse_meteora_pool_created_from_data,
51
+ parse_meteora_pools_set_pool_fees_from_data,
52
+ parse_meteora_remove_from_data,
53
+ parse_meteora_swap_from_data,
26
54
  parse_orca_liq_dec_from_data,
27
55
  parse_orca_liq_inc_from_data,
56
+ parse_orca_pool_init_from_data,
28
57
  parse_orca_traded_from_data,
58
+ parse_pump_fees_create_fee_sharing_config_from_data,
59
+ parse_pump_fees_initialize_fee_config_from_data,
60
+ parse_pump_fees_reset_fee_sharing_config_from_data,
61
+ parse_pump_fees_revoke_fee_sharing_authority_from_data,
62
+ parse_pump_fees_transfer_fee_sharing_authority_from_data,
63
+ parse_pump_fees_update_admin_from_data,
64
+ parse_pump_fees_update_fee_config_from_data,
65
+ parse_pump_fees_update_fee_shares_from_data,
66
+ parse_pump_fees_upsert_fee_tiers_from_data,
29
67
  parse_ps_add_liq_from_data,
30
68
  parse_ps_buy_from_data,
31
69
  parse_ps_create_pool_from_data,
@@ -44,6 +82,7 @@ from .event_types import (
44
82
  )
45
83
  from .grpc_types import EventType, EventTypeFilter
46
84
  from .grpc_types import (
85
+ event_type_filter_includes_pump_fees,
47
86
  event_type_filter_includes_meteora_damm_v2,
48
87
  event_type_filter_includes_meteora_dlmm,
49
88
  event_type_filter_includes_meteora_pools,
@@ -62,6 +101,7 @@ from .instructions import (
62
101
  METEORA_POOLS_PROGRAM_ID,
63
102
  ORCA_WHIRLPOOL_PROGRAM_ID,
64
103
  PUMPFUN_PROGRAM_ID,
104
+ PUMP_FEES_PROGRAM_ID,
65
105
  PUMPSWAP_PROGRAM_ID,
66
106
  RAYDIUM_AMM_V4_PROGRAM_ID,
67
107
  RAYDIUM_CLMM_PROGRAM_ID,
@@ -80,15 +120,26 @@ _PS_ADD_LIQ = bytes([228, 69, 165, 46, 81, 203, 154, 29, 120, 248, 61, 83, 31, 1
80
120
  _PS_REMOVE_LIQ = bytes([228, 69, 165, 46, 81, 203, 154, 29, 22, 9, 133, 26, 160, 44, 71, 192])
81
121
 
82
122
  # Raydium CLMM(raydium_clmm_inner::discriminators)
83
- _CLMM_SWAP = bytes([248, 198, 158, 145, 225, 117, 135, 200, 155, 167, 108, 32, 122, 76, 173, 64])
84
- _CLMM_INC = bytes([133, 29, 89, 223, 69, 238, 176, 10, 155, 167, 108, 32, 122, 76, 173, 64])
85
- _CLMM_DEC = bytes([160, 38, 208, 111, 104, 91, 44, 1, 155, 167, 108, 32, 122, 76, 173, 64])
86
- _CLMM_CREATE_POOL = bytes([233, 146, 209, 142, 207, 104, 64, 188, 155, 167, 108, 32, 122, 76, 173, 64])
87
- _CLMM_COLLECT_FEE = bytes([164, 152, 207, 99, 187, 104, 171, 119, 155, 167, 108, 32, 122, 76, 173, 64])
123
+ _CLMM_SWAP = bytes([64, 198, 205, 232, 38, 8, 113, 226, 155, 167, 108, 32, 122, 76, 173, 64])
124
+ _CLMM_INC = bytes([49, 79, 105, 212, 32, 34, 30, 84, 155, 167, 108, 32, 122, 76, 173, 64])
125
+ _CLMM_DEC = bytes([58, 222, 86, 58, 68, 50, 85, 56, 155, 167, 108, 32, 122, 76, 173, 64])
126
+ _CLMM_LIQUIDITY_CHANGE = bytes([126, 240, 175, 206, 158, 88, 153, 107, 155, 167, 108, 32, 122, 76, 173, 64])
127
+ _CLMM_CONFIG_CHANGE = bytes([247, 189, 7, 119, 106, 112, 95, 151, 155, 167, 108, 32, 122, 76, 173, 64])
128
+ _CLMM_CREATE_PERSONAL_POSITION = bytes([100, 30, 87, 249, 196, 223, 154, 206, 155, 167, 108, 32, 122, 76, 173, 64])
129
+ _CLMM_LIQUIDITY_CALCULATE = bytes([237, 112, 148, 230, 57, 84, 180, 162, 155, 167, 108, 32, 122, 76, 173, 64])
130
+ _CLMM_OPEN_LIMIT_ORDER = bytes([106, 24, 71, 85, 57, 169, 158, 216, 155, 167, 108, 32, 122, 76, 173, 64])
131
+ _CLMM_INCREASE_LIMIT_ORDER = bytes([11, 120, 13, 204, 199, 87, 19, 200, 155, 167, 108, 32, 122, 76, 173, 64])
132
+ _CLMM_DECREASE_LIMIT_ORDER = bytes([70, 48, 40, 221, 219, 237, 212, 163, 155, 167, 108, 32, 122, 76, 173, 64])
133
+ _CLMM_SETTLE_LIMIT_ORDER = bytes([88, 119, 77, 164, 125, 124, 10, 194, 155, 167, 108, 32, 122, 76, 173, 64])
134
+ _CLMM_UPDATE_REWARD_INFOS = bytes([109, 127, 186, 78, 114, 65, 37, 236, 155, 167, 108, 32, 122, 76, 173, 64])
135
+ _CLMM_CREATE_POOL = bytes([25, 94, 75, 47, 112, 99, 53, 63, 155, 167, 108, 32, 122, 76, 173, 64])
136
+ _CLMM_COLLECT_PERSONAL_FEE = bytes([166, 174, 105, 192, 81, 161, 83, 105, 155, 167, 108, 32, 122, 76, 173, 64])
137
+ _CLMM_COLLECT_PROTOCOL_FEE = bytes([206, 87, 17, 79, 45, 41, 213, 61, 155, 167, 108, 32, 122, 76, 173, 64])
88
138
 
89
139
  # Raydium CPMM(all_inner::raydium_cpmm::discriminators)
90
140
  _CPMM_SWAP_IN = bytes([143, 190, 90, 218, 196, 30, 51, 222, 155, 167, 108, 32, 122, 76, 173, 64])
91
141
  _CPMM_SWAP_OUT = bytes([55, 217, 98, 86, 163, 74, 180, 173, 155, 167, 108, 32, 122, 76, 173, 64])
142
+ _CPMM_CREATE_POOL = bytes([233, 146, 209, 142, 207, 104, 64, 188, 155, 167, 108, 32, 122, 76, 173, 64])
92
143
  _CPMM_DEP = bytes([242, 35, 198, 137, 82, 225, 242, 182, 155, 167, 108, 32, 122, 76, 173, 64])
93
144
  _CPMM_WIT = bytes([183, 18, 70, 156, 148, 109, 161, 34, 155, 167, 108, 32, 122, 76, 173, 64])
94
145
 
@@ -97,16 +148,33 @@ _AMM_SWAP_IN = bytes([0, 0, 0, 0, 0, 0, 0, 9, 155, 167, 108, 32, 122, 76, 173, 6
97
148
  _AMM_SWAP_OUT = bytes([0, 0, 0, 0, 0, 0, 0, 11, 155, 167, 108, 32, 122, 76, 173, 64])
98
149
  _AMM_DEP = bytes([0, 0, 0, 0, 0, 0, 0, 3, 155, 167, 108, 32, 122, 76, 173, 64])
99
150
  _AMM_WIT = bytes([0, 0, 0, 0, 0, 0, 0, 4, 155, 167, 108, 32, 122, 76, 173, 64])
151
+ _AMM_INIT2 = bytes([0, 0, 0, 0, 0, 0, 0, 1, 155, 167, 108, 32, 122, 76, 173, 64])
152
+ _AMM_WITHDRAW_PNL = bytes([0, 0, 0, 0, 0, 0, 0, 7, 155, 167, 108, 32, 122, 76, 173, 64])
100
153
 
101
154
  # Orca
102
155
  _ORCA_TRADED = bytes([225, 202, 73, 175, 147, 43, 160, 150, 155, 167, 108, 32, 122, 76, 173, 64])
103
156
  _ORCA_LIQ_INC = bytes([30, 7, 144, 181, 102, 254, 155, 161, 155, 167, 108, 32, 122, 76, 173, 64])
104
157
  _ORCA_LIQ_DEC = bytes([166, 1, 36, 71, 112, 202, 181, 171, 155, 167, 108, 32, 122, 76, 173, 64])
158
+ _ORCA_POOL_INITIALIZED = bytes([100, 118, 173, 87, 12, 198, 254, 229, 155, 167, 108, 32, 122, 76, 173, 64])
105
159
 
106
160
  # Meteora Pools AMM
107
161
  _MP_SWAP = bytes([81, 108, 227, 190, 205, 208, 10, 196, 155, 167, 108, 32, 122, 76, 173, 64])
108
162
  _MP_ADD = bytes([31, 94, 125, 90, 227, 52, 61, 186, 155, 167, 108, 32, 122, 76, 173, 64])
109
163
  _MP_REM = bytes([116, 244, 97, 232, 103, 31, 152, 58, 155, 167, 108, 32, 122, 76, 173, 64])
164
+ _MP_BOOTSTRAP = bytes([121, 127, 38, 136, 92, 55, 14, 247, 155, 167, 108, 32, 122, 76, 173, 64])
165
+ _MP_POOL_CREATED = bytes([202, 44, 41, 88, 104, 220, 157, 82, 155, 167, 108, 32, 122, 76, 173, 64])
166
+ _MP_SET_POOL_FEES = bytes([245, 26, 198, 164, 88, 18, 75, 9, 155, 167, 108, 32, 122, 76, 173, 64])
167
+
168
+ _EVENT_CPI_PREFIX = bytes([228, 69, 165, 46, 81, 203, 154, 29])
169
+ _EVENT_CPI_SUFFIX = bytes([155, 167, 108, 32, 122, 76, 173, 64])
170
+
171
+
172
+ def _event_cpi_disc8(disc16: bytes) -> Optional[int]:
173
+ if disc16[:8] == _EVENT_CPI_PREFIX:
174
+ return struct.unpack("<Q", disc16[8:16])[0]
175
+ if disc16[8:16] == _EVENT_CPI_SUFFIX:
176
+ return struct.unpack("<Q", disc16[:8])[0]
177
+ return None
110
178
 
111
179
  # Meteora DAMM V2(inner 16 字节:magic + 8 字节 event disc,与 ``parse_meteora_damm_from_buf`` 的 disc 一致)
112
180
  def _damm_buf_from_inner(disc16: bytes, inner: bytes) -> bytes:
@@ -116,11 +184,6 @@ def _damm_buf_from_inner(disc16: bytes, inner: bytes) -> bytes:
116
184
  _RAYDIUM_LAUNCHLAB_TRADE = bytes([189, 219, 127, 211, 78, 230, 97, 238, 155, 167, 108, 32, 122, 76, 173, 64])
117
185
  _RAYDIUM_LAUNCHLAB_POOL_CREATE = bytes([151, 215, 226, 9, 118, 161, 115, 174, 155, 167, 108, 32, 122, 76, 173, 64])
118
186
 
119
- # DLMM(8 字节 event disc + payload)
120
- def _dlmm_buf_from_inner(disc16: bytes, inner: bytes) -> bytes:
121
- return disc16[8:16] + inner
122
-
123
-
124
187
  def _meteora_pools_swap_inner(data: bytes, meta_d: dict) -> Optional[DexEvent]:
125
188
  if len(data) < 16:
126
189
  return None
@@ -234,6 +297,30 @@ def parse_inner_instruction(
234
297
  return emit(parse_ps_remove_liq_from_data(inner, meta_d))
235
298
  return None
236
299
 
300
+ if program_id_b58 == PUMP_FEES_PROGRAM_ID:
301
+ if filter is not None and not event_type_filter_includes_pump_fees(filter):
302
+ return None
303
+ event_disc = _event_cpi_disc8(disc16)
304
+ if event_disc == PUMP_FEES_CREATE_FEE_SHARING_CONFIG:
305
+ return emit(parse_pump_fees_create_fee_sharing_config_from_data(inner, meta_d))
306
+ if event_disc == PUMP_FEES_INITIALIZE_FEE_CONFIG:
307
+ return emit(parse_pump_fees_initialize_fee_config_from_data(inner, meta_d))
308
+ if event_disc == PUMP_FEES_RESET_FEE_SHARING_CONFIG:
309
+ return emit(parse_pump_fees_reset_fee_sharing_config_from_data(inner, meta_d))
310
+ if event_disc == PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY:
311
+ return emit(parse_pump_fees_revoke_fee_sharing_authority_from_data(inner, meta_d))
312
+ if event_disc == PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY:
313
+ return emit(parse_pump_fees_transfer_fee_sharing_authority_from_data(inner, meta_d))
314
+ if event_disc == PUMP_FEES_UPDATE_ADMIN:
315
+ return emit(parse_pump_fees_update_admin_from_data(inner, meta_d))
316
+ if event_disc == PUMP_FEES_UPDATE_FEE_CONFIG:
317
+ return emit(parse_pump_fees_update_fee_config_from_data(inner, meta_d))
318
+ if event_disc == PUMP_FEES_UPDATE_FEE_SHARES:
319
+ return emit(parse_pump_fees_update_fee_shares_from_data(inner, meta_d))
320
+ if event_disc == PUMP_FEES_UPSERT_FEE_TIERS:
321
+ return emit(parse_pump_fees_upsert_fee_tiers_from_data(inner, meta_d))
322
+ return None
323
+
237
324
  if program_id_b58 == RAYDIUM_CLMM_PROGRAM_ID:
238
325
  if filter is not None and not event_type_filter_includes_raydium_clmm(filter):
239
326
  return None
@@ -243,10 +330,30 @@ def parse_inner_instruction(
243
330
  return emit(parse_clmm_inc_from_data(inner, meta_d))
244
331
  if disc16 == _CLMM_DEC:
245
332
  return emit(parse_clmm_dec_from_data(inner, meta_d))
333
+ if disc16 == _CLMM_LIQUIDITY_CHANGE:
334
+ return emit(parse_clmm_liquidity_change_from_data(inner, meta_d))
335
+ if disc16 == _CLMM_CONFIG_CHANGE:
336
+ return emit(parse_clmm_config_change_from_data(inner, meta_d))
337
+ if disc16 == _CLMM_CREATE_PERSONAL_POSITION:
338
+ return emit(parse_clmm_create_personal_position_from_data(inner, meta_d))
339
+ if disc16 == _CLMM_LIQUIDITY_CALCULATE:
340
+ return emit(parse_clmm_liquidity_calculate_from_data(inner, meta_d))
341
+ if disc16 == _CLMM_OPEN_LIMIT_ORDER:
342
+ return emit(parse_clmm_open_limit_order_from_data(inner, meta_d))
343
+ if disc16 == _CLMM_INCREASE_LIMIT_ORDER:
344
+ return emit(parse_clmm_increase_limit_order_from_data(inner, meta_d))
345
+ if disc16 == _CLMM_DECREASE_LIMIT_ORDER:
346
+ return emit(parse_clmm_decrease_limit_order_from_data(inner, meta_d))
347
+ if disc16 == _CLMM_SETTLE_LIMIT_ORDER:
348
+ return emit(parse_clmm_settle_limit_order_from_data(inner, meta_d))
349
+ if disc16 == _CLMM_UPDATE_REWARD_INFOS:
350
+ return emit(parse_clmm_update_reward_infos_from_data(inner, meta_d))
246
351
  if disc16 == _CLMM_CREATE_POOL:
247
352
  return emit(parse_clmm_create_from_data(inner, meta_d))
248
- if disc16 == _CLMM_COLLECT_FEE:
249
- return emit(parse_clmm_collect_from_data(inner, meta_d))
353
+ if disc16 == _CLMM_COLLECT_PERSONAL_FEE:
354
+ return emit(parse_clmm_collect_personal_from_data(inner, meta_d))
355
+ if disc16 == _CLMM_COLLECT_PROTOCOL_FEE:
356
+ return emit(parse_clmm_collect_protocol_from_data(inner, meta_d))
250
357
  return None
251
358
 
252
359
  if program_id_b58 == RAYDIUM_CPMM_PROGRAM_ID:
@@ -256,6 +363,8 @@ def parse_inner_instruction(
256
363
  return emit(parse_cpmm_swap_in_from_data(inner, meta_d))
257
364
  if disc16 == _CPMM_SWAP_OUT:
258
365
  return emit(parse_cpmm_swap_out_from_data(inner, meta_d))
366
+ if disc16 == _CPMM_CREATE_POOL:
367
+ return emit(parse_cpmm_create_from_data(inner, meta_d))
259
368
  if disc16 == _CPMM_DEP:
260
369
  return emit(parse_cpmm_deposit_from_data(inner, meta_d))
261
370
  if disc16 == _CPMM_WIT:
@@ -273,6 +382,10 @@ def parse_inner_instruction(
273
382
  return emit(parse_amm_deposit_from_data(inner, meta_d))
274
383
  if disc16 == _AMM_WIT:
275
384
  return emit(parse_amm_withdraw_from_data(inner, meta_d))
385
+ if disc16 == _AMM_INIT2:
386
+ return emit(parse_amm_init2_from_data(inner, meta_d))
387
+ if disc16 == _AMM_WITHDRAW_PNL:
388
+ return emit(parse_amm_withdraw_pnl_from_data(inner, meta_d))
276
389
  return None
277
390
 
278
391
  if program_id_b58 == ORCA_WHIRLPOOL_PROGRAM_ID:
@@ -284,17 +397,25 @@ def parse_inner_instruction(
284
397
  return emit(parse_orca_liq_inc_from_data(inner, meta_d))
285
398
  if disc16 == _ORCA_LIQ_DEC:
286
399
  return emit(parse_orca_liq_dec_from_data(inner, meta_d))
400
+ if disc16 == _ORCA_POOL_INITIALIZED:
401
+ return emit(parse_orca_pool_init_from_data(inner, meta_d))
287
402
  return None
288
403
 
289
404
  if program_id_b58 == METEORA_POOLS_PROGRAM_ID:
290
405
  if filter is not None and not event_type_filter_includes_meteora_pools(filter):
291
406
  return None
292
407
  if disc16 == _MP_SWAP:
293
- return emit(_meteora_pools_swap_inner(inner, meta_d))
408
+ return emit(parse_meteora_swap_from_data(inner, meta_d) or _meteora_pools_swap_inner(inner, meta_d))
294
409
  if disc16 == _MP_ADD:
295
- return emit(_meteora_pools_add_inner(inner, meta_d))
410
+ return emit(parse_meteora_add_from_data(inner, meta_d))
296
411
  if disc16 == _MP_REM:
297
- return emit(_meteora_pools_rem_inner(inner, meta_d))
412
+ return emit(parse_meteora_remove_from_data(inner, meta_d))
413
+ if disc16 == _MP_BOOTSTRAP:
414
+ return emit(parse_meteora_bootstrap_from_data(inner, meta_d))
415
+ if disc16 == _MP_POOL_CREATED:
416
+ return emit(parse_meteora_pool_created_from_data(inner, meta_d))
417
+ if disc16 == _MP_SET_POOL_FEES:
418
+ return emit(parse_meteora_pools_set_pool_fees_from_data(inner, meta_d))
298
419
  return None
299
420
 
300
421
  if program_id_b58 == METEORA_DAMM_V2_PROGRAM_ID:
@@ -314,6 +435,9 @@ def parse_inner_instruction(
314
435
  if program_id_b58 == METEORA_DLMM_PROGRAM_ID:
315
436
  if filter is not None and not event_type_filter_includes_meteora_dlmm(filter):
316
437
  return None
317
- return emit(parse_dlmm_from_program_data(_dlmm_buf_from_inner(disc16, inner), meta_d))
438
+ event_disc = _event_cpi_disc8(disc16)
439
+ if event_disc is None:
440
+ return None
441
+ return emit(parse_dlmm_event_from_data(event_disc, inner, meta_d))
318
442
 
319
443
  return None