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/__init__.py CHANGED
@@ -104,6 +104,15 @@ from .event_types import (
104
104
  RaydiumClmmOpenPositionWithTokenExtNftEvent,
105
105
  RaydiumClmmClosePositionEvent,
106
106
  RaydiumClmmCollectFeeEvent,
107
+ RaydiumClmmLiquidityChangeEvent,
108
+ RaydiumClmmConfigChangeEvent,
109
+ RaydiumClmmCreatePersonalPositionEvent,
110
+ RaydiumClmmLiquidityCalculateEvent,
111
+ RaydiumClmmOpenLimitOrderEvent,
112
+ RaydiumClmmIncreaseLimitOrderEvent,
113
+ RaydiumClmmDecreaseLimitOrderEvent,
114
+ RaydiumClmmSettleLimitOrderEvent,
115
+ RaydiumClmmUpdateRewardInfosEvent,
107
116
  # Raydium AMM V4 (legacy)
108
117
  RaydiumAmmV4SwapEvent,
109
118
  RaydiumAmmV4DepositEvent,
@@ -143,6 +152,11 @@ from .event_types import (
143
152
  MeteoraDammV2AddLiquidityEvent,
144
153
  MeteoraDammV2RemoveLiquidityEvent,
145
154
  MeteoraDammV2InitializePoolEvent,
155
+ MeteoraDammV2DynamicFeeParameters,
156
+ MeteoraDammV2UpdateDelegatePermissionEvent,
157
+ MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
158
+ MeteoraDammV2CreateConfigEvent,
159
+ MeteoraDammV2CreateDynamicConfigEvent,
146
160
  MeteoraDbcCurveCompleteEvent,
147
161
  MeteoraDbcInitializePoolEvent,
148
162
  MeteoraDbcSwapEvent,
@@ -381,6 +395,15 @@ __all__ = [
381
395
  "RaydiumClmmOpenPositionWithTokenExtNftEvent",
382
396
  "RaydiumClmmClosePositionEvent",
383
397
  "RaydiumClmmCollectFeeEvent",
398
+ "RaydiumClmmLiquidityChangeEvent",
399
+ "RaydiumClmmConfigChangeEvent",
400
+ "RaydiumClmmCreatePersonalPositionEvent",
401
+ "RaydiumClmmLiquidityCalculateEvent",
402
+ "RaydiumClmmOpenLimitOrderEvent",
403
+ "RaydiumClmmIncreaseLimitOrderEvent",
404
+ "RaydiumClmmDecreaseLimitOrderEvent",
405
+ "RaydiumClmmSettleLimitOrderEvent",
406
+ "RaydiumClmmUpdateRewardInfosEvent",
384
407
  "RaydiumAmmV4SwapEvent",
385
408
  "RaydiumAmmV4DepositEvent",
386
409
  "RaydiumAmmV4WithdrawEvent",
@@ -414,6 +437,11 @@ __all__ = [
414
437
  "MeteoraDammV2AddLiquidityEvent",
415
438
  "MeteoraDammV2RemoveLiquidityEvent",
416
439
  "MeteoraDammV2InitializePoolEvent",
440
+ "MeteoraDammV2DynamicFeeParameters",
441
+ "MeteoraDammV2UpdateDelegatePermissionEvent",
442
+ "MeteoraDammV2WithdrawDeadLiquidityRewardEvent",
443
+ "MeteoraDammV2CreateConfigEvent",
444
+ "MeteoraDammV2CreateDynamicConfigEvent",
417
445
  "MeteoraDbcCurveCompleteEvent",
418
446
  "MeteoraDbcInitializePoolEvent",
419
447
  "MeteoraDbcSwapEvent",
@@ -167,6 +167,8 @@ def fill_accounts_with_owned_keys(
167
167
  run(METEORA_DAMM_V2_PROGRAM_ID, lambda g: meteora.fill_damm_v2_add_liquidity_accounts(data, g))
168
168
  elif et == EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY:
169
169
  run(METEORA_DAMM_V2_PROGRAM_ID, lambda g: meteora.fill_damm_v2_remove_liquidity_accounts(data, g))
170
+ elif et == EventType.METEORA_DAMM_V2_INITIALIZE_POOL:
171
+ run(METEORA_DAMM_V2_PROGRAM_ID, lambda g: meteora.fill_damm_v2_initialize_pool_accounts(data, g))
170
172
  elif et == EventType.METEORA_POOLS_SWAP:
171
173
  run(METEORA_POOLS_PROGRAM_ID, lambda g: meteora.fill_pools_swap_accounts(data, g))
172
174
  elif et == EventType.METEORA_POOLS_ADD_LIQUIDITY:
@@ -207,3 +209,82 @@ def fill_data(
207
209
  return
208
210
  is_pump = raw[9] != 0
209
211
  setattr(data, "is_pump_pool", is_pump)
212
+
213
+
214
+ def _account_index(transaction_pb: Any, meta_pb: Any, account: str) -> Optional[int]:
215
+ if not account or account == "11111111111111111111111111111111":
216
+ return None
217
+ msg = getattr(transaction_pb, "message", None)
218
+ if msg is None:
219
+ return None
220
+ keys: List[str] = []
221
+ for b in getattr(msg, "account_keys", []) or []:
222
+ raw = bytes(b) if not isinstance(b, (bytes, bytearray)) else bytes(b)
223
+ if len(raw) == 32:
224
+ keys.append(base58.b58encode(raw).decode("ascii"))
225
+ for b in getattr(meta_pb, "loaded_writable_addresses", []) or []:
226
+ raw = bytes(b) if not isinstance(b, (bytes, bytearray)) else bytes(b)
227
+ if len(raw) == 32:
228
+ keys.append(base58.b58encode(raw).decode("ascii"))
229
+ for b in getattr(meta_pb, "loaded_readonly_addresses", []) or []:
230
+ raw = bytes(b) if not isinstance(b, (bytes, bytearray)) else bytes(b)
231
+ if len(raw) == 32:
232
+ keys.append(base58.b58encode(raw).decode("ascii"))
233
+ try:
234
+ return keys.index(account)
235
+ except ValueError:
236
+ return None
237
+
238
+
239
+ def _token_balance_raw(t: Any) -> int:
240
+ ui = getattr(t, "ui_token_amount", None)
241
+ if ui is None:
242
+ return 0
243
+ amt = getattr(ui, "amount", None)
244
+ if amt is None:
245
+ return 0
246
+ try:
247
+ return int(str(amt))
248
+ except Exception:
249
+ return 0
250
+
251
+
252
+ def fill_token_balances(event: DexEvent, meta_pb: Any, transaction_pb: Any) -> None:
253
+ """对齐 Rust ``common_filler::fill_token_balances``(PumpFun trade 用户余额)。"""
254
+ if meta_pb is None or transaction_pb is None:
255
+ return
256
+ if event.type not in (
257
+ EventType.PUMP_FUN_TRADE,
258
+ EventType.PUMP_FUN_BUY,
259
+ EventType.PUMP_FUN_SELL,
260
+ EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
261
+ ):
262
+ return
263
+ trade = event.data
264
+ user = getattr(trade, "user", "") or ""
265
+ associated_user = getattr(trade, "associated_user", "") or ""
266
+ user_idx = _account_index(transaction_pb, meta_pb, user)
267
+ if user_idx is not None:
268
+ pre_balances = list(getattr(meta_pb, "pre_balances", []) or [])
269
+ post_balances = list(getattr(meta_pb, "post_balances", []) or [])
270
+ if user_idx < len(pre_balances):
271
+ trade.pre_sol_balance = int(pre_balances[user_idx])
272
+ if user_idx < len(post_balances):
273
+ trade.post_sol_balance = int(post_balances[user_idx])
274
+ token_idx = _account_index(transaction_pb, meta_pb, associated_user)
275
+ if token_idx is None:
276
+ return
277
+ token_idx_u32 = token_idx
278
+ pre = None
279
+ post = None
280
+ for bal in getattr(meta_pb, "pre_token_balances", []) or []:
281
+ if int(getattr(bal, "account_index", -1)) == token_idx_u32:
282
+ pre = _token_balance_raw(bal)
283
+ break
284
+ for bal in getattr(meta_pb, "post_token_balances", []) or []:
285
+ if int(getattr(bal, "account_index", -1)) == token_idx_u32:
286
+ post = _token_balance_raw(bal)
287
+ break
288
+ if pre is not None or post is not None:
289
+ trade.pre_token_balance = pre if pre is not None else 0
290
+ trade.post_token_balance = post if post is not None else 0
@@ -27,6 +27,21 @@ def fill_damm_v2_remove_liquidity_accounts(_e: Any, _get: AccountGetter) -> None
27
27
  pass
28
28
 
29
29
 
30
+ def fill_damm_v2_initialize_pool_accounts(e: Any, get: AccountGetter) -> None:
31
+ if getattr(e, "creator", "") == "":
32
+ e.creator = get(0)
33
+ if getattr(e, "position_nft_mint", "") == "":
34
+ e.position_nft_mint = get(1)
35
+ if getattr(e, "pool", "") == "":
36
+ e.pool = get(6)
37
+ if getattr(e, "position", "") == "":
38
+ e.position = get(7)
39
+ if getattr(e, "token_a_mint", "") == "":
40
+ e.token_a_mint = get(8)
41
+ if getattr(e, "token_b_mint", "") == "":
42
+ e.token_b_mint = get(9)
43
+
44
+
30
45
  def fill_pools_swap_accounts(_e: Any, _get: AccountGetter) -> None:
31
46
  pass
32
47
 
@@ -39,8 +54,16 @@ def fill_pools_remove_liquidity_accounts(_e: Any, _get: AccountGetter) -> None:
39
54
  pass
40
55
 
41
56
 
42
- def fill_dlmm_swap_accounts(_e: Any, _get: AccountGetter) -> None:
43
- pass
57
+ def fill_dlmm_swap_accounts(e: Any, get: AccountGetter) -> None:
58
+ z = "11111111111111111111111111111111"
59
+ if not getattr(e, "user_token_in", "") or e.user_token_in == z:
60
+ e.user_token_in = get(4)
61
+ if not getattr(e, "user_token_out", "") or e.user_token_out == z:
62
+ e.user_token_out = get(5)
63
+ if not getattr(e, "token_x_mint", "") or e.token_x_mint == z:
64
+ e.token_x_mint = get(6)
65
+ if not getattr(e, "token_y_mint", "") or e.token_y_mint == z:
66
+ e.token_y_mint = get(7)
44
67
 
45
68
 
46
69
  def fill_dlmm_add_liquidity_accounts(_e: Any, _get: AccountGetter) -> None:
@@ -113,6 +113,9 @@ def fill_trade_accounts(e: PumpFunTradeEvent, get: AccountGetter) -> None:
113
113
 
114
114
 
115
115
  def fill_create_accounts(e: PumpFunCreateEvent, get: AccountGetter) -> None:
116
+ if get(15) == "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P":
117
+ fill_create_v2_accounts(e, get) # type: ignore[arg-type]
118
+ return
116
119
  if _empty(e.mint):
117
120
  e.mint = get(0)
118
121
  if _empty(e.bonding_curve):
@@ -154,6 +157,14 @@ def fill_create_v2_accounts(e: PumpFunCreateV2TokenEvent, get: AccountGetter) ->
154
157
  e.event_authority = get(14)
155
158
  if _empty(e.program):
156
159
  e.program = get(15)
160
+ if _empty(e.quote_mint) or e.quote_mint == "So11111111111111111111111111111111111111111":
161
+ e.quote_mint = get(16)
162
+ if _empty(e.quote_vault):
163
+ e.quote_vault = get(17)
164
+ if _empty(e.quote_token_program):
165
+ e.quote_token_program = get(18)
166
+ if getattr(e, "ix_name", "") in ("", "create"):
167
+ e.ix_name = "create_v2"
157
168
 
158
169
 
159
170
  def fill_migrate_accounts(_e: PumpFunMigrateEvent, _get: AccountGetter) -> None:
@@ -77,8 +77,9 @@ def fill_clmm_close_position_accounts(e: RaydiumClmmClosePositionEvent, get: Acc
77
77
  e.position_nft_mint = get(1)
78
78
 
79
79
 
80
- def fill_cpmm_swap_accounts(_e: RaydiumCpmmSwapEvent, _get: AccountGetter) -> None:
81
- pass
80
+ def fill_cpmm_swap_accounts(e: RaydiumCpmmSwapEvent, get: AccountGetter) -> None:
81
+ if _empty(e.pool_id):
82
+ e.pool_id = get(3)
82
83
 
83
84
 
84
85
  def fill_cpmm_deposit_accounts(e: RaydiumCpmmDepositEvent, get: AccountGetter) -> None:
@@ -7,6 +7,7 @@ from typing import Callable
7
7
  from ..event_types import RaydiumLaunchlabPoolCreateEvent, RaydiumLaunchlabTradeEvent
8
8
 
9
9
  Z = "11111111111111111111111111111111"
10
+ RAYDIUM_LAUNCHLAB_PROGRAM_ID = "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"
10
11
 
11
12
 
12
13
  def _empty(s: str) -> bool:
@@ -21,6 +22,26 @@ def fill_trade_accounts(e: RaydiumLaunchlabTradeEvent, get: AccountGetter) -> No
21
22
  e.user = get(0)
22
23
  if _empty(e.pool_state):
23
24
  e.pool_state = get(4)
25
+ if _empty(e.global_config):
26
+ e.global_config = get(2)
27
+ if _empty(e.platform_config):
28
+ e.platform_config = get(3)
29
+ if _empty(e.user_base_token):
30
+ e.user_base_token = get(5)
31
+ if _empty(e.user_quote_token):
32
+ e.user_quote_token = get(6)
33
+ if _empty(e.base_vault):
34
+ e.base_vault = get(7)
35
+ if _empty(e.quote_vault):
36
+ e.quote_vault = get(8)
37
+ if _empty(e.base_mint):
38
+ e.base_mint = get(9)
39
+ if _empty(e.quote_mint):
40
+ e.quote_mint = get(10)
41
+ if _empty(e.base_token_program):
42
+ e.base_token_program = get(11)
43
+ if _empty(e.quote_token_program):
44
+ e.quote_token_program = get(12)
24
45
 
25
46
 
26
47
  def fill_pool_create_accounts(e: RaydiumLaunchlabPoolCreateEvent, get: AccountGetter) -> None:
@@ -28,3 +49,32 @@ def fill_pool_create_accounts(e: RaydiumLaunchlabPoolCreateEvent, get: AccountGe
28
49
  e.pool_state = get(5)
29
50
  if _empty(e.creator):
30
51
  e.creator = get(1)
52
+ if _empty(e.payer):
53
+ e.payer = get(0)
54
+ if _empty(e.global_config):
55
+ e.global_config = get(2)
56
+ if _empty(e.platform_config):
57
+ e.platform_config = get(3)
58
+ if _empty(e.base_mint):
59
+ e.base_mint = get(6)
60
+ if _empty(e.quote_mint):
61
+ e.quote_mint = get(7)
62
+ if _empty(e.base_vault):
63
+ e.base_vault = get(8)
64
+ if _empty(e.quote_vault):
65
+ e.quote_vault = get(9)
66
+ # initialize / initialize_v2 use token-program indices 11-12;
67
+ # initialize_with_token_2022 uses 10-11 (detect via program id at end).
68
+ try:
69
+ if get(17) == RAYDIUM_LAUNCHLAB_PROGRAM_ID:
70
+ bi, qi = 11, 12
71
+ elif get(14) == RAYDIUM_LAUNCHLAB_PROGRAM_ID:
72
+ bi, qi = 10, 11
73
+ else:
74
+ return
75
+ except Exception:
76
+ return
77
+ if _empty(e.base_token_program):
78
+ e.base_token_program = get(bi)
79
+ if _empty(e.quote_token_program):
80
+ e.quote_token_program = get(qi)
@@ -42,10 +42,15 @@ TOKEN_ACCOUNT_SIZE = 165
42
42
  NONCE_ACCOUNT_SIZE = 80
43
43
  PUMPFUN_GLOBAL_BODY = 1037
44
44
  PUMPFUN_BONDING_CURVE_BODY = 107
45
+ PUMPFUN_BONDING_CURVE_CREATOR_FEE_BODY = 116
46
+ PUMPFUN_BONDING_CURVE_HOLDER_REWARD_BODY = 117
45
47
  PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR_BODY = 536
46
48
  PUMPFUN_USER_VOLUME_ACCUMULATOR_BODY = 98
47
49
  GLOBAL_CONFIG_BODY = 634
48
- POOL_BODY = 244
50
+ POOL_LEGACY_BODY = 244
51
+ POOL_BOOST_BODY = 253
52
+ POOL_CREATOR_FEE_BODY = 262
53
+ POOL_BODY = 263
49
54
  MAX_PUMPFUN_FEE_TIERS = 64
50
55
  MAX_PUMPFUN_SHAREHOLDERS = 64
51
56
 
@@ -483,6 +488,12 @@ def _parse_pumpfun_bonding_curve_fast(
483
488
  is_cashback_coin = data[o] != 0
484
489
  o += 1
485
490
  quote_mint = read_pubkey_fast(data, o)
491
+ o += 32
492
+ creator_fee_bps = read_u64_fast(data, o) if o + 8 <= len(data) else 0
493
+ o += 8
494
+ can_edit_creator_fee = data[o] != 0 if o < len(data) else False
495
+ o += 1
496
+ is_holder_reward = data[o] != 0 if o < len(data) else False
486
497
  return _account_event(
487
498
  EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE,
488
499
  {
@@ -499,6 +510,9 @@ def _parse_pumpfun_bonding_curve_fast(
499
510
  "is_mayhem_mode": is_mayhem_mode,
500
511
  "is_cashback_coin": is_cashback_coin,
501
512
  "quote_mint": quote_mint,
513
+ "creator_fee_bps": creator_fee_bps,
514
+ "can_edit_creator_fee": can_edit_creator_fee,
515
+ "is_holder_reward": is_holder_reward,
502
516
  },
503
517
  },
504
518
  )
@@ -752,6 +766,18 @@ def _parse_pumpswap_pool_fast(account: AccountData, metadata: EventMetadata) ->
752
766
  o += 32
753
767
  is_mayhem = data[o] != 0
754
768
  is_cashback = data[o + 1] != 0
769
+ o += 2
770
+ virtual_quote_reserves = (
771
+ int.from_bytes(data[o : o + 16], "little", signed=True)
772
+ if len(data) >= POOL_BOOST_BODY
773
+ else 0
774
+ )
775
+ o += 16
776
+ creator_fee_bps = read_u64_fast(data, o) if o + 8 <= len(data) else 0
777
+ o += 8
778
+ can_edit_creator_fee = data[o] != 0 if o < len(data) else False
779
+ o += 1
780
+ is_holder_reward = data[o] != 0 if o < len(data) else False
755
781
  return _account_event(
756
782
  EventType.ACCOUNT_PUMP_SWAP_POOL,
757
783
  {
@@ -770,6 +796,10 @@ def _parse_pumpswap_pool_fast(account: AccountData, metadata: EventMetadata) ->
770
796
  "coin_creator": coin_creator,
771
797
  "is_mayhem_mode": is_mayhem,
772
798
  "is_cashback_coin": is_cashback,
799
+ "virtual_quote_reserves": virtual_quote_reserves,
800
+ "creator_fee_bps": creator_fee_bps,
801
+ "can_edit_creator_fee": can_edit_creator_fee,
802
+ "is_holder_reward": is_holder_reward,
773
803
  },
774
804
  },
775
805
  )
@@ -807,6 +837,13 @@ def parse_pumpfun_bonding_curve(
807
837
  ) -> Optional[DexEvent]:
808
838
  if len(account.data) < 8 + PUMPFUN_BONDING_CURVE_BODY:
809
839
  return None
840
+ body_len = len(account.data) - 8
841
+ if (
842
+ body_len != PUMPFUN_BONDING_CURVE_BODY
843
+ and body_len != PUMPFUN_BONDING_CURVE_CREATOR_FEE_BODY
844
+ and body_len < PUMPFUN_BONDING_CURVE_HOLDER_REWARD_BODY
845
+ ):
846
+ return None
810
847
  if not has_discriminator(account.data, _DISC_PUMPFUN_BONDING_CURVE):
811
848
  return None
812
849
  return _parse_pumpfun_bonding_curve_fast(account, metadata)
@@ -861,7 +898,15 @@ def parse_pumpswap_global_config(account: AccountData, metadata: EventMetadata)
861
898
 
862
899
 
863
900
  def parse_pumpswap_pool(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
864
- if len(account.data) < 8 + POOL_BODY:
901
+ if len(account.data) < 8 + POOL_LEGACY_BODY:
902
+ return None
903
+ body_len = len(account.data) - 8
904
+ if (
905
+ body_len != POOL_LEGACY_BODY
906
+ and body_len != POOL_BOOST_BODY
907
+ and body_len != POOL_CREATOR_FEE_BODY
908
+ and body_len < POOL_BODY
909
+ ):
865
910
  return None
866
911
  if not has_discriminator(account.data, _DISC_POOL):
867
912
  return None
@@ -6,11 +6,14 @@ import sys
6
6
 
7
7
  from .u128_parity import run_all_u128_checks
8
8
  from .verify_discriminators import main as _verify_main
9
+ from .event_type_parity import run_event_type_parity_check
9
10
 
10
11
 
11
12
  def main() -> None:
12
13
  if _verify_main() != 0:
13
14
  sys.exit(1)
15
+ if run_event_type_parity_check() != 0:
16
+ sys.exit(1)
14
17
  sys.exit(run_all_u128_checks())
15
18
 
16
19