sol-parser-sdk-python 0.5.7__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 +10 -0
- sol_parser/account_dispatcher.py +79 -0
- sol_parser/account_fillers/meteora.py +10 -2
- sol_parser/account_fillers/raydium.py +3 -2
- sol_parser/account_fillers/raydium_launchlab.py +50 -0
- sol_parser/accounts/__init__.py +47 -2
- sol_parser/dex_parsers.py +648 -68
- sol_parser/event_type_parity.py +4 -0
- sol_parser/event_types.py +221 -3
- sol_parser/grpc_instruction_parser.py +85 -26
- sol_parser/grpc_types.py +12 -0
- sol_parser/inner_instruction_parser.py +5 -7
- sol_parser/instructions.py +213 -49
- sol_parser/log_instr_dedup.py +56 -12
- sol_parser/merger.py +73 -85
- sol_parser/parser.py +11 -0
- sol_parser/pumpfun_fee_enrich.py +2 -0
- sol_parser/rpc_parser.py +30 -4
- {sol_parser_sdk_python-0.5.7.dist-info → sol_parser_sdk_python-0.5.8.dist-info}/METADATA +26 -9
- {sol_parser_sdk_python-0.5.7.dist-info → sol_parser_sdk_python-0.5.8.dist-info}/RECORD +22 -22
- {sol_parser_sdk_python-0.5.7.dist-info → sol_parser_sdk_python-0.5.8.dist-info}/WHEEL +1 -1
- {sol_parser_sdk_python-0.5.7.dist-info → sol_parser_sdk_python-0.5.8.dist-info}/entry_points.txt +0 -0
sol_parser/event_type_parity.py
CHANGED
|
@@ -75,6 +75,10 @@ RUST_EVENT_TYPES = [
|
|
|
75
75
|
"MeteoraDammV2InitializePool",
|
|
76
76
|
"MeteoraDammV2CreatePosition",
|
|
77
77
|
"MeteoraDammV2ClosePosition",
|
|
78
|
+
"MeteoraDammV2UpdateDelegatePermission",
|
|
79
|
+
"MeteoraDammV2WithdrawDeadLiquidityReward",
|
|
80
|
+
"MeteoraDammV2CreateConfig",
|
|
81
|
+
"MeteoraDammV2CreateDynamicConfig",
|
|
78
82
|
"MeteoraDbcSwap",
|
|
79
83
|
"MeteoraDbcInitializePool",
|
|
80
84
|
"MeteoraDbcCurveComplete",
|
sol_parser/event_types.py
CHANGED
|
@@ -153,6 +153,8 @@ class PumpFunTradeEvent(DexEventBase):
|
|
|
153
153
|
quote_amount: int = 0
|
|
154
154
|
virtual_quote_reserves: int = 0
|
|
155
155
|
real_quote_reserves: int = 0
|
|
156
|
+
holder_rewards_bps: int = 0
|
|
157
|
+
holder_rewards: int = 0
|
|
156
158
|
is_cashback_coin: bool = False
|
|
157
159
|
amount: int = 0
|
|
158
160
|
max_sol_cost: int = 0
|
|
@@ -160,6 +162,11 @@ class PumpFunTradeEvent(DexEventBase):
|
|
|
160
162
|
spendable_sol_in: int = 0
|
|
161
163
|
spendable_quote_in: int = 0
|
|
162
164
|
min_tokens_out: int = 0
|
|
165
|
+
# Transaction balance fields (raw units; None when meta unavailable)
|
|
166
|
+
pre_token_balance: Optional[int] = None
|
|
167
|
+
post_token_balance: Optional[int] = None
|
|
168
|
+
pre_sol_balance: Optional[int] = None
|
|
169
|
+
post_sol_balance: Optional[int] = None
|
|
163
170
|
global_account: str = ""
|
|
164
171
|
bonding_curve: str = ""
|
|
165
172
|
bonding_curve_v2: str = ""
|
|
@@ -210,6 +217,8 @@ class PumpFunCreateEvent(DexEventBase):
|
|
|
210
217
|
quote_vault: str = ""
|
|
211
218
|
quote_token_program: str = ""
|
|
212
219
|
virtual_quote_reserves: int = 0
|
|
220
|
+
creator_fee_bps: int = 0
|
|
221
|
+
is_holder_reward: bool = False
|
|
213
222
|
|
|
214
223
|
|
|
215
224
|
@dataclass
|
|
@@ -238,6 +247,8 @@ class PumpFunCreateV2TokenEvent(DexEventBase):
|
|
|
238
247
|
quote_vault: str = ""
|
|
239
248
|
quote_token_program: str = ""
|
|
240
249
|
virtual_quote_reserves: int = 0
|
|
250
|
+
creator_fee_bps: int = 0
|
|
251
|
+
is_holder_reward: bool = False
|
|
241
252
|
mint_authority: str = ""
|
|
242
253
|
associated_bonding_curve: str = ""
|
|
243
254
|
global_account: str = "" # Rust `global` PumpFun global config
|
|
@@ -418,6 +429,13 @@ class PumpSwapBuyEvent(DexEventBase):
|
|
|
418
429
|
mayhem_mode: bool = False
|
|
419
430
|
cashback_fee_basis_points: int = 0
|
|
420
431
|
cashback: int = 0
|
|
432
|
+
buyback_fee_basis_points: int = 0
|
|
433
|
+
buyback_fee: int = 0
|
|
434
|
+
virtual_quote_reserves: int = 0
|
|
435
|
+
can_boost: bool = False
|
|
436
|
+
base_supply: int = 0
|
|
437
|
+
holder_rewards_bps: int = 0
|
|
438
|
+
holder_rewards: int = 0
|
|
421
439
|
is_cashback_coin: bool = False
|
|
422
440
|
base_mint: str = ""
|
|
423
441
|
quote_mint: str = ""
|
|
@@ -461,6 +479,13 @@ class PumpSwapSellEvent(DexEventBase):
|
|
|
461
479
|
coin_creator_fee: int = 0
|
|
462
480
|
cashback_fee_basis_points: int = 0
|
|
463
481
|
cashback: int = 0
|
|
482
|
+
buyback_fee_basis_points: int = 0
|
|
483
|
+
buyback_fee: int = 0
|
|
484
|
+
virtual_quote_reserves: int = 0
|
|
485
|
+
can_boost: bool = False
|
|
486
|
+
base_supply: int = 0
|
|
487
|
+
holder_rewards_bps: int = 0
|
|
488
|
+
holder_rewards: int = 0
|
|
464
489
|
base_mint: str = ""
|
|
465
490
|
quote_mint: str = ""
|
|
466
491
|
pool_base_token_account: str = ""
|
|
@@ -499,6 +524,10 @@ class PumpSwapCreatePoolEvent(DexEventBase):
|
|
|
499
524
|
user_quote_token_account: str = ""
|
|
500
525
|
coin_creator: str = ""
|
|
501
526
|
is_mayhem_mode: bool = False
|
|
527
|
+
is_cashback_coin: bool = False
|
|
528
|
+
creator_fee_bps: int = 0
|
|
529
|
+
can_edit_creator_fee: bool = False
|
|
530
|
+
is_holder_reward: bool = False
|
|
502
531
|
|
|
503
532
|
|
|
504
533
|
@dataclass
|
|
@@ -997,6 +1026,12 @@ class OrcaWhirlpoolPoolInitializedEvent(DexEventBase):
|
|
|
997
1026
|
@dataclass
|
|
998
1027
|
class MeteoraDlmmSwapEvent(DexEventBase):
|
|
999
1028
|
"""Meteora DLMM 交换事件"""
|
|
1029
|
+
# Instruction / account context (not in Borsh event payload)
|
|
1030
|
+
token_x_mint: str = ""
|
|
1031
|
+
token_y_mint: str = ""
|
|
1032
|
+
user_token_in: str = ""
|
|
1033
|
+
user_token_out: str = ""
|
|
1034
|
+
min_amount_out: int = 0
|
|
1000
1035
|
pool: str = ""
|
|
1001
1036
|
from_addr: str = ""
|
|
1002
1037
|
start_bin_id: int = 0
|
|
@@ -1141,10 +1176,14 @@ class MeteoraPoolsPoolCreatedEvent(DexEventBase):
|
|
|
1141
1176
|
|
|
1142
1177
|
@dataclass
|
|
1143
1178
|
class MeteoraDammV2SwapEvent(DexEventBase):
|
|
1144
|
-
"""Meteora DAMM v2
|
|
1179
|
+
"""Meteora DAMM v2 交换事件(含 EvtSwap / EvtSwap2 全字段)"""
|
|
1145
1180
|
pool: str = ""
|
|
1146
1181
|
trade_direction: int = 0
|
|
1182
|
+
collect_fee_mode: int = 0
|
|
1147
1183
|
has_referral: bool = False
|
|
1184
|
+
amount_0: int = 0
|
|
1185
|
+
amount_1: int = 0
|
|
1186
|
+
swap_mode: int = 0
|
|
1148
1187
|
amount_in: int = 0
|
|
1149
1188
|
minimum_amount_out: int = 0
|
|
1150
1189
|
output_amount: int = 0
|
|
@@ -1154,7 +1193,16 @@ class MeteoraDammV2SwapEvent(DexEventBase):
|
|
|
1154
1193
|
partner_fee: int = 0
|
|
1155
1194
|
referral_fee: int = 0
|
|
1156
1195
|
actual_amount_in: int = 0
|
|
1196
|
+
excluded_fee_input_amount: int = 0
|
|
1197
|
+
amount_left: int = 0
|
|
1198
|
+
claiming_fee: int = 0
|
|
1199
|
+
compounding_fee: int = 0
|
|
1200
|
+
included_transfer_fee_amount_in: int = 0
|
|
1201
|
+
included_transfer_fee_amount_out: int = 0
|
|
1202
|
+
excluded_transfer_fee_amount_out: int = 0
|
|
1157
1203
|
current_timestamp: int = 0
|
|
1204
|
+
reserve_a_amount: int = 0
|
|
1205
|
+
reserve_b_amount: int = 0
|
|
1158
1206
|
token_a_vault: str = ""
|
|
1159
1207
|
token_b_vault: str = ""
|
|
1160
1208
|
token_a_mint: str = ""
|
|
@@ -1194,6 +1242,8 @@ class MeteoraDammV2AddLiquidityEvent(DexEventBase):
|
|
|
1194
1242
|
token_b_amount: int = 0
|
|
1195
1243
|
total_amount_a: int = 0
|
|
1196
1244
|
total_amount_b: int = 0
|
|
1245
|
+
reserve_a_amount: int = 0
|
|
1246
|
+
reserve_b_amount: int = 0
|
|
1197
1247
|
|
|
1198
1248
|
|
|
1199
1249
|
@dataclass
|
|
@@ -1207,6 +1257,10 @@ class MeteoraDammV2RemoveLiquidityEvent(DexEventBase):
|
|
|
1207
1257
|
token_b_amount_threshold: int = 0
|
|
1208
1258
|
token_a_amount: int = 0
|
|
1209
1259
|
token_b_amount: int = 0
|
|
1260
|
+
total_amount_a: int = 0
|
|
1261
|
+
total_amount_b: int = 0
|
|
1262
|
+
reserve_a_amount: int = 0
|
|
1263
|
+
reserve_b_amount: int = 0
|
|
1210
1264
|
|
|
1211
1265
|
|
|
1212
1266
|
@dataclass
|
|
@@ -1237,6 +1291,62 @@ class MeteoraDammV2InitializePoolEvent(DexEventBase):
|
|
|
1237
1291
|
pool_type: int = 0
|
|
1238
1292
|
|
|
1239
1293
|
|
|
1294
|
+
@dataclass
|
|
1295
|
+
class MeteoraDammV2DynamicFeeParameters:
|
|
1296
|
+
"""DAMM v2 PoolFeeParameters.dynamic_fee"""
|
|
1297
|
+
bin_step: int = 0
|
|
1298
|
+
bin_step_u128: str = "0"
|
|
1299
|
+
filter_period: int = 0
|
|
1300
|
+
decay_period: int = 0
|
|
1301
|
+
reduction_factor: int = 0
|
|
1302
|
+
max_volatility_accumulator: int = 0
|
|
1303
|
+
variable_fee_control: int = 0
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
@dataclass
|
|
1307
|
+
class MeteoraDammV2UpdateDelegatePermissionEvent(DexEventBase):
|
|
1308
|
+
"""Meteora DAMM v2 EvtUpdateDelegatePermission"""
|
|
1309
|
+
position: str = ""
|
|
1310
|
+
owner: str = ""
|
|
1311
|
+
permission: int = 0
|
|
1312
|
+
delegate: Optional[str] = None
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
@dataclass
|
|
1316
|
+
class MeteoraDammV2WithdrawDeadLiquidityRewardEvent(DexEventBase):
|
|
1317
|
+
"""Meteora DAMM v2 EvtWithdrawDeadLiquidityReward"""
|
|
1318
|
+
pool: str = ""
|
|
1319
|
+
reward_mint: str = ""
|
|
1320
|
+
amount: int = 0
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
@dataclass
|
|
1324
|
+
class MeteoraDammV2CreateConfigEvent(DexEventBase):
|
|
1325
|
+
"""Meteora DAMM v2 EvtCreateConfig(含 0.2.4 permission)"""
|
|
1326
|
+
base_fee_data: bytes = field(default_factory=lambda: bytes(27))
|
|
1327
|
+
compounding_fee_bps: int = 0
|
|
1328
|
+
padding: int = 0
|
|
1329
|
+
dynamic_fee: Optional[MeteoraDammV2DynamicFeeParameters] = None
|
|
1330
|
+
vault_config_key: str = ""
|
|
1331
|
+
pool_creator_authority: str = ""
|
|
1332
|
+
activation_type: int = 0
|
|
1333
|
+
sqrt_min_price: str = "0"
|
|
1334
|
+
sqrt_max_price: str = "0"
|
|
1335
|
+
collect_fee_mode: int = 0
|
|
1336
|
+
index: int = 0
|
|
1337
|
+
config: str = ""
|
|
1338
|
+
permission: str = "0"
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
@dataclass
|
|
1342
|
+
class MeteoraDammV2CreateDynamicConfigEvent(DexEventBase):
|
|
1343
|
+
"""Meteora DAMM v2 EvtCreateDynamicConfig"""
|
|
1344
|
+
config: str = ""
|
|
1345
|
+
pool_creator_authority: str = ""
|
|
1346
|
+
index: int = 0
|
|
1347
|
+
permission: str = "0"
|
|
1348
|
+
|
|
1349
|
+
|
|
1240
1350
|
@dataclass
|
|
1241
1351
|
class MeteoraDbcSwapEvent(DexEventBase):
|
|
1242
1352
|
"""Meteora DBC 交易事件"""
|
|
@@ -1289,6 +1399,16 @@ class RaydiumLaunchlabTradeEvent(DexEventBase):
|
|
|
1289
1399
|
is_buy: bool = False
|
|
1290
1400
|
trade_direction: str = ""
|
|
1291
1401
|
exact_in: bool = False
|
|
1402
|
+
global_config: str = ""
|
|
1403
|
+
platform_config: str = ""
|
|
1404
|
+
user_base_token: str = ""
|
|
1405
|
+
user_quote_token: str = ""
|
|
1406
|
+
base_vault: str = ""
|
|
1407
|
+
quote_vault: str = ""
|
|
1408
|
+
base_mint: str = ""
|
|
1409
|
+
quote_mint: str = ""
|
|
1410
|
+
base_token_program: str = ""
|
|
1411
|
+
quote_token_program: str = ""
|
|
1292
1412
|
|
|
1293
1413
|
|
|
1294
1414
|
@dataclass
|
|
@@ -1297,6 +1417,15 @@ class RaydiumLaunchlabPoolCreateEvent(DexEventBase):
|
|
|
1297
1417
|
pool_state: str = ""
|
|
1298
1418
|
creator: str = ""
|
|
1299
1419
|
base_mint_param: Optional[Dict[str, Any]] = None
|
|
1420
|
+
payer: str = ""
|
|
1421
|
+
global_config: str = ""
|
|
1422
|
+
platform_config: str = ""
|
|
1423
|
+
base_mint: str = ""
|
|
1424
|
+
quote_mint: str = ""
|
|
1425
|
+
base_vault: str = ""
|
|
1426
|
+
quote_vault: str = ""
|
|
1427
|
+
base_token_program: str = ""
|
|
1428
|
+
quote_token_program: str = ""
|
|
1300
1429
|
|
|
1301
1430
|
|
|
1302
1431
|
@dataclass
|
|
@@ -1373,6 +1502,10 @@ TypedDexEvent = Union[
|
|
|
1373
1502
|
MeteoraDammV2AddLiquidityEvent,
|
|
1374
1503
|
MeteoraDammV2RemoveLiquidityEvent,
|
|
1375
1504
|
MeteoraDammV2InitializePoolEvent,
|
|
1505
|
+
MeteoraDammV2UpdateDelegatePermissionEvent,
|
|
1506
|
+
MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
|
|
1507
|
+
MeteoraDammV2CreateConfigEvent,
|
|
1508
|
+
MeteoraDammV2CreateDynamicConfigEvent,
|
|
1376
1509
|
RaydiumLaunchlabTradeEvent,
|
|
1377
1510
|
RaydiumLaunchlabPoolCreateEvent,
|
|
1378
1511
|
RaydiumLaunchlabMigrateAmmEvent,
|
|
@@ -1409,11 +1542,20 @@ def _get_int(m: dict, key: str) -> int:
|
|
|
1409
1542
|
v = m.get(key, 0)
|
|
1410
1543
|
if isinstance(v, int):
|
|
1411
1544
|
return v
|
|
1412
|
-
if isinstance(v, str)
|
|
1413
|
-
|
|
1545
|
+
if isinstance(v, str):
|
|
1546
|
+
try:
|
|
1547
|
+
return int(v, 10)
|
|
1548
|
+
except ValueError:
|
|
1549
|
+
pass
|
|
1414
1550
|
return 0
|
|
1415
1551
|
|
|
1416
1552
|
|
|
1553
|
+
def _get_optional_int(m: dict, key: str) -> Optional[int]:
|
|
1554
|
+
if key not in m or m.get(key) is None:
|
|
1555
|
+
return None
|
|
1556
|
+
return _get_int(m, key)
|
|
1557
|
+
|
|
1558
|
+
|
|
1417
1559
|
def _get_bool(m: dict, key: str) -> bool:
|
|
1418
1560
|
v = m.get(key, False)
|
|
1419
1561
|
return bool(v)
|
|
@@ -1517,6 +1659,8 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1517
1659
|
quote_amount=_get_int(data, "quote_amount"),
|
|
1518
1660
|
virtual_quote_reserves=_get_int(data, "virtual_quote_reserves"),
|
|
1519
1661
|
real_quote_reserves=_get_int(data, "real_quote_reserves"),
|
|
1662
|
+
holder_rewards_bps=_get_int(data, "holder_rewards_bps"),
|
|
1663
|
+
holder_rewards=_get_int(data, "holder_rewards"),
|
|
1520
1664
|
is_cashback_coin=_get_bool(data, "is_cashback_coin"),
|
|
1521
1665
|
amount=_get_int(data, "amount"),
|
|
1522
1666
|
max_sol_cost=_get_int(data, "max_sol_cost"),
|
|
@@ -1524,6 +1668,10 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1524
1668
|
spendable_sol_in=_get_int(data, "spendable_sol_in"),
|
|
1525
1669
|
spendable_quote_in=_get_int(data, "spendable_quote_in"),
|
|
1526
1670
|
min_tokens_out=_get_int(data, "min_tokens_out"),
|
|
1671
|
+
pre_token_balance=_get_optional_int(data, "pre_token_balance"),
|
|
1672
|
+
post_token_balance=_get_optional_int(data, "post_token_balance"),
|
|
1673
|
+
pre_sol_balance=_get_optional_int(data, "pre_sol_balance"),
|
|
1674
|
+
post_sol_balance=_get_optional_int(data, "post_sol_balance"),
|
|
1527
1675
|
global_account=_get_str(data, "global") or _get_str(data, "global_account"),
|
|
1528
1676
|
bonding_curve=_get_str(data, "bonding_curve"),
|
|
1529
1677
|
bonding_curve_v2=_get_str(data, "bonding_curve_v2"),
|
|
@@ -1573,6 +1721,8 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1573
1721
|
quote_vault=_get_str(data, "quote_vault"),
|
|
1574
1722
|
quote_token_program=_get_str(data, "quote_token_program"),
|
|
1575
1723
|
virtual_quote_reserves=_get_int(data, "virtual_quote_reserves"),
|
|
1724
|
+
creator_fee_bps=_get_int(data, "creator_fee_bps"),
|
|
1725
|
+
is_holder_reward=_get_bool(data, "is_holder_reward"),
|
|
1576
1726
|
)
|
|
1577
1727
|
|
|
1578
1728
|
if event_type == EventType.PUMP_FUN_CREATE_V2:
|
|
@@ -1598,6 +1748,8 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1598
1748
|
quote_vault=_get_str(data, "quote_vault"),
|
|
1599
1749
|
quote_token_program=_get_str(data, "quote_token_program"),
|
|
1600
1750
|
virtual_quote_reserves=_get_int(data, "virtual_quote_reserves"),
|
|
1751
|
+
creator_fee_bps=_get_int(data, "creator_fee_bps"),
|
|
1752
|
+
is_holder_reward=_get_bool(data, "is_holder_reward"),
|
|
1601
1753
|
mint_authority=_get_str(data, "mint_authority"),
|
|
1602
1754
|
associated_bonding_curve=_get_str(data, "associated_bonding_curve"),
|
|
1603
1755
|
global_account=g,
|
|
@@ -1663,6 +1815,13 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1663
1815
|
mayhem_mode=_get_bool(data, "mayhem_mode"),
|
|
1664
1816
|
cashback_fee_basis_points=_get_int(data, "cashback_fee_basis_points"),
|
|
1665
1817
|
cashback=_get_int(data, "cashback"),
|
|
1818
|
+
buyback_fee_basis_points=_get_int(data, "buyback_fee_basis_points"),
|
|
1819
|
+
buyback_fee=_get_int(data, "buyback_fee"),
|
|
1820
|
+
virtual_quote_reserves=_get_int(data, "virtual_quote_reserves"),
|
|
1821
|
+
can_boost=_get_bool(data, "can_boost"),
|
|
1822
|
+
base_supply=_get_int(data, "base_supply"),
|
|
1823
|
+
holder_rewards_bps=_get_int(data, "holder_rewards_bps"),
|
|
1824
|
+
holder_rewards=_get_int(data, "holder_rewards"),
|
|
1666
1825
|
is_cashback_coin=_get_bool(data, "is_cashback_coin"),
|
|
1667
1826
|
is_pump_pool=_get_bool(data, "is_pump_pool"),
|
|
1668
1827
|
base_mint=_get_str(data, "base_mint"),
|
|
@@ -1706,6 +1865,13 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1706
1865
|
coin_creator_fee=_get_int(data, "coin_creator_fee"),
|
|
1707
1866
|
cashback_fee_basis_points=_get_int(data, "cashback_fee_basis_points"),
|
|
1708
1867
|
cashback=_get_int(data, "cashback"),
|
|
1868
|
+
buyback_fee_basis_points=_get_int(data, "buyback_fee_basis_points"),
|
|
1869
|
+
buyback_fee=_get_int(data, "buyback_fee"),
|
|
1870
|
+
virtual_quote_reserves=_get_int(data, "virtual_quote_reserves"),
|
|
1871
|
+
can_boost=_get_bool(data, "can_boost"),
|
|
1872
|
+
base_supply=_get_int(data, "base_supply"),
|
|
1873
|
+
holder_rewards_bps=_get_int(data, "holder_rewards_bps"),
|
|
1874
|
+
holder_rewards=_get_int(data, "holder_rewards"),
|
|
1709
1875
|
is_pump_pool=_get_bool(data, "is_pump_pool"),
|
|
1710
1876
|
base_mint=_get_str(data, "base_mint"),
|
|
1711
1877
|
quote_mint=_get_str(data, "quote_mint"),
|
|
@@ -1744,6 +1910,10 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1744
1910
|
user_quote_token_account=_get_str(data, "user_quote_token_account"),
|
|
1745
1911
|
coin_creator=_get_str(data, "coin_creator"),
|
|
1746
1912
|
is_mayhem_mode=_get_bool(data, "is_mayhem_mode"),
|
|
1913
|
+
is_cashback_coin=_get_bool(data, "is_cashback_coin"),
|
|
1914
|
+
creator_fee_bps=_get_int(data, "creator_fee_bps"),
|
|
1915
|
+
can_edit_creator_fee=_get_bool(data, "can_edit_creator_fee"),
|
|
1916
|
+
is_holder_reward=_get_bool(data, "is_holder_reward"),
|
|
1747
1917
|
)
|
|
1748
1918
|
|
|
1749
1919
|
if event_type == EventType.PUMP_SWAP_LIQUIDITY_ADDED:
|
|
@@ -1801,6 +1971,35 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
1801
1971
|
return MeteoraDammV2ClosePositionEvent(metadata=meta, pool=_get_str(data, "pool"))
|
|
1802
1972
|
if event_type == EventType.METEORA_DAMM_V2_INITIALIZE_POOL:
|
|
1803
1973
|
return MeteoraDammV2InitializePoolEvent(metadata=meta, pool=_get_str(data, "pool"))
|
|
1974
|
+
if event_type == EventType.METEORA_DAMM_V2_UPDATE_DELEGATE_PERMISSION:
|
|
1975
|
+
return MeteoraDammV2UpdateDelegatePermissionEvent(
|
|
1976
|
+
metadata=meta,
|
|
1977
|
+
position=_get_str(data, "position"),
|
|
1978
|
+
owner=_get_str(data, "owner"),
|
|
1979
|
+
permission=_get_int(data, "permission"),
|
|
1980
|
+
delegate=data.get("delegate"),
|
|
1981
|
+
)
|
|
1982
|
+
if event_type == EventType.METEORA_DAMM_V2_WITHDRAW_DEAD_LIQUIDITY_REWARD:
|
|
1983
|
+
return MeteoraDammV2WithdrawDeadLiquidityRewardEvent(
|
|
1984
|
+
metadata=meta,
|
|
1985
|
+
pool=_get_str(data, "pool"),
|
|
1986
|
+
reward_mint=_get_str(data, "reward_mint"),
|
|
1987
|
+
amount=_get_int(data, "amount"),
|
|
1988
|
+
)
|
|
1989
|
+
if event_type == EventType.METEORA_DAMM_V2_CREATE_CONFIG:
|
|
1990
|
+
return MeteoraDammV2CreateConfigEvent(
|
|
1991
|
+
metadata=meta,
|
|
1992
|
+
config=_get_str(data, "config"),
|
|
1993
|
+
permission=str(data.get("permission", "0")),
|
|
1994
|
+
)
|
|
1995
|
+
if event_type == EventType.METEORA_DAMM_V2_CREATE_DYNAMIC_CONFIG:
|
|
1996
|
+
return MeteoraDammV2CreateDynamicConfigEvent(
|
|
1997
|
+
metadata=meta,
|
|
1998
|
+
config=_get_str(data, "config"),
|
|
1999
|
+
pool_creator_authority=_get_str(data, "pool_creator_authority"),
|
|
2000
|
+
index=_get_int(data, "index"),
|
|
2001
|
+
permission=str(data.get("permission", "0")),
|
|
2002
|
+
)
|
|
1804
2003
|
|
|
1805
2004
|
if event_type == EventType.RAYDIUM_CLMM_SWAP:
|
|
1806
2005
|
return RaydiumClmmSwapEvent(
|
|
@@ -2124,6 +2323,16 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
2124
2323
|
is_buy=_get_bool(data, "is_buy"),
|
|
2125
2324
|
trade_direction=_get_str(data, "trade_direction"),
|
|
2126
2325
|
exact_in=_get_bool(data, "exact_in"),
|
|
2326
|
+
global_config=_get_str(data, "global_config"),
|
|
2327
|
+
platform_config=_get_str(data, "platform_config"),
|
|
2328
|
+
user_base_token=_get_str(data, "user_base_token"),
|
|
2329
|
+
user_quote_token=_get_str(data, "user_quote_token"),
|
|
2330
|
+
base_vault=_get_str(data, "base_vault"),
|
|
2331
|
+
quote_vault=_get_str(data, "quote_vault"),
|
|
2332
|
+
base_mint=_get_str(data, "base_mint"),
|
|
2333
|
+
quote_mint=_get_str(data, "quote_mint"),
|
|
2334
|
+
base_token_program=_get_str(data, "base_token_program"),
|
|
2335
|
+
quote_token_program=_get_str(data, "quote_token_program"),
|
|
2127
2336
|
)
|
|
2128
2337
|
|
|
2129
2338
|
if event_type == EventType.RAYDIUM_LAUNCHLAB_POOL_CREATE:
|
|
@@ -2132,6 +2341,15 @@ def to_typed_event(event: dict) -> Optional[TypedDexEvent]:
|
|
|
2132
2341
|
pool_state=_get_str(data, "pool_state"),
|
|
2133
2342
|
creator=_get_str(data, "creator"),
|
|
2134
2343
|
base_mint_param=_get_dict_any(data, "base_mint_param"),
|
|
2344
|
+
payer=_get_str(data, "payer"),
|
|
2345
|
+
global_config=_get_str(data, "global_config"),
|
|
2346
|
+
platform_config=_get_str(data, "platform_config"),
|
|
2347
|
+
base_mint=_get_str(data, "base_mint"),
|
|
2348
|
+
quote_mint=_get_str(data, "quote_mint"),
|
|
2349
|
+
base_vault=_get_str(data, "base_vault"),
|
|
2350
|
+
quote_vault=_get_str(data, "quote_vault"),
|
|
2351
|
+
base_token_program=_get_str(data, "base_token_program"),
|
|
2352
|
+
quote_token_program=_get_str(data, "quote_token_program"),
|
|
2135
2353
|
)
|
|
2136
2354
|
|
|
2137
2355
|
if event_type == EventType.RAYDIUM_LAUNCHLAB_MIGRATE_AMM:
|
|
@@ -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
20
|
from .instructions import parse_inner_compiled_instruction_if_supported, parse_instruction_unified
|
|
20
|
-
from .merger import
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
161
|
+
for outer_idx, inner_idx, stack_height, is_dlmm_event_cpi, event in normalized:
|
|
138
162
|
if inner_idx is None:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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[
|
|
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,7 +324,7 @@ 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
|
|
@@ -298,7 +350,13 @@ def parse_instructions_enhanced_from_parsed(
|
|
|
298
350
|
is_created_buy,
|
|
299
351
|
)
|
|
300
352
|
if ev:
|
|
301
|
-
result.append((
|
|
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
|
+
))
|
|
302
360
|
|
|
303
361
|
merged = merge_instruction_events(result)
|
|
304
362
|
enrich_pumpfun_same_tx_post_merge(merged)
|
|
@@ -310,6 +368,7 @@ def parse_instructions_enhanced_from_parsed(
|
|
|
310
368
|
for ev in merged:
|
|
311
369
|
fill_accounts_with_owned_keys(ev, meta, transaction_pb, invokes_raw)
|
|
312
370
|
fill_data(ev, meta, transaction_pb, invokes_str)
|
|
371
|
+
fill_token_balances(ev, meta, transaction_pb)
|
|
313
372
|
|
|
314
373
|
for ev in merged:
|
|
315
374
|
if isinstance(ev.data, object) and hasattr(ev.data, "metadata"):
|
sol_parser/grpc_types.py
CHANGED
|
@@ -115,6 +115,10 @@ class EventType(str, Enum):
|
|
|
115
115
|
METEORA_DAMM_V2_INITIALIZE_POOL = "MeteoraDammV2InitializePool"
|
|
116
116
|
METEORA_DAMM_V2_CREATE_POSITION = "MeteoraDammV2CreatePosition"
|
|
117
117
|
METEORA_DAMM_V2_CLOSE_POSITION = "MeteoraDammV2ClosePosition"
|
|
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"
|
|
118
122
|
# Meteora DBC
|
|
119
123
|
METEORA_DBC_SWAP = "MeteoraDbcSwap"
|
|
120
124
|
METEORA_DBC_INITIALIZE_POOL = "MeteoraDbcInitializePool"
|
|
@@ -206,6 +210,10 @@ METEORA_DAMM_V2_FILTER_TYPES = (
|
|
|
206
210
|
EventType.METEORA_DAMM_V2_CLOSE_POSITION,
|
|
207
211
|
EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
|
|
208
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,
|
|
209
217
|
)
|
|
210
218
|
METEORA_DBC_FILTER_TYPES = (
|
|
211
219
|
EventType.METEORA_DBC_SWAP,
|
|
@@ -372,6 +380,10 @@ def all_event_types() -> List[EventType]:
|
|
|
372
380
|
EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
|
|
373
381
|
EventType.METEORA_DAMM_V2_CREATE_POSITION,
|
|
374
382
|
EventType.METEORA_DAMM_V2_CLOSE_POSITION,
|
|
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,
|
|
375
387
|
# Meteora DBC
|
|
376
388
|
EventType.METEORA_DBC_SWAP,
|
|
377
389
|
EventType.METEORA_DBC_INITIALIZE_POOL,
|
|
@@ -43,7 +43,7 @@ from .dex_parsers import (
|
|
|
43
43
|
parse_cpmm_swap_in_from_data,
|
|
44
44
|
parse_cpmm_swap_out_from_data,
|
|
45
45
|
parse_cpmm_withdraw_from_data,
|
|
46
|
-
|
|
46
|
+
parse_dlmm_event_from_data,
|
|
47
47
|
parse_meteora_damm_from_buf,
|
|
48
48
|
parse_meteora_add_from_data,
|
|
49
49
|
parse_meteora_bootstrap_from_data,
|
|
@@ -184,11 +184,6 @@ def _damm_buf_from_inner(disc16: bytes, inner: bytes) -> bytes:
|
|
|
184
184
|
_RAYDIUM_LAUNCHLAB_TRADE = bytes([189, 219, 127, 211, 78, 230, 97, 238, 155, 167, 108, 32, 122, 76, 173, 64])
|
|
185
185
|
_RAYDIUM_LAUNCHLAB_POOL_CREATE = bytes([151, 215, 226, 9, 118, 161, 115, 174, 155, 167, 108, 32, 122, 76, 173, 64])
|
|
186
186
|
|
|
187
|
-
# DLMM(8 字节 event disc + payload)
|
|
188
|
-
def _dlmm_buf_from_inner(disc16: bytes, inner: bytes) -> bytes:
|
|
189
|
-
return disc16[:8] + inner
|
|
190
|
-
|
|
191
|
-
|
|
192
187
|
def _meteora_pools_swap_inner(data: bytes, meta_d: dict) -> Optional[DexEvent]:
|
|
193
188
|
if len(data) < 16:
|
|
194
189
|
return None
|
|
@@ -440,6 +435,9 @@ def parse_inner_instruction(
|
|
|
440
435
|
if program_id_b58 == METEORA_DLMM_PROGRAM_ID:
|
|
441
436
|
if filter is not None and not event_type_filter_includes_meteora_dlmm(filter):
|
|
442
437
|
return None
|
|
443
|
-
|
|
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))
|
|
444
442
|
|
|
445
443
|
return None
|