sol-parser-sdk-python 0.4.4__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 +400 -0
- sol_parser/account_dispatcher.py +209 -0
- sol_parser/account_fillers/__init__.py +5 -0
- sol_parser/account_fillers/bonk.py +30 -0
- sol_parser/account_fillers/meteora.py +51 -0
- sol_parser/account_fillers/orca.py +40 -0
- sol_parser/account_fillers/pumpfun.py +97 -0
- sol_parser/account_fillers/pumpswap.py +93 -0
- sol_parser/account_fillers/raydium.py +119 -0
- sol_parser/accounts/__init__.py +461 -0
- sol_parser/accounts/rpc_wallet.py +64 -0
- sol_parser/accounts/utils.py +71 -0
- sol_parser/check_migration.py +18 -0
- sol_parser/clock.py +10 -0
- sol_parser/common/__init__.py +27 -0
- sol_parser/dex_parsers.py +2576 -0
- sol_parser/entries_decode.py +186 -0
- sol_parser/env_config.py +215 -0
- sol_parser/event_types.py +1750 -0
- sol_parser/geyser_pb2.py +148 -0
- sol_parser/geyser_pb2_grpc.py +398 -0
- sol_parser/grpc/__init__.py +61 -0
- sol_parser/grpc/geyser_connect.py +42 -0
- sol_parser/grpc/subscribe_builder.py +133 -0
- sol_parser/grpc/transaction_meta.py +183 -0
- sol_parser/grpc_client.py +870 -0
- sol_parser/grpc_instruction_parser.py +318 -0
- sol_parser/grpc_types.py +919 -0
- sol_parser/inner_instruction_parser.py +281 -0
- sol_parser/instr/__init__.py +15 -0
- sol_parser/instr_account_utils.py +58 -0
- sol_parser/instructions.py +1026 -0
- sol_parser/json_util.py +41 -0
- sol_parser/log_instr_dedup.py +284 -0
- sol_parser/logs/__init__.py +15 -0
- sol_parser/merger.py +233 -0
- sol_parser/order_buffer.py +171 -0
- sol_parser/parser.py +300 -0
- sol_parser/pumpfun_fee_enrich.py +75 -0
- sol_parser/rpc_parser.py +655 -0
- sol_parser/rust_api_inventory.py +42 -0
- sol_parser/rust_event_json.py +50 -0
- sol_parser/shredstream_client.py +191 -0
- sol_parser/shredstream_pb2.py +40 -0
- sol_parser/shredstream_pb2_grpc.py +81 -0
- sol_parser/shredstream_pumpfun.py +296 -0
- sol_parser/solana_storage_pb2.py +75 -0
- sol_parser/solana_storage_pb2_grpc.py +24 -0
- sol_parser/u128_parity.py +115 -0
- sol_parser/verify_discriminators.py +85 -0
- sol_parser_sdk_python-0.4.4.dist-info/METADATA +14 -0
- sol_parser_sdk_python-0.4.4.dist-info/RECORD +54 -0
- sol_parser_sdk_python-0.4.4.dist-info/WHEEL +4 -0
- sol_parser_sdk_python-0.4.4.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: solana-storage.proto
|
|
5
|
+
# Protobuf Python Version: 6.31.0
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
31,
|
|
16
|
+
0,
|
|
17
|
+
'',
|
|
18
|
+
'solana-storage.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14solana-storage.proto\x12\x1dsolana.storage.ConfirmedBlock\"\xa1\x03\n\x0e\x43onfirmedBlock\x12\x1a\n\x12previous_blockhash\x18\x01 \x01(\t\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x13\n\x0bparent_slot\x18\x03 \x01(\x04\x12I\n\x0ctransactions\x18\x04 \x03(\x0b\x32\x33.solana.storage.ConfirmedBlock.ConfirmedTransaction\x12\x36\n\x07rewards\x18\x05 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12@\n\nblock_time\x18\x06 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x07 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x44\n\x0enum_partitions\x18\x08 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions\"\x9b\x01\n\x14\x43onfirmedTransaction\x12?\n\x0btransaction\x18\x01 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.Transaction\x12\x42\n\x04meta\x18\x02 \x01(\x0b\x32\x34.solana.storage.ConfirmedBlock.TransactionStatusMeta\"Z\n\x0bTransaction\x12\x12\n\nsignatures\x18\x01 \x03(\x0c\x12\x37\n\x07message\x18\x02 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Message\"\xad\x02\n\x07Message\x12<\n\x06header\x18\x01 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.MessageHeader\x12\x14\n\x0c\x61\x63\x63ount_keys\x18\x02 \x03(\x0c\x12\x18\n\x10recent_blockhash\x18\x03 \x01(\x0c\x12H\n\x0cinstructions\x18\x04 \x03(\x0b\x32\x32.solana.storage.ConfirmedBlock.CompiledInstruction\x12\x11\n\tversioned\x18\x05 \x01(\x08\x12W\n\x15\x61\x64\x64ress_table_lookups\x18\x06 \x03(\x0b\x32\x38.solana.storage.ConfirmedBlock.MessageAddressTableLookup\"~\n\rMessageHeader\x12\x1f\n\x17num_required_signatures\x18\x01 \x01(\r\x12$\n\x1cnum_readonly_signed_accounts\x18\x02 \x01(\r\x12&\n\x1enum_readonly_unsigned_accounts\x18\x03 \x01(\r\"d\n\x19MessageAddressTableLookup\x12\x13\n\x0b\x61\x63\x63ount_key\x18\x01 \x01(\x0c\x12\x18\n\x10writable_indexes\x18\x02 \x01(\x0c\x12\x18\n\x10readonly_indexes\x18\x03 \x01(\x0c\"\x82\x06\n\x15TransactionStatusMeta\x12<\n\x03\x65rr\x18\x01 \x01(\x0b\x32/.solana.storage.ConfirmedBlock.TransactionError\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x14\n\x0cpre_balances\x18\x03 \x03(\x04\x12\x15\n\rpost_balances\x18\x04 \x03(\x04\x12L\n\x12inner_instructions\x18\x05 \x03(\x0b\x32\x30.solana.storage.ConfirmedBlock.InnerInstructions\x12\x1f\n\x17inner_instructions_none\x18\n \x01(\x08\x12\x14\n\x0clog_messages\x18\x06 \x03(\t\x12\x19\n\x11log_messages_none\x18\x0b \x01(\x08\x12G\n\x12pre_token_balances\x18\x07 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12H\n\x13post_token_balances\x18\x08 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12\x36\n\x07rewards\x18\t \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12!\n\x19loaded_writable_addresses\x18\x0c \x03(\x0c\x12!\n\x19loaded_readonly_addresses\x18\r \x03(\x0c\x12>\n\x0breturn_data\x18\x0e \x01(\x0b\x32).solana.storage.ConfirmedBlock.ReturnData\x12\x18\n\x10return_data_none\x18\x0f \x01(\x08\x12#\n\x16\x63ompute_units_consumed\x18\x10 \x01(\x04H\x00\x88\x01\x01\x12\x17\n\ncost_units\x18\x11 \x01(\x04H\x01\x88\x01\x01\x42\x19\n\x17_compute_units_consumedB\r\n\x0b_cost_units\"\x1f\n\x10TransactionError\x12\x0b\n\x03\x65rr\x18\x01 \x01(\x0c\"i\n\x11InnerInstructions\x12\r\n\x05index\x18\x01 \x01(\r\x12\x45\n\x0cinstructions\x18\x02 \x03(\x0b\x32/.solana.storage.ConfirmedBlock.InnerInstruction\"x\n\x10InnerInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x19\n\x0cstack_height\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x0f\n\r_stack_height\"O\n\x13\x43ompiledInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\"\x9d\x01\n\x0cTokenBalance\x12\x15\n\raccount_index\x18\x01 \x01(\r\x12\x0c\n\x04mint\x18\x02 \x01(\t\x12\x45\n\x0fui_token_amount\x18\x03 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UiTokenAmount\x12\r\n\x05owner\x18\x04 \x01(\t\x12\x12\n\nprogram_id\x18\x05 \x01(\t\"^\n\rUiTokenAmount\x12\x11\n\tui_amount\x18\x01 \x01(\x01\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\r\x12\x0e\n\x06\x61mount\x18\x03 \x01(\t\x12\x18\n\x10ui_amount_string\x18\x04 \x01(\t\".\n\nReturnData\x12\x12\n\nprogram_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"\x94\x01\n\x06Reward\x12\x0e\n\x06pubkey\x18\x01 \x01(\t\x12\x10\n\x08lamports\x18\x02 \x01(\x03\x12\x14\n\x0cpost_balance\x18\x03 \x01(\x04\x12>\n\x0breward_type\x18\x04 \x01(\x0e\x32).solana.storage.ConfirmedBlock.RewardType\x12\x12\n\ncommission\x18\x05 \x01(\t\"\x87\x01\n\x07Rewards\x12\x36\n\x07rewards\x18\x01 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12\x44\n\x0enum_partitions\x18\x02 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions\"\"\n\rUnixTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\"#\n\x0b\x42lockHeight\x12\x14\n\x0c\x62lock_height\x18\x01 \x01(\x04\"\'\n\rNumPartitions\x12\x16\n\x0enum_partitions\x18\x01 \x01(\x04*I\n\nRewardType\x12\x0f\n\x0bUnspecified\x10\x00\x12\x07\n\x03\x46\x65\x65\x10\x01\x12\x08\n\x04Rent\x10\x02\x12\x0b\n\x07Staking\x10\x03\x12\n\n\x06Voting\x10\x04\x42;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protob\x06proto3')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'solana_storage_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'Z9github.com/rpcpool/yellowstone-grpc/examples/golang/proto'
|
|
35
|
+
_globals['_REWARDTYPE']._serialized_start=3082
|
|
36
|
+
_globals['_REWARDTYPE']._serialized_end=3155
|
|
37
|
+
_globals['_CONFIRMEDBLOCK']._serialized_start=56
|
|
38
|
+
_globals['_CONFIRMEDBLOCK']._serialized_end=473
|
|
39
|
+
_globals['_CONFIRMEDTRANSACTION']._serialized_start=476
|
|
40
|
+
_globals['_CONFIRMEDTRANSACTION']._serialized_end=631
|
|
41
|
+
_globals['_TRANSACTION']._serialized_start=633
|
|
42
|
+
_globals['_TRANSACTION']._serialized_end=723
|
|
43
|
+
_globals['_MESSAGE']._serialized_start=726
|
|
44
|
+
_globals['_MESSAGE']._serialized_end=1027
|
|
45
|
+
_globals['_MESSAGEHEADER']._serialized_start=1029
|
|
46
|
+
_globals['_MESSAGEHEADER']._serialized_end=1155
|
|
47
|
+
_globals['_MESSAGEADDRESSTABLELOOKUP']._serialized_start=1157
|
|
48
|
+
_globals['_MESSAGEADDRESSTABLELOOKUP']._serialized_end=1257
|
|
49
|
+
_globals['_TRANSACTIONSTATUSMETA']._serialized_start=1260
|
|
50
|
+
_globals['_TRANSACTIONSTATUSMETA']._serialized_end=2030
|
|
51
|
+
_globals['_TRANSACTIONERROR']._serialized_start=2032
|
|
52
|
+
_globals['_TRANSACTIONERROR']._serialized_end=2063
|
|
53
|
+
_globals['_INNERINSTRUCTIONS']._serialized_start=2065
|
|
54
|
+
_globals['_INNERINSTRUCTIONS']._serialized_end=2170
|
|
55
|
+
_globals['_INNERINSTRUCTION']._serialized_start=2172
|
|
56
|
+
_globals['_INNERINSTRUCTION']._serialized_end=2292
|
|
57
|
+
_globals['_COMPILEDINSTRUCTION']._serialized_start=2294
|
|
58
|
+
_globals['_COMPILEDINSTRUCTION']._serialized_end=2373
|
|
59
|
+
_globals['_TOKENBALANCE']._serialized_start=2376
|
|
60
|
+
_globals['_TOKENBALANCE']._serialized_end=2533
|
|
61
|
+
_globals['_UITOKENAMOUNT']._serialized_start=2535
|
|
62
|
+
_globals['_UITOKENAMOUNT']._serialized_end=2629
|
|
63
|
+
_globals['_RETURNDATA']._serialized_start=2631
|
|
64
|
+
_globals['_RETURNDATA']._serialized_end=2677
|
|
65
|
+
_globals['_REWARD']._serialized_start=2680
|
|
66
|
+
_globals['_REWARD']._serialized_end=2828
|
|
67
|
+
_globals['_REWARDS']._serialized_start=2831
|
|
68
|
+
_globals['_REWARDS']._serialized_end=2966
|
|
69
|
+
_globals['_UNIXTIMESTAMP']._serialized_start=2968
|
|
70
|
+
_globals['_UNIXTIMESTAMP']._serialized_end=3002
|
|
71
|
+
_globals['_BLOCKHEIGHT']._serialized_start=3004
|
|
72
|
+
_globals['_BLOCKHEIGHT']._serialized_end=3039
|
|
73
|
+
_globals['_NUMPARTITIONS']._serialized_start=3041
|
|
74
|
+
_globals['_NUMPARTITIONS']._serialized_end=3080
|
|
75
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
GRPC_GENERATED_VERSION = '1.73.1'
|
|
8
|
+
GRPC_VERSION = grpc.__version__
|
|
9
|
+
_version_not_supported = False
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from grpc._utilities import first_version_is_lower
|
|
13
|
+
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
|
14
|
+
except ImportError:
|
|
15
|
+
_version_not_supported = True
|
|
16
|
+
|
|
17
|
+
if _version_not_supported:
|
|
18
|
+
raise RuntimeError(
|
|
19
|
+
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
20
|
+
+ f' but the generated code in solana_storage_pb2_grpc.py depends on'
|
|
21
|
+
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
22
|
+
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
23
|
+
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
24
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""u128 小端十进制字符串与 Go `u128LEDecimalString` 语义一致性的自检(不依赖 Go 运行时)。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import struct
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from .dex_parsers import (
|
|
9
|
+
DLMM_SWAP,
|
|
10
|
+
_u128le_int,
|
|
11
|
+
parse_dlmm_from_program_data,
|
|
12
|
+
parse_orca_traded_from_data,
|
|
13
|
+
)
|
|
14
|
+
from .event_types import MeteoraDlmmSwapEvent, OrcaWhirlpoolSwapEvent
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def verify_u128_le_decimal() -> int:
|
|
18
|
+
"""断言 `_u128le_int` → `str` 与无符号 128 位小端整数值一致。"""
|
|
19
|
+
cases = [
|
|
20
|
+
0,
|
|
21
|
+
1,
|
|
22
|
+
255,
|
|
23
|
+
256,
|
|
24
|
+
10**18,
|
|
25
|
+
2**64 - 1,
|
|
26
|
+
2**127 - 1,
|
|
27
|
+
2**128 - 1,
|
|
28
|
+
]
|
|
29
|
+
buf = bytearray(32)
|
|
30
|
+
for n in cases:
|
|
31
|
+
le = n.to_bytes(16, "little")
|
|
32
|
+
buf[:16] = le
|
|
33
|
+
got = str(_u128le_int(bytes(buf), 0))
|
|
34
|
+
if got != str(n):
|
|
35
|
+
print(
|
|
36
|
+
f"[u128-parity] 失败: 期望十进制 {n!s}, 得到 {got!s}",
|
|
37
|
+
file=sys.stderr,
|
|
38
|
+
)
|
|
39
|
+
return 1
|
|
40
|
+
print("[u128-parity] OK:小端 u128 十进制与 Go u128LEDecimalString 一致")
|
|
41
|
+
return 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def verify_orca_swap_sqrt_decimal_strings() -> int:
|
|
45
|
+
"""合成 OrcaWhirlpoolSwap 载荷,确认 `pre_sqrt_price` / `post_sqrt_price` 为十进制字符串。"""
|
|
46
|
+
meta = {
|
|
47
|
+
"signature": "",
|
|
48
|
+
"slot": 0,
|
|
49
|
+
"tx_index": 0,
|
|
50
|
+
"block_time_us": 0,
|
|
51
|
+
"grpc_recv_us": 0,
|
|
52
|
+
}
|
|
53
|
+
whirlpool = bytes(32)
|
|
54
|
+
pre = (1000).to_bytes(16, "little")
|
|
55
|
+
post = (2000).to_bytes(16, "little")
|
|
56
|
+
tail = b"".join((0).to_bytes(8, "little") for _ in range(6))
|
|
57
|
+
data = whirlpool + b"\x00" + pre + post + tail
|
|
58
|
+
ev = parse_orca_traded_from_data(data, meta)
|
|
59
|
+
if ev is None or not isinstance(ev.data, OrcaWhirlpoolSwapEvent):
|
|
60
|
+
print("[u128-parity] Orca 合成载荷解析失败", file=sys.stderr)
|
|
61
|
+
return 1
|
|
62
|
+
inner = ev.data
|
|
63
|
+
if inner.pre_sqrt_price != "1000" or inner.post_sqrt_price != "2000":
|
|
64
|
+
print(f"[u128-parity] Orca sqrt 字段不符: {inner!r}", file=sys.stderr)
|
|
65
|
+
return 1
|
|
66
|
+
print("[u128-parity] OK:OrcaWhirlpoolSwap u128 字段为十进制字符串")
|
|
67
|
+
return 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def verify_dlmm_swap_fee_bps_decimal_string() -> int:
|
|
71
|
+
"""合成 MeteoraDlmmSwap 载荷,确认 `fee_bps` 为十进制字符串。"""
|
|
72
|
+
meta = {
|
|
73
|
+
"signature": "",
|
|
74
|
+
"slot": 0,
|
|
75
|
+
"tx_index": 0,
|
|
76
|
+
"block_time_us": 0,
|
|
77
|
+
"grpc_recv_us": 0,
|
|
78
|
+
}
|
|
79
|
+
fee_bps_val = 4242
|
|
80
|
+
data = (
|
|
81
|
+
bytes(64)
|
|
82
|
+
+ struct.pack("<ii", 0, 0)
|
|
83
|
+
+ struct.pack("<QQ", 0, 0)
|
|
84
|
+
+ b"\x00"
|
|
85
|
+
+ struct.pack("<QQ", 0, 0)
|
|
86
|
+
+ fee_bps_val.to_bytes(16, "little")
|
|
87
|
+
+ struct.pack("<Q", 0)
|
|
88
|
+
)
|
|
89
|
+
buf = struct.pack("<Q", DLMM_SWAP) + data
|
|
90
|
+
ev = parse_dlmm_from_program_data(buf, meta)
|
|
91
|
+
if ev is None or not isinstance(ev.data, MeteoraDlmmSwapEvent):
|
|
92
|
+
print("[u128-parity] DLMM 合成载荷解析失败", file=sys.stderr)
|
|
93
|
+
return 1
|
|
94
|
+
inner = ev.data
|
|
95
|
+
if inner.fee_bps != str(fee_bps_val):
|
|
96
|
+
print(f"[u128-parity] DLMM fee_bps 不符: {inner!r}", file=sys.stderr)
|
|
97
|
+
return 1
|
|
98
|
+
print("[u128-parity] OK:MeteoraDlmmSwap fee_bps 为十进制字符串")
|
|
99
|
+
return 0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def run_all_u128_checks() -> int:
|
|
103
|
+
if verify_u128_le_decimal() != 0:
|
|
104
|
+
return 1
|
|
105
|
+
if verify_orca_swap_sqrt_decimal_strings() != 0:
|
|
106
|
+
return 1
|
|
107
|
+
return verify_dlmm_swap_fee_bps_decimal_string()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def main() -> None:
|
|
111
|
+
sys.exit(run_all_u128_checks())
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
main()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
校验本包 `dex_parsers.dispatch_program_data` 与 Go matcher 是否覆盖
|
|
3
|
+
Node/TS 快照 `scripts/program-log-discriminators.json` 中的字节序列。
|
|
4
|
+
|
|
5
|
+
用法(在仓库内任意目录均可,依赖 `__file__` 定位)::
|
|
6
|
+
|
|
7
|
+
python3 -m sol_parser.verify_discriminators
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _repo_root() -> Path:
|
|
18
|
+
# sol-parser-sdk-python/sol_parser/verify_discriminators.py -> parents[2] = monorepo root
|
|
19
|
+
return Path(__file__).resolve().parents[2]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _comma_seq(arr: list[int]) -> str:
|
|
23
|
+
return ", ".join(str(b) for b in arr)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> int:
|
|
27
|
+
root = _repo_root()
|
|
28
|
+
snap_candidates = [
|
|
29
|
+
root / "sol-parser-sdk-nodejs/scripts/program-log-discriminators.json",
|
|
30
|
+
root / "sol-parser-sdk-ts/scripts/program-log-discriminators.json",
|
|
31
|
+
]
|
|
32
|
+
snap_path = next((p for p in snap_candidates if p.is_file()), None)
|
|
33
|
+
py_path = root / "sol-parser-sdk-python/sol_parser/dex_parsers.py"
|
|
34
|
+
go_dir = root / "sol-parser-sdk-golang/solparser"
|
|
35
|
+
|
|
36
|
+
if snap_path is None:
|
|
37
|
+
joined = ", ".join(str(p) for p in snap_candidates)
|
|
38
|
+
print(f"[verify-discriminators] 缺少快照,已检查: {joined}", file=sys.stderr)
|
|
39
|
+
return 1
|
|
40
|
+
if not py_path.is_file():
|
|
41
|
+
print(f"[verify-discriminators] 缺少: {py_path}", file=sys.stderr)
|
|
42
|
+
return 1
|
|
43
|
+
if not go_dir.is_dir():
|
|
44
|
+
print(f"[verify-discriminators] 缺少: {go_dir}", file=sys.stderr)
|
|
45
|
+
return 1
|
|
46
|
+
|
|
47
|
+
snap = json.loads(snap_path.read_text(encoding="utf-8"))
|
|
48
|
+
py_text = py_path.read_text(encoding="utf-8")
|
|
49
|
+
go_parts = [p.read_text(encoding="utf-8") for p in sorted(go_dir.glob("*.go"))]
|
|
50
|
+
go_text = "\n".join(go_parts)
|
|
51
|
+
|
|
52
|
+
entries: dict[str, list[int]] = {}
|
|
53
|
+
for block in ("PROGRAM_LOG_DISC", "PUMPSWAP_DISC"):
|
|
54
|
+
for k, arr in snap[block].items():
|
|
55
|
+
if not isinstance(arr, list) or len(arr) != 8:
|
|
56
|
+
print(f"[verify-discriminators] {block}.{k} 须为长度 8 的数组", file=sys.stderr)
|
|
57
|
+
return 1
|
|
58
|
+
entries[f"{block}.{k}"] = [int(x) for x in arr]
|
|
59
|
+
|
|
60
|
+
failed = False
|
|
61
|
+
for label, arr in sorted(entries.items()):
|
|
62
|
+
seq = _comma_seq(arr)
|
|
63
|
+
if seq not in py_text:
|
|
64
|
+
print(f"[verify-discriminators] Python dex_parsers 未出现字节序列: {label} [{seq}]", file=sys.stderr)
|
|
65
|
+
failed = True
|
|
66
|
+
if seq not in go_text:
|
|
67
|
+
print(f"[verify-discriminators] Go solparser 未出现字节序列: {label} [{seq}]", file=sys.stderr)
|
|
68
|
+
failed = True
|
|
69
|
+
|
|
70
|
+
if failed:
|
|
71
|
+
print(
|
|
72
|
+
"[verify-discriminators] 请同步 Node/TS scripts/program-log-discriminators.json、"
|
|
73
|
+
"Go matcher 与 Python dex_parsers。",
|
|
74
|
+
file=sys.stderr,
|
|
75
|
+
)
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
print(
|
|
79
|
+
f"[verify-discriminators] OK:{len(entries)} 条字节序列在 Python dex_parsers 与 Go solparser 中均可找到"
|
|
80
|
+
)
|
|
81
|
+
return 0
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sol-parser-sdk-python
|
|
3
|
+
Version: 0.4.4
|
|
4
|
+
Summary: Solana DEX program log parsing (pure Python, API aligned with sol-parser-sdk)
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: base58>=2.0
|
|
7
|
+
Requires-Dist: grpcio-tools>=1.64.0
|
|
8
|
+
Requires-Dist: grpcio>=1.64.0
|
|
9
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
|
|
12
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
13
|
+
Provides-Extra: shredstream
|
|
14
|
+
Requires-Dist: solders>=0.21.0; extra == 'shredstream'
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
sol_parser/__init__.py,sha256=eJ7E4UG5ImAkLFQWRwyYl2BxiEsH5N_7k4cJj_yP078,12209
|
|
2
|
+
sol_parser/account_dispatcher.py,sha256=QnsCRb0IH3qn-c_Zm9sMVv5rCnaouVNgjpG40UZNXcc,9678
|
|
3
|
+
sol_parser/check_migration.py,sha256=hW2qb-EVVoqBUTH3ARhEkSvP9aHcNEkg3ket7lfMVzQ,415
|
|
4
|
+
sol_parser/clock.py,sha256=RHF99qMerKvEsT55krkftIh-uqy_uTzpgdKCqKBMDmA,278
|
|
5
|
+
sol_parser/dex_parsers.py,sha256=xHrkrq4L7rYH8XEX_2p1WMGO8upzZFL3rtQgweAWGuU,74314
|
|
6
|
+
sol_parser/entries_decode.py,sha256=-eooIYrXOcpNtrSgSEVehY8NkBhwUMnziAR5Wx8S0Nk,5620
|
|
7
|
+
sol_parser/env_config.py,sha256=Lw0SdZuy_MvUaVkyFxS0qPBgMzR9UBbxbN0CVz8nxg4,7296
|
|
8
|
+
sol_parser/event_types.py,sha256=UmEaZ_w2PM3FvHTK4vIhAgGM-shKSp4wFU80mdxY7yk,60872
|
|
9
|
+
sol_parser/geyser_pb2.py,sha256=Hq66wmWxXD2jSbSVQW7vmBRB7nWmR1DuYDMQ6nKgl3o,20123
|
|
10
|
+
sol_parser/geyser_pb2_grpc.py,sha256=ASPmZsCNvyCzt_j4IrhKjSacWUNLVuAiLfpjmyd-2Qc,15322
|
|
11
|
+
sol_parser/grpc_client.py,sha256=eVa_R3jnqOSA-yp9LCkjXFHboDDV2Yyc8p3WhPkmZdo,31215
|
|
12
|
+
sol_parser/grpc_instruction_parser.py,sha256=Fz01WbHbfAMFSpfIu935qgJBg-dmHX2RLBaTM-67svo,11016
|
|
13
|
+
sol_parser/grpc_types.py,sha256=6EKVJHnGPrVQrIPVPVLN7FWiqWbRpqNKGlmEe7wNePI,29975
|
|
14
|
+
sol_parser/inner_instruction_parser.py,sha256=M6Rh6S2IIphyn1_GiTEKYCTnxVQPonk_q_4hwZOwy74,11161
|
|
15
|
+
sol_parser/instr_account_utils.py,sha256=MY8bgoIDiv2yJKeWxqhpfKc3pV4xUFTcYKnSXtnQMWc,1990
|
|
16
|
+
sol_parser/instructions.py,sha256=jiG81vaKgVYYLHr2fDSl6lgoNiSDZK4KZf3Lejw4sKo,37697
|
|
17
|
+
sol_parser/json_util.py,sha256=qq0A5bs-HxxQH6vgg1Kja4tQ8cPaop9uItBcW7Ajox4,1458
|
|
18
|
+
sol_parser/log_instr_dedup.py,sha256=g9nqcMFw8eGjib3eHSOsBlRUu6LszOisJiBfq4j0cdc,10216
|
|
19
|
+
sol_parser/merger.py,sha256=xe-ohG-UBwByIGr-Dr8HRbJRSysvV_UHls13RZoyW2k,9102
|
|
20
|
+
sol_parser/order_buffer.py,sha256=xW-Okii8a9t9tCqbBKtxFh1moTEi7RqycMFO2kwp-d4,6447
|
|
21
|
+
sol_parser/parser.py,sha256=aueK1XF6BMcxhXiw2aPQn_9ohWpVhXaimh9t9AMzq0A,8215
|
|
22
|
+
sol_parser/pumpfun_fee_enrich.py,sha256=rVP5INqafa7u9Z7bM9VbHo0XALuASkIS1FEwn9kniOk,2619
|
|
23
|
+
sol_parser/rpc_parser.py,sha256=cFtMH2DD2ZZVPbq2j4SpCK3cV6_ZdxwFUlht6Zg4tB0,21229
|
|
24
|
+
sol_parser/rust_api_inventory.py,sha256=V5Bx1M3GT-ku_vj_kD6lnbqWExv1K_A00PrmhCFfRec,2257
|
|
25
|
+
sol_parser/rust_event_json.py,sha256=7hho9TGfSOQjHev_8uRa4YHU1hrEsW1RfwcU9qHYz1o,1649
|
|
26
|
+
sol_parser/shredstream_client.py,sha256=xU7MoKzGRSlNPtRbKgGkVWIUMR-xR52KtSe61Un6kqo,6949
|
|
27
|
+
sol_parser/shredstream_pb2.py,sha256=BMrgCTcvRu5sY_QG1nj5AhWK9RL1fqF9Ga0xYihQfio,1703
|
|
28
|
+
sol_parser/shredstream_pb2_grpc.py,sha256=zfRJaDj-76Gbr6tC3x4gFOz6Xpu2fmJFWWcTOTmyIXs,3013
|
|
29
|
+
sol_parser/shredstream_pumpfun.py,sha256=0QsEUqBqKSpM-yiTZYNxCypiFU25l-6XXzYZVid5N4I,9934
|
|
30
|
+
sol_parser/solana_storage_pb2.py,sha256=_mi8CkHCzIc85DZKjI4dApJdEGmLsoNemSrGY2f9m8k,8443
|
|
31
|
+
sol_parser/solana_storage_pb2_grpc.py,sha256=-Gys-K2Kw5Uy3JjtgIXmaYE6YKnXd5ZfBaMHTYQeycA,895
|
|
32
|
+
sol_parser/u128_parity.py,sha256=D8PYuy1l-1QwkIEeGCLvrGfzAfTzpBDcGINxRIJAEPs,3487
|
|
33
|
+
sol_parser/verify_discriminators.py,sha256=oqCBWL065ixBIjhHW255nk4S-F1F0x4zfTzs68nXMqA,3011
|
|
34
|
+
sol_parser/account_fillers/__init__.py,sha256=XNS5Yu-YId17qVPcwHnvg92JuwwDZIfUs_iVEtlC8XM,209
|
|
35
|
+
sol_parser/account_fillers/bonk.py,sha256=HSl2UHn0GH7EymCNgylRqd0zISdTqv9_ZxoVL-hcVBY,708
|
|
36
|
+
sol_parser/account_fillers/meteora.py,sha256=seS80dMIeFE-E0Kd2U50p09w69wDi4sf4UxWFl-WP8U,1159
|
|
37
|
+
sol_parser/account_fillers/orca.py,sha256=2s-hfi20fa5sy6p1rGc7_7NxzkpaleJdqn3YD41aBAw,895
|
|
38
|
+
sol_parser/account_fillers/pumpfun.py,sha256=bB89cWs6ZJlMECyIsjc9I3BTPPPN3_wMfz4SCmznT0E,2881
|
|
39
|
+
sol_parser/account_fillers/pumpswap.py,sha256=76KVjXI7hsOqZazJnB-ytqMq38e63gp0-3IiwvC_LAc,2722
|
|
40
|
+
sol_parser/account_fillers/raydium.py,sha256=j5vNSKAV-8bJuakG2dicc8ao5I-ZD2TEthLM6ooZqQ4,3350
|
|
41
|
+
sol_parser/accounts/__init__.py,sha256=BU2mQgF6IqL56KTob31XZmjAYMAaTDRWIOFptLFihCc,15387
|
|
42
|
+
sol_parser/accounts/rpc_wallet.py,sha256=IT0WEzna9phG7AzhJR8o4GA_BlB4ZvhuDWfCHQcMXwg,1944
|
|
43
|
+
sol_parser/accounts/utils.py,sha256=BAACAIvA2Uz0U26BpYPTalTqiuarXYhkbS-i2o1uJUY,2140
|
|
44
|
+
sol_parser/common/__init__.py,sha256=bAdNd5lDj8CBXKuoIUHzdqUw0zmhBeCGCEH7fZuj_1w,761
|
|
45
|
+
sol_parser/grpc/__init__.py,sha256=1tyV7rLRVs-o_3SKaT1tbdUu5JByJKW0t8bievC6guQ,1796
|
|
46
|
+
sol_parser/grpc/geyser_connect.py,sha256=vgrY-UI75Y7U-Ei6vpwAYkCvKXRfmHN5FQtZSlF8RvA,1474
|
|
47
|
+
sol_parser/grpc/subscribe_builder.py,sha256=fv6_jQAR6Q0seUhXjgcDPnPsG03Bxs59lHGetExBRLI,4383
|
|
48
|
+
sol_parser/grpc/transaction_meta.py,sha256=NmIffIQ1_OIfWGjy6JY-f8pIK5ucjDZXXJryjnlgoQs,5894
|
|
49
|
+
sol_parser/instr/__init__.py,sha256=i4HlMIWmEZu60rDcJnzWxHu30W2M3fGWorHgv-MOpEg,353
|
|
50
|
+
sol_parser/logs/__init__.py,sha256=e1cbhbCNeXy-NZvVsYCpGksBpZf4NJBLmdlky06og-U,349
|
|
51
|
+
sol_parser_sdk_python-0.4.4.dist-info/METADATA,sha256=HNqsrb7yHHaf2m7uEOpgXYbfI-3efwCxJgePTJEsqhg,504
|
|
52
|
+
sol_parser_sdk_python-0.4.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
53
|
+
sol_parser_sdk_python-0.4.4.dist-info/entry_points.txt,sha256=ZGXRb-2jBdc56d8PCAZFiJBLTAzUKFeHPohysJnKVbA,206
|
|
54
|
+
sol_parser_sdk_python-0.4.4.dist-info/RECORD,,
|