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
sol_parser/grpc_types.py
ADDED
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
"""gRPC 类型定义,对齐 yellowstone-grpc 和 TypeScript SDK"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import Enum, IntEnum
|
|
6
|
+
from typing import Any, Dict, List, Optional, Callable
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OrderMode(str, Enum):
|
|
11
|
+
"""gRPC 订阅顺序模式"""
|
|
12
|
+
UNORDERED = "Unordered"
|
|
13
|
+
ORDERED = "Ordered"
|
|
14
|
+
STREAMING_ORDERED = "StreamingOrdered"
|
|
15
|
+
MICRO_BATCH = "MicroBatch"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CommitmentLevel(IntEnum):
|
|
19
|
+
"""Solana 确认级别"""
|
|
20
|
+
PROCESSED = 0
|
|
21
|
+
CONFIRMED = 1
|
|
22
|
+
FINALIZED = 2
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SlotStatus(IntEnum):
|
|
26
|
+
"""Slot 状态"""
|
|
27
|
+
PROCESSED = 0
|
|
28
|
+
CONFIRMED = 1
|
|
29
|
+
FINALIZED = 2
|
|
30
|
+
FIRST_SHRED_RECEIVED = 3
|
|
31
|
+
COMPLETED = 4
|
|
32
|
+
CREATED_BANK = 5
|
|
33
|
+
DEAD = 6
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class EventType(str, Enum):
|
|
37
|
+
"""事件类型"""
|
|
38
|
+
# Block
|
|
39
|
+
BLOCK_META = "BlockMeta"
|
|
40
|
+
# PumpFun
|
|
41
|
+
BONK_TRADE = "BonkTrade"
|
|
42
|
+
BONK_POOL_CREATE = "BonkPoolCreate"
|
|
43
|
+
BONK_MIGRATE_AMM = "BonkMigrateAmm"
|
|
44
|
+
PUMP_FUN_TRADE = "PumpFunTrade"
|
|
45
|
+
PUMP_FUN_BUY = "PumpFunBuy"
|
|
46
|
+
PUMP_FUN_SELL = "PumpFunSell"
|
|
47
|
+
PUMP_FUN_BUY_EXACT_SOL_IN = "PumpFunBuyExactSolIn"
|
|
48
|
+
PUMP_FUN_CREATE = "PumpFunCreate"
|
|
49
|
+
PUMP_FUN_CREATE_V2 = "PumpFunCreateV2"
|
|
50
|
+
PUMP_FUN_COMPLETE = "PumpFunComplete"
|
|
51
|
+
PUMP_FUN_MIGRATE = "PumpFunMigrate"
|
|
52
|
+
PUMP_FEES_CREATE_FEE_SHARING_CONFIG = "PumpFeesCreateFeeSharingConfig"
|
|
53
|
+
PUMP_FEES_INITIALIZE_FEE_CONFIG = "PumpFeesInitializeFeeConfig"
|
|
54
|
+
PUMP_FEES_RESET_FEE_SHARING_CONFIG = "PumpFeesResetFeeSharingConfig"
|
|
55
|
+
PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY = "PumpFeesRevokeFeeSharingAuthority"
|
|
56
|
+
PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY = "PumpFeesTransferFeeSharingAuthority"
|
|
57
|
+
PUMP_FEES_UPDATE_ADMIN = "PumpFeesUpdateAdmin"
|
|
58
|
+
PUMP_FEES_UPDATE_FEE_CONFIG = "PumpFeesUpdateFeeConfig"
|
|
59
|
+
PUMP_FEES_UPDATE_FEE_SHARES = "PumpFeesUpdateFeeShares"
|
|
60
|
+
PUMP_FEES_UPSERT_FEE_TIERS = "PumpFeesUpsertFeeTiers"
|
|
61
|
+
PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR = "PumpFunMigrateBondingCurveCreator"
|
|
62
|
+
# PumpSwap
|
|
63
|
+
PUMP_SWAP_TRADE = "PumpSwapTrade"
|
|
64
|
+
PUMP_SWAP_BUY = "PumpSwapBuy"
|
|
65
|
+
PUMP_SWAP_SELL = "PumpSwapSell"
|
|
66
|
+
PUMP_SWAP_CREATE_POOL = "PumpSwapCreatePool"
|
|
67
|
+
PUMP_SWAP_LIQUIDITY_ADDED = "PumpSwapLiquidityAdded"
|
|
68
|
+
PUMP_SWAP_LIQUIDITY_REMOVED = "PumpSwapLiquidityRemoved"
|
|
69
|
+
# Raydium CLMM
|
|
70
|
+
RAYDIUM_CLMM_SWAP = "RaydiumClmmSwap"
|
|
71
|
+
RAYDIUM_CLMM_INCREASE_LIQUIDITY = "RaydiumClmmIncreaseLiquidity"
|
|
72
|
+
RAYDIUM_CLMM_DECREASE_LIQUIDITY = "RaydiumClmmDecreaseLiquidity"
|
|
73
|
+
RAYDIUM_CLMM_CREATE_POOL = "RaydiumClmmCreatePool"
|
|
74
|
+
RAYDIUM_CLMM_OPEN_POSITION = "RaydiumClmmOpenPosition"
|
|
75
|
+
RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT = "RaydiumClmmOpenPositionWithTokenExtNft"
|
|
76
|
+
RAYDIUM_CLMM_CLOSE_POSITION = "RaydiumClmmClosePosition"
|
|
77
|
+
RAYDIUM_CLMM_COLLECT_FEE = "RaydiumClmmCollectFee"
|
|
78
|
+
# Raydium CPMM
|
|
79
|
+
RAYDIUM_CPMM_SWAP = "RaydiumCpmmSwap"
|
|
80
|
+
RAYDIUM_CPMM_DEPOSIT = "RaydiumCpmmDeposit"
|
|
81
|
+
RAYDIUM_CPMM_WITHDRAW = "RaydiumCpmmWithdraw"
|
|
82
|
+
RAYDIUM_CPMM_INITIALIZE = "RaydiumCpmmInitialize"
|
|
83
|
+
# Raydium AMM V4
|
|
84
|
+
RAYDIUM_AMM_V4_SWAP = "RaydiumAmmV4Swap"
|
|
85
|
+
RAYDIUM_AMM_V4_DEPOSIT = "RaydiumAmmV4Deposit"
|
|
86
|
+
RAYDIUM_AMM_V4_WITHDRAW = "RaydiumAmmV4Withdraw"
|
|
87
|
+
RAYDIUM_AMM_V4_WITHDRAW_PNL = "RaydiumAmmV4WithdrawPnl"
|
|
88
|
+
RAYDIUM_AMM_V4_INITIALIZE2 = "RaydiumAmmV4Initialize2"
|
|
89
|
+
# Orca Whirlpool
|
|
90
|
+
ORCA_WHIRLPOOL_SWAP = "OrcaWhirlpoolSwap"
|
|
91
|
+
ORCA_WHIRLPOOL_LIQUIDITY_INCREASED = "OrcaWhirlpoolLiquidityIncreased"
|
|
92
|
+
ORCA_WHIRLPOOL_LIQUIDITY_DECREASED = "OrcaWhirlpoolLiquidityDecreased"
|
|
93
|
+
ORCA_WHIRLPOOL_POOL_INITIALIZED = "OrcaWhirlpoolPoolInitialized"
|
|
94
|
+
# Meteora Pools
|
|
95
|
+
METEORA_POOLS_SWAP = "MeteoraPoolsSwap"
|
|
96
|
+
METEORA_POOLS_ADD_LIQUIDITY = "MeteoraPoolsAddLiquidity"
|
|
97
|
+
METEORA_POOLS_REMOVE_LIQUIDITY = "MeteoraPoolsRemoveLiquidity"
|
|
98
|
+
METEORA_POOLS_BOOTSTRAP_LIQUIDITY = "MeteoraPoolsBootstrapLiquidity"
|
|
99
|
+
METEORA_POOLS_POOL_CREATED = "MeteoraPoolsPoolCreated"
|
|
100
|
+
METEORA_POOLS_SET_POOL_FEES = "MeteoraPoolsSetPoolFees"
|
|
101
|
+
# Meteora DAMM V2
|
|
102
|
+
METEORA_DAMM_V2_SWAP = "MeteoraDammV2Swap"
|
|
103
|
+
METEORA_DAMM_V2_ADD_LIQUIDITY = "MeteoraDammV2AddLiquidity"
|
|
104
|
+
METEORA_DAMM_V2_REMOVE_LIQUIDITY = "MeteoraDammV2RemoveLiquidity"
|
|
105
|
+
METEORA_DAMM_V2_CREATE_POSITION = "MeteoraDammV2CreatePosition"
|
|
106
|
+
METEORA_DAMM_V2_CLOSE_POSITION = "MeteoraDammV2ClosePosition"
|
|
107
|
+
METEORA_DAMM_V2_INITIALIZE_POOL = "MeteoraDammV2InitializePool"
|
|
108
|
+
# Meteora DLMM
|
|
109
|
+
METEORA_DLMM_SWAP = "MeteoraDlmmSwap"
|
|
110
|
+
METEORA_DLMM_ADD_LIQUIDITY = "MeteoraDlmmAddLiquidity"
|
|
111
|
+
METEORA_DLMM_REMOVE_LIQUIDITY = "MeteoraDlmmRemoveLiquidity"
|
|
112
|
+
METEORA_DLMM_INITIALIZE_POOL = "MeteoraDlmmInitializePool"
|
|
113
|
+
METEORA_DLMM_INITIALIZE_BIN_ARRAY = "MeteoraDlmmInitializeBinArray"
|
|
114
|
+
METEORA_DLMM_CREATE_POSITION = "MeteoraDlmmCreatePosition"
|
|
115
|
+
METEORA_DLMM_CLOSE_POSITION = "MeteoraDlmmClosePosition"
|
|
116
|
+
METEORA_DLMM_CLAIM_FEE = "MeteoraDlmmClaimFee"
|
|
117
|
+
# Account types
|
|
118
|
+
TOKEN_ACCOUNT = "TokenAccount"
|
|
119
|
+
TOKEN_INFO = "TokenInfo"
|
|
120
|
+
NONCE_ACCOUNT = "NonceAccount"
|
|
121
|
+
ACCOUNT_PUMP_FUN_GLOBAL = "AccountPumpFunGlobal"
|
|
122
|
+
ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG = "AccountPumpSwapGlobalConfig"
|
|
123
|
+
ACCOUNT_PUMP_SWAP_POOL = "AccountPumpSwapPool"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def all_event_types() -> List[EventType]:
|
|
127
|
+
"""返回所有支持的事件类型列表"""
|
|
128
|
+
return [
|
|
129
|
+
# Block
|
|
130
|
+
EventType.BLOCK_META,
|
|
131
|
+
# Bonk
|
|
132
|
+
EventType.BONK_TRADE,
|
|
133
|
+
EventType.BONK_POOL_CREATE,
|
|
134
|
+
EventType.BONK_MIGRATE_AMM,
|
|
135
|
+
# PumpFun
|
|
136
|
+
EventType.PUMP_FUN_TRADE,
|
|
137
|
+
EventType.PUMP_FUN_BUY,
|
|
138
|
+
EventType.PUMP_FUN_SELL,
|
|
139
|
+
EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
|
|
140
|
+
EventType.PUMP_FUN_CREATE,
|
|
141
|
+
EventType.PUMP_FUN_CREATE_V2,
|
|
142
|
+
EventType.PUMP_FUN_COMPLETE,
|
|
143
|
+
EventType.PUMP_FUN_MIGRATE,
|
|
144
|
+
EventType.PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
|
|
145
|
+
EventType.PUMP_FEES_INITIALIZE_FEE_CONFIG,
|
|
146
|
+
EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
|
|
147
|
+
EventType.PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
|
|
148
|
+
EventType.PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
|
|
149
|
+
EventType.PUMP_FEES_UPDATE_ADMIN,
|
|
150
|
+
EventType.PUMP_FEES_UPDATE_FEE_CONFIG,
|
|
151
|
+
EventType.PUMP_FEES_UPDATE_FEE_SHARES,
|
|
152
|
+
EventType.PUMP_FEES_UPSERT_FEE_TIERS,
|
|
153
|
+
EventType.PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR,
|
|
154
|
+
# PumpSwap
|
|
155
|
+
EventType.PUMP_SWAP_TRADE,
|
|
156
|
+
EventType.PUMP_SWAP_BUY,
|
|
157
|
+
EventType.PUMP_SWAP_SELL,
|
|
158
|
+
EventType.PUMP_SWAP_CREATE_POOL,
|
|
159
|
+
EventType.PUMP_SWAP_LIQUIDITY_ADDED,
|
|
160
|
+
EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
|
|
161
|
+
# Raydium CLMM
|
|
162
|
+
EventType.RAYDIUM_CLMM_SWAP,
|
|
163
|
+
EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
|
|
164
|
+
EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
|
|
165
|
+
EventType.RAYDIUM_CLMM_CREATE_POOL,
|
|
166
|
+
EventType.RAYDIUM_CLMM_OPEN_POSITION,
|
|
167
|
+
EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT,
|
|
168
|
+
EventType.RAYDIUM_CLMM_CLOSE_POSITION,
|
|
169
|
+
EventType.RAYDIUM_CLMM_COLLECT_FEE,
|
|
170
|
+
# Raydium CPMM
|
|
171
|
+
EventType.RAYDIUM_CPMM_SWAP,
|
|
172
|
+
EventType.RAYDIUM_CPMM_DEPOSIT,
|
|
173
|
+
EventType.RAYDIUM_CPMM_WITHDRAW,
|
|
174
|
+
EventType.RAYDIUM_CPMM_INITIALIZE,
|
|
175
|
+
# Raydium AMM V4
|
|
176
|
+
EventType.RAYDIUM_AMM_V4_SWAP,
|
|
177
|
+
EventType.RAYDIUM_AMM_V4_DEPOSIT,
|
|
178
|
+
EventType.RAYDIUM_AMM_V4_WITHDRAW,
|
|
179
|
+
EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
|
|
180
|
+
EventType.RAYDIUM_AMM_V4_INITIALIZE2,
|
|
181
|
+
# Orca Whirlpool
|
|
182
|
+
EventType.ORCA_WHIRLPOOL_SWAP,
|
|
183
|
+
EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED,
|
|
184
|
+
EventType.ORCA_WHIRLPOOL_LIQUIDITY_DECREASED,
|
|
185
|
+
EventType.ORCA_WHIRLPOOL_POOL_INITIALIZED,
|
|
186
|
+
# Meteora Pools
|
|
187
|
+
EventType.METEORA_POOLS_SWAP,
|
|
188
|
+
EventType.METEORA_POOLS_ADD_LIQUIDITY,
|
|
189
|
+
EventType.METEORA_POOLS_REMOVE_LIQUIDITY,
|
|
190
|
+
EventType.METEORA_POOLS_BOOTSTRAP_LIQUIDITY,
|
|
191
|
+
EventType.METEORA_POOLS_POOL_CREATED,
|
|
192
|
+
EventType.METEORA_POOLS_SET_POOL_FEES,
|
|
193
|
+
# Meteora DAMM V2
|
|
194
|
+
EventType.METEORA_DAMM_V2_SWAP,
|
|
195
|
+
EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
|
|
196
|
+
EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
|
|
197
|
+
EventType.METEORA_DAMM_V2_CREATE_POSITION,
|
|
198
|
+
EventType.METEORA_DAMM_V2_CLOSE_POSITION,
|
|
199
|
+
EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
|
|
200
|
+
# Meteora DLMM
|
|
201
|
+
EventType.METEORA_DLMM_SWAP,
|
|
202
|
+
EventType.METEORA_DLMM_ADD_LIQUIDITY,
|
|
203
|
+
EventType.METEORA_DLMM_REMOVE_LIQUIDITY,
|
|
204
|
+
EventType.METEORA_DLMM_INITIALIZE_POOL,
|
|
205
|
+
EventType.METEORA_DLMM_INITIALIZE_BIN_ARRAY,
|
|
206
|
+
EventType.METEORA_DLMM_CREATE_POSITION,
|
|
207
|
+
EventType.METEORA_DLMM_CLOSE_POSITION,
|
|
208
|
+
EventType.METEORA_DLMM_CLAIM_FEE,
|
|
209
|
+
# Account types
|
|
210
|
+
EventType.TOKEN_ACCOUNT,
|
|
211
|
+
EventType.TOKEN_INFO,
|
|
212
|
+
EventType.NONCE_ACCOUNT,
|
|
213
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL,
|
|
214
|
+
EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG,
|
|
215
|
+
EventType.ACCOUNT_PUMP_SWAP_POOL,
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass
|
|
220
|
+
class EventMetadata:
|
|
221
|
+
"""事件元数据"""
|
|
222
|
+
|
|
223
|
+
signature: str = ""
|
|
224
|
+
slot: int = 0
|
|
225
|
+
#: 区块内交易序号(Yellowstone ``SubscribeUpdateTransactionInfo.index`` / RPC ``transactionIndex``)
|
|
226
|
+
tx_index: int = 0
|
|
227
|
+
block_time_us: int = 0
|
|
228
|
+
grpc_recv_us: int = 0
|
|
229
|
+
recent_blockhash: str = ""
|
|
230
|
+
is_created_buy: bool = False
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@dataclass
|
|
234
|
+
class ClientConfig:
|
|
235
|
+
"""gRPC 客户端配置"""
|
|
236
|
+
enable_metrics: bool = False
|
|
237
|
+
connection_timeout_ms: int = 8000
|
|
238
|
+
request_timeout_ms: int = 15000
|
|
239
|
+
enable_tls: bool = True
|
|
240
|
+
max_retries: int = 3
|
|
241
|
+
retry_delay_ms: int = 1000
|
|
242
|
+
max_concurrent_streams: int = 100
|
|
243
|
+
keep_alive_interval_ms: int = 30000
|
|
244
|
+
keep_alive_timeout_ms: int = 5000
|
|
245
|
+
buffer_size: int = 8192
|
|
246
|
+
order_mode: OrderMode = OrderMode.UNORDERED
|
|
247
|
+
order_timeout_ms: int = 100
|
|
248
|
+
micro_batch_us: int = 100
|
|
249
|
+
|
|
250
|
+
@staticmethod
|
|
251
|
+
def default() -> ClientConfig:
|
|
252
|
+
"""返回默认客户端配置"""
|
|
253
|
+
return ClientConfig()
|
|
254
|
+
|
|
255
|
+
@staticmethod
|
|
256
|
+
def low_latency() -> ClientConfig:
|
|
257
|
+
"""对齐 Rust ``ClientConfig::low_latency``"""
|
|
258
|
+
return ClientConfig(
|
|
259
|
+
enable_metrics=False,
|
|
260
|
+
connection_timeout_ms=5000,
|
|
261
|
+
request_timeout_ms=10000,
|
|
262
|
+
enable_tls=True,
|
|
263
|
+
max_retries=1,
|
|
264
|
+
retry_delay_ms=100,
|
|
265
|
+
max_concurrent_streams=200,
|
|
266
|
+
keep_alive_interval_ms=10000,
|
|
267
|
+
keep_alive_timeout_ms=2000,
|
|
268
|
+
buffer_size=16384,
|
|
269
|
+
order_mode=OrderMode.UNORDERED,
|
|
270
|
+
order_timeout_ms=50,
|
|
271
|
+
micro_batch_us=50,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
@staticmethod
|
|
275
|
+
def high_throughput() -> ClientConfig:
|
|
276
|
+
"""对齐 Rust ``ClientConfig::high_throughput``"""
|
|
277
|
+
return ClientConfig(
|
|
278
|
+
enable_metrics=True,
|
|
279
|
+
connection_timeout_ms=10000,
|
|
280
|
+
request_timeout_ms=30000,
|
|
281
|
+
enable_tls=True,
|
|
282
|
+
max_retries=5,
|
|
283
|
+
retry_delay_ms=2000,
|
|
284
|
+
max_concurrent_streams=500,
|
|
285
|
+
keep_alive_interval_ms=60000,
|
|
286
|
+
keep_alive_timeout_ms=10000,
|
|
287
|
+
buffer_size=32768,
|
|
288
|
+
order_mode=OrderMode.UNORDERED,
|
|
289
|
+
order_timeout_ms=200,
|
|
290
|
+
micro_batch_us=200,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@dataclass
|
|
295
|
+
class TransactionFilter:
|
|
296
|
+
"""交易过滤器"""
|
|
297
|
+
account_include: List[str] = field(default_factory=list)
|
|
298
|
+
account_exclude: List[str] = field(default_factory=list)
|
|
299
|
+
account_required: List[str] = field(default_factory=list)
|
|
300
|
+
vote: Optional[bool] = None
|
|
301
|
+
failed: Optional[bool] = None
|
|
302
|
+
signature: str = ""
|
|
303
|
+
|
|
304
|
+
@staticmethod
|
|
305
|
+
def new() -> TransactionFilter:
|
|
306
|
+
"""创建新的交易过滤器"""
|
|
307
|
+
return TransactionFilter()
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def from_program_ids(program_ids: List[str]) -> TransactionFilter:
|
|
311
|
+
"""对齐 Rust ``TransactionFilter::from_program_ids``"""
|
|
312
|
+
return TransactionFilter(account_include=list(program_ids))
|
|
313
|
+
|
|
314
|
+
def include_account(self, account: str) -> TransactionFilter:
|
|
315
|
+
self.account_include.append(account)
|
|
316
|
+
return self
|
|
317
|
+
|
|
318
|
+
def exclude_account(self, account: str) -> TransactionFilter:
|
|
319
|
+
self.account_exclude.append(account)
|
|
320
|
+
return self
|
|
321
|
+
|
|
322
|
+
def require_account(self, account: str) -> TransactionFilter:
|
|
323
|
+
self.account_required.append(account)
|
|
324
|
+
return self
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class EventTypeFilter:
|
|
328
|
+
"""事件类型过滤器接口"""
|
|
329
|
+
|
|
330
|
+
def should_include(self, event_type: EventType) -> bool:
|
|
331
|
+
raise NotImplementedError
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class IncludeOnlyFilter(EventTypeFilter):
|
|
335
|
+
"""仅包含指定类型的事件过滤器"""
|
|
336
|
+
|
|
337
|
+
def __init__(self, include_only: List[EventType]):
|
|
338
|
+
self.include_only = include_only
|
|
339
|
+
|
|
340
|
+
def should_include(self, event_type: EventType) -> bool:
|
|
341
|
+
if event_type in self.include_only:
|
|
342
|
+
return True
|
|
343
|
+
# PumpFunTrade 包含 PumpFunBuy, PumpFunSell, PumpFunBuyExactSolIn
|
|
344
|
+
if event_type == EventType.PUMP_FUN_TRADE:
|
|
345
|
+
pumpfun_types = [
|
|
346
|
+
EventType.PUMP_FUN_BUY,
|
|
347
|
+
EventType.PUMP_FUN_SELL,
|
|
348
|
+
EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
|
|
349
|
+
]
|
|
350
|
+
if any(t in self.include_only for t in pumpfun_types):
|
|
351
|
+
return True
|
|
352
|
+
return False
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class ExcludeFilter(EventTypeFilter):
|
|
356
|
+
"""排除指定类型的事件过滤器"""
|
|
357
|
+
|
|
358
|
+
def __init__(self, exclude_types: List[EventType]):
|
|
359
|
+
self.exclude_types = exclude_types
|
|
360
|
+
|
|
361
|
+
def should_include(self, event_type: EventType) -> bool:
|
|
362
|
+
return event_type not in self.exclude_types
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def event_type_filter_include_only(types: List[EventType]) -> EventTypeFilter:
|
|
366
|
+
"""创建仅包含指定类型的事件过滤器"""
|
|
367
|
+
return IncludeOnlyFilter(types)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def event_type_filter_exclude(types: List[EventType]) -> EventTypeFilter:
|
|
371
|
+
"""创建排除指定类型的事件过滤器"""
|
|
372
|
+
return ExcludeFilter(types)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _event_type_filter_includes_any(filter: EventTypeFilter, types: List[EventType]) -> bool:
|
|
376
|
+
if isinstance(filter, IncludeOnlyFilter):
|
|
377
|
+
return any(t in types for t in filter.include_only)
|
|
378
|
+
if isinstance(filter, ExcludeFilter):
|
|
379
|
+
return not any(t in types for t in filter.exclude_types)
|
|
380
|
+
return any(filter.should_include(t) for t in types)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
PUMP_FEES_EVENT_TYPES = [
|
|
384
|
+
EventType.PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
|
|
385
|
+
EventType.PUMP_FEES_INITIALIZE_FEE_CONFIG,
|
|
386
|
+
EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
|
|
387
|
+
EventType.PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
|
|
388
|
+
EventType.PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
|
|
389
|
+
EventType.PUMP_FEES_UPDATE_ADMIN,
|
|
390
|
+
EventType.PUMP_FEES_UPDATE_FEE_CONFIG,
|
|
391
|
+
EventType.PUMP_FEES_UPDATE_FEE_SHARES,
|
|
392
|
+
EventType.PUMP_FEES_UPSERT_FEE_TIERS,
|
|
393
|
+
]
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def event_type_filter_includes_pumpfun(filter: EventTypeFilter) -> bool:
|
|
397
|
+
"""判断过滤器是否包含 PumpFun 相关类型"""
|
|
398
|
+
pumpfun_types = [
|
|
399
|
+
EventType.PUMP_FUN_TRADE,
|
|
400
|
+
EventType.PUMP_FUN_BUY,
|
|
401
|
+
EventType.PUMP_FUN_SELL,
|
|
402
|
+
EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
|
|
403
|
+
EventType.PUMP_FUN_CREATE,
|
|
404
|
+
EventType.PUMP_FUN_CREATE_V2,
|
|
405
|
+
EventType.PUMP_FUN_COMPLETE,
|
|
406
|
+
EventType.PUMP_FUN_MIGRATE,
|
|
407
|
+
EventType.PUMP_FEES_CREATE_FEE_SHARING_CONFIG,
|
|
408
|
+
EventType.PUMP_FEES_INITIALIZE_FEE_CONFIG,
|
|
409
|
+
EventType.PUMP_FEES_RESET_FEE_SHARING_CONFIG,
|
|
410
|
+
EventType.PUMP_FEES_REVOKE_FEE_SHARING_AUTHORITY,
|
|
411
|
+
EventType.PUMP_FEES_TRANSFER_FEE_SHARING_AUTHORITY,
|
|
412
|
+
EventType.PUMP_FEES_UPDATE_ADMIN,
|
|
413
|
+
EventType.PUMP_FEES_UPDATE_FEE_CONFIG,
|
|
414
|
+
EventType.PUMP_FEES_UPDATE_FEE_SHARES,
|
|
415
|
+
EventType.PUMP_FEES_UPSERT_FEE_TIERS,
|
|
416
|
+
EventType.PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR,
|
|
417
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL,
|
|
418
|
+
]
|
|
419
|
+
return _event_type_filter_includes_any(filter, pumpfun_types)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def event_type_filter_includes_pump_fees(filter: EventTypeFilter) -> bool:
|
|
423
|
+
"""判断过滤器是否包含 Pump Fees 相关类型"""
|
|
424
|
+
return _event_type_filter_includes_any(filter, PUMP_FEES_EVENT_TYPES)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def event_type_filter_includes_pumpswap(filter: EventTypeFilter) -> bool:
|
|
428
|
+
"""判断过滤器是否包含 PumpSwap 相关类型"""
|
|
429
|
+
pumpswap_types = [
|
|
430
|
+
EventType.PUMP_SWAP_BUY,
|
|
431
|
+
EventType.PUMP_SWAP_SELL,
|
|
432
|
+
EventType.PUMP_SWAP_CREATE_POOL,
|
|
433
|
+
EventType.PUMP_SWAP_LIQUIDITY_ADDED,
|
|
434
|
+
EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
|
|
435
|
+
]
|
|
436
|
+
return _event_type_filter_includes_any(filter, pumpswap_types)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def event_type_filter_includes_meteora_damm_v2(filter: EventTypeFilter) -> bool:
|
|
440
|
+
"""判断过滤器是否包含 Meteora DAMM V2 相关类型"""
|
|
441
|
+
meteora_types = [
|
|
442
|
+
EventType.METEORA_DAMM_V2_SWAP,
|
|
443
|
+
EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
|
|
444
|
+
EventType.METEORA_DAMM_V2_CREATE_POSITION,
|
|
445
|
+
EventType.METEORA_DAMM_V2_CLOSE_POSITION,
|
|
446
|
+
EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
|
|
447
|
+
EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
|
|
448
|
+
]
|
|
449
|
+
return _event_type_filter_includes_any(filter, meteora_types)
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def event_type_filter_allows_instruction_parsing(include_only: List[EventType]) -> bool:
|
|
453
|
+
"""判断过滤器是否允许指令解析"""
|
|
454
|
+
ix_types = [
|
|
455
|
+
EventType.PUMP_FUN_TRADE,
|
|
456
|
+
EventType.PUMP_FUN_BUY,
|
|
457
|
+
EventType.PUMP_FUN_SELL,
|
|
458
|
+
EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
|
|
459
|
+
EventType.PUMP_FUN_CREATE,
|
|
460
|
+
EventType.PUMP_FUN_CREATE_V2,
|
|
461
|
+
EventType.PUMP_FUN_MIGRATE,
|
|
462
|
+
EventType.PUMP_FUN_MIGRATE_BONDING_CURVE_CREATOR,
|
|
463
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL,
|
|
464
|
+
*PUMP_FEES_EVENT_TYPES,
|
|
465
|
+
EventType.PUMP_SWAP_BUY,
|
|
466
|
+
EventType.PUMP_SWAP_SELL,
|
|
467
|
+
EventType.PUMP_SWAP_CREATE_POOL,
|
|
468
|
+
EventType.PUMP_SWAP_LIQUIDITY_ADDED,
|
|
469
|
+
EventType.PUMP_SWAP_LIQUIDITY_REMOVED,
|
|
470
|
+
EventType.METEORA_DAMM_V2_SWAP,
|
|
471
|
+
EventType.METEORA_DAMM_V2_ADD_LIQUIDITY,
|
|
472
|
+
EventType.METEORA_DAMM_V2_CREATE_POSITION,
|
|
473
|
+
EventType.METEORA_DAMM_V2_CLOSE_POSITION,
|
|
474
|
+
EventType.METEORA_DAMM_V2_INITIALIZE_POOL,
|
|
475
|
+
EventType.METEORA_DAMM_V2_REMOVE_LIQUIDITY,
|
|
476
|
+
EventType.RAYDIUM_CLMM_SWAP,
|
|
477
|
+
EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
|
|
478
|
+
EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
|
|
479
|
+
EventType.RAYDIUM_CLMM_CREATE_POOL,
|
|
480
|
+
EventType.RAYDIUM_CLMM_OPEN_POSITION,
|
|
481
|
+
EventType.RAYDIUM_CLMM_OPEN_POSITION_WITH_TOKEN_EXT_NFT,
|
|
482
|
+
EventType.RAYDIUM_CLMM_CLOSE_POSITION,
|
|
483
|
+
EventType.RAYDIUM_CLMM_COLLECT_FEE,
|
|
484
|
+
EventType.RAYDIUM_CPMM_SWAP,
|
|
485
|
+
EventType.RAYDIUM_CPMM_DEPOSIT,
|
|
486
|
+
EventType.RAYDIUM_CPMM_WITHDRAW,
|
|
487
|
+
EventType.RAYDIUM_CPMM_INITIALIZE,
|
|
488
|
+
EventType.RAYDIUM_AMM_V4_SWAP,
|
|
489
|
+
EventType.RAYDIUM_AMM_V4_DEPOSIT,
|
|
490
|
+
EventType.RAYDIUM_AMM_V4_WITHDRAW,
|
|
491
|
+
EventType.RAYDIUM_AMM_V4_WITHDRAW_PNL,
|
|
492
|
+
EventType.RAYDIUM_AMM_V4_INITIALIZE2,
|
|
493
|
+
EventType.ORCA_WHIRLPOOL_SWAP,
|
|
494
|
+
EventType.ORCA_WHIRLPOOL_LIQUIDITY_INCREASED,
|
|
495
|
+
EventType.ORCA_WHIRLPOOL_LIQUIDITY_DECREASED,
|
|
496
|
+
EventType.ORCA_WHIRLPOOL_POOL_INITIALIZED,
|
|
497
|
+
EventType.BONK_TRADE,
|
|
498
|
+
EventType.BONK_POOL_CREATE,
|
|
499
|
+
EventType.BONK_MIGRATE_AMM,
|
|
500
|
+
]
|
|
501
|
+
return any(t in include_only for t in ix_types)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
# Subscribe 请求/响应类型
|
|
505
|
+
|
|
506
|
+
@dataclass
|
|
507
|
+
class SubscribeRequestFilterAccountsFilterMemcmp:
|
|
508
|
+
"""Memcmp 过滤器"""
|
|
509
|
+
offset: int
|
|
510
|
+
bytes: Optional[bytes] = None
|
|
511
|
+
base58: str = ""
|
|
512
|
+
base64: str = ""
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
@dataclass
|
|
516
|
+
class SubscribeRequestFilterAccountsFilterLamports:
|
|
517
|
+
"""Lamports 过滤器"""
|
|
518
|
+
eq: Optional[int] = None
|
|
519
|
+
ne: Optional[int] = None
|
|
520
|
+
lt: Optional[int] = None
|
|
521
|
+
gt: Optional[int] = None
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
@dataclass
|
|
525
|
+
class SubscribeRequestFilterAccountsFilter:
|
|
526
|
+
"""账户过滤条件"""
|
|
527
|
+
memcmp: Optional[SubscribeRequestFilterAccountsFilterMemcmp] = None
|
|
528
|
+
datasize: Optional[int] = None
|
|
529
|
+
token_account_state: Optional[bool] = None
|
|
530
|
+
lamports: Optional[SubscribeRequestFilterAccountsFilterLamports] = None
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@dataclass
|
|
534
|
+
class AccountFilter:
|
|
535
|
+
"""账户订阅过滤器(对齐 Rust ``grpc/types::AccountFilter``,用于 ``subscribe_builder``)"""
|
|
536
|
+
|
|
537
|
+
account: List[str] = field(default_factory=list)
|
|
538
|
+
owner: List[str] = field(default_factory=list)
|
|
539
|
+
filters: List[SubscribeRequestFilterAccountsFilter] = field(default_factory=list)
|
|
540
|
+
|
|
541
|
+
@staticmethod
|
|
542
|
+
def new() -> AccountFilter:
|
|
543
|
+
return AccountFilter()
|
|
544
|
+
|
|
545
|
+
def add_account(self, account: str) -> AccountFilter:
|
|
546
|
+
self.account.append(account)
|
|
547
|
+
return self
|
|
548
|
+
|
|
549
|
+
def add_owner(self, owner: str) -> AccountFilter:
|
|
550
|
+
self.owner.append(owner)
|
|
551
|
+
return self
|
|
552
|
+
|
|
553
|
+
def add_filter(self, f: SubscribeRequestFilterAccountsFilter) -> AccountFilter:
|
|
554
|
+
self.filters.append(f)
|
|
555
|
+
return self
|
|
556
|
+
|
|
557
|
+
@staticmethod
|
|
558
|
+
def from_program_owners(program_ids: List[str]) -> AccountFilter:
|
|
559
|
+
return AccountFilter(owner=list(program_ids))
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class Protocol(str, Enum):
|
|
563
|
+
"""DEX 协议枚举(对齐 Rust ``grpc/types::Protocol``)"""
|
|
564
|
+
|
|
565
|
+
PUMP_FUN = "PumpFun"
|
|
566
|
+
PUMP_SWAP = "PumpSwap"
|
|
567
|
+
BONK = "Bonk"
|
|
568
|
+
RAYDIUM_CPMM = "RaydiumCpmm"
|
|
569
|
+
RAYDIUM_CLMM = "RaydiumClmm"
|
|
570
|
+
RAYDIUM_AMM_V4 = "RaydiumAmmV4"
|
|
571
|
+
METEORA_DAMM_V2 = "MeteoraDammV2"
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
# 与 Rust ``grpc/program_ids::PROTOCOL_PROGRAM_IDS`` 一致
|
|
575
|
+
_PROTOCOL_PROGRAM_IDS: Dict[Protocol, List[str]] = {
|
|
576
|
+
Protocol.PUMP_FUN: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
|
|
577
|
+
Protocol.PUMP_SWAP: ["pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"],
|
|
578
|
+
Protocol.BONK: ["BSwp6bEBihVLdqJRKS58NaebUBSDNjN7MdpFwNaR6gn3"],
|
|
579
|
+
Protocol.RAYDIUM_CPMM: ["CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"],
|
|
580
|
+
Protocol.RAYDIUM_CLMM: ["CAMMCzo5YL8w4VFF8KVHrK22GGUQtcaMpgYqJPXBDvfE"],
|
|
581
|
+
Protocol.RAYDIUM_AMM_V4: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"],
|
|
582
|
+
Protocol.METEORA_DAMM_V2: ["cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"],
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def program_ids_for_protocols(protocols: List[Protocol]) -> List[str]:
|
|
587
|
+
"""对齐 Rust ``get_program_ids_for_protocols``。"""
|
|
588
|
+
out: List[str] = []
|
|
589
|
+
for p in protocols:
|
|
590
|
+
out.extend(_PROTOCOL_PROGRAM_IDS.get(p, []))
|
|
591
|
+
return sorted(set(out))
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def transaction_filter_for_protocols(protocols: List[Protocol]) -> TransactionFilter:
|
|
595
|
+
"""对齐 Rust ``TransactionFilter::for_protocols``。"""
|
|
596
|
+
ids = program_ids_for_protocols(protocols)
|
|
597
|
+
return TransactionFilter(account_include=ids, account_exclude=[], account_required=[])
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def account_filter_for_protocols(protocols: List[Protocol]) -> AccountFilter:
|
|
601
|
+
"""对齐 Rust ``AccountFilter::for_protocols``(owner = 程序 ID 列表)。"""
|
|
602
|
+
ids = program_ids_for_protocols(protocols)
|
|
603
|
+
return AccountFilter(account=[], owner=ids, filters=[])
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
@dataclass
|
|
607
|
+
class SlotFilter:
|
|
608
|
+
"""Slot 范围过滤(对齐 Rust ``SlotFilter``)"""
|
|
609
|
+
|
|
610
|
+
min_slot: Optional[int] = None
|
|
611
|
+
max_slot: Optional[int] = None
|
|
612
|
+
|
|
613
|
+
@staticmethod
|
|
614
|
+
def new() -> SlotFilter:
|
|
615
|
+
return SlotFilter()
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def account_filter_memcmp(offset: int, bs: bytes) -> SubscribeRequestFilterAccountsFilter:
|
|
619
|
+
"""对齐 Rust ``account_filter_memcmp``:用于 ``AccountFilter.filters``。"""
|
|
620
|
+
return SubscribeRequestFilterAccountsFilter(
|
|
621
|
+
memcmp=SubscribeRequestFilterAccountsFilterMemcmp(offset=offset, bytes=bs)
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
@dataclass
|
|
626
|
+
class SubscribeRequestFilterAccounts:
|
|
627
|
+
"""账户过滤器"""
|
|
628
|
+
account: List[str] = field(default_factory=list)
|
|
629
|
+
owner: List[str] = field(default_factory=list)
|
|
630
|
+
filters: List[SubscribeRequestFilterAccountsFilter] = field(default_factory=list)
|
|
631
|
+
nonempty_txn_signature: Optional[bool] = None
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
@dataclass
|
|
635
|
+
class SubscribeRequestFilterSlots:
|
|
636
|
+
"""Slot 过滤器"""
|
|
637
|
+
filter_by_commitment: Optional[bool] = None
|
|
638
|
+
interslot_updates: Optional[bool] = None
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
@dataclass
|
|
642
|
+
class SubscribeRequestFilterTransactions:
|
|
643
|
+
"""交易过滤器(proto 定义)"""
|
|
644
|
+
vote: Optional[bool] = None
|
|
645
|
+
failed: Optional[bool] = None
|
|
646
|
+
signature: str = ""
|
|
647
|
+
account_include: List[str] = field(default_factory=list)
|
|
648
|
+
account_exclude: List[str] = field(default_factory=list)
|
|
649
|
+
account_required: List[str] = field(default_factory=list)
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
@dataclass
|
|
653
|
+
class SubscribeRequestFilterBlocks:
|
|
654
|
+
"""区块过滤器"""
|
|
655
|
+
account_include: List[str] = field(default_factory=list)
|
|
656
|
+
include_transactions: Optional[bool] = None
|
|
657
|
+
include_accounts: Optional[bool] = None
|
|
658
|
+
include_entries: Optional[bool] = None
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
@dataclass
|
|
662
|
+
class SubscribeRequestFilterBlocksMeta:
|
|
663
|
+
"""区块元数据过滤器"""
|
|
664
|
+
pass
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
@dataclass
|
|
668
|
+
class SubscribeRequestFilterEntry:
|
|
669
|
+
"""Entry 过滤器"""
|
|
670
|
+
pass
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
@dataclass
|
|
674
|
+
class SubscribeRequestAccountsDataSlice:
|
|
675
|
+
"""账户数据切片"""
|
|
676
|
+
offset: int = 0
|
|
677
|
+
length: int = 0
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
@dataclass
|
|
681
|
+
class SubscribeRequestPing:
|
|
682
|
+
"""Ping 请求"""
|
|
683
|
+
id: int = 0
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
@dataclass
|
|
687
|
+
class SubscribeRequest:
|
|
688
|
+
"""订阅请求"""
|
|
689
|
+
accounts: Dict[str, SubscribeRequestFilterAccounts] = field(default_factory=dict)
|
|
690
|
+
slots: Dict[str, SubscribeRequestFilterSlots] = field(default_factory=dict)
|
|
691
|
+
transactions: Dict[str, SubscribeRequestFilterTransactions] = field(default_factory=dict)
|
|
692
|
+
transactions_status: Dict[str, SubscribeRequestFilterTransactions] = field(default_factory=dict)
|
|
693
|
+
blocks: Dict[str, SubscribeRequestFilterBlocks] = field(default_factory=dict)
|
|
694
|
+
blocks_meta: Dict[str, SubscribeRequestFilterBlocksMeta] = field(default_factory=dict)
|
|
695
|
+
entry: Dict[str, SubscribeRequestFilterEntry] = field(default_factory=dict)
|
|
696
|
+
commitment: Optional[CommitmentLevel] = None
|
|
697
|
+
accounts_data_slice: List[SubscribeRequestAccountsDataSlice] = field(default_factory=list)
|
|
698
|
+
ping: Optional[SubscribeRequestPing] = None
|
|
699
|
+
from_slot: Optional[int] = None
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
# Subscribe 更新类型
|
|
703
|
+
|
|
704
|
+
@dataclass
|
|
705
|
+
class SubscribeUpdateAccountInfo:
|
|
706
|
+
"""账户信息"""
|
|
707
|
+
pubkey: bytes = b""
|
|
708
|
+
lamports: int = 0
|
|
709
|
+
owner: bytes = b""
|
|
710
|
+
executable: bool = False
|
|
711
|
+
rent_epoch: int = 0
|
|
712
|
+
data: bytes = b""
|
|
713
|
+
write_version: int = 0
|
|
714
|
+
txn_signature: Optional[bytes] = None
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
@dataclass
|
|
718
|
+
class SubscribeUpdateAccount:
|
|
719
|
+
"""账户更新"""
|
|
720
|
+
account: Optional[SubscribeUpdateAccountInfo] = None
|
|
721
|
+
slot: int = 0
|
|
722
|
+
is_startup: bool = False
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
@dataclass
|
|
726
|
+
class SubscribeUpdateSlot:
|
|
727
|
+
"""Slot 更新"""
|
|
728
|
+
slot: int = 0
|
|
729
|
+
parent: Optional[int] = None
|
|
730
|
+
status: SlotStatus = SlotStatus.PROCESSED
|
|
731
|
+
dead_error: Optional[str] = None
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
@dataclass
|
|
735
|
+
class SubscribeUpdateTransactionInfo:
|
|
736
|
+
"""交易信息"""
|
|
737
|
+
signature: bytes = b""
|
|
738
|
+
is_vote: bool = False
|
|
739
|
+
transaction_raw: bytes = b""
|
|
740
|
+
meta_raw: bytes = b""
|
|
741
|
+
index: int = 0
|
|
742
|
+
log_messages: List[str] = field(default_factory=list)
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
@dataclass
|
|
746
|
+
class SubscribeUpdateTransaction:
|
|
747
|
+
"""交易更新"""
|
|
748
|
+
transaction: Optional[SubscribeUpdateTransactionInfo] = None
|
|
749
|
+
slot: int = 0
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
@dataclass
|
|
753
|
+
class SubscribeUpdateTransactionStatus:
|
|
754
|
+
"""交易状态更新"""
|
|
755
|
+
slot: int = 0
|
|
756
|
+
signature: bytes = b""
|
|
757
|
+
is_vote: bool = False
|
|
758
|
+
index: int = 0
|
|
759
|
+
err: bytes = b""
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
@dataclass
|
|
763
|
+
class SubscribeUpdateBlock:
|
|
764
|
+
"""区块更新"""
|
|
765
|
+
slot: int = 0
|
|
766
|
+
blockhash: str = ""
|
|
767
|
+
parent_slot: int = 0
|
|
768
|
+
parent_blockhash: str = ""
|
|
769
|
+
executed_transaction_count: int = 0
|
|
770
|
+
transactions: List[SubscribeUpdateTransactionInfo] = field(default_factory=list)
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
@dataclass
|
|
774
|
+
class SubscribeUpdatePing:
|
|
775
|
+
"""Ping 更新"""
|
|
776
|
+
pass
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
@dataclass
|
|
780
|
+
class SubscribeUpdatePong:
|
|
781
|
+
"""Pong 更新"""
|
|
782
|
+
id: int = 0
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
@dataclass
|
|
786
|
+
class SubscribeUpdateBlockMeta:
|
|
787
|
+
"""区块元数据更新"""
|
|
788
|
+
slot: int = 0
|
|
789
|
+
blockhash: str = ""
|
|
790
|
+
parent_slot: int = 0
|
|
791
|
+
parent_blockhash: str = ""
|
|
792
|
+
executed_transaction_count: int = 0
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
@dataclass
|
|
796
|
+
class SubscribeUpdateEntry:
|
|
797
|
+
"""Entry 更新"""
|
|
798
|
+
slot: int = 0
|
|
799
|
+
index: int = 0
|
|
800
|
+
num_hashes: int = 0
|
|
801
|
+
hash: bytes = b""
|
|
802
|
+
executed_transaction_count: int = 0
|
|
803
|
+
starting_transaction_index: int = 0
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
@dataclass
|
|
807
|
+
class SubscribeUpdate:
|
|
808
|
+
"""订阅更新"""
|
|
809
|
+
filters: List[str] = field(default_factory=list)
|
|
810
|
+
account: Optional[SubscribeUpdateAccount] = None
|
|
811
|
+
slot: Optional[SubscribeUpdateSlot] = None
|
|
812
|
+
transaction: Optional[SubscribeUpdateTransaction] = None
|
|
813
|
+
transaction_status: Optional[SubscribeUpdateTransactionStatus] = None
|
|
814
|
+
block: Optional[SubscribeUpdateBlock] = None
|
|
815
|
+
ping: Optional[SubscribeUpdatePing] = None
|
|
816
|
+
pong: Optional[SubscribeUpdatePong] = None
|
|
817
|
+
block_meta: Optional[SubscribeUpdateBlockMeta] = None
|
|
818
|
+
entry: Optional[SubscribeUpdateEntry] = None
|
|
819
|
+
created_at: Optional[int] = None # Unix timestamp in microseconds
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
# RPC 请求/响应类型
|
|
823
|
+
|
|
824
|
+
@dataclass
|
|
825
|
+
class GetLatestBlockhashRequest:
|
|
826
|
+
"""获取最新区块哈希请求"""
|
|
827
|
+
commitment: Optional[CommitmentLevel] = None
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
@dataclass
|
|
831
|
+
class GetLatestBlockhashResponse:
|
|
832
|
+
"""获取最新区块哈希响应"""
|
|
833
|
+
slot: int = 0
|
|
834
|
+
blockhash: str = ""
|
|
835
|
+
last_valid_block_height: int = 0
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
@dataclass
|
|
839
|
+
class GetBlockHeightRequest:
|
|
840
|
+
"""获取区块高度请求"""
|
|
841
|
+
commitment: Optional[CommitmentLevel] = None
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
@dataclass
|
|
845
|
+
class GetBlockHeightResponse:
|
|
846
|
+
"""获取区块高度响应"""
|
|
847
|
+
block_height: int = 0
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
@dataclass
|
|
851
|
+
class GetSlotRequest:
|
|
852
|
+
"""获取 Slot 请求"""
|
|
853
|
+
commitment: Optional[CommitmentLevel] = None
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
@dataclass
|
|
857
|
+
class GetSlotResponse:
|
|
858
|
+
"""获取 Slot 响应"""
|
|
859
|
+
slot: int = 0
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
@dataclass
|
|
863
|
+
class GetVersionRequest:
|
|
864
|
+
"""获取版本请求"""
|
|
865
|
+
pass
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
@dataclass
|
|
869
|
+
class GetVersionResponse:
|
|
870
|
+
"""获取版本响应"""
|
|
871
|
+
version: str = ""
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
@dataclass
|
|
875
|
+
class IsBlockhashValidRequest:
|
|
876
|
+
"""验证区块哈希请求"""
|
|
877
|
+
blockhash: str = ""
|
|
878
|
+
commitment: Optional[CommitmentLevel] = None
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
@dataclass
|
|
882
|
+
class IsBlockhashValidResponse:
|
|
883
|
+
"""验证区块哈希响应"""
|
|
884
|
+
slot: int = 0
|
|
885
|
+
valid: bool = False
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
@dataclass
|
|
889
|
+
class PingRequest:
|
|
890
|
+
"""Ping 请求"""
|
|
891
|
+
count: int = 0
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
@dataclass
|
|
895
|
+
class PongResponse:
|
|
896
|
+
"""Pong 响应"""
|
|
897
|
+
count: int = 0
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
@dataclass
|
|
901
|
+
class SubscribeReplayInfoRequest:
|
|
902
|
+
"""订阅重放信息请求"""
|
|
903
|
+
pass
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
@dataclass
|
|
907
|
+
class SubscribeReplayInfoResponse:
|
|
908
|
+
"""订阅重放信息响应"""
|
|
909
|
+
first_available: Optional[int] = None
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
# SubscribeCallbacks 类型
|
|
913
|
+
|
|
914
|
+
@dataclass
|
|
915
|
+
class SubscribeCallbacks:
|
|
916
|
+
"""订阅回调函数"""
|
|
917
|
+
on_update: Optional[Callable[[SubscribeUpdate], None]] = None
|
|
918
|
+
on_error: Optional[Callable[[Exception], None]] = None
|
|
919
|
+
on_end: Optional[Callable[[], None]] = None
|