sol-parser-sdk-python 0.5.10__py3-none-any.whl → 0.5.11__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 +21 -0
- sol_parser/account_dispatcher.py +93 -5
- sol_parser/account_fillers/pumpfun.py +19 -0
- sol_parser/account_fillers/pumpswap.py +45 -2
- sol_parser/account_fillers/raydium.py +25 -0
- sol_parser/accounts/__init__.py +19 -1
- sol_parser/dex_parsers.py +238 -5
- sol_parser/event_type_parity.py +8 -0
- sol_parser/event_types.py +232 -2
- sol_parser/grpc_client.py +4 -2
- sol_parser/grpc_instruction_parser.py +70 -8
- sol_parser/grpc_types.py +38 -1
- sol_parser/inner_instruction_parser.py +14 -0
- sol_parser/instructions.py +197 -28
- sol_parser/log_instr_dedup.py +65 -7
- sol_parser/merger.py +18 -0
- sol_parser/order_buffer.py +37 -12
- sol_parser/parser.py +22 -5
- sol_parser/pump_upgrade.py +194 -0
- sol_parser/rpc_parser.py +4 -2
- sol_parser/shredstream_client.py +4 -1
- sol_parser/simulation_route.py +18 -6
- sol_parser/transaction_route.py +10 -1
- sol_parser/wire_transaction.py +8 -14
- {sol_parser_sdk_python-0.5.10.dist-info → sol_parser_sdk_python-0.5.11.dist-info}/METADATA +24 -14
- {sol_parser_sdk_python-0.5.10.dist-info → sol_parser_sdk_python-0.5.11.dist-info}/RECORD +28 -27
- {sol_parser_sdk_python-0.5.10.dist-info → sol_parser_sdk_python-0.5.11.dist-info}/WHEEL +0 -0
- {sol_parser_sdk_python-0.5.10.dist-info → sol_parser_sdk_python-0.5.11.dist-info}/entry_points.txt +0 -0
sol_parser/__init__.py
CHANGED
|
@@ -148,6 +148,9 @@ from .event_types import (
|
|
|
148
148
|
# Meteora DAMM v2 events
|
|
149
149
|
MeteoraDammV2SwapEvent,
|
|
150
150
|
MeteoraDammV2CreatePositionEvent,
|
|
151
|
+
MeteoraDammV2ClaimPositionFeeEvent,
|
|
152
|
+
MeteoraDammV2ClaimRewardEvent,
|
|
153
|
+
MeteoraDlmmClaimRewardEvent,
|
|
151
154
|
MeteoraDammV2ClosePositionEvent,
|
|
152
155
|
MeteoraDammV2AddLiquidityEvent,
|
|
153
156
|
MeteoraDammV2RemoveLiquidityEvent,
|
|
@@ -155,6 +158,11 @@ from .event_types import (
|
|
|
155
158
|
MeteoraDammV2DynamicFeeParameters,
|
|
156
159
|
MeteoraDammV2UpdateDelegatePermissionEvent,
|
|
157
160
|
MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
|
|
161
|
+
MeteoraDammV2WithdrawIneligibleRewardEvent,
|
|
162
|
+
MeteoraDammV2UpdateRewardFunderEvent,
|
|
163
|
+
MeteoraDammV2UpdateRewardDurationEvent,
|
|
164
|
+
MeteoraDammV2InitializeRewardEvent,
|
|
165
|
+
MeteoraDammV2FundRewardEvent,
|
|
158
166
|
MeteoraDammV2CreateConfigEvent,
|
|
159
167
|
MeteoraDammV2CreateDynamicConfigEvent,
|
|
160
168
|
MeteoraDbcCurveCompleteEvent,
|
|
@@ -433,6 +441,9 @@ __all__ = [
|
|
|
433
441
|
"MeteoraPoolsPoolCreatedEvent",
|
|
434
442
|
"MeteoraDammV2SwapEvent",
|
|
435
443
|
"MeteoraDammV2CreatePositionEvent",
|
|
444
|
+
"MeteoraDammV2ClaimPositionFeeEvent",
|
|
445
|
+
"MeteoraDammV2ClaimRewardEvent",
|
|
446
|
+
"MeteoraDlmmClaimRewardEvent",
|
|
436
447
|
"MeteoraDammV2ClosePositionEvent",
|
|
437
448
|
"MeteoraDammV2AddLiquidityEvent",
|
|
438
449
|
"MeteoraDammV2RemoveLiquidityEvent",
|
|
@@ -440,6 +451,11 @@ __all__ = [
|
|
|
440
451
|
"MeteoraDammV2DynamicFeeParameters",
|
|
441
452
|
"MeteoraDammV2UpdateDelegatePermissionEvent",
|
|
442
453
|
"MeteoraDammV2WithdrawDeadLiquidityRewardEvent",
|
|
454
|
+
"MeteoraDammV2WithdrawIneligibleRewardEvent",
|
|
455
|
+
"MeteoraDammV2UpdateRewardFunderEvent",
|
|
456
|
+
"MeteoraDammV2UpdateRewardDurationEvent",
|
|
457
|
+
"MeteoraDammV2InitializeRewardEvent",
|
|
458
|
+
"MeteoraDammV2FundRewardEvent",
|
|
443
459
|
"MeteoraDammV2CreateConfigEvent",
|
|
444
460
|
"MeteoraDammV2CreateDynamicConfigEvent",
|
|
445
461
|
"MeteoraDbcCurveCompleteEvent",
|
|
@@ -490,3 +506,8 @@ __all__ += ["LaunchLabPoolCreateEvent", "StonkFunPoolCreateEvent", "LaunchLabTra
|
|
|
490
506
|
|
|
491
507
|
from .grpc_client import DexEventQueue, GrpcStreamStatus
|
|
492
508
|
__all__ += ["DexEventQueue", "GrpcStreamStatus"]
|
|
509
|
+
|
|
510
|
+
from .pump_upgrade import decode_pump_multi_hop_intent
|
|
511
|
+
|
|
512
|
+
from .pump_upgrade import PumpFunPostCompleteBuyEvent, PumpFunSweepBondingCurveFeeEvent, PumpFunCompleteEvent, PumpSwapSweepPoolFeeEvent
|
|
513
|
+
__all__ += ['decode_pump_multi_hop_intent','PumpFunPostCompleteBuyEvent','PumpFunSweepBondingCurveFeeEvent','PumpFunCompleteEvent','PumpSwapSweepPoolFeeEvent']
|
sol_parser/account_dispatcher.py
CHANGED
|
@@ -110,6 +110,94 @@ def fill_accounts_with_owned_keys(
|
|
|
110
110
|
return
|
|
111
111
|
filler(get)
|
|
112
112
|
|
|
113
|
+
def fill_clmm_liquidity(remove=False):
|
|
114
|
+
position_index = 2 if remove else 4
|
|
115
|
+
allowed = (bytes([58,127,188,62,79,82,196,96]), bytes([160,38,208,111,104,91,44,1])) if remove else (bytes([133,29,89,223,69,238,176,10]), bytes([46,156,243,118,13,205,251,178]))
|
|
116
|
+
selected = None
|
|
117
|
+
for invocation in invokes.get(base58.b58decode(RAYDIUM_CLMM_PROGRAM_ID), []):
|
|
118
|
+
raw = get_instruction_data(meta_pb, transaction_pb, invocation)
|
|
119
|
+
if not raw or raw[:8] not in allowed:
|
|
120
|
+
continue
|
|
121
|
+
get = get_instruction_account_getter(meta_pb, transaction_pb, static_keys, w, r, invocation)
|
|
122
|
+
if get is None or not raydium.clmm_position_matches(data.position_nft_mint, get(position_index)):
|
|
123
|
+
continue
|
|
124
|
+
data.personal_position = get(position_index)
|
|
125
|
+
if selected is not None and any(selected(i) != get(i) for i in range(18)):
|
|
126
|
+
return
|
|
127
|
+
selected = get
|
|
128
|
+
if selected is not None:
|
|
129
|
+
(raydium.fill_clmm_decrease_liquidity_accounts if remove else raydium.fill_clmm_increase_liquidity_accounts)(data, selected)
|
|
130
|
+
|
|
131
|
+
def fill_pump_trade():
|
|
132
|
+
if not data.mint or data.mint == "11111111111111111111111111111111":
|
|
133
|
+
return
|
|
134
|
+
layouts = {
|
|
135
|
+
bytes([102,6,61,18,1,218,235,234]): (2,6,True,16),
|
|
136
|
+
bytes([56,252,116,8,158,223,205,95]): (2,6,True,16),
|
|
137
|
+
bytes([51,230,133,164,1,127,131,173]): (2,6,False,14),
|
|
138
|
+
bytes([184,23,238,97,103,197,211,61]): (1,13,True,27),
|
|
139
|
+
bytes([194,171,28,70,104,77,91,47]): (1,13,True,27),
|
|
140
|
+
bytes([93,246,130,60,231,233,64,178]): (1,13,False,26),
|
|
141
|
+
bytes([7,5,29,196,245,23,101,80]): (1,8,True,17),
|
|
142
|
+
bytes([225,247,80,30,213,179,132,136]): (1,8,True,17),
|
|
143
|
+
bytes([28,146,222,119,38,196,105,213]): (1,8,False,17),
|
|
144
|
+
}
|
|
145
|
+
selected = None
|
|
146
|
+
for invocation in invokes.get(base58.b58decode(PUMPFUN_PROGRAM_ID), []):
|
|
147
|
+
raw = get_instruction_data(meta_pb, transaction_pb, invocation)
|
|
148
|
+
layout = layouts.get(raw[:8]) if raw else None
|
|
149
|
+
if layout is None:
|
|
150
|
+
continue
|
|
151
|
+
mint_index, user_index, buy, minimum = layout
|
|
152
|
+
oi, ii = invocation
|
|
153
|
+
instruction = (transaction_pb.message.instructions[oi] if ii < 0 else
|
|
154
|
+
next(g for g in meta_pb.inner_instructions if g.index == oi).instructions[ii])
|
|
155
|
+
if buy != data.is_buy or len(instruction.accounts) < minimum:
|
|
156
|
+
continue
|
|
157
|
+
get = get_instruction_account_getter(meta_pb, transaction_pb, static_keys, w, r, invocation)
|
|
158
|
+
if get is None or get(mint_index) != data.mint:
|
|
159
|
+
continue
|
|
160
|
+
if data.user and data.user != "11111111111111111111111111111111" and get(user_index) != data.user:
|
|
161
|
+
continue
|
|
162
|
+
if selected is not None:
|
|
163
|
+
return
|
|
164
|
+
selected = get
|
|
165
|
+
if selected is not None:
|
|
166
|
+
pumpfun.fill_trade_accounts(data, selected)
|
|
167
|
+
|
|
168
|
+
def fill_swap(buy):
|
|
169
|
+
# Match the event's own pool, user and direction, not the largest invoke.
|
|
170
|
+
if not data.pool or data.pool == "11111111111111111111111111111111":
|
|
171
|
+
return
|
|
172
|
+
selected = None
|
|
173
|
+
legacy = (bytes([102, 6, 61, 18, 1, 218, 235, 234]),
|
|
174
|
+
bytes([198, 46, 21, 82, 180, 217, 232, 112])) if buy else (bytes([51, 230, 133, 164, 1, 127, 131, 173]),)
|
|
175
|
+
compact = (bytes([184, 23, 238, 97, 103, 197, 211, 61]),
|
|
176
|
+
bytes([194, 171, 28, 70, 104, 77, 91, 47])) if buy else (bytes([93, 246, 130, 60, 231, 233, 64, 178]),)
|
|
177
|
+
for invocation in invokes.get(base58.b58decode(PUMPSWAP_PROGRAM_ID), []):
|
|
178
|
+
raw = get_instruction_data(meta_pb, transaction_pb, invocation)
|
|
179
|
+
boost = buy and raw is not None and raw[:8] == bytes([105, 68, 6, 175, 0, 7, 35, 162])
|
|
180
|
+
if raw is None or (not boost and raw[:8] not in legacy + compact):
|
|
181
|
+
continue
|
|
182
|
+
oi, ii = invocation
|
|
183
|
+
instruction = (transaction_pb.message.instructions[oi] if ii < 0 else
|
|
184
|
+
next(g for g in meta_pb.inner_instructions if g.index == oi).instructions[ii])
|
|
185
|
+
minimum = 13 if boost else (17 if raw[:8] in compact else (23 if buy else 21))
|
|
186
|
+
if len(instruction.accounts) < minimum:
|
|
187
|
+
continue
|
|
188
|
+
get = get_instruction_account_getter(meta_pb, transaction_pb, static_keys, w, r, invocation)
|
|
189
|
+
if get is None or get(0) != data.pool:
|
|
190
|
+
continue
|
|
191
|
+
if data.user and data.user != "11111111111111111111111111111111" and get(7 if boost else 1) != data.user:
|
|
192
|
+
continue
|
|
193
|
+
if selected is not None:
|
|
194
|
+
return # Invocation positions are unavailable; ambiguous context stays blank.
|
|
195
|
+
selected = (get, boost)
|
|
196
|
+
if selected is not None:
|
|
197
|
+
get, boost = selected
|
|
198
|
+
filler = pumpswap.fill_boost_buy_accounts if boost else (pumpswap.fill_buy_accounts if buy else pumpswap.fill_sell_accounts)
|
|
199
|
+
filler(data, get)
|
|
200
|
+
|
|
113
201
|
def fill_create(v2_only=False):
|
|
114
202
|
selected = None
|
|
115
203
|
for ix in invokes.get(base58.b58decode(PUMPFUN_PROGRAM_ID), []):
|
|
@@ -144,7 +232,7 @@ def fill_accounts_with_owned_keys(
|
|
|
144
232
|
EventType.PUMP_FUN_SELL,
|
|
145
233
|
EventType.PUMP_FUN_BUY_EXACT_SOL_IN,
|
|
146
234
|
):
|
|
147
|
-
|
|
235
|
+
fill_pump_trade()
|
|
148
236
|
elif et == EventType.PUMP_FUN_CREATE:
|
|
149
237
|
fill_create()
|
|
150
238
|
elif et == EventType.PUMP_FUN_CREATE_V2:
|
|
@@ -152,9 +240,9 @@ def fill_accounts_with_owned_keys(
|
|
|
152
240
|
elif et == EventType.PUMP_FUN_MIGRATE:
|
|
153
241
|
run(PUMPFUN_PROGRAM_ID, lambda g: pumpfun.fill_migrate_accounts(data, g))
|
|
154
242
|
elif et == EventType.PUMP_SWAP_BUY:
|
|
155
|
-
|
|
243
|
+
fill_swap(True)
|
|
156
244
|
elif et == EventType.PUMP_SWAP_SELL:
|
|
157
|
-
|
|
245
|
+
fill_swap(False)
|
|
158
246
|
elif et == EventType.PUMP_SWAP_TRADE:
|
|
159
247
|
run(PUMPSWAP_PROGRAM_ID, lambda g: pumpswap.fill_trade_accounts(data, g))
|
|
160
248
|
elif et == EventType.PUMP_SWAP_CREATE_POOL:
|
|
@@ -174,9 +262,9 @@ def fill_accounts_with_owned_keys(
|
|
|
174
262
|
elif et == EventType.RAYDIUM_CLMM_CLOSE_POSITION:
|
|
175
263
|
run(RAYDIUM_CLMM_PROGRAM_ID, lambda g: raydium.fill_clmm_close_position_accounts(data, g))
|
|
176
264
|
elif et == EventType.RAYDIUM_CLMM_INCREASE_LIQUIDITY:
|
|
177
|
-
|
|
265
|
+
fill_clmm_liquidity()
|
|
178
266
|
elif et == EventType.RAYDIUM_CLMM_DECREASE_LIQUIDITY:
|
|
179
|
-
|
|
267
|
+
fill_clmm_liquidity(True)
|
|
180
268
|
elif et == EventType.RAYDIUM_CPMM_SWAP:
|
|
181
269
|
run(RAYDIUM_CPMM_PROGRAM_ID, lambda g: raydium.fill_cpmm_swap_accounts(data, g))
|
|
182
270
|
elif et == EventType.RAYDIUM_CPMM_DEPOSIT:
|
|
@@ -29,6 +29,25 @@ def fill_trade_accounts(e: PumpFunTradeEvent, get: AccountGetter) -> None:
|
|
|
29
29
|
if _empty(getattr(e, name)):
|
|
30
30
|
setattr(e, name, get(idx))
|
|
31
31
|
|
|
32
|
+
if get(16)=="6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" and account_at_matches_mint(1):
|
|
33
|
+
set_attr("global_account",0)
|
|
34
|
+
set_attr("mint",1)
|
|
35
|
+
set_attr("quote_mint",2)
|
|
36
|
+
set_attr("token_program",3)
|
|
37
|
+
set_attr("quote_token_program",4)
|
|
38
|
+
set_attr("bonding_curve",5)
|
|
39
|
+
set_attr("associated_bonding_curve",6)
|
|
40
|
+
set_attr("associated_quote_bonding_curve",7)
|
|
41
|
+
set_attr("user",8)
|
|
42
|
+
set_attr("associated_user",9)
|
|
43
|
+
set_attr("associated_quote_user",10)
|
|
44
|
+
set_attr("user_volume_accumulator",11)
|
|
45
|
+
set_attr("fee_config",12)
|
|
46
|
+
set_attr("buyback_fee_recipient",13)
|
|
47
|
+
set_attr("system_program",14)
|
|
48
|
+
set_attr("event_authority",15)
|
|
49
|
+
set_attr("program",16)
|
|
50
|
+
return
|
|
32
51
|
is_v2 = e.ix_name in ("buy_v2", "sell_v2", "buy_exact_quote_in_v2") or account_at_matches_mint(1)
|
|
33
52
|
if is_v2:
|
|
34
53
|
set_attr("global_account", 0)
|
|
@@ -22,6 +22,21 @@ def _empty(s: str) -> bool:
|
|
|
22
22
|
AccountGetter = Callable[[int], str]
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
TOKEN_PROGRAMS = {
|
|
26
|
+
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
|
|
27
|
+
"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _is_compact_trade(get: AccountGetter) -> bool:
|
|
32
|
+
# Both legacy and compact layouts have the PumpSwap program at index 16.
|
|
33
|
+
return (
|
|
34
|
+
get(16) == "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
|
|
35
|
+
and get(9) in TOKEN_PROGRAMS
|
|
36
|
+
and get(10) in TOKEN_PROGRAMS
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
25
40
|
def _fill_trade_common(
|
|
26
41
|
e: PumpSwapBuyEvent | PumpSwapSellEvent,
|
|
27
42
|
get: AccountGetter,
|
|
@@ -42,6 +57,15 @@ def _fill_trade_common(
|
|
|
42
57
|
e.pool_base_token_account = get(7)
|
|
43
58
|
if _empty(e.pool_quote_token_account):
|
|
44
59
|
e.pool_quote_token_account = get(8)
|
|
60
|
+
if _is_compact_trade(get):
|
|
61
|
+
for field, index in (
|
|
62
|
+
("base_token_program", 9),
|
|
63
|
+
("quote_token_program", 10),
|
|
64
|
+
("fee_recipient_quote_token_account", 14),
|
|
65
|
+
):
|
|
66
|
+
if _empty(getattr(e, field)):
|
|
67
|
+
setattr(e, field, get(index))
|
|
68
|
+
return
|
|
45
69
|
if _empty(e.protocol_fee_recipient):
|
|
46
70
|
e.protocol_fee_recipient = get(9)
|
|
47
71
|
if _empty(e.protocol_fee_recipient_token_account):
|
|
@@ -56,8 +80,21 @@ def _fill_trade_common(
|
|
|
56
80
|
e.coin_creator_vault_authority = get(18)
|
|
57
81
|
|
|
58
82
|
|
|
83
|
+
def fill_boost_buy_accounts(e: PumpSwapBuyEvent, get: AccountGetter) -> None:
|
|
84
|
+
"""Boost has different vault slots and no user ATAs or fee accounts."""
|
|
85
|
+
for field, index in (
|
|
86
|
+
("pool", 0), ("base_mint", 3), ("quote_mint", 4),
|
|
87
|
+
("pool_base_token_account", 5), ("pool_quote_token_account", 6),
|
|
88
|
+
("base_token_program", 9), ("quote_token_program", 10),
|
|
89
|
+
):
|
|
90
|
+
if _empty(getattr(e, field)):
|
|
91
|
+
setattr(e, field, get(index))
|
|
92
|
+
|
|
93
|
+
|
|
59
94
|
def fill_buy_accounts(e: PumpSwapBuyEvent, get: AccountGetter) -> None:
|
|
60
95
|
_fill_trade_common(e, get)
|
|
96
|
+
if _is_compact_trade(get):
|
|
97
|
+
return
|
|
61
98
|
a26 = get(26)
|
|
62
99
|
if not _empty(a26):
|
|
63
100
|
if _empty(e.pool_v2):
|
|
@@ -82,6 +119,8 @@ def fill_buy_accounts(e: PumpSwapBuyEvent, get: AccountGetter) -> None:
|
|
|
82
119
|
|
|
83
120
|
def fill_sell_accounts(e: PumpSwapSellEvent, get: AccountGetter) -> None:
|
|
84
121
|
_fill_trade_common(e, get)
|
|
122
|
+
if _is_compact_trade(get):
|
|
123
|
+
return
|
|
85
124
|
a25 = get(25)
|
|
86
125
|
if not _empty(a25):
|
|
87
126
|
if _empty(e.pool_v2):
|
|
@@ -125,9 +164,13 @@ def fill_create_pool_accounts(e: PumpSwapCreatePoolEvent, get: AccountGetter) ->
|
|
|
125
164
|
e.user_quote_token_account = get(7)
|
|
126
165
|
|
|
127
166
|
|
|
128
|
-
def fill_liquidity_added_accounts(
|
|
167
|
+
def fill_liquidity_added_accounts(
|
|
168
|
+
_e: PumpSwapLiquidityAddedEvent, _get: AccountGetter
|
|
169
|
+
) -> None:
|
|
129
170
|
pass
|
|
130
171
|
|
|
131
172
|
|
|
132
|
-
def fill_liquidity_removed_accounts(
|
|
173
|
+
def fill_liquidity_removed_accounts(
|
|
174
|
+
_e: PumpSwapLiquidityRemovedEvent, _get: AccountGetter
|
|
175
|
+
) -> None:
|
|
133
176
|
pass
|
|
@@ -46,11 +46,15 @@ def fill_clmm_create_pool_accounts(e: RaydiumClmmCreatePoolEvent, get: AccountGe
|
|
|
46
46
|
def fill_clmm_increase_liquidity_accounts(e: RaydiumClmmIncreaseLiquidityEvent, get: AccountGetter) -> None:
|
|
47
47
|
if _empty(e.user):
|
|
48
48
|
e.user = get(0)
|
|
49
|
+
if _empty(e.pool):
|
|
50
|
+
e.pool = get(2)
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
def fill_clmm_decrease_liquidity_accounts(e: RaydiumClmmDecreaseLiquidityEvent, get: AccountGetter) -> None:
|
|
52
54
|
if _empty(e.user):
|
|
53
55
|
e.user = get(0)
|
|
56
|
+
if _empty(e.pool):
|
|
57
|
+
e.pool = get(3)
|
|
54
58
|
|
|
55
59
|
|
|
56
60
|
def fill_clmm_open_position_accounts(e: RaydiumClmmOpenPositionEvent, get: AccountGetter) -> None:
|
|
@@ -122,3 +126,24 @@ def fill_amm_v4_withdraw_accounts(e: RaydiumAmmV4WithdrawEvent, get: AccountGett
|
|
|
122
126
|
e.amm_authority = get(2)
|
|
123
127
|
if _empty(e.amm_open_orders):
|
|
124
128
|
e.amm_open_orders = get(3)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def clmm_position_matches(mint: str, position: str) -> bool:
|
|
132
|
+
"""Match a candidate PDA to the log mint without a crypto dependency.
|
|
133
|
+
|
|
134
|
+
This checks seed hashes against an existing instruction address; it does
|
|
135
|
+
not create or validate a new PDA or prove transaction authorization.
|
|
136
|
+
"""
|
|
137
|
+
import base58
|
|
138
|
+
import hashlib
|
|
139
|
+
if _empty(mint) or _empty(position):
|
|
140
|
+
return False
|
|
141
|
+
try:
|
|
142
|
+
raw_mint = base58.b58decode(mint)
|
|
143
|
+
target = base58.b58decode(position)
|
|
144
|
+
except ValueError:
|
|
145
|
+
return False
|
|
146
|
+
if len(raw_mint) != 32 or len(target) != 32:
|
|
147
|
+
return False
|
|
148
|
+
program = base58.b58decode("CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK")
|
|
149
|
+
return any(hashlib.sha256(b"position" + raw_mint + bytes([bump]) + program + b"ProgramDerivedAddress").digest() == target for bump in range(255, -1, -1))
|
sol_parser/accounts/__init__.py
CHANGED
|
@@ -464,6 +464,12 @@ def _parse_pumpfun_global_fast(account: AccountData, metadata: EventMetadata) ->
|
|
|
464
464
|
"buyback_basis_points": buyback_basis_points,
|
|
465
465
|
"initial_virtual_quote_reserves": initial_virtual_quote_reserves,
|
|
466
466
|
"whitelisted_quote_mints": whitelisted_quote_mints,
|
|
467
|
+
"creator_fee_configurable": len(data)>1037 and data[1037]==1,
|
|
468
|
+
"max_configurable_creator_fee_bps": int.from_bytes(data[1038:1046],"little") if len(data)>=1046 else 0,
|
|
469
|
+
"holder_reward_claim_authority": read_pubkey_fast(data,1046) if len(data)>=1078 else "11111111111111111111111111111111",
|
|
470
|
+
"is_holder_reward_enabled": len(data)>1078 and data[1078]==1,
|
|
471
|
+
"max_curve_depth": data[1079] if len(data)>1079 else 0,
|
|
472
|
+
|
|
467
473
|
},
|
|
468
474
|
},
|
|
469
475
|
)
|
|
@@ -505,6 +511,12 @@ def _parse_pumpfun_bonding_curve_fast(
|
|
|
505
511
|
"metadata": metadata,
|
|
506
512
|
"pubkey": account.pubkey,
|
|
507
513
|
"bonding_curve": {
|
|
514
|
+
"creator_fee": read_u64_fast(data,117) if len(data)>=125 else 0,
|
|
515
|
+
"protocol_fees": read_u64_fast(data,125) if len(data)>=133 else 0,
|
|
516
|
+
"depth": data[133] if len(data)>133 else 0,
|
|
517
|
+
"initial_virtual_quote_reserves": read_u64_fast(data,134) if len(data)>=142 else 0,
|
|
518
|
+
"post_complete_base_out": read_u64_fast(data,142) if len(data)>=150 else 0,
|
|
519
|
+
"post_complete_quote_in": read_u64_fast(data,150) if len(data)>=158 else 0,
|
|
508
520
|
"virtual_token_reserves": virtual_token_reserves,
|
|
509
521
|
"virtual_quote_reserves": virtual_quote_reserves,
|
|
510
522
|
"real_token_reserves": real_token_reserves,
|
|
@@ -543,7 +555,10 @@ def _parse_pumpfun_fee_config_fast(
|
|
|
543
555
|
stable_fee_tiers_result = _read_pumpfun_fee_tiers(data, o)
|
|
544
556
|
if stable_fee_tiers_result is None:
|
|
545
557
|
return None
|
|
546
|
-
stable_fee_tiers,
|
|
558
|
+
stable_fee_tiers, o = stable_fee_tiers_result
|
|
559
|
+
exotic_result=_read_pumpfun_fees(data,o) if len(data)>o else ({"lp_fee_bps":0,"protocol_fee_bps":0,"creator_fee_bps":0},o)
|
|
560
|
+
if exotic_result is None:return None
|
|
561
|
+
exotic_flat_fees,_=exotic_result
|
|
547
562
|
return _account_event(
|
|
548
563
|
EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG,
|
|
549
564
|
{
|
|
@@ -555,6 +570,7 @@ def _parse_pumpfun_fee_config_fast(
|
|
|
555
570
|
"flat_fees": flat_fees,
|
|
556
571
|
"fee_tiers": fee_tiers,
|
|
557
572
|
"stable_fee_tiers": stable_fee_tiers,
|
|
573
|
+
"exotic_flat_fees":exotic_flat_fees,
|
|
558
574
|
},
|
|
559
575
|
},
|
|
560
576
|
)
|
|
@@ -789,6 +805,8 @@ def _parse_pumpswap_pool_fast(account: AccountData, metadata: EventMetadata) ->
|
|
|
789
805
|
"metadata": metadata,
|
|
790
806
|
"pubkey": account.pubkey,
|
|
791
807
|
"pool": {
|
|
808
|
+
"protocol_fees": read_u64_fast(data,263) if len(data)>=271 else 0,
|
|
809
|
+
"creator_fees": read_u64_fast(data,271) if len(data)>=279 else 0,
|
|
792
810
|
"pool_bump": pool_bump,
|
|
793
811
|
"index": index,
|
|
794
812
|
"creator": creator,
|