sol-parser-sdk-python 0.4.4__py3-none-any.whl → 0.4.5__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/account_fillers/pumpfun.py +83 -18
- sol_parser/account_fillers/pumpswap.py +40 -0
- sol_parser/accounts/__init__.py +386 -4
- sol_parser/dex_parsers.py +54 -1
- sol_parser/event_types.py +114 -1
- sol_parser/grpc_types.py +20 -0
- sol_parser/instructions.py +260 -21
- sol_parser/log_instr_dedup.py +39 -2
- sol_parser/merger.py +74 -2
- sol_parser/shredstream_pumpfun.py +6 -0
- {sol_parser_sdk_python-0.4.4.dist-info → sol_parser_sdk_python-0.4.5.dist-info}/METADATA +1 -1
- {sol_parser_sdk_python-0.4.4.dist-info → sol_parser_sdk_python-0.4.5.dist-info}/RECORD +14 -14
- {sol_parser_sdk_python-0.4.4.dist-info → sol_parser_sdk_python-0.4.5.dist-info}/WHEEL +0 -0
- {sol_parser_sdk_python-0.4.4.dist-info → sol_parser_sdk_python-0.4.5.dist-info}/entry_points.txt +0 -0
|
@@ -22,31 +22,96 @@ AccountGetter = Callable[[int], str]
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def fill_trade_accounts(e: PumpFunTradeEvent, get: AccountGetter) -> None:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
def account_at_matches_mint(idx: int) -> bool:
|
|
26
|
+
return not _empty(e.mint) and get(idx) == e.mint
|
|
27
|
+
|
|
28
|
+
def set_attr(name: str, idx: int) -> None:
|
|
29
|
+
if _empty(getattr(e, name)):
|
|
30
|
+
setattr(e, name, get(idx))
|
|
31
|
+
|
|
32
|
+
is_v2 = e.ix_name in ("buy_v2", "sell_v2", "buy_exact_quote_in_v2") or (
|
|
33
|
+
e.ix_name == "buy_exact_quote_in" and account_at_matches_mint(1)
|
|
34
|
+
)
|
|
35
|
+
if is_v2:
|
|
36
|
+
set_attr("global_account", 0)
|
|
37
|
+
set_attr("quote_mint", 2)
|
|
38
|
+
set_attr("fee_recipient", 6)
|
|
39
|
+
set_attr("bonding_curve", 10)
|
|
40
|
+
set_attr("associated_bonding_curve", 11)
|
|
41
|
+
set_attr("associated_quote_bonding_curve", 12)
|
|
42
|
+
set_attr("user", 13)
|
|
43
|
+
set_attr("associated_user", 14)
|
|
44
|
+
set_attr("associated_quote_user", 15)
|
|
45
|
+
set_attr("token_program", 3)
|
|
46
|
+
set_attr("quote_token_program", 4)
|
|
47
|
+
set_attr("associated_token_program", 5)
|
|
48
|
+
set_attr("creator_vault", 16)
|
|
49
|
+
set_attr("associated_quote_fee_recipient", 7)
|
|
50
|
+
set_attr("buyback_fee_recipient", 8)
|
|
51
|
+
set_attr("associated_quote_buyback_fee_recipient", 9)
|
|
52
|
+
set_attr("associated_creator_vault", 17)
|
|
53
|
+
set_attr("sharing_config", 18)
|
|
54
|
+
if e.ix_name == "sell_v2":
|
|
55
|
+
set_attr("user_volume_accumulator", 19)
|
|
56
|
+
set_attr("associated_user_volume_accumulator", 20)
|
|
57
|
+
set_attr("fee_config", 21)
|
|
58
|
+
set_attr("fee_program", 22)
|
|
59
|
+
set_attr("system_program", 23)
|
|
60
|
+
set_attr("event_authority", 24)
|
|
61
|
+
set_attr("program", 25)
|
|
62
|
+
else:
|
|
63
|
+
set_attr("global_volume_accumulator", 19)
|
|
64
|
+
set_attr("user_volume_accumulator", 20)
|
|
65
|
+
set_attr("associated_user_volume_accumulator", 21)
|
|
66
|
+
set_attr("fee_config", 22)
|
|
67
|
+
set_attr("fee_program", 23)
|
|
68
|
+
set_attr("system_program", 24)
|
|
69
|
+
set_attr("event_authority", 25)
|
|
70
|
+
set_attr("program", 26)
|
|
36
71
|
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
72
|
+
set_attr("global_account", 0)
|
|
73
|
+
set_attr("fee_recipient", 1)
|
|
74
|
+
set_attr("bonding_curve", 3)
|
|
75
|
+
set_attr("associated_bonding_curve", 4)
|
|
76
|
+
set_attr("associated_user", 5)
|
|
77
|
+
set_attr("user", 6)
|
|
78
|
+
set_attr("system_program", 7)
|
|
43
79
|
if _empty(e.creator_vault):
|
|
44
80
|
e.creator_vault = get(9) if e.is_buy else get(8)
|
|
45
81
|
if _empty(e.token_program):
|
|
46
82
|
e.token_program = get(8) if e.is_buy else get(9)
|
|
83
|
+
set_attr("event_authority", 10)
|
|
84
|
+
set_attr("program", 11)
|
|
85
|
+
if e.is_buy:
|
|
86
|
+
set_attr("global_volume_accumulator", 12)
|
|
87
|
+
set_attr("user_volume_accumulator", 13)
|
|
88
|
+
set_attr("fee_config", 14)
|
|
89
|
+
set_attr("fee_program", 15)
|
|
90
|
+
set_attr("bonding_curve_v2", 16)
|
|
91
|
+
set_attr("buyback_fee_recipient", 17)
|
|
92
|
+
a17 = get(17)
|
|
93
|
+
if not _empty(a17) and _empty(e.extra_instruction_account):
|
|
94
|
+
e.extra_instruction_account = a17
|
|
95
|
+
return
|
|
96
|
+
set_attr("fee_config", 12)
|
|
97
|
+
set_attr("fee_program", 13)
|
|
47
98
|
a16 = get(16)
|
|
48
99
|
if not _empty(a16):
|
|
49
|
-
|
|
100
|
+
set_attr("user_volume_accumulator", 14)
|
|
101
|
+
set_attr("bonding_curve_v2", 15)
|
|
102
|
+
set_attr("buyback_fee_recipient", 16)
|
|
103
|
+
if _empty(e.extra_instruction_account):
|
|
104
|
+
e.extra_instruction_account = a16
|
|
105
|
+
return
|
|
106
|
+
if e.is_cashback_coin:
|
|
107
|
+
set_attr("user_volume_accumulator", 14)
|
|
108
|
+
set_attr("bonding_curve_v2", 15)
|
|
109
|
+
return
|
|
110
|
+
set_attr("bonding_curve_v2", 14)
|
|
111
|
+
set_attr("buyback_fee_recipient", 15)
|
|
112
|
+
a15 = get(15)
|
|
113
|
+
if not _empty(a15) and _empty(e.extra_instruction_account):
|
|
114
|
+
e.extra_instruction_account = a15
|
|
50
115
|
|
|
51
116
|
|
|
52
117
|
def fill_create_accounts(e: PumpFunCreateEvent, get: AccountGetter) -> None:
|
|
@@ -58,10 +58,50 @@ def _fill_trade_common(
|
|
|
58
58
|
|
|
59
59
|
def fill_buy_accounts(e: PumpSwapBuyEvent, get: AccountGetter) -> None:
|
|
60
60
|
_fill_trade_common(e, get)
|
|
61
|
+
a26 = get(26)
|
|
62
|
+
if not _empty(a26):
|
|
63
|
+
if _empty(e.pool_v2):
|
|
64
|
+
e.pool_v2 = get(24)
|
|
65
|
+
if _empty(e.fee_recipient):
|
|
66
|
+
e.fee_recipient = get(25)
|
|
67
|
+
if _empty(e.fee_recipient_quote_token_account):
|
|
68
|
+
e.fee_recipient_quote_token_account = a26
|
|
69
|
+
return
|
|
70
|
+
a25 = get(25)
|
|
71
|
+
if not _empty(a25):
|
|
72
|
+
if _empty(e.pool_v2):
|
|
73
|
+
e.pool_v2 = get(23)
|
|
74
|
+
if _empty(e.fee_recipient):
|
|
75
|
+
e.fee_recipient = get(24)
|
|
76
|
+
if _empty(e.fee_recipient_quote_token_account):
|
|
77
|
+
e.fee_recipient_quote_token_account = a25
|
|
78
|
+
return
|
|
79
|
+
if _empty(e.pool_v2):
|
|
80
|
+
e.pool_v2 = get(23)
|
|
61
81
|
|
|
62
82
|
|
|
63
83
|
def fill_sell_accounts(e: PumpSwapSellEvent, get: AccountGetter) -> None:
|
|
64
84
|
_fill_trade_common(e, get)
|
|
85
|
+
a25 = get(25)
|
|
86
|
+
if not _empty(a25):
|
|
87
|
+
if _empty(e.pool_v2):
|
|
88
|
+
e.pool_v2 = get(23)
|
|
89
|
+
if _empty(e.fee_recipient):
|
|
90
|
+
e.fee_recipient = get(24)
|
|
91
|
+
if _empty(e.fee_recipient_quote_token_account):
|
|
92
|
+
e.fee_recipient_quote_token_account = a25
|
|
93
|
+
return
|
|
94
|
+
a23 = get(23)
|
|
95
|
+
if not _empty(a23):
|
|
96
|
+
if _empty(e.pool_v2):
|
|
97
|
+
e.pool_v2 = get(21)
|
|
98
|
+
if _empty(e.fee_recipient):
|
|
99
|
+
e.fee_recipient = get(22)
|
|
100
|
+
if _empty(e.fee_recipient_quote_token_account):
|
|
101
|
+
e.fee_recipient_quote_token_account = a23
|
|
102
|
+
return
|
|
103
|
+
if _empty(e.pool_v2):
|
|
104
|
+
e.pool_v2 = get(21)
|
|
65
105
|
|
|
66
106
|
|
|
67
107
|
def fill_trade_accounts(_e: Any, _get: AccountGetter) -> None:
|
sol_parser/accounts/__init__.py
CHANGED
|
@@ -16,9 +16,15 @@ from . import utils as acc_utils
|
|
|
16
16
|
|
|
17
17
|
# 程序 ID(与 Rust ``accounts/program_ids`` / ``instr/program_ids`` 一致)
|
|
18
18
|
PUMPFUN_PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
|
|
19
|
+
PUMP_FEES_PROGRAM_ID = "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ"
|
|
19
20
|
PUMPSWAP_PROGRAM_ID = "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
|
|
20
21
|
|
|
21
22
|
_DISC_PUMPFUN_GLOBAL = bytes([167, 232, 232, 177, 200, 108, 114, 127])
|
|
23
|
+
_DISC_PUMPFUN_BONDING_CURVE = bytes([23, 183, 248, 55, 96, 216, 172, 96])
|
|
24
|
+
_DISC_PUMPFUN_FEE_CONFIG = bytes([143, 52, 146, 187, 219, 123, 76, 155])
|
|
25
|
+
_DISC_PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR = bytes([202, 42, 246, 43, 142, 190, 30, 255])
|
|
26
|
+
_DISC_PUMPFUN_SHARING_CONFIG = bytes([216, 74, 9, 0, 56, 140, 93, 75])
|
|
27
|
+
_DISC_PUMPFUN_USER_VOLUME_ACCUMULATOR = bytes([86, 255, 112, 14, 102, 53, 154, 250])
|
|
22
28
|
_DISC_GLOBAL_CONFIG = bytes([149, 8, 156, 202, 160, 252, 176, 217])
|
|
23
29
|
_DISC_POOL = bytes([241, 154, 109, 4, 17, 177, 109, 188])
|
|
24
30
|
_DISC_NONCE = bytes([1, 0, 0, 0, 1, 0, 0, 0])
|
|
@@ -26,9 +32,14 @@ _DISC_NONCE = bytes([1, 0, 0, 0, 1, 0, 0, 0])
|
|
|
26
32
|
MINT_SIZE = 82
|
|
27
33
|
TOKEN_ACCOUNT_SIZE = 165
|
|
28
34
|
NONCE_ACCOUNT_SIZE = 80
|
|
29
|
-
PUMPFUN_GLOBAL_BODY =
|
|
35
|
+
PUMPFUN_GLOBAL_BODY = 1037
|
|
36
|
+
PUMPFUN_BONDING_CURVE_BODY = 107
|
|
37
|
+
PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR_BODY = 536
|
|
38
|
+
PUMPFUN_USER_VOLUME_ACCUMULATOR_BODY = 98
|
|
30
39
|
GLOBAL_CONFIG_BODY = 634
|
|
31
40
|
POOL_BODY = 244
|
|
41
|
+
MAX_PUMPFUN_FEE_TIERS = 64
|
|
42
|
+
MAX_PUMPFUN_SHAREHOLDERS = 64
|
|
32
43
|
|
|
33
44
|
SUPPLY_OFFSET = 36
|
|
34
45
|
DECIMALS_OFFSET = 44
|
|
@@ -75,6 +86,71 @@ def read_u16_fast(data: bytes, offset: int) -> int:
|
|
|
75
86
|
return struct.unpack_from("<H", data, offset)[0]
|
|
76
87
|
|
|
77
88
|
|
|
89
|
+
def read_i64_fast(data: bytes, offset: int) -> int:
|
|
90
|
+
return struct.unpack_from("<q", data, offset)[0]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def read_u32_fast(data: bytes, offset: int) -> int:
|
|
94
|
+
return struct.unpack_from("<I", data, offset)[0]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def read_u128_fast(data: bytes, offset: int) -> int:
|
|
98
|
+
return int.from_bytes(data[offset : offset + 16], "little")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _read_pumpfun_fees(data: bytes, offset: int) -> Optional[tuple[dict, int]]:
|
|
102
|
+
if offset + 24 > len(data):
|
|
103
|
+
return None
|
|
104
|
+
return (
|
|
105
|
+
{
|
|
106
|
+
"lp_fee_bps": read_u64_fast(data, offset),
|
|
107
|
+
"protocol_fee_bps": read_u64_fast(data, offset + 8),
|
|
108
|
+
"creator_fee_bps": read_u64_fast(data, offset + 16),
|
|
109
|
+
},
|
|
110
|
+
offset + 24,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _read_pumpfun_fee_tiers(data: bytes, offset: int) -> Optional[tuple[list[dict], int]]:
|
|
115
|
+
if offset + 4 > len(data):
|
|
116
|
+
return None
|
|
117
|
+
length = read_u32_fast(data, offset)
|
|
118
|
+
if length > MAX_PUMPFUN_FEE_TIERS:
|
|
119
|
+
return None
|
|
120
|
+
offset += 4
|
|
121
|
+
if offset + length * 40 > len(data):
|
|
122
|
+
return None
|
|
123
|
+
out = []
|
|
124
|
+
for _ in range(length):
|
|
125
|
+
threshold = read_u128_fast(data, offset)
|
|
126
|
+
offset += 16
|
|
127
|
+
fees_result = _read_pumpfun_fees(data, offset)
|
|
128
|
+
if fees_result is None:
|
|
129
|
+
return None
|
|
130
|
+
fees, offset = fees_result
|
|
131
|
+
out.append({"market_cap_lamports_threshold": threshold, "fees": fees})
|
|
132
|
+
return out, offset
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _read_pumpfun_shareholders(data: bytes, offset: int) -> Optional[tuple[list[dict], int]]:
|
|
136
|
+
if offset + 4 > len(data):
|
|
137
|
+
return None
|
|
138
|
+
length = read_u32_fast(data, offset)
|
|
139
|
+
if length > MAX_PUMPFUN_SHAREHOLDERS:
|
|
140
|
+
return None
|
|
141
|
+
offset += 4
|
|
142
|
+
if offset + length * 34 > len(data):
|
|
143
|
+
return None
|
|
144
|
+
out = []
|
|
145
|
+
for _ in range(length):
|
|
146
|
+
address = read_pubkey_fast(data, offset)
|
|
147
|
+
offset += 32
|
|
148
|
+
share_bps = read_u16_fast(data, offset)
|
|
149
|
+
offset += 2
|
|
150
|
+
out.append({"address": address, "share_bps": share_bps})
|
|
151
|
+
return out, offset
|
|
152
|
+
|
|
153
|
+
|
|
78
154
|
def parse_account_unified(
|
|
79
155
|
account: AccountData,
|
|
80
156
|
metadata: EventMetadata,
|
|
@@ -93,6 +169,11 @@ def parse_account_unified(
|
|
|
93
169
|
EventType.TOKEN_INFO,
|
|
94
170
|
EventType.NONCE_ACCOUNT,
|
|
95
171
|
EventType.ACCOUNT_PUMP_FUN_GLOBAL,
|
|
172
|
+
EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE,
|
|
173
|
+
EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG,
|
|
174
|
+
EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG,
|
|
175
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR,
|
|
176
|
+
EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR,
|
|
96
177
|
EventType.ACCOUNT_PUMP_SWAP_GLOBAL_CONFIG,
|
|
97
178
|
EventType.ACCOUNT_PUMP_SWAP_POOL,
|
|
98
179
|
}
|
|
@@ -107,8 +188,20 @@ def parse_account_unified(
|
|
|
107
188
|
if ev is not None:
|
|
108
189
|
return ev
|
|
109
190
|
|
|
110
|
-
if account.owner
|
|
111
|
-
if event_type_filter.should_include(
|
|
191
|
+
if account.owner in (PUMPFUN_PROGRAM_ID, PUMP_FEES_PROGRAM_ID) and event_type_filter is not None:
|
|
192
|
+
if event_type_filter.should_include(
|
|
193
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL
|
|
194
|
+
) or event_type_filter.should_include(
|
|
195
|
+
EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE
|
|
196
|
+
) or event_type_filter.should_include(
|
|
197
|
+
EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG
|
|
198
|
+
) or event_type_filter.should_include(
|
|
199
|
+
EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG
|
|
200
|
+
) or event_type_filter.should_include(
|
|
201
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR
|
|
202
|
+
) or event_type_filter.should_include(
|
|
203
|
+
EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR
|
|
204
|
+
):
|
|
112
205
|
ev = _parse_pumpfun_account(account, metadata)
|
|
113
206
|
if ev is not None:
|
|
114
207
|
return ev
|
|
@@ -134,6 +227,16 @@ def _parse_pumpswap_account(account: AccountData, metadata: EventMetadata) -> Op
|
|
|
134
227
|
|
|
135
228
|
|
|
136
229
|
def _parse_pumpfun_account(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
230
|
+
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_FEE_CONFIG):
|
|
231
|
+
return parse_pumpfun_fee_config(account, metadata)
|
|
232
|
+
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_SHARING_CONFIG):
|
|
233
|
+
return parse_pumpfun_sharing_config(account, metadata)
|
|
234
|
+
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR):
|
|
235
|
+
return parse_pumpfun_global_volume_accumulator(account, metadata)
|
|
236
|
+
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_USER_VOLUME_ACCUMULATOR):
|
|
237
|
+
return parse_pumpfun_user_volume_accumulator(account, metadata)
|
|
238
|
+
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_BONDING_CURVE):
|
|
239
|
+
return parse_pumpfun_bonding_curve(account, metadata)
|
|
137
240
|
if acc_utils.has_discriminator(account.data, _DISC_PUMPFUN_GLOBAL):
|
|
138
241
|
return parse_pumpfun_global(account, metadata)
|
|
139
242
|
return None
|
|
@@ -219,7 +322,7 @@ def _parse_pumpfun_global_fast(account: AccountData, metadata: EventMetadata) ->
|
|
|
219
322
|
creator_fee_basis_points = read_u64_fast(data, o)
|
|
220
323
|
o += 8
|
|
221
324
|
fee_recipients = []
|
|
222
|
-
for _ in range(
|
|
325
|
+
for _ in range(7):
|
|
223
326
|
fee_recipients.append(read_pubkey_fast(data, o))
|
|
224
327
|
o += 32
|
|
225
328
|
set_creator_authority = read_pubkey_fast(data, o)
|
|
@@ -238,6 +341,18 @@ def _parse_pumpfun_global_fast(account: AccountData, metadata: EventMetadata) ->
|
|
|
238
341
|
for _ in range(7):
|
|
239
342
|
reserved_fee_recipients.append(read_pubkey_fast(data, o))
|
|
240
343
|
o += 32
|
|
344
|
+
is_cashback_enabled = data[o] != 0
|
|
345
|
+
o += 1
|
|
346
|
+
buyback_fee_recipients = []
|
|
347
|
+
for _ in range(8):
|
|
348
|
+
buyback_fee_recipients.append(read_pubkey_fast(data, o))
|
|
349
|
+
o += 32
|
|
350
|
+
buyback_basis_points = read_u64_fast(data, o)
|
|
351
|
+
o += 8
|
|
352
|
+
initial_virtual_quote_reserves = read_u64_fast(data, o)
|
|
353
|
+
o += 8
|
|
354
|
+
whitelisted_quote_mints = [read_pubkey_fast(data, o)]
|
|
355
|
+
o += 32
|
|
241
356
|
return _account_event(
|
|
242
357
|
EventType.ACCOUNT_PUMP_FUN_GLOBAL,
|
|
243
358
|
{
|
|
@@ -264,6 +379,221 @@ def _parse_pumpfun_global_fast(account: AccountData, metadata: EventMetadata) ->
|
|
|
264
379
|
"reserved_fee_recipient": reserved_fee_recipient,
|
|
265
380
|
"mayhem_mode_enabled": mayhem_mode_enabled,
|
|
266
381
|
"reserved_fee_recipients": reserved_fee_recipients,
|
|
382
|
+
"is_cashback_enabled": is_cashback_enabled,
|
|
383
|
+
"buyback_fee_recipients": buyback_fee_recipients,
|
|
384
|
+
"buyback_basis_points": buyback_basis_points,
|
|
385
|
+
"initial_virtual_quote_reserves": initial_virtual_quote_reserves,
|
|
386
|
+
"whitelisted_quote_mints": whitelisted_quote_mints,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _parse_pumpfun_bonding_curve_fast(
|
|
393
|
+
account: AccountData, metadata: EventMetadata
|
|
394
|
+
) -> Optional[DexEvent]:
|
|
395
|
+
data = account.data[8:]
|
|
396
|
+
o = 0
|
|
397
|
+
virtual_token_reserves = read_u64_fast(data, o)
|
|
398
|
+
o += 8
|
|
399
|
+
virtual_quote_reserves = read_u64_fast(data, o)
|
|
400
|
+
o += 8
|
|
401
|
+
real_token_reserves = read_u64_fast(data, o)
|
|
402
|
+
o += 8
|
|
403
|
+
real_quote_reserves = read_u64_fast(data, o)
|
|
404
|
+
o += 8
|
|
405
|
+
token_total_supply = read_u64_fast(data, o)
|
|
406
|
+
o += 8
|
|
407
|
+
complete = data[o] != 0
|
|
408
|
+
o += 1
|
|
409
|
+
creator = read_pubkey_fast(data, o)
|
|
410
|
+
o += 32
|
|
411
|
+
is_mayhem_mode = data[o] != 0
|
|
412
|
+
o += 1
|
|
413
|
+
is_cashback_coin = data[o] != 0
|
|
414
|
+
o += 1
|
|
415
|
+
quote_mint = read_pubkey_fast(data, o)
|
|
416
|
+
return _account_event(
|
|
417
|
+
EventType.ACCOUNT_PUMP_FUN_BONDING_CURVE,
|
|
418
|
+
{
|
|
419
|
+
"metadata": metadata,
|
|
420
|
+
"pubkey": account.pubkey,
|
|
421
|
+
"bonding_curve": {
|
|
422
|
+
"virtual_token_reserves": virtual_token_reserves,
|
|
423
|
+
"virtual_quote_reserves": virtual_quote_reserves,
|
|
424
|
+
"real_token_reserves": real_token_reserves,
|
|
425
|
+
"real_quote_reserves": real_quote_reserves,
|
|
426
|
+
"token_total_supply": token_total_supply,
|
|
427
|
+
"complete": complete,
|
|
428
|
+
"creator": creator,
|
|
429
|
+
"is_mayhem_mode": is_mayhem_mode,
|
|
430
|
+
"is_cashback_coin": is_cashback_coin,
|
|
431
|
+
"quote_mint": quote_mint,
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def _parse_pumpfun_fee_config_fast(
|
|
438
|
+
account: AccountData, metadata: EventMetadata
|
|
439
|
+
) -> Optional[DexEvent]:
|
|
440
|
+
data = account.data[8:]
|
|
441
|
+
o = 0
|
|
442
|
+
bump = data[o]
|
|
443
|
+
o += 1
|
|
444
|
+
admin = read_pubkey_fast(data, o)
|
|
445
|
+
o += 32
|
|
446
|
+
flat_fees_result = _read_pumpfun_fees(data, o)
|
|
447
|
+
if flat_fees_result is None:
|
|
448
|
+
return None
|
|
449
|
+
flat_fees, o = flat_fees_result
|
|
450
|
+
fee_tiers_result = _read_pumpfun_fee_tiers(data, o)
|
|
451
|
+
if fee_tiers_result is None:
|
|
452
|
+
return None
|
|
453
|
+
fee_tiers, o = fee_tiers_result
|
|
454
|
+
stable_fee_tiers_result = _read_pumpfun_fee_tiers(data, o)
|
|
455
|
+
if stable_fee_tiers_result is None:
|
|
456
|
+
return None
|
|
457
|
+
stable_fee_tiers, _ = stable_fee_tiers_result
|
|
458
|
+
return _account_event(
|
|
459
|
+
EventType.ACCOUNT_PUMP_FUN_FEE_CONFIG,
|
|
460
|
+
{
|
|
461
|
+
"metadata": metadata,
|
|
462
|
+
"pubkey": account.pubkey,
|
|
463
|
+
"fee_config": {
|
|
464
|
+
"bump": bump,
|
|
465
|
+
"admin": admin,
|
|
466
|
+
"flat_fees": flat_fees,
|
|
467
|
+
"fee_tiers": fee_tiers,
|
|
468
|
+
"stable_fee_tiers": stable_fee_tiers,
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def _parse_pumpfun_sharing_config_fast(
|
|
475
|
+
account: AccountData, metadata: EventMetadata
|
|
476
|
+
) -> Optional[DexEvent]:
|
|
477
|
+
data = account.data[8:]
|
|
478
|
+
o = 0
|
|
479
|
+
bump = data[o]
|
|
480
|
+
o += 1
|
|
481
|
+
version = data[o]
|
|
482
|
+
o += 1
|
|
483
|
+
status_raw = data[o]
|
|
484
|
+
if status_raw > 1:
|
|
485
|
+
return None
|
|
486
|
+
status = "Paused" if status_raw == 0 else "Active"
|
|
487
|
+
o += 1
|
|
488
|
+
mint = read_pubkey_fast(data, o)
|
|
489
|
+
o += 32
|
|
490
|
+
admin = read_pubkey_fast(data, o)
|
|
491
|
+
o += 32
|
|
492
|
+
admin_revoked = data[o] != 0
|
|
493
|
+
o += 1
|
|
494
|
+
shareholders_result = _read_pumpfun_shareholders(data, o)
|
|
495
|
+
if shareholders_result is None:
|
|
496
|
+
return None
|
|
497
|
+
shareholders, _ = shareholders_result
|
|
498
|
+
return _account_event(
|
|
499
|
+
EventType.ACCOUNT_PUMP_FUN_SHARING_CONFIG,
|
|
500
|
+
{
|
|
501
|
+
"metadata": metadata,
|
|
502
|
+
"pubkey": account.pubkey,
|
|
503
|
+
"sharing_config": {
|
|
504
|
+
"bump": bump,
|
|
505
|
+
"version": version,
|
|
506
|
+
"status": status,
|
|
507
|
+
"mint": mint,
|
|
508
|
+
"admin": admin,
|
|
509
|
+
"admin_revoked": admin_revoked,
|
|
510
|
+
"shareholders": shareholders,
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def _parse_pumpfun_global_volume_accumulator_fast(
|
|
517
|
+
account: AccountData, metadata: EventMetadata
|
|
518
|
+
) -> Optional[DexEvent]:
|
|
519
|
+
data = account.data[8:]
|
|
520
|
+
o = 0
|
|
521
|
+
start_time = read_i64_fast(data, o)
|
|
522
|
+
o += 8
|
|
523
|
+
end_time = read_i64_fast(data, o)
|
|
524
|
+
o += 8
|
|
525
|
+
seconds_in_a_day = read_i64_fast(data, o)
|
|
526
|
+
o += 8
|
|
527
|
+
mint = read_pubkey_fast(data, o)
|
|
528
|
+
o += 32
|
|
529
|
+
total_token_supply = []
|
|
530
|
+
for _ in range(30):
|
|
531
|
+
total_token_supply.append(read_u64_fast(data, o))
|
|
532
|
+
o += 8
|
|
533
|
+
sol_volumes = []
|
|
534
|
+
for _ in range(30):
|
|
535
|
+
sol_volumes.append(read_u64_fast(data, o))
|
|
536
|
+
o += 8
|
|
537
|
+
return _account_event(
|
|
538
|
+
EventType.ACCOUNT_PUMP_FUN_GLOBAL_VOLUME_ACCUMULATOR,
|
|
539
|
+
{
|
|
540
|
+
"metadata": metadata,
|
|
541
|
+
"pubkey": account.pubkey,
|
|
542
|
+
"global_volume_accumulator": {
|
|
543
|
+
"start_time": start_time,
|
|
544
|
+
"end_time": end_time,
|
|
545
|
+
"seconds_in_a_day": seconds_in_a_day,
|
|
546
|
+
"mint": mint,
|
|
547
|
+
"total_token_supply": total_token_supply,
|
|
548
|
+
"sol_volumes": sol_volumes,
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def _parse_pumpfun_user_volume_accumulator_fast(
|
|
555
|
+
account: AccountData, metadata: EventMetadata
|
|
556
|
+
) -> Optional[DexEvent]:
|
|
557
|
+
data = account.data[8:]
|
|
558
|
+
o = 0
|
|
559
|
+
user = read_pubkey_fast(data, o)
|
|
560
|
+
o += 32
|
|
561
|
+
needs_claim = data[o] != 0
|
|
562
|
+
o += 1
|
|
563
|
+
total_unclaimed_tokens = read_u64_fast(data, o)
|
|
564
|
+
o += 8
|
|
565
|
+
total_claimed_tokens = read_u64_fast(data, o)
|
|
566
|
+
o += 8
|
|
567
|
+
current_sol_volume = read_u64_fast(data, o)
|
|
568
|
+
o += 8
|
|
569
|
+
last_update_timestamp = read_i64_fast(data, o)
|
|
570
|
+
o += 8
|
|
571
|
+
has_total_claimed_tokens = data[o] != 0
|
|
572
|
+
o += 1
|
|
573
|
+
cashback_earned = read_u64_fast(data, o)
|
|
574
|
+
o += 8
|
|
575
|
+
total_cashback_claimed = read_u64_fast(data, o)
|
|
576
|
+
o += 8
|
|
577
|
+
stable_cashback_earned = read_u64_fast(data, o)
|
|
578
|
+
o += 8
|
|
579
|
+
total_stable_cashback_claimed = read_u64_fast(data, o)
|
|
580
|
+
return _account_event(
|
|
581
|
+
EventType.ACCOUNT_PUMP_FUN_USER_VOLUME_ACCUMULATOR,
|
|
582
|
+
{
|
|
583
|
+
"metadata": metadata,
|
|
584
|
+
"pubkey": account.pubkey,
|
|
585
|
+
"user_volume_accumulator": {
|
|
586
|
+
"user": user,
|
|
587
|
+
"needs_claim": needs_claim,
|
|
588
|
+
"total_unclaimed_tokens": total_unclaimed_tokens,
|
|
589
|
+
"total_claimed_tokens": total_claimed_tokens,
|
|
590
|
+
"current_sol_volume": current_sol_volume,
|
|
591
|
+
"last_update_timestamp": last_update_timestamp,
|
|
592
|
+
"has_total_claimed_tokens": has_total_claimed_tokens,
|
|
593
|
+
"cashback_earned": cashback_earned,
|
|
594
|
+
"total_cashback_claimed": total_cashback_claimed,
|
|
595
|
+
"stable_cashback_earned": stable_cashback_earned,
|
|
596
|
+
"total_stable_cashback_claimed": total_stable_cashback_claimed,
|
|
267
597
|
},
|
|
268
598
|
},
|
|
269
599
|
)
|
|
@@ -399,6 +729,52 @@ def parse_pumpfun_global(account: AccountData, metadata: EventMetadata) -> Optio
|
|
|
399
729
|
return _parse_pumpfun_global_fast(account, metadata)
|
|
400
730
|
|
|
401
731
|
|
|
732
|
+
def parse_pumpfun_bonding_curve(
|
|
733
|
+
account: AccountData, metadata: EventMetadata
|
|
734
|
+
) -> Optional[DexEvent]:
|
|
735
|
+
if len(account.data) < 8 + PUMPFUN_BONDING_CURVE_BODY:
|
|
736
|
+
return None
|
|
737
|
+
if not has_discriminator(account.data, _DISC_PUMPFUN_BONDING_CURVE):
|
|
738
|
+
return None
|
|
739
|
+
return _parse_pumpfun_bonding_curve_fast(account, metadata)
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def parse_pumpfun_fee_config(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
743
|
+
if len(account.data) < 8 + 1 + 32 + 24 + 4 + 4:
|
|
744
|
+
return None
|
|
745
|
+
if not has_discriminator(account.data, _DISC_PUMPFUN_FEE_CONFIG):
|
|
746
|
+
return None
|
|
747
|
+
return _parse_pumpfun_fee_config_fast(account, metadata)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def parse_pumpfun_sharing_config(account: AccountData, metadata: EventMetadata) -> Optional[DexEvent]:
|
|
751
|
+
if len(account.data) < 8 + 1 + 1 + 1 + 32 + 32 + 1 + 4:
|
|
752
|
+
return None
|
|
753
|
+
if not has_discriminator(account.data, _DISC_PUMPFUN_SHARING_CONFIG):
|
|
754
|
+
return None
|
|
755
|
+
return _parse_pumpfun_sharing_config_fast(account, metadata)
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
def parse_pumpfun_global_volume_accumulator(
|
|
759
|
+
account: AccountData, metadata: EventMetadata
|
|
760
|
+
) -> Optional[DexEvent]:
|
|
761
|
+
if len(account.data) < 8 + PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR_BODY:
|
|
762
|
+
return None
|
|
763
|
+
if not has_discriminator(account.data, _DISC_PUMPFUN_GLOBAL_VOLUME_ACCUMULATOR):
|
|
764
|
+
return None
|
|
765
|
+
return _parse_pumpfun_global_volume_accumulator_fast(account, metadata)
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
def parse_pumpfun_user_volume_accumulator(
|
|
769
|
+
account: AccountData, metadata: EventMetadata
|
|
770
|
+
) -> Optional[DexEvent]:
|
|
771
|
+
if len(account.data) < 8 + PUMPFUN_USER_VOLUME_ACCUMULATOR_BODY:
|
|
772
|
+
return None
|
|
773
|
+
if not has_discriminator(account.data, _DISC_PUMPFUN_USER_VOLUME_ACCUMULATOR):
|
|
774
|
+
return None
|
|
775
|
+
return _parse_pumpfun_user_volume_accumulator_fast(account, metadata)
|
|
776
|
+
|
|
777
|
+
|
|
402
778
|
def is_nonce_account(data: bytes) -> bool:
|
|
403
779
|
return acc_utils.is_nonce_account(data)
|
|
404
780
|
|
|
@@ -445,6 +821,11 @@ __all__ = [
|
|
|
445
821
|
"parse_token_account",
|
|
446
822
|
"parse_nonce_account",
|
|
447
823
|
"parse_pumpfun_global",
|
|
824
|
+
"parse_pumpfun_bonding_curve",
|
|
825
|
+
"parse_pumpfun_fee_config",
|
|
826
|
+
"parse_pumpfun_sharing_config",
|
|
827
|
+
"parse_pumpfun_global_volume_accumulator",
|
|
828
|
+
"parse_pumpfun_user_volume_accumulator",
|
|
448
829
|
"is_nonce_account",
|
|
449
830
|
"is_pumpfun_global_account",
|
|
450
831
|
"parse_pumpswap_global_config",
|
|
@@ -453,6 +834,7 @@ __all__ = [
|
|
|
453
834
|
"is_pool_account",
|
|
454
835
|
"has_discriminator",
|
|
455
836
|
"PUMPFUN_PROGRAM_ID",
|
|
837
|
+
"PUMP_FEES_PROGRAM_ID",
|
|
456
838
|
"PUMPSWAP_PROGRAM_ID",
|
|
457
839
|
"rpc_resolve_user_wallet_pubkey",
|
|
458
840
|
"user_wallet_pubkey_for_onchain_account",
|