sol-parser-sdk-python 0.5.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 +8 -0
- sol_parser/accounts/__init__.py +61 -0
- sol_parser/accounts/raydium_orca.py +515 -0
- sol_parser/dex_parsers.py +186 -0
- sol_parser/event_types.py +39 -0
- sol_parser/grpc_client.py +22 -2
- sol_parser/grpc_instruction_parser.py +7 -17
- sol_parser/instructions.py +6 -1
- sol_parser/parser.py +70 -2
- sol_parser/rpc_parser.py +66 -25
- sol_parser/shredstream_client.py +19 -1
- {sol_parser_sdk_python-0.5.5.dist-info → sol_parser_sdk_python-0.5.6.dist-info}/METADATA +10 -2
- {sol_parser_sdk_python-0.5.5.dist-info → sol_parser_sdk_python-0.5.6.dist-info}/RECORD +15 -14
- {sol_parser_sdk_python-0.5.5.dist-info → sol_parser_sdk_python-0.5.6.dist-info}/WHEEL +0 -0
- {sol_parser_sdk_python-0.5.5.dist-info → sol_parser_sdk_python-0.5.6.dist-info}/entry_points.txt +0 -0
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,
|
|
@@ -142,6 +143,9 @@ from .event_types import (
|
|
|
142
143
|
MeteoraDammV2AddLiquidityEvent,
|
|
143
144
|
MeteoraDammV2RemoveLiquidityEvent,
|
|
144
145
|
MeteoraDammV2InitializePoolEvent,
|
|
146
|
+
MeteoraDbcCurveCompleteEvent,
|
|
147
|
+
MeteoraDbcInitializePoolEvent,
|
|
148
|
+
MeteoraDbcSwapEvent,
|
|
145
149
|
# RaydiumLaunchlab events
|
|
146
150
|
RaydiumLaunchlabTradeEvent,
|
|
147
151
|
RaydiumLaunchlabPoolCreateEvent,
|
|
@@ -235,6 +239,7 @@ __all__ = [
|
|
|
235
239
|
"enrich_dex_events_with_subscribe_tx_info",
|
|
236
240
|
"parse_log_unified",
|
|
237
241
|
"parse_log_optimized",
|
|
242
|
+
"parse_log_optimized_with_program_id",
|
|
238
243
|
"parse_log",
|
|
239
244
|
"parse_logs_only",
|
|
240
245
|
"parse_logs_streaming",
|
|
@@ -409,6 +414,9 @@ __all__ = [
|
|
|
409
414
|
"MeteoraDammV2AddLiquidityEvent",
|
|
410
415
|
"MeteoraDammV2RemoveLiquidityEvent",
|
|
411
416
|
"MeteoraDammV2InitializePoolEvent",
|
|
417
|
+
"MeteoraDbcCurveCompleteEvent",
|
|
418
|
+
"MeteoraDbcInitializePoolEvent",
|
|
419
|
+
"MeteoraDbcSwapEvent",
|
|
412
420
|
"RaydiumLaunchlabTradeEvent",
|
|
413
421
|
"RaydiumLaunchlabPoolCreateEvent",
|
|
414
422
|
"RaydiumLaunchlabMigrateAmmEvent",
|
sol_parser/accounts/__init__.py
CHANGED
|
@@ -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"
|
|
@@ -173,6 +181,16 @@ ACCOUNT_EVENT_TYPES = frozenset(
|
|
|
173
181
|
EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR,
|
|
174
182
|
EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG,
|
|
175
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,
|
|
176
194
|
)
|
|
177
195
|
)
|
|
178
196
|
|
|
@@ -219,6 +237,43 @@ def parse_account_unified(
|
|
|
219
237
|
return _filter_account_event(ev, event_type_filter)
|
|
220
238
|
return None
|
|
221
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
|
|
276
|
+
|
|
222
277
|
if acc_utils.is_nonce_account(data):
|
|
223
278
|
if event_type_filter is not None:
|
|
224
279
|
if not event_type_filter.should_include(EventType.NONCE_ACCOUNT):
|
|
@@ -848,12 +903,18 @@ __all__ = [
|
|
|
848
903
|
"is_pumpfun_global_account",
|
|
849
904
|
"parse_pumpswap_global_config",
|
|
850
905
|
"parse_pumpswap_pool",
|
|
906
|
+
"parse_raydium_clmm_account",
|
|
907
|
+
"parse_raydium_cpmm_account",
|
|
908
|
+
"parse_orca_whirlpool_account",
|
|
851
909
|
"is_global_config_account",
|
|
852
910
|
"is_pool_account",
|
|
853
911
|
"has_discriminator",
|
|
854
912
|
"PUMPFUN_PROGRAM_ID",
|
|
855
913
|
"PUMP_FEES_PROGRAM_ID",
|
|
856
914
|
"PUMPSWAP_PROGRAM_ID",
|
|
915
|
+
"RAYDIUM_CLMM_PROGRAM_ID",
|
|
916
|
+
"RAYDIUM_CPMM_PROGRAM_ID",
|
|
917
|
+
"ORCA_WHIRLPOOL_PROGRAM_ID",
|
|
857
918
|
"rpc_resolve_user_wallet_pubkey",
|
|
858
919
|
"user_wallet_pubkey_for_onchain_account",
|
|
859
920
|
"rpc_wallet",
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
"""Raydium CLMM/CPMM and Orca Whirlpool account parsers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import struct
|
|
6
|
+
from typing import Any, Callable, Optional, TypeVar
|
|
7
|
+
|
|
8
|
+
import base58
|
|
9
|
+
|
|
10
|
+
from ..dex_parsers import DexEvent
|
|
11
|
+
from ..grpc_types import EventMetadata, EventType
|
|
12
|
+
|
|
13
|
+
RAYDIUM_CLMM_PROGRAM_ID = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"
|
|
14
|
+
RAYDIUM_CPMM_PROGRAM_ID = "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"
|
|
15
|
+
ORCA_WHIRLPOOL_PROGRAM_ID = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"
|
|
16
|
+
|
|
17
|
+
CLMM_AMM_CONFIG_DISC = bytes([218, 244, 33, 104, 203, 203, 43, 111])
|
|
18
|
+
CLMM_POOL_STATE_DISC = bytes([247, 237, 227, 245, 215, 195, 222, 70])
|
|
19
|
+
CLMM_TICK_ARRAY_STATE_DISC = bytes([192, 155, 85, 205, 49, 249, 129, 42])
|
|
20
|
+
CLMM_AMM_CONFIG_BODY = 109
|
|
21
|
+
CLMM_POOL_STATE_BODY = 1536
|
|
22
|
+
CLMM_TICK_ARRAY_STATE_BODY = 10232
|
|
23
|
+
CLMM_TICK_ARRAY_LEN = 60
|
|
24
|
+
|
|
25
|
+
CPMM_AMM_CONFIG_DISC = CLMM_AMM_CONFIG_DISC
|
|
26
|
+
CPMM_POOL_STATE_DISC = CLMM_POOL_STATE_DISC
|
|
27
|
+
CPMM_AMM_CONFIG_BODY = 228
|
|
28
|
+
CPMM_POOL_STATE_BODY = 629
|
|
29
|
+
|
|
30
|
+
ORCA_WHIRLPOOL_DISC = bytes([63, 149, 209, 12, 225, 128, 99, 9])
|
|
31
|
+
ORCA_POSITION_DISC = bytes([170, 188, 143, 228, 122, 64, 247, 208])
|
|
32
|
+
ORCA_TICK_ARRAY_DISC = bytes([69, 97, 189, 190, 110, 7, 66, 187])
|
|
33
|
+
ORCA_FEE_TIER_DISC = bytes([56, 75, 159, 76, 142, 68, 190, 105])
|
|
34
|
+
ORCA_WHIRLPOOLS_CONFIG_DISC = bytes([157, 20, 49, 224, 217, 87, 193, 254])
|
|
35
|
+
ORCA_WHIRLPOOL_BODY = 645
|
|
36
|
+
ORCA_POSITION_BODY = 208
|
|
37
|
+
ORCA_TICK_ARRAY_BODY = 9980
|
|
38
|
+
ORCA_FEE_TIER_BODY = 36
|
|
39
|
+
ORCA_WHIRLPOOLS_CONFIG_BODY = 98
|
|
40
|
+
ORCA_TICK_ARRAY_LEN = 88
|
|
41
|
+
|
|
42
|
+
T = TypeVar("T")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Reader:
|
|
46
|
+
def __init__(self, data: bytes):
|
|
47
|
+
self.data = data
|
|
48
|
+
self.offset = 0
|
|
49
|
+
|
|
50
|
+
def _take(self, size: int) -> int:
|
|
51
|
+
if self.offset + size > len(self.data):
|
|
52
|
+
raise ValueError("account data is truncated")
|
|
53
|
+
start = self.offset
|
|
54
|
+
self.offset += size
|
|
55
|
+
return start
|
|
56
|
+
|
|
57
|
+
def u8(self) -> int:
|
|
58
|
+
return self.data[self._take(1)]
|
|
59
|
+
|
|
60
|
+
def bool(self) -> bool:
|
|
61
|
+
return self.u8() != 0
|
|
62
|
+
|
|
63
|
+
def u16(self) -> int:
|
|
64
|
+
return struct.unpack_from("<H", self.data, self._take(2))[0]
|
|
65
|
+
|
|
66
|
+
def u32(self) -> int:
|
|
67
|
+
return struct.unpack_from("<I", self.data, self._take(4))[0]
|
|
68
|
+
|
|
69
|
+
def i32(self) -> int:
|
|
70
|
+
return struct.unpack_from("<i", self.data, self._take(4))[0]
|
|
71
|
+
|
|
72
|
+
def u64(self) -> int:
|
|
73
|
+
return struct.unpack_from("<Q", self.data, self._take(8))[0]
|
|
74
|
+
|
|
75
|
+
def u128(self) -> int:
|
|
76
|
+
start = self._take(16)
|
|
77
|
+
return int.from_bytes(self.data[start : start + 16], "little", signed=False)
|
|
78
|
+
|
|
79
|
+
def i128(self) -> int:
|
|
80
|
+
start = self._take(16)
|
|
81
|
+
return int.from_bytes(self.data[start : start + 16], "little", signed=True)
|
|
82
|
+
|
|
83
|
+
def pubkey(self) -> str:
|
|
84
|
+
start = self._take(32)
|
|
85
|
+
return base58.b58encode(self.data[start : start + 32]).decode("ascii")
|
|
86
|
+
|
|
87
|
+
def bytes(self, length: int) -> list[int]:
|
|
88
|
+
start = self._take(length)
|
|
89
|
+
return list(self.data[start : start + length])
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _event(event_type: EventType, data: dict[str, Any]) -> DexEvent:
|
|
93
|
+
return DexEvent(type=event_type, data=data)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _parse_body(data: bytes, parse: Callable[[Reader], T]) -> Optional[T]:
|
|
97
|
+
try:
|
|
98
|
+
return parse(Reader(data))
|
|
99
|
+
except (IndexError, struct.error, ValueError):
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _body_after_discriminator(data: bytes, disc: bytes, body_size: int) -> Optional[bytes]:
|
|
104
|
+
if len(data) < 8 + body_size or not data.startswith(disc):
|
|
105
|
+
return None
|
|
106
|
+
return data[8:]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _array(count: int, read: Callable[[], T]) -> list[T]:
|
|
110
|
+
return [read() for _ in range(count)]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def parse_raydium_clmm_account(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
114
|
+
if account.owner != RAYDIUM_CLMM_PROGRAM_ID:
|
|
115
|
+
return None
|
|
116
|
+
return (
|
|
117
|
+
parse_raydium_clmm_amm_config(account, metadata)
|
|
118
|
+
or parse_raydium_clmm_pool_state(account, metadata)
|
|
119
|
+
or parse_raydium_clmm_tick_array_state(account, metadata)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def parse_raydium_cpmm_account(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
124
|
+
if account.owner != RAYDIUM_CPMM_PROGRAM_ID:
|
|
125
|
+
return None
|
|
126
|
+
return parse_raydium_cpmm_amm_config(account, metadata) or parse_raydium_cpmm_pool_state(
|
|
127
|
+
account, metadata
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def parse_orca_whirlpool_account(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
132
|
+
if account.owner != ORCA_WHIRLPOOL_PROGRAM_ID:
|
|
133
|
+
return None
|
|
134
|
+
return (
|
|
135
|
+
parse_orca_whirlpool(account, metadata)
|
|
136
|
+
or parse_orca_position(account, metadata)
|
|
137
|
+
or parse_orca_tick_array(account, metadata)
|
|
138
|
+
or parse_orca_fee_tier(account, metadata)
|
|
139
|
+
or parse_orca_whirlpools_config(account, metadata)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def parse_raydium_clmm_amm_config(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
144
|
+
body = _body_after_discriminator(account.data, CLMM_AMM_CONFIG_DISC, CLMM_AMM_CONFIG_BODY)
|
|
145
|
+
if body is None:
|
|
146
|
+
return None
|
|
147
|
+
amm_config = _parse_body(
|
|
148
|
+
body,
|
|
149
|
+
lambda r: {
|
|
150
|
+
"bump": r.u8(),
|
|
151
|
+
"index": r.u16(),
|
|
152
|
+
"owner": r.pubkey(),
|
|
153
|
+
"protocol_fee_rate": r.u32(),
|
|
154
|
+
"trade_fee_rate": r.u32(),
|
|
155
|
+
"tick_spacing": r.u16(),
|
|
156
|
+
"fund_fee_rate": r.u32(),
|
|
157
|
+
"padding_u32": r.u32(),
|
|
158
|
+
"fund_owner": r.pubkey(),
|
|
159
|
+
"padding": _array(3, r.u64),
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
if amm_config is None:
|
|
163
|
+
return None
|
|
164
|
+
return _event(
|
|
165
|
+
EventType.ACCOUNT_RAYDIUM_CLMM_AMM_CONFIG,
|
|
166
|
+
{"metadata": metadata, "pubkey": account.pubkey, "amm_config": amm_config},
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def parse_raydium_clmm_pool_state(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
171
|
+
body = _body_after_discriminator(account.data, CLMM_POOL_STATE_DISC, CLMM_POOL_STATE_BODY)
|
|
172
|
+
if body is None:
|
|
173
|
+
return None
|
|
174
|
+
pool_state = _parse_body(body, _read_clmm_pool_state)
|
|
175
|
+
if pool_state is None:
|
|
176
|
+
return None
|
|
177
|
+
return _event(
|
|
178
|
+
EventType.ACCOUNT_RAYDIUM_CLMM_POOL_STATE,
|
|
179
|
+
{"metadata": metadata, "pubkey": account.pubkey, "pool_state": pool_state},
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _read_clmm_pool_state(r: Reader) -> dict[str, Any]:
|
|
184
|
+
return {
|
|
185
|
+
"bump": [r.u8()],
|
|
186
|
+
"amm_config": r.pubkey(),
|
|
187
|
+
"owner": r.pubkey(),
|
|
188
|
+
"token_mint_0": r.pubkey(),
|
|
189
|
+
"token_mint_1": r.pubkey(),
|
|
190
|
+
"token_vault_0": r.pubkey(),
|
|
191
|
+
"token_vault_1": r.pubkey(),
|
|
192
|
+
"observation_key": r.pubkey(),
|
|
193
|
+
"mint_decimals_0": r.u8(),
|
|
194
|
+
"mint_decimals_1": r.u8(),
|
|
195
|
+
"tick_spacing": r.u16(),
|
|
196
|
+
"liquidity": r.u128(),
|
|
197
|
+
"sqrt_price_x64": r.u128(),
|
|
198
|
+
"tick_current": r.i32(),
|
|
199
|
+
"padding3": r.u16(),
|
|
200
|
+
"padding4": r.u16(),
|
|
201
|
+
"fee_growth_global_0_x64": r.u128(),
|
|
202
|
+
"fee_growth_global_1_x64": r.u128(),
|
|
203
|
+
"protocol_fees_token_0": r.u64(),
|
|
204
|
+
"protocol_fees_token_1": r.u64(),
|
|
205
|
+
"padding5": _array(4, r.u128),
|
|
206
|
+
"status": r.u8(),
|
|
207
|
+
"fee_on": r.u8(),
|
|
208
|
+
"padding": r.bytes(6),
|
|
209
|
+
"reward_infos": _array(3, lambda: _read_clmm_reward_info(r)),
|
|
210
|
+
"tick_array_bitmap": _array(16, r.u64),
|
|
211
|
+
"padding6": _array(4, r.u64),
|
|
212
|
+
"fund_fees_token_0": r.u64(),
|
|
213
|
+
"fund_fees_token_1": r.u64(),
|
|
214
|
+
"open_time": r.u64(),
|
|
215
|
+
"recent_epoch": r.u64(),
|
|
216
|
+
"dynamic_fee_info": _read_clmm_dynamic_fee_info(r),
|
|
217
|
+
"padding1": _array(14, r.u64),
|
|
218
|
+
"padding2": _array(32, r.u64),
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def parse_raydium_clmm_tick_array_state(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
223
|
+
body = _body_after_discriminator(account.data, CLMM_TICK_ARRAY_STATE_DISC, CLMM_TICK_ARRAY_STATE_BODY)
|
|
224
|
+
if body is None:
|
|
225
|
+
return None
|
|
226
|
+
tick_array_state = _parse_body(
|
|
227
|
+
body,
|
|
228
|
+
lambda r: {
|
|
229
|
+
"pool_id": r.pubkey(),
|
|
230
|
+
"start_tick_index": r.i32(),
|
|
231
|
+
"ticks": _array(CLMM_TICK_ARRAY_LEN, lambda: _read_clmm_tick(r)),
|
|
232
|
+
"initialized_tick_count": r.u8(),
|
|
233
|
+
"recent_epoch": r.u64(),
|
|
234
|
+
"padding": r.bytes(107),
|
|
235
|
+
},
|
|
236
|
+
)
|
|
237
|
+
if tick_array_state is None:
|
|
238
|
+
return None
|
|
239
|
+
return _event(
|
|
240
|
+
EventType.ACCOUNT_RAYDIUM_CLMM_TICK_ARRAY_STATE,
|
|
241
|
+
{"metadata": metadata, "pubkey": account.pubkey, "tick_array_state": tick_array_state},
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _read_clmm_reward_info(r: Reader) -> dict[str, Any]:
|
|
246
|
+
return {
|
|
247
|
+
"reward_state": r.u8(),
|
|
248
|
+
"open_time": r.u64(),
|
|
249
|
+
"end_time": r.u64(),
|
|
250
|
+
"last_update_time": r.u64(),
|
|
251
|
+
"emissions_per_second_x64": r.u128(),
|
|
252
|
+
"reward_total_emitted": r.u64(),
|
|
253
|
+
"reward_claimed": r.u64(),
|
|
254
|
+
"token_mint": r.pubkey(),
|
|
255
|
+
"token_vault": r.pubkey(),
|
|
256
|
+
"authority": r.pubkey(),
|
|
257
|
+
"reward_growth_global_x64": r.u128(),
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _read_clmm_dynamic_fee_info(r: Reader) -> dict[str, Any]:
|
|
262
|
+
return {
|
|
263
|
+
"filter_period": r.u16(),
|
|
264
|
+
"decay_period": r.u16(),
|
|
265
|
+
"reduction_factor": r.u16(),
|
|
266
|
+
"dynamic_fee_control": r.u32(),
|
|
267
|
+
"max_volatility_accumulator": r.u32(),
|
|
268
|
+
"tick_spacing_index_reference": r.i32(),
|
|
269
|
+
"volatility_reference": r.u32(),
|
|
270
|
+
"volatility_accumulator": r.u32(),
|
|
271
|
+
"last_update_timestamp": r.u64(),
|
|
272
|
+
"padding": r.bytes(46),
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _read_clmm_tick(r: Reader) -> dict[str, Any]:
|
|
277
|
+
return {
|
|
278
|
+
"tick": r.i32(),
|
|
279
|
+
"liquidity_net": r.i128(),
|
|
280
|
+
"liquidity_gross": r.u128(),
|
|
281
|
+
"fee_growth_outside_0_x64": r.u128(),
|
|
282
|
+
"fee_growth_outside_1_x64": r.u128(),
|
|
283
|
+
"reward_growths_outside_x64": _array(3, r.u128),
|
|
284
|
+
"order_phase": r.u64(),
|
|
285
|
+
"orders_amount": r.u64(),
|
|
286
|
+
"part_filled_orders_remaining": r.u64(),
|
|
287
|
+
"unfilled_ratio_x64": r.u128(),
|
|
288
|
+
"padding": _array(3, r.u32),
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def parse_raydium_cpmm_amm_config(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
293
|
+
body = _body_after_discriminator(account.data, CPMM_AMM_CONFIG_DISC, CPMM_AMM_CONFIG_BODY)
|
|
294
|
+
if body is None:
|
|
295
|
+
return None
|
|
296
|
+
amm_config = _parse_body(
|
|
297
|
+
body,
|
|
298
|
+
lambda r: {
|
|
299
|
+
"bump": r.u8(),
|
|
300
|
+
"disable_create_pool": r.bool(),
|
|
301
|
+
"index": r.u16(),
|
|
302
|
+
"trade_fee_rate": r.u64(),
|
|
303
|
+
"protocol_fee_rate": r.u64(),
|
|
304
|
+
"fund_fee_rate": r.u64(),
|
|
305
|
+
"create_pool_fee": r.u64(),
|
|
306
|
+
"protocol_owner": r.pubkey(),
|
|
307
|
+
"fund_owner": r.pubkey(),
|
|
308
|
+
"creator_fee_rate": r.u64(),
|
|
309
|
+
"padding": _array(15, r.u64),
|
|
310
|
+
},
|
|
311
|
+
)
|
|
312
|
+
if amm_config is None:
|
|
313
|
+
return None
|
|
314
|
+
return _event(
|
|
315
|
+
EventType.ACCOUNT_RAYDIUM_CPMM_AMM_CONFIG,
|
|
316
|
+
{"metadata": metadata, "pubkey": account.pubkey, "amm_config": amm_config},
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def parse_raydium_cpmm_pool_state(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
321
|
+
body = _body_after_discriminator(account.data, CPMM_POOL_STATE_DISC, CPMM_POOL_STATE_BODY)
|
|
322
|
+
if body is None:
|
|
323
|
+
return None
|
|
324
|
+
pool_state = _parse_body(body, _read_cpmm_pool_state)
|
|
325
|
+
if pool_state is None:
|
|
326
|
+
return None
|
|
327
|
+
return _event(
|
|
328
|
+
EventType.ACCOUNT_RAYDIUM_CPMM_POOL_STATE,
|
|
329
|
+
{"metadata": metadata, "pubkey": account.pubkey, "pool_state": pool_state},
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _read_cpmm_pool_state(r: Reader) -> dict[str, Any]:
|
|
334
|
+
return {
|
|
335
|
+
"amm_config": r.pubkey(),
|
|
336
|
+
"pool_creator": r.pubkey(),
|
|
337
|
+
"token_0_vault": r.pubkey(),
|
|
338
|
+
"token_1_vault": r.pubkey(),
|
|
339
|
+
"lp_mint": r.pubkey(),
|
|
340
|
+
"token_0_mint": r.pubkey(),
|
|
341
|
+
"token_1_mint": r.pubkey(),
|
|
342
|
+
"token_0_program": r.pubkey(),
|
|
343
|
+
"token_1_program": r.pubkey(),
|
|
344
|
+
"observation_key": r.pubkey(),
|
|
345
|
+
"auth_bump": r.u8(),
|
|
346
|
+
"status": r.u8(),
|
|
347
|
+
"lp_mint_decimals": r.u8(),
|
|
348
|
+
"mint_0_decimals": r.u8(),
|
|
349
|
+
"mint_1_decimals": r.u8(),
|
|
350
|
+
"lp_supply": r.u64(),
|
|
351
|
+
"protocol_fees_token_0": r.u64(),
|
|
352
|
+
"protocol_fees_token_1": r.u64(),
|
|
353
|
+
"fund_fees_token_0": r.u64(),
|
|
354
|
+
"fund_fees_token_1": r.u64(),
|
|
355
|
+
"open_time": r.u64(),
|
|
356
|
+
"recent_epoch": r.u64(),
|
|
357
|
+
"creator_fee_on": r.u8(),
|
|
358
|
+
"enable_creator_fee": r.bool(),
|
|
359
|
+
"padding1": r.bytes(6),
|
|
360
|
+
"creator_fees_token_0": r.u64(),
|
|
361
|
+
"creator_fees_token_1": r.u64(),
|
|
362
|
+
"padding": _array(28, r.u64),
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def parse_orca_whirlpool(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
367
|
+
body = _body_after_discriminator(account.data, ORCA_WHIRLPOOL_DISC, ORCA_WHIRLPOOL_BODY)
|
|
368
|
+
if body is None:
|
|
369
|
+
return None
|
|
370
|
+
whirlpool = _parse_body(
|
|
371
|
+
body,
|
|
372
|
+
lambda r: {
|
|
373
|
+
"whirlpools_config": r.pubkey(),
|
|
374
|
+
"whirlpool_bump": r.u8(),
|
|
375
|
+
"tick_spacing": r.u16(),
|
|
376
|
+
"tick_spacing_seed": r.bytes(2),
|
|
377
|
+
"fee_rate": r.u16(),
|
|
378
|
+
"protocol_fee_rate": r.u16(),
|
|
379
|
+
"liquidity": r.u128(),
|
|
380
|
+
"sqrt_price": r.u128(),
|
|
381
|
+
"tick_current_index": r.i32(),
|
|
382
|
+
"protocol_fee_owed_a": r.u64(),
|
|
383
|
+
"protocol_fee_owed_b": r.u64(),
|
|
384
|
+
"token_mint_a": r.pubkey(),
|
|
385
|
+
"token_vault_a": r.pubkey(),
|
|
386
|
+
"fee_growth_global_a": r.u128(),
|
|
387
|
+
"token_mint_b": r.pubkey(),
|
|
388
|
+
"token_vault_b": r.pubkey(),
|
|
389
|
+
"fee_growth_global_b": r.u128(),
|
|
390
|
+
"reward_last_updated_timestamp": r.u64(),
|
|
391
|
+
"reward_infos": _array(3, lambda: _read_orca_whirlpool_reward_info(r)),
|
|
392
|
+
},
|
|
393
|
+
)
|
|
394
|
+
if whirlpool is None:
|
|
395
|
+
return None
|
|
396
|
+
return _event(
|
|
397
|
+
EventType.ACCOUNT_ORCA_WHIRLPOOL,
|
|
398
|
+
{"metadata": metadata, "pubkey": account.pubkey, "whirlpool": whirlpool},
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def parse_orca_position(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
403
|
+
body = _body_after_discriminator(account.data, ORCA_POSITION_DISC, ORCA_POSITION_BODY)
|
|
404
|
+
if body is None:
|
|
405
|
+
return None
|
|
406
|
+
position = _parse_body(
|
|
407
|
+
body,
|
|
408
|
+
lambda r: {
|
|
409
|
+
"whirlpool": r.pubkey(),
|
|
410
|
+
"position_mint": r.pubkey(),
|
|
411
|
+
"liquidity": r.u128(),
|
|
412
|
+
"tick_lower_index": r.i32(),
|
|
413
|
+
"tick_upper_index": r.i32(),
|
|
414
|
+
"fee_growth_checkpoint_a": r.u128(),
|
|
415
|
+
"fee_owed_a": r.u64(),
|
|
416
|
+
"fee_growth_checkpoint_b": r.u128(),
|
|
417
|
+
"fee_owed_b": r.u64(),
|
|
418
|
+
"reward_infos": _array(3, lambda: _read_orca_position_reward_info(r)),
|
|
419
|
+
},
|
|
420
|
+
)
|
|
421
|
+
if position is None:
|
|
422
|
+
return None
|
|
423
|
+
return _event(
|
|
424
|
+
EventType.ACCOUNT_ORCA_POSITION,
|
|
425
|
+
{"metadata": metadata, "pubkey": account.pubkey, "position": position},
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def parse_orca_tick_array(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
430
|
+
body = _body_after_discriminator(account.data, ORCA_TICK_ARRAY_DISC, ORCA_TICK_ARRAY_BODY)
|
|
431
|
+
if body is None:
|
|
432
|
+
return None
|
|
433
|
+
tick_array = _parse_body(
|
|
434
|
+
body,
|
|
435
|
+
lambda r: {
|
|
436
|
+
"start_tick_index": r.i32(),
|
|
437
|
+
"ticks": _array(ORCA_TICK_ARRAY_LEN, lambda: _read_orca_tick(r)),
|
|
438
|
+
"whirlpool": r.pubkey(),
|
|
439
|
+
},
|
|
440
|
+
)
|
|
441
|
+
if tick_array is None:
|
|
442
|
+
return None
|
|
443
|
+
return _event(
|
|
444
|
+
EventType.ACCOUNT_ORCA_TICK_ARRAY,
|
|
445
|
+
{"metadata": metadata, "pubkey": account.pubkey, "tick_array": tick_array},
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def parse_orca_fee_tier(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
450
|
+
body = _body_after_discriminator(account.data, ORCA_FEE_TIER_DISC, ORCA_FEE_TIER_BODY)
|
|
451
|
+
if body is None:
|
|
452
|
+
return None
|
|
453
|
+
fee_tier = _parse_body(
|
|
454
|
+
body,
|
|
455
|
+
lambda r: {
|
|
456
|
+
"whirlpools_config": r.pubkey(),
|
|
457
|
+
"tick_spacing": r.u16(),
|
|
458
|
+
"default_fee_rate": r.u16(),
|
|
459
|
+
},
|
|
460
|
+
)
|
|
461
|
+
if fee_tier is None:
|
|
462
|
+
return None
|
|
463
|
+
return _event(
|
|
464
|
+
EventType.ACCOUNT_ORCA_FEE_TIER,
|
|
465
|
+
{"metadata": metadata, "pubkey": account.pubkey, "fee_tier": fee_tier},
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def parse_orca_whirlpools_config(account: Any, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
470
|
+
body = _body_after_discriminator(account.data, ORCA_WHIRLPOOLS_CONFIG_DISC, ORCA_WHIRLPOOLS_CONFIG_BODY)
|
|
471
|
+
if body is None:
|
|
472
|
+
return None
|
|
473
|
+
config = _parse_body(
|
|
474
|
+
body,
|
|
475
|
+
lambda r: {
|
|
476
|
+
"fee_authority": r.pubkey(),
|
|
477
|
+
"collect_protocol_fees_authority": r.pubkey(),
|
|
478
|
+
"reward_emissions_super_authority": r.pubkey(),
|
|
479
|
+
"default_protocol_fee_rate": r.u16(),
|
|
480
|
+
},
|
|
481
|
+
)
|
|
482
|
+
if config is None:
|
|
483
|
+
return None
|
|
484
|
+
return _event(
|
|
485
|
+
EventType.ACCOUNT_ORCA_WHIRLPOOLS_CONFIG,
|
|
486
|
+
{"metadata": metadata, "pubkey": account.pubkey, "config": config},
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def _read_orca_whirlpool_reward_info(r: Reader) -> dict[str, Any]:
|
|
491
|
+
return {
|
|
492
|
+
"mint": r.pubkey(),
|
|
493
|
+
"vault": r.pubkey(),
|
|
494
|
+
"authority": r.pubkey(),
|
|
495
|
+
"emissions_per_second_x64": r.u128(),
|
|
496
|
+
"growth_global_x64": r.u128(),
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _read_orca_position_reward_info(r: Reader) -> dict[str, Any]:
|
|
501
|
+
return {
|
|
502
|
+
"growth_inside_checkpoint": r.u128(),
|
|
503
|
+
"amount_owed": r.u64(),
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def _read_orca_tick(r: Reader) -> dict[str, Any]:
|
|
508
|
+
return {
|
|
509
|
+
"initialized": r.bool(),
|
|
510
|
+
"liquidity_net": r.i128(),
|
|
511
|
+
"liquidity_gross": r.u128(),
|
|
512
|
+
"fee_growth_outside_a": r.u128(),
|
|
513
|
+
"fee_growth_outside_b": r.u128(),
|
|
514
|
+
"reward_growths_outside": _array(3, r.u128),
|
|
515
|
+
}
|