sol-parser-sdk-python 0.4.5__py3-none-any.whl → 0.5.6__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
@@ -6,6 +6,7 @@ from .parser import (
6
6
  StreamingEventListener,
7
7
  parse_log,
8
8
  parse_log_optimized,
9
+ parse_log_optimized_with_program_id,
9
10
  parse_log_unified,
10
11
  parse_logs_only,
11
12
  parse_logs_streaming,
@@ -16,6 +17,12 @@ from .parser import (
16
17
  warmup_parser,
17
18
  )
18
19
  from .clock import now_micros
20
+ from .market import (
21
+ sqrt_price_x64_to_price,
22
+ vault_price_from_balances,
23
+ normalize_buy_sell_from_token_delta,
24
+ normalize_buy_sell_from_input_mint,
25
+ )
19
26
  from .grpc_types import (
20
27
  OrderMode,
21
28
  CommitmentLevel,
@@ -46,6 +53,14 @@ from .grpc_types import (
46
53
  event_type_filter_includes_pumpfun,
47
54
  event_type_filter_includes_pumpswap,
48
55
  event_type_filter_includes_meteora_damm_v2,
56
+ event_type_filter_includes_meteora_dbc,
57
+ event_type_filter_includes_meteora_pools,
58
+ event_type_filter_includes_meteora_dlmm,
59
+ event_type_filter_includes_raydium_clmm,
60
+ event_type_filter_includes_raydium_cpmm,
61
+ event_type_filter_includes_raydium_amm_v4,
62
+ event_type_filter_includes_orca_whirlpool,
63
+ event_type_filter_includes_raydium_launchlab,
49
64
  event_type_filter_includes_pump_fees,
50
65
  event_type_filter_allows_instruction_parsing,
51
66
  all_event_types,
@@ -128,16 +143,20 @@ from .event_types import (
128
143
  MeteoraDammV2AddLiquidityEvent,
129
144
  MeteoraDammV2RemoveLiquidityEvent,
130
145
  MeteoraDammV2InitializePoolEvent,
131
- # Bonk events
132
- BonkTradeEvent,
133
- BonkPoolCreateEvent,
134
- BonkMigrateAmmEvent,
146
+ MeteoraDbcCurveCompleteEvent,
147
+ MeteoraDbcInitializePoolEvent,
148
+ MeteoraDbcSwapEvent,
149
+ # RaydiumLaunchlab events
150
+ RaydiumLaunchlabTradeEvent,
151
+ RaydiumLaunchlabPoolCreateEvent,
152
+ RaydiumLaunchlabMigrateAmmEvent,
135
153
  # Union type and helper
136
154
  TypedDexEvent,
137
155
  to_typed_event,
138
156
  legacy_dict_to_dex_event,
139
157
  )
140
158
  from .pumpfun_fee_enrich import (
159
+ enrich_create_v2_from_create_events,
141
160
  enrich_create_v2_observed_fee_recipient,
142
161
  enrich_pumpfun_same_tx_post_merge,
143
162
  enrich_pumpfun_trades_from_create_instructions,
@@ -206,6 +225,8 @@ from .instructions import (
206
225
  parse_pumpfun_instruction,
207
226
  parse_pumpswap_instruction,
208
227
  parse_meteora_damm_instruction,
228
+ parse_meteora_pools_instruction,
229
+ parse_meteora_dlmm_instruction,
209
230
  parse_pump_fees_instruction,
210
231
  )
211
232
 
@@ -218,6 +239,7 @@ __all__ = [
218
239
  "enrich_dex_events_with_subscribe_tx_info",
219
240
  "parse_log_unified",
220
241
  "parse_log_optimized",
242
+ "parse_log_optimized_with_program_id",
221
243
  "parse_log",
222
244
  "parse_logs_only",
223
245
  "parse_logs_streaming",
@@ -229,6 +251,10 @@ __all__ = [
229
251
  "StreamingEventListener",
230
252
  "warmup_parser",
231
253
  "now_micros",
254
+ "sqrt_price_x64_to_price",
255
+ "vault_price_from_balances",
256
+ "normalize_buy_sell_from_token_delta",
257
+ "normalize_buy_sell_from_input_mint",
232
258
  # RPC parser
233
259
  "ParseError",
234
260
  "RpcClient",
@@ -264,6 +290,8 @@ __all__ = [
264
290
  "parse_pumpfun_instruction",
265
291
  "parse_pumpswap_instruction",
266
292
  "parse_meteora_damm_instruction",
293
+ "parse_meteora_pools_instruction",
294
+ "parse_meteora_dlmm_instruction",
267
295
  "parse_pump_fees_instruction",
268
296
  # gRPC types
269
297
  "OrderMode",
@@ -296,6 +324,14 @@ __all__ = [
296
324
  "event_type_filter_includes_pumpfun",
297
325
  "event_type_filter_includes_pumpswap",
298
326
  "event_type_filter_includes_meteora_damm_v2",
327
+ "event_type_filter_includes_meteora_dbc",
328
+ "event_type_filter_includes_meteora_pools",
329
+ "event_type_filter_includes_meteora_dlmm",
330
+ "event_type_filter_includes_raydium_clmm",
331
+ "event_type_filter_includes_raydium_cpmm",
332
+ "event_type_filter_includes_raydium_amm_v4",
333
+ "event_type_filter_includes_orca_whirlpool",
334
+ "event_type_filter_includes_raydium_launchlab",
299
335
  "event_type_filter_includes_pump_fees",
300
336
  "event_type_filter_allows_instruction_parsing",
301
337
  "all_event_types",
@@ -378,12 +414,16 @@ __all__ = [
378
414
  "MeteoraDammV2AddLiquidityEvent",
379
415
  "MeteoraDammV2RemoveLiquidityEvent",
380
416
  "MeteoraDammV2InitializePoolEvent",
381
- "BonkTradeEvent",
382
- "BonkPoolCreateEvent",
383
- "BonkMigrateAmmEvent",
417
+ "MeteoraDbcCurveCompleteEvent",
418
+ "MeteoraDbcInitializePoolEvent",
419
+ "MeteoraDbcSwapEvent",
420
+ "RaydiumLaunchlabTradeEvent",
421
+ "RaydiumLaunchlabPoolCreateEvent",
422
+ "RaydiumLaunchlabMigrateAmmEvent",
384
423
  "TypedDexEvent",
385
424
  "to_typed_event",
386
425
  "legacy_dict_to_dex_event",
426
+ "enrich_create_v2_from_create_events",
387
427
  "enrich_create_v2_observed_fee_recipient",
388
428
  "enrich_pumpfun_same_tx_post_merge",
389
429
  "enrich_pumpfun_trades_from_create_instructions",
@@ -6,12 +6,12 @@ from typing import Any, Dict, List, Optional, Tuple
6
6
 
7
7
  import base58
8
8
 
9
- from .account_fillers import bonk, meteora, orca, pumpfun, pumpswap, raydium
9
+ from .account_fillers import raydium_launchlab, meteora, orca, pumpfun, pumpswap, raydium
10
10
  from .event_types import DexEvent
11
11
  from .grpc_types import EventType
12
12
  from .instr_account_utils import get_instruction_account_getter
13
13
  from .instructions import (
14
- BONK_LAUNCHPAD_PROGRAM_ID,
14
+ RAYDIUM_LAUNCHLAB_PROGRAM_ID,
15
15
  METEORA_DAMM_V2_PROGRAM_ID,
16
16
  METEORA_DLMM_PROGRAM_ID,
17
17
  METEORA_POOLS_PROGRAM_ID,
@@ -179,10 +179,10 @@ def fill_accounts_with_owned_keys(
179
179
  run(METEORA_DLMM_PROGRAM_ID, lambda g: meteora.fill_dlmm_add_liquidity_accounts(data, g))
180
180
  elif et == EventType.METEORA_DLMM_REMOVE_LIQUIDITY:
181
181
  run(METEORA_DLMM_PROGRAM_ID, lambda g: meteora.fill_dlmm_remove_liquidity_accounts(data, g))
182
- elif et == EventType.BONK_TRADE:
183
- run(BONK_LAUNCHPAD_PROGRAM_ID, lambda g: bonk.fill_trade_accounts(data, g))
184
- elif et == EventType.BONK_POOL_CREATE:
185
- run(BONK_LAUNCHPAD_PROGRAM_ID, lambda g: bonk.fill_pool_create_accounts(data, g))
182
+ elif et == EventType.RAYDIUM_LAUNCHLAB_TRADE:
183
+ run(RAYDIUM_LAUNCHLAB_PROGRAM_ID, lambda g: raydium_launchlab.fill_trade_accounts(data, g))
184
+ elif et == EventType.RAYDIUM_LAUNCHLAB_POOL_CREATE:
185
+ run(RAYDIUM_LAUNCHLAB_PROGRAM_ID, lambda g: raydium_launchlab.fill_pool_create_accounts(data, g))
186
186
 
187
187
 
188
188
  def fill_data(
@@ -1,5 +1,5 @@
1
1
  """账户填充子模块(对齐 Rust ``core/account_fillers``)。"""
2
2
 
3
- from . import bonk, meteora, orca, pumpfun, pumpswap, raydium
3
+ from . import raydium_launchlab, meteora, orca, pumpfun, pumpswap, raydium
4
4
 
5
- __all__ = ["bonk", "meteora", "orca", "pumpfun", "pumpswap", "raydium"]
5
+ __all__ = ["raydium_launchlab", "meteora", "orca", "pumpfun", "pumpswap", "raydium"]
@@ -29,9 +29,7 @@ def fill_trade_accounts(e: PumpFunTradeEvent, get: AccountGetter) -> None:
29
29
  if _empty(getattr(e, name)):
30
30
  setattr(e, name, get(idx))
31
31
 
32
- is_v2 = e.ix_name in ("buy_v2", "sell_v2", "buy_exact_quote_in_v2") or (
33
- e.ix_name == "buy_exact_quote_in" and account_at_matches_mint(1)
34
- )
32
+ is_v2 = e.ix_name in ("buy_v2", "sell_v2", "buy_exact_quote_in_v2") or account_at_matches_mint(1)
35
33
  if is_v2:
36
34
  set_attr("global_account", 0)
37
35
  set_attr("quote_mint", 2)
@@ -51,7 +49,7 @@ def fill_trade_accounts(e: PumpFunTradeEvent, get: AccountGetter) -> None:
51
49
  set_attr("associated_quote_buyback_fee_recipient", 9)
52
50
  set_attr("associated_creator_vault", 17)
53
51
  set_attr("sharing_config", 18)
54
- if e.ix_name == "sell_v2":
52
+ if e.ix_name == "sell_v2" or (e.ix_name == "sell" and not e.is_buy):
55
53
  set_attr("user_volume_accumulator", 19)
56
54
  set_attr("associated_user_volume_accumulator", 20)
57
55
  set_attr("fee_config", 21)
@@ -0,0 +1,30 @@
1
+ """RaydiumLaunchlab 账户填充(对齐 ``account_fillers/raydium_launchlab.rs``)。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Callable
6
+
7
+ from ..event_types import RaydiumLaunchlabPoolCreateEvent, RaydiumLaunchlabTradeEvent
8
+
9
+ Z = "11111111111111111111111111111111"
10
+
11
+
12
+ def _empty(s: str) -> bool:
13
+ return not s or s == Z
14
+
15
+
16
+ AccountGetter = Callable[[int], str]
17
+
18
+
19
+ def fill_trade_accounts(e: RaydiumLaunchlabTradeEvent, get: AccountGetter) -> None:
20
+ if _empty(e.user):
21
+ e.user = get(0)
22
+ if _empty(e.pool_state):
23
+ e.pool_state = get(4)
24
+
25
+
26
+ def fill_pool_create_accounts(e: RaydiumLaunchlabPoolCreateEvent, get: AccountGetter) -> None:
27
+ if _empty(e.pool_state):
28
+ e.pool_state = get(5)
29
+ if _empty(e.creator):
30
+ e.creator = get(1)
@@ -13,6 +13,14 @@ from ..dex_parsers import DexEvent
13
13
 
14
14
  from . import rpc_wallet
15
15
  from . import utils as acc_utils
16
+ from .raydium_orca import (
17
+ ORCA_WHIRLPOOL_PROGRAM_ID,
18
+ RAYDIUM_CLMM_PROGRAM_ID,
19
+ RAYDIUM_CPMM_PROGRAM_ID,
20
+ parse_orca_whirlpool_account,
21
+ parse_raydium_clmm_account,
22
+ parse_raydium_cpmm_account,
23
+ )
16
24
 
17
25
  # 程序 ID(与 Rust ``accounts/program_ids`` / ``instr/program_ids`` 一致)
18
26
  PUMPFUN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
@@ -151,6 +159,42 @@ def _read_pumpfun_shareholders(data: bytes, offset: int) -> Optional[tuple[list[
151
159
  return out, offset
152
160
 
153
161
 
162
+ def _filter_account_event(
163
+ ev: Optional[DexEvent],
164
+ event_type_filter: Optional[EventTypeFilter],
165
+ ) -> Optional[DexEvent]:
166
+ if ev is None or event_type_filter is None:
167
+ return ev
168
+ return ev if event_type_filter.should_include(ev.type) else None
169
+
170
+
171
+ ACCOUNT_EVENT_TYPES = frozenset(
172
+ (
173
+ EventType.TOKEN_ACCOUNT,
174
+ EventType.TOKEN_INFO,
175
+ EventType.NONCE_ACCOUNT,
176
+ EventType.ACCOUNT_PUMP_FUN_GLOBAL,
177
+ EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE,
178
+ EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG,
179
+ EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG,
180
+ EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR,
181
+ EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR,
182
+ EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG,
183
+ EventType.ACCOUNT_PUMP_SWAP_POOL,
184
+ EventType.ACCOUNT_RAYDIUM_CLMM_AMM_CONFIG,
185
+ EventType.ACCOUNT_RAYDIUM_CLMM_POOL_STATE,
186
+ EventType.ACCOUNT_RAYDIUM_CLMM_TICK_ARRAY_STATE,
187
+ EventType.ACCOUNT_RAYDIUM_CPMM_AMM_CONFIG,
188
+ EventType.ACCOUNT_RAYDIUM_CPMM_POOL_STATE,
189
+ EventType.ACCOUNT_ORCA_WHIRLPOOL,
190
+ EventType.ACCOUNT_ORCA_POSITION,
191
+ EventType.ACCOUNT_ORCA_TICK_ARRAY,
192
+ EventType.ACCOUNT_ORCA_FEE_TIER,
193
+ EventType.ACCOUNT_ORCA_WHIRLPOOLS_CONFIG,
194
+ )
195
+ )
196
+
197
+
154
198
  def parse_account_unified(
155
199
  account: AccountData,
156
200
  metadata: EventMetadata,
@@ -164,47 +208,71 @@ def parse_account_unified(
164
208
  if event_type_filter is not None:
165
209
  inc = getattr(event_type_filter, "include_only", None)
166
210
  if inc is not None and len(inc) > 0:
167
- need = {
168
- EventType.TOKEN_ACCOUNT,
169
- EventType.TOKEN_INFO,
170
- EventType.NONCE_ACCOUNT,
171
- EventType.ACCOUNT_PUMP_FUN_GLOBAL,
172
- EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE,
173
- EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG,
174
- EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG,
175
- EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR,
176
- EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR,
177
- EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG,
178
- EventType.ACCOUNT_PUMP_SWAP_POOL,
179
- }
180
- if not any(t in need for t in inc):
211
+ if not any(t in ACCOUNT_EVENT_TYPES for t in inc):
181
212
  return None
182
213
 
183
- if account.owner == PUMPSWAP_PROGRAM_ID and event_type_filter is not None:
184
- if event_type_filter.should_include(
185
- EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG
186
- ) or event_type_filter.should_include(EventType.ACCOUNT_PUMP_SWAP_POOL):
214
+ if account.owner == PUMPSWAP_PROGRAM_ID:
215
+ should_parse_pumpswap = event_type_filter is None or (
216
+ event_type_filter.should_include(EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG)
217
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_SWAP_POOL)
218
+ )
219
+ if should_parse_pumpswap:
187
220
  ev = _parse_pumpswap_account(account, metadata)
188
221
  if ev is not None:
189
- return ev
190
-
191
- if account.owner in (PUMPFUN_PROGRAM_ID, PUMP_FEES_PROGRAM_ID) and event_type_filter is not None:
192
- if event_type_filter.should_include(
193
- EventType.ACCOUNT_PUMP_FUN_GLOBAL
194
- ) or event_type_filter.should_include(
195
- EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE
196
- ) or event_type_filter.should_include(
197
- EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG
198
- ) or event_type_filter.should_include(
199
- EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG
200
- ) or event_type_filter.should_include(
201
- EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR
202
- ) or event_type_filter.should_include(
203
- EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR
204
- ):
222
+ return _filter_account_event(ev, event_type_filter)
223
+ return None
224
+
225
+ if account.owner in (PUMPFUN_PROGRAM_ID, PUMP_FEES_PROGRAM_ID):
226
+ should_parse_pumpfun = event_type_filter is None or (
227
+ event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_GLOBAL)
228
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE)
229
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG)
230
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG)
231
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR)
232
+ or event_type_filter.should_include(EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR)
233
+ )
234
+ if should_parse_pumpfun:
205
235
  ev = _parse_pumpfun_account(account, metadata)
206
236
  if ev is not None:
207
- return ev
237
+ return _filter_account_event(ev, event_type_filter)
238
+ return None
239
+
240
+ if account.owner == RAYDIUM_CLMM_PROGRAM_ID:
241
+ should_parse_clmm = event_type_filter is None or (
242
+ event_type_filter.should_include(EventType.ACCOUNT_RAYDIUM_CLMM_AMM_CONFIG)
243
+ or event_type_filter.should_include(EventType.ACCOUNT_RAYDIUM_CLMM_POOL_STATE)
244
+ or event_type_filter.should_include(EventType.ACCOUNT_RAYDIUM_CLMM_TICK_ARRAY_STATE)
245
+ )
246
+ if should_parse_clmm:
247
+ ev = parse_raydium_clmm_account(account, metadata)
248
+ if ev is not None:
249
+ return _filter_account_event(ev, event_type_filter)
250
+ return None
251
+
252
+ if account.owner == RAYDIUM_CPMM_PROGRAM_ID:
253
+ should_parse_cpmm = event_type_filter is None or (
254
+ event_type_filter.should_include(EventType.ACCOUNT_RAYDIUM_CPMM_AMM_CONFIG)
255
+ or event_type_filter.should_include(EventType.ACCOUNT_RAYDIUM_CPMM_POOL_STATE)
256
+ )
257
+ if should_parse_cpmm:
258
+ ev = parse_raydium_cpmm_account(account, metadata)
259
+ if ev is not None:
260
+ return _filter_account_event(ev, event_type_filter)
261
+ return None
262
+
263
+ if account.owner == ORCA_WHIRLPOOL_PROGRAM_ID:
264
+ should_parse_orca = event_type_filter is None or (
265
+ event_type_filter.should_include(EventType.ACCOUNT_ORCA_WHIRLPOOL)
266
+ or event_type_filter.should_include(EventType.ACCOUNT_ORCA_POSITION)
267
+ or event_type_filter.should_include(EventType.ACCOUNT_ORCA_TICK_ARRAY)
268
+ or event_type_filter.should_include(EventType.ACCOUNT_ORCA_FEE_TIER)
269
+ or event_type_filter.should_include(EventType.ACCOUNT_ORCA_WHIRLPOOLS_CONFIG)
270
+ )
271
+ if should_parse_orca:
272
+ ev = parse_orca_whirlpool_account(account, metadata)
273
+ if ev is not None:
274
+ return _filter_account_event(ev, event_type_filter)
275
+ return None
208
276
 
209
277
  if acc_utils.is_nonce_account(data):
210
278
  if event_type_filter is not None:
@@ -213,9 +281,11 @@ def parse_account_unified(
213
281
  return _parse_nonce_fast(account, metadata)
214
282
 
215
283
  if event_type_filter is not None:
216
- if not event_type_filter.should_include(EventType.TOKEN_ACCOUNT):
284
+ if not event_type_filter.should_include(
285
+ EventType.TOKEN_ACCOUNT
286
+ ) and not event_type_filter.should_include(EventType.TOKEN_INFO):
217
287
  return None
218
- return parse_token_account(account, metadata)
288
+ return _filter_account_event(parse_token_account(account, metadata), event_type_filter)
219
289
 
220
290
 
221
291
  def _parse_pumpswap_account(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
@@ -706,6 +776,9 @@ def _parse_pumpswap_pool_fast(account: AccountData, metadata: EventMetadata) ->
706
776
 
707
777
 
708
778
  def parse_token_account(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
779
+ if not acc_utils.is_token_program_account(account.owner):
780
+ return None
781
+
709
782
  if len(account.data) <= 100:
710
783
  event = _parse_mint_fast(account, metadata)
711
784
  if event:
@@ -830,12 +903,18 @@ __all__ = [
830
903
  "is_pumpfun_global_account",
831
904
  "parse_pumpswap_global_config",
832
905
  "parse_pumpswap_pool",
906
+ "parse_raydium_clmm_account",
907
+ "parse_raydium_cpmm_account",
908
+ "parse_orca_whirlpool_account",
833
909
  "is_global_config_account",
834
910
  "is_pool_account",
835
911
  "has_discriminator",
836
912
  "PUMPFUN_PROGRAM_ID",
837
913
  "PUMP_FEES_PROGRAM_ID",
838
914
  "PUMPSWAP_PROGRAM_ID",
915
+ "RAYDIUM_CLMM_PROGRAM_ID",
916
+ "RAYDIUM_CPMM_PROGRAM_ID",
917
+ "ORCA_WHIRLPOOL_PROGRAM_ID",
839
918
  "rpc_resolve_user_wallet_pubkey",
840
919
  "user_wallet_pubkey_for_onchain_account",
841
920
  "rpc_wallet",