sol-parser-sdk 0.5.16 → 0.5.18

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.
Files changed (66) hide show
  1. package/README.md +31 -15
  2. package/README_CN.md +30 -14
  3. package/dist/accounts/pumpfun.js +15 -0
  4. package/dist/accounts/pumpswap.js +2 -0
  5. package/dist/core/account_dispatcher_rpc.d.ts +2 -1
  6. package/dist/core/account_dispatcher_rpc.js +120 -11
  7. package/dist/core/account_fill_pumpfun.js +27 -16
  8. package/dist/core/account_fill_pumpswap.d.ts +2 -0
  9. package/dist/core/account_fill_pumpswap.js +55 -6
  10. package/dist/core/account_fill_raydium.js +4 -0
  11. package/dist/core/dex_event.d.ts +149 -0
  12. package/dist/grpc/client.js +2 -0
  13. package/dist/grpc/log_instr_dedup.js +75 -7
  14. package/dist/grpc/order_buffer.d.ts +5 -0
  15. package/dist/grpc/order_buffer.js +53 -17
  16. package/dist/grpc/rpc_to_grpc.js +3 -2
  17. package/dist/grpc/types.d.ts +4 -1
  18. package/dist/grpc/types.js +23 -0
  19. package/dist/grpc/yellowstone_transaction_adapter.js +1 -1
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +1 -0
  22. package/dist/instr/inner.js +28 -1
  23. package/dist/instr/meteora_damm_ix.js +26 -0
  24. package/dist/instr/meteora_pools_ix.js +17 -9
  25. package/dist/instr/orca_whirlpool_ix.js +13 -9
  26. package/dist/instr/pumpfun_ix.js +87 -3
  27. package/dist/instr/pumpswap_ix.js +85 -10
  28. package/dist/instr/raydium_clmm_ix.js +5 -3
  29. package/dist/instr/raydium_cpmm_ix.js +11 -8
  30. package/dist/logs/meteora_damm.d.ts +7 -0
  31. package/dist/logs/meteora_damm.js +211 -0
  32. package/dist/logs/meteora_dbc.d.ts +3 -0
  33. package/dist/logs/meteora_dbc.js +23 -0
  34. package/dist/logs/meteora_dlmm.js +16 -4
  35. package/dist/logs/optimized_matcher.js +93 -10
  36. package/dist/logs/program_log_discriminators.d.ts +11 -0
  37. package/dist/logs/program_log_discriminators.js +11 -0
  38. package/dist/logs/pump.js +17 -3
  39. package/dist/logs/pump_amm.js +8 -2
  40. package/dist/logs/pump_upgrade.d.ts +68 -0
  41. package/dist/logs/pump_upgrade.js +128 -0
  42. package/dist/logs/raydium_cpmm.js +7 -3
  43. package/dist/rpc_transaction.js +87 -7
  44. package/dist/shredstream/alt_cache.d.ts +26 -0
  45. package/dist/shredstream/alt_cache.js +138 -0
  46. package/dist/shredstream/client.d.ts +11 -3
  47. package/dist/shredstream/client.js +76 -72
  48. package/dist/shredstream/config.d.ts +7 -3
  49. package/dist/shredstream/index.d.ts +3 -2
  50. package/dist/shredstream/index.js +5 -3
  51. package/dist/shredstream/instruction_parse.d.ts +1 -1
  52. package/dist/shredstream/instruction_parse.js +1 -0
  53. package/dist/simulation_route.d.ts +1 -1
  54. package/dist/simulation_route.js +17 -4
  55. package/dist/transaction_route.js +20 -1
  56. package/dist/wire_transaction.js +9 -10
  57. package/docs/USAGE.md +161 -0
  58. package/package.json +2 -5
  59. package/NATIVE_ALIGNMENT.md +0 -312
  60. package/NATIVE_DAMM_FACTORY_ALIGNMENT_20261004.md +0 -16
  61. package/NATIVE_DAMM_FACTORY_EVIDENCE_20261004.json +0 -55
  62. package/NATIVE_MIGRATION.md +0 -38
  63. package/NATIVE_PUMPFUN_NATIVE_DEBIT_ALIGNMENT_20261004.md +0 -18
  64. package/NATIVE_PUMPFUN_NATIVE_DEBIT_EVIDENCE_20261004.json +0 -57
  65. package/NATIVE_PUMPFUN_SETTLEMENT_ALIGNMENT_20261004.md +0 -11
  66. package/NATIVE_PUMPFUN_SETTLEMENT_EVIDENCE_20261004.json +0 -70
package/README.md CHANGED
@@ -18,17 +18,27 @@
18
18
 
19
19
  ---
20
20
 
21
- ## Other language SDKs
21
+ ## 📦 SDK Versions and Related SDKs
22
22
 
23
- | Language | Repository |
24
- |----------|------------|
25
- | Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) |
26
- | Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) |
27
- | Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) |
28
- | Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) |
23
+ Parser SDK language versions and related Rust SDKs:
24
+
25
+ | Language | Repository | Description | Version |
26
+ |----------|------------|-------------|---------|
27
+ | Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | Solana DEX transaction and account event parsing |
28
+ | Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | TypeScript/JavaScript for Node.js |
29
+ | Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | Async/await native support |
30
+ | Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | Go transaction and account event parsing |
31
+ | **Rust** | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | Raw Solana shred decoding and ShredStream DEX event parsing | `v4.0.3` |
32
+ | **Rust** | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | Solana DEX trade construction and transaction execution | `v6.0.0` |
29
33
 
30
34
  ---
31
35
 
36
+ ## v0.5.18 — Signed transaction and hot-path hardening
37
+
38
+ Hardens signed transaction sanitization, loaded-address boundaries, ordered stream filtering and parser lifecycle. Aligns CLMM and DEX instruction/event layouts, nested CPI route attribution and liquidity/reward accounting. Adds independently signed wire fixtures, ALT failure cases and offline bank regressions.
39
+
40
+ Validation includes local CPU benchmarks and offline signed-bank scenarios. Measured hot paths use cached inputs without RPC. Benchmarks do not establish production network or transaction-landing latency. No funded mainnet transactions were broadcast.
41
+
32
42
  ## What This SDK Is For
33
43
 
34
44
  `sol-parser-sdk` is the TypeScript/Node.js implementation of the FnZero Solana DEX parser SDK. The GitHub repository is named `sol-parser-sdk-nodejs` to distinguish it from the Rust/Python/Go repositories. It is built for bots, indexers, copy-trading services, sniper pipelines, and backend systems that need typed DEX events from Yellowstone gRPC, Jito ShredStream, RPC transactions, or protocol account data.
@@ -44,6 +54,13 @@
44
54
 
45
55
  ## Release notes
46
56
 
57
+ ### v0.5.17
58
+
59
+ - Matches PumpFun create/create_v2 accounts by the actual instruction discriminator and event mint, including CPI calls; ambiguous matches are left unspecified.
60
+ - Stops inferring quote mint/vault/token-program fields from arbitrary remaining create_v2 accounts and preserves authoritative decoded fields.
61
+ - Restores historical CreateEvent decoding and verifies successful and failed transactions using saved mainnet fixtures.
62
+ - Suppresses rolled-back DEX events from failed transactions and preserves failure status through RPC/gRPC adapters.
63
+
47
64
  ### v0.5.16
48
65
 
49
66
  - Adds native gRPC lifecycle and block metadata support, instruction-level route analysis and StonkFun registry/snapshot examples.
@@ -96,7 +113,7 @@
96
113
  **From npm**
97
114
 
98
115
  ```bash
99
- npm install sol-parser-sdk@0.5.16
116
+ npm install sol-parser-sdk@0.5.18
100
117
  ```
101
118
 
102
119
  **From source** (folder may be named `sol-parser-sdk-ts` in a monorepo)
@@ -263,7 +280,7 @@ The client decodes gRPC `entries` bytes in **TypeScript** (same layout as the Go
263
280
  npx tsx examples/shredstream_example.ts -- --url=http://127.0.0.1:10800
264
281
  ```
265
282
 
266
- Without RPC, V0 ALT-loaded account indexes are represented with default pubkey placeholders and parsed best-effort. `shredstream_pumpfun_json.ts` can also use Solana **`RPC_URL`** (or `--rpc`) to expand ALTs when exact loaded-account fields are required.
283
+ Without `connection` or prewarmed ALT snapshots, V0 ALT-loaded indexes retain the static-account, default-pubkey best-effort behavior. With `connection` or `address_lookup_tables`, parsing uses complete cached ALT snapshots only: a cache miss skips the entire transaction, increments `getReceiveStats().altCacheMissTransactions`, and is never replayed. `connection` performs RPC only during explicit `await client.preloadAddressLookupTables(altAddresses)` before subscribing and in the independent background refresher (default 1000 ms, at most one request in flight). Supply already loaded tables via `config.address_lookup_tables` to avoid cold misses. The cache and pending refresh queue each retain at most 2048 tables; refreshed snapshots apply only to later messages. `shredstream_pumpfun_json.ts` uses **`RPC_URL`** (or `--rpc`) for this background refresh; its entry parsing never waits for RPC.
267
284
 
268
285
  ---
269
286
 
@@ -291,7 +308,7 @@ From the **package root** after `npm install`. Examples use `npx tsx` and load `
291
308
  | Meteora DAMM V2 events | `npx tsx examples/meteora_damm_grpc.ts` | [meteora_damm_grpc.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/meteora_damm_grpc.ts) |
292
309
  | **ShredStream** (HTTP, not Yellowstone gRPC; see **step 5** above) | | |
293
310
  | Ultra-low-latency subscribe + queue / latency stats. URL: `--url` / `SHREDSTREAM_URL` / `.env` (default `http://127.0.0.1:10800`). | `npx tsx examples/shredstream_example.ts` | [shredstream_example.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_example.ts) |
294
- | PumpFun `DexEvent` JSON from ShredStream; static ALT fallback works without RPC, and Solana **RPC** (`RPC_URL` or `--rpc`) expands full ALT accounts when needed. | `npx tsx examples/shredstream_pumpfun_json.ts` | [shredstream_pumpfun_json.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_pumpfun_json.ts) |
311
+ | PumpFun `DexEvent` JSON from ShredStream; RPC (`RPC_URL` or `--rpc`) refreshes ALT snapshots outside parsing. Cold cache misses are skipped, counted, and not replayed; prewarm required tables. | `npx tsx examples/shredstream_pumpfun_json.ts` | [shredstream_pumpfun_json.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_pumpfun_json.ts) |
295
312
  | **Multi-protocol** | | |
296
313
  | Subscribe to all DEX protocols | `npx tsx examples/multi_protocol_grpc.ts` | [multi_protocol_grpc.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/multi_protocol_grpc.ts) |
297
314
  | **Utility** | | |
@@ -335,12 +352,11 @@ npm run check:migration # parity checks; needs build
335
352
 
336
353
  MIT — https://github.com/0xfnzero/sol-parser-sdk-nodejs
337
354
 
338
- ## Native alignment status
339
-
340
- See [NATIVE_ALIGNMENT.md](NATIVE_ALIGNMENT.md) for implemented native APIs, Rust golden tests, mainnet simulation evidence, examples, and remaining parity gaps. Full cross-language parity is still in progress.
355
+ ## API compatibility
341
356
 
357
+ Full cross-language API parity is still in progress. See the [API migration guide](docs/USAGE.md#api-compatibility) for public behavior and support boundaries, and the examples directory for usage.
342
358
 
343
- 实时 parser → trade 接入使用 Yellowstone **gRPC**;见 [gRPC 缓存接入与三语言示例](examples/GRPC_CACHE.md)。此路径不使用 WebSocket,报价和构建热路径不调用 RPC。
344
359
 
360
+ 实时 parser → trade 接入使用 Yellowstone **gRPC**;见 [gRPC 缓存接入与三语言示例](docs/USAGE.md#grpc-cache)。此路径不使用 WebSocket,报价和构建热路径不调用 RPC。
345
361
 
346
- [本轮原生对齐 API 迁移](NATIVE_MIGRATION.md)(实施中,尚未发布)。
362
+ Shared PumpFun create/create_v2 mainnet fixtures, replay instructions and verification limits are documented in the [validation guide](https://github.com/0xfnzero/sol-parser-sdk-golang/tree/main/validation/pumpfun_create_20261007).
package/README_CN.md CHANGED
@@ -18,14 +18,18 @@
18
18
 
19
19
  ---
20
20
 
21
- ## 其他语言 SDK
21
+ ## 📦 SDK 版本与相关项目
22
22
 
23
- | 语言 | 仓库 |
24
- |------|------|
25
- | Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) |
26
- | Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) |
27
- | Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) |
28
- | Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) |
23
+ 解析 SDK 的各语言版本及相关 Rust SDK:
24
+
25
+ | 语言 | 仓库 | 描述 | 版本 |
26
+ |------|------|------|
27
+ | Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | Solana DEX 交易与账户事件解析 |
28
+ | Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | TypeScript/JavaScript,Node.js 支持 |
29
+ | Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | 原生 async/await 支持 |
30
+ | Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | Go 交易与账户事件解析 |
31
+ | **Rust** | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | Solana 原始 shred 解码与 ShredStream DEX 事件解析 | `v4.0.3` |
32
+ | **Rust** | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | Solana DEX 交易构建与交易执行 | `v6.0.0` |
29
33
 
30
34
  ---
31
35
 
@@ -44,6 +48,19 @@
44
48
 
45
49
  ## 发布说明
46
50
 
51
+ ## v0.5.18 — Signed transaction and hot-path hardening
52
+
53
+ Hardens signed transaction sanitization, loaded-address boundaries, ordered stream filtering and parser lifecycle. Aligns CLMM and DEX instruction/event layouts, nested CPI route attribution and liquidity/reward accounting. Adds independently signed wire fixtures, ALT failure cases and offline bank regressions.
54
+
55
+ Validation includes local CPU benchmarks and offline signed-bank scenarios. Measured hot paths use cached inputs without RPC. Benchmarks do not establish production network or transaction-landing latency. No funded mainnet transactions were broadcast.
56
+
57
+ ### v0.5.17
58
+
59
+ - 按实际指令 discriminator 和事件 mint 匹配 PumpFun create/create_v2 账户,支持 CPI,并拒绝猜测有歧义的匹配。
60
+ - 停止从 create_v2 的任意尾部账户推断 quote mint、vault、token program,保留权威解码字段。
61
+ - 恢复历史 CreateEvent 布局,并通过保存的真实主网成功、失败交易验证。
62
+ - 过滤失败交易中已经回滚的 Create/Buy 等 DEX 事件,并在 RPC/gRPC 转换中保留失败状态。
63
+
47
64
  ### v0.5.16
48
65
 
49
66
  - Adds native gRPC lifecycle and block metadata support, instruction-level route analysis and StonkFun registry/snapshot examples.
@@ -96,7 +113,7 @@
96
113
  **npm**
97
114
 
98
115
  ```bash
99
- npm install sol-parser-sdk@0.5.16
116
+ npm install sol-parser-sdk@0.5.18
100
117
  ```
101
118
 
102
119
  **源码**(monorepo 里目录可能是 `sol-parser-sdk-ts`)
@@ -256,7 +273,7 @@ mint 或 quote mint 映射到 pool,再将 `PumpSwapLiquidityAdded.user` 与该
256
273
  npx tsx examples/shredstream_example.ts -- --url=http://127.0.0.1:10800
257
274
  ```
258
275
 
259
- 无 RPC 时,V0 ALT-loaded 账户索引用默认 pubkey 占位并继续 best-effort 解析。若需要精确的 ALT 加载账户字段,`shredstream_pumpfun_json.ts` 也可以使用 Solana **`RPC_URL`**(或 `--rpc`)展开 ALT。
276
+ 未配置 `connection` 或预热 ALT 快照时,保留静态账户表及默认 pubkey 占位的 best-effort 行为。配置 `connection` 或 `address_lookup_tables` 后,解析只读取完整的 ALT 缓存快照:缓存 miss 跳过整笔交易,累计 `getReceiveStats().altCacheMissTransactions`,不会重放。`connection` 仅用于订阅前显式调用 `await client.preloadAddressLookupTables(altAddresses)` 预热,以及独立后台刷新任务(默认间隔 1000 毫秒,最多一个请求在途);也可通过 `config.address_lookup_tables` 注入已加载的快照。缓存和待刷新队列各最多保留 2048 张表,刷新结果只供后续消息使用。`shredstream_pumpfun_json.ts` 的 **`RPC_URL`**(或 `--rpc`)用于后台刷新,Entry 解析不等待 RPC。
260
277
 
261
278
  ---
262
279
 
@@ -284,7 +301,7 @@ npx tsx examples/shredstream_example.ts -- --url=http://127.0.0.1:10800
284
301
  | Meteora DAMM V2 事件 | `npx tsx examples/meteora_damm_grpc.ts` | [meteora_damm_grpc.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/meteora_damm_grpc.ts) |
285
302
  | **ShredStream**(HTTP,**非** Yellowstone gRPC;端点见上文步骤 5) | | |
286
303
  | 超低延迟订阅、队列与延迟统计。端点:`--url` / `SHREDSTREAM_URL` / `.env`(默认 `http://127.0.0.1:10800`)。 | `npx tsx examples/shredstream_example.ts` | [shredstream_example.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_example.ts) |
287
- | ShredStream → PumpFun `DexEvent` JSON;无 RPC 时可静态 ALT fallback,配置 Solana **RPC**(`RPC_URL` 或 `--rpc`)时可展开完整 ALT 账户。 | `npx tsx examples/shredstream_pumpfun_json.ts` | [shredstream_pumpfun_json.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_pumpfun_json.ts) |
304
+ | ShredStream → PumpFun `DexEvent` JSON;RPC(`RPC_URL` 或 `--rpc`)只后台刷新 ALT,冷缓存 miss 跳过并计数、不重放;应预热所需表。 | `npx tsx examples/shredstream_pumpfun_json.ts` | [shredstream_pumpfun_json.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/shredstream_pumpfun_json.ts) |
288
305
  | **多协议** | | |
289
306
  | 同时订阅所有 DEX 协议 | `npx tsx examples/multi_protocol_grpc.ts` | [multi_protocol_grpc.ts](https://github.com/0xfnzero/sol-parser-sdk-nodejs/blob/main/examples/multi_protocol_grpc.ts) |
290
307
  | **工具** | | |
@@ -328,9 +345,8 @@ npm run check:migration # 对齐与校验,需先 build
328
345
 
329
346
  MIT — https://github.com/0xfnzero/sol-parser-sdk-nodejs
330
347
 
331
- ## Native alignment status
332
-
333
- See [NATIVE_ALIGNMENT.md](NATIVE_ALIGNMENT.md) for implemented native APIs, Rust golden tests, mainnet simulation evidence, examples, and remaining parity gaps. Full cross-language parity is still in progress.
348
+ ## API 兼容性
334
349
 
350
+ 完整跨语言 API 对齐仍在进行;公开行为和支持边界见 [API 迁移说明](docs/USAGE.md#api-compatibility),使用方法见 examples 目录。
335
351
 
336
- [本轮原生对齐 API 迁移](NATIVE_MIGRATION.md)(实施中,尚未发布)。
352
+ PumpFun create/create_v2 的共享主网样本、重放方法和验证边界见 [验证说明](https://github.com/0xfnzero/sol-parser-sdk-golang/tree/main/validation/pumpfun_create_20261007)。
@@ -220,6 +220,11 @@ function parsePumpfunGlobal(account, metadata) {
220
220
  return null;
221
221
  const whitelisted_quote_mints = whitelistedQuoteMints.value;
222
222
  const global = {
223
+ creator_fee_configurable: d[1037] === 1,
224
+ max_configurable_creator_fee_bps: (0, binary_js_1.readU64LE)(d, 1038) ?? 0n,
225
+ holder_reward_claim_authority: (0, binary_js_1.readPubkey)(d, 1046) ?? "11111111111111111111111111111111",
226
+ is_holder_reward_enabled: d[1078] === 1,
227
+ max_curve_depth: d[1079] ?? 0,
223
228
  initialized,
224
229
  authority,
225
230
  fee_recipient,
@@ -311,6 +316,12 @@ function parsePumpfunBondingCurve(account, metadata) {
311
316
  o += 1;
312
317
  const is_holder_reward = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
313
318
  const bonding_curve = {
319
+ creator_fee: (0, binary_js_1.readU64LE)(d, 117) ?? 0n,
320
+ protocol_fees: (0, binary_js_1.readU64LE)(d, 125) ?? 0n,
321
+ depth: (0, binary_js_1.readU8)(d, 133) ?? 0,
322
+ initial_virtual_quote_reserves: (0, binary_js_1.readU64LE)(d, 134) ?? 0n,
323
+ post_complete_base_out: (0, binary_js_1.readU64LE)(d, 142) ?? 0n,
324
+ post_complete_quote_in: (0, binary_js_1.readU64LE)(d, 150) ?? 0n,
314
325
  virtual_token_reserves,
315
326
  virtual_quote_reserves,
316
327
  real_token_reserves,
@@ -356,7 +367,11 @@ function parsePumpfunFeeConfig(account, metadata) {
356
367
  const stableFeeTiers = readFeeTiers(d, o);
357
368
  if (stableFeeTiers === null)
358
369
  return null;
370
+ const exotic = stableFeeTiers.next === d.length ? { value: { lp_fee_bps: 0n, protocol_fee_bps: 0n, creator_fee_bps: 0n } } : readFees(d, stableFeeTiers.next);
371
+ if (exotic === null)
372
+ return null;
359
373
  const fee_config = {
374
+ exotic_flat_fees: exotic.value,
360
375
  bump,
361
376
  admin,
362
377
  flat_fees: flatFees.value,
@@ -181,6 +181,8 @@ function parsePumpswapPool(account, metadata) {
181
181
  o += 1;
182
182
  const is_holder_reward = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
183
183
  const pool = {
184
+ protocol_fees: (0, binary_js_1.readU64LE)(d, 263) ?? 0n,
185
+ creator_fees: (0, binary_js_1.readU64LE)(d, 271) ?? 0n,
184
186
  pool_bump,
185
187
  index,
186
188
  creator,
@@ -1,9 +1,10 @@
1
+ import { PublicKey } from "@solana/web3.js";
1
2
  /**
2
3
  * RPC 路径账户填充(`fillAccountsFromTransactionDataRpc`)。
3
4
  * `RaydiumClmmOpenPositionWithTokenExtNft` 与 `openPosition` 共用账户索引(见 `account_fill_raydium.ts`)。
4
5
  */
5
6
  import type { DexEvent } from "./dex_event.js";
6
- import type { ConfirmedTransactionMeta, Message, MessageV0, PublicKey } from "@solana/web3.js";
7
+ import type { ConfirmedTransactionMeta, Message, MessageV0 } from "@solana/web3.js";
7
8
  import { type InvokePair } from "./rpc_invoke_map.js";
8
9
  /** 就地修改事件体内字段 */
9
10
  export declare function fillAccountsFromTransactionDataRpc(ev: DexEvent, message: Message | MessageV0, meta: ConfirmedTransactionMeta | null, programInvokes: Map<string, InvokePair[]>, resolver: {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fillAccountsFromTransactionDataRpc = fillAccountsFromTransactionDataRpc;
4
+ const web3_js_1 = require("@solana/web3.js");
4
5
  const program_ids_js_1 = require("../instr/program_ids.js");
5
6
  const rpc_invoke_map_js_1 = require("./rpc_invoke_map.js");
6
7
  const account_fill_pumpfun_js_1 = require("./account_fill_pumpfun.js");
@@ -9,13 +10,18 @@ const account_fill_raydium_js_1 = require("./account_fill_raydium.js");
9
10
  const account_fill_orca_js_1 = require("./account_fill_orca.js");
10
11
  const account_fill_raydium_launchlab_js_1 = require("./account_fill_raydium_launchlab.js");
11
12
  const account_fill_meteora_js_1 = require("./account_fill_meteora.js");
12
- function tryFill(programId, programInvokes, message, meta, resolver, fn, anchor, unambiguous = false) {
13
+ function tryFill(programId, programInvokes, message, meta, resolver, fn, anchor, unambiguous = false, allowedDiscriminators) {
13
14
  if (anchor || unambiguous) {
14
15
  const hasAnchor = anchor && anchor.pool && anchor.pool !== "11111111111111111111111111111111";
15
16
  if (!hasAnchor && !unambiguous)
16
17
  return;
17
18
  let selected = null;
18
19
  for (const invocation of programInvokes.get(programId) ?? []) {
20
+ if (allowedDiscriminators) {
21
+ const raw = (0, rpc_invoke_map_js_1.getInstructionDataBytes)(message, meta, invocation);
22
+ if (!raw || !allowedDiscriminators.some(disc => disc.every((v, i) => raw[i] === v)))
23
+ continue;
24
+ }
19
25
  const candidate = (0, rpc_invoke_map_js_1.makeInvokeAccountGetter)(resolver, invocation, message, meta);
20
26
  if (!candidate || (hasAnchor && candidate(anchor.index) !== anchor.pool))
21
27
  continue;
@@ -40,32 +46,129 @@ function tryFill(programId, programInvokes, message, meta, resolver, fn, anchor,
40
46
  }
41
47
  /** 就地修改事件体内字段 */
42
48
  function fillAccountsFromTransactionDataRpc(ev, message, meta, programInvokes, resolver) {
49
+ const fillPumpTrade = (e) => {
50
+ if (!e.mint || e.mint === "11111111111111111111111111111111")
51
+ return;
52
+ // Discriminator -> mint index, user index, direction, required IDL accounts.
53
+ const layouts = {
54
+ "102,6,61,18,1,218,235,234": [2, 6, true, 16],
55
+ "56,252,116,8,158,223,205,95": [2, 6, true, 16],
56
+ "51,230,133,164,1,127,131,173": [2, 6, false, 14],
57
+ "184,23,238,97,103,197,211,61": [1, 13, true, 27],
58
+ "194,171,28,70,104,77,91,47": [1, 13, true, 27],
59
+ "93,246,130,60,231,233,64,178": [1, 13, false, 26],
60
+ "7,5,29,196,245,23,101,80": [1, 8, true, 17],
61
+ "225,247,80,30,213,179,132,136": [1, 8, true, 17],
62
+ "28,146,222,119,38,196,105,213": [1, 8, false, 17],
63
+ };
64
+ let selected;
65
+ for (const invoke of programInvokes.get(program_ids_js_1.PUMPFUN_PROGRAM_ID) ?? []) {
66
+ const raw = (0, rpc_invoke_map_js_1.getInstructionDataBytes)(message, meta, invoke);
67
+ const layout = raw && layouts[raw.slice(0, 8).join(",")];
68
+ if (!layout)
69
+ continue;
70
+ const [mintIndex, userIndex, buy, minimum] = layout;
71
+ if (buy !== e.is_buy || (0, rpc_invoke_map_js_1.countInstructionAccounts)(message, meta, invoke) < minimum)
72
+ continue;
73
+ const get = (0, rpc_invoke_map_js_1.makeInvokeAccountGetter)(resolver, invoke, message, meta);
74
+ if (!get || get(mintIndex) !== e.mint || (e.user && e.user !== "11111111111111111111111111111111" && get(userIndex) !== e.user))
75
+ continue;
76
+ if (selected)
77
+ return;
78
+ selected = get;
79
+ }
80
+ if (selected)
81
+ (0, account_fill_pumpfun_js_1.fillPumpfunTradeAccounts)(e, selected);
82
+ };
83
+ const fillSwap = (e, buy) => {
84
+ if (!e.pool || e.pool === "11111111111111111111111111111111")
85
+ return;
86
+ const legacy = buy
87
+ ? ["102,6,61,18,1,218,235,234", "198,46,21,82,180,217,232,112"]
88
+ : ["51,230,133,164,1,127,131,173"];
89
+ const compact = buy
90
+ ? ["184,23,238,97,103,197,211,61", "194,171,28,70,104,77,91,47"]
91
+ : ["93,246,130,60,231,233,64,178"];
92
+ let selected;
93
+ for (const invoke of programInvokes.get(program_ids_js_1.PUMPSWAP_PROGRAM_ID) ?? []) {
94
+ const raw = (0, rpc_invoke_map_js_1.getInstructionDataBytes)(message, meta, invoke);
95
+ const disc = raw?.slice(0, 8).join(",");
96
+ const boost = buy && disc === "105,68,6,175,0,7,35,162";
97
+ if (!disc || (!boost && !legacy.includes(disc) && !compact.includes(disc)))
98
+ continue;
99
+ const minimum = boost ? 13 : compact.includes(disc) ? 17 : buy ? 23 : 21;
100
+ if ((0, rpc_invoke_map_js_1.countInstructionAccounts)(message, meta, invoke) < minimum)
101
+ continue;
102
+ const get = (0, rpc_invoke_map_js_1.makeInvokeAccountGetter)(resolver, invoke, message, meta);
103
+ if (!get ||
104
+ get(0) !== e.pool ||
105
+ (e.user &&
106
+ e.user !== "11111111111111111111111111111111" &&
107
+ get(boost ? 7 : 1) !== e.user))
108
+ continue;
109
+ if (selected)
110
+ return;
111
+ selected = { get, boost };
112
+ }
113
+ if (selected) {
114
+ if (selected.boost)
115
+ (0, account_fill_pumpswap_js_1.fillPumpswapBoostBuyAccounts)(e, selected.get);
116
+ else if (buy)
117
+ (0, account_fill_pumpswap_js_1.fillPumpswapBuyAccounts)(e, selected.get);
118
+ else
119
+ (0, account_fill_pumpswap_js_1.fillPumpswapSellAccounts)(e, selected.get);
120
+ }
121
+ };
122
+ const fillCreate = (e, v2Only = false) => {
123
+ let selected;
124
+ for (const invoke of programInvokes.get(program_ids_js_1.PUMPFUN_PROGRAM_ID) ?? []) {
125
+ const raw = (0, rpc_invoke_map_js_1.getInstructionDataBytes)(message, meta, invoke);
126
+ const matches = (disc) => raw && disc.every((b, i) => raw[i] === b);
127
+ const v2 = !!matches([214, 144, 76, 236, 95, 139, 49, 180]);
128
+ if (!v2 && (v2Only || !matches([24, 30, 200, 40, 5, 28, 7, 119])))
129
+ continue;
130
+ if ((0, rpc_invoke_map_js_1.countInstructionAccounts)(message, meta, invoke) < (v2 ? 16 : 14))
131
+ continue;
132
+ const get = (0, rpc_invoke_map_js_1.makeInvokeAccountGetter)(resolver, invoke, message, meta);
133
+ if (!get || (e.mint && e.mint !== "11111111111111111111111111111111" && get(0) !== e.mint))
134
+ continue;
135
+ if (selected)
136
+ return;
137
+ selected = { get, v2 };
138
+ }
139
+ if (selected) {
140
+ if (selected.v2)
141
+ (0, account_fill_pumpfun_js_1.fillPumpfunCreateV2Accounts)(e, selected.get);
142
+ else
143
+ (0, account_fill_pumpfun_js_1.fillPumpfunCreateAccounts)(e, selected.get);
144
+ }
145
+ };
43
146
  if ("PumpFunTrade" in ev) {
44
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunTradeAccounts)(ev.PumpFunTrade, g));
147
+ fillPumpTrade(ev.PumpFunTrade);
45
148
  }
46
149
  else if ("PumpFunBuy" in ev) {
47
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunTradeAccounts)(ev.PumpFunBuy, g));
150
+ fillPumpTrade(ev.PumpFunBuy);
48
151
  }
49
152
  else if ("PumpFunSell" in ev) {
50
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunTradeAccounts)(ev.PumpFunSell, g));
153
+ fillPumpTrade(ev.PumpFunSell);
51
154
  }
52
155
  else if ("PumpFunBuyExactSolIn" in ev) {
53
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunTradeAccounts)(ev.PumpFunBuyExactSolIn, g));
156
+ fillPumpTrade(ev.PumpFunBuyExactSolIn);
54
157
  }
55
158
  else if ("PumpFunCreate" in ev) {
56
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunCreateAccounts)(ev.PumpFunCreate, g));
159
+ fillCreate(ev.PumpFunCreate);
57
160
  }
58
161
  else if ("PumpFunCreateV2" in ev) {
59
- tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunCreateV2Accounts)(ev.PumpFunCreateV2, g));
162
+ fillCreate(ev.PumpFunCreateV2, true);
60
163
  }
61
164
  else if ("PumpFunMigrate" in ev) {
62
165
  tryFill(program_ids_js_1.PUMPFUN_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpfun_js_1.fillPumpfunMigrateAccounts)(ev.PumpFunMigrate, g));
63
166
  }
64
167
  else if ("PumpSwapBuy" in ev) {
65
- tryFill(program_ids_js_1.PUMPSWAP_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpswap_js_1.fillPumpswapBuyAccounts)(ev.PumpSwapBuy, g));
168
+ fillSwap(ev.PumpSwapBuy, true);
66
169
  }
67
170
  else if ("PumpSwapSell" in ev) {
68
- tryFill(program_ids_js_1.PUMPSWAP_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpswap_js_1.fillPumpswapSellAccounts)(ev.PumpSwapSell, g));
171
+ fillSwap(ev.PumpSwapSell, false);
69
172
  }
70
173
  else if ("PumpSwapTrade" in ev) {
71
174
  tryFill(program_ids_js_1.PUMPSWAP_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_pumpswap_js_1.fillPumpswapTradeAccounts)(ev.PumpSwapTrade, g));
@@ -95,10 +198,16 @@ function fillAccountsFromTransactionDataRpc(ev, message, meta, programInvokes, r
95
198
  tryFill(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumClmmClosePositionAccounts)(ev.RaydiumClmmClosePosition, g));
96
199
  }
97
200
  else if ("RaydiumClmmIncreaseLiquidity" in ev) {
98
- tryFill(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumClmmIncreaseLiquidityAccounts)(ev.RaydiumClmmIncreaseLiquidity, g));
201
+ if (ev.RaydiumClmmIncreaseLiquidity.position_nft_mint && ev.RaydiumClmmIncreaseLiquidity.position_nft_mint !== "11111111111111111111111111111111") {
202
+ ev.RaydiumClmmIncreaseLiquidity.personal_position = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("position"), new web3_js_1.PublicKey(ev.RaydiumClmmIncreaseLiquidity.position_nft_mint).toBuffer()], new web3_js_1.PublicKey(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID))[0].toBase58();
203
+ }
204
+ tryFill(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumClmmIncreaseLiquidityAccounts)(ev.RaydiumClmmIncreaseLiquidity, g), { pool: ev.RaydiumClmmIncreaseLiquidity.personal_position ?? "", index: 4 }, false, [[133, 29, 89, 223, 69, 238, 176, 10], [46, 156, 243, 118, 13, 205, 251, 178]]);
99
205
  }
100
206
  else if ("RaydiumClmmDecreaseLiquidity" in ev) {
101
- tryFill(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumClmmDecreaseLiquidityAccounts)(ev.RaydiumClmmDecreaseLiquidity, g));
207
+ if (ev.RaydiumClmmDecreaseLiquidity.position_nft_mint && ev.RaydiumClmmDecreaseLiquidity.position_nft_mint !== "11111111111111111111111111111111") {
208
+ ev.RaydiumClmmDecreaseLiquidity.personal_position = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("position"), new web3_js_1.PublicKey(ev.RaydiumClmmDecreaseLiquidity.position_nft_mint).toBuffer()], new web3_js_1.PublicKey(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID))[0].toBase58();
209
+ }
210
+ tryFill(program_ids_js_1.RAYDIUM_CLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumClmmDecreaseLiquidityAccounts)(ev.RaydiumClmmDecreaseLiquidity, g), { pool: ev.RaydiumClmmDecreaseLiquidity.personal_position ?? "", index: 2 }, false, [[58, 127, 188, 62, 79, 82, 196, 96], [160, 38, 208, 111, 104, 91, 44, 1]]);
102
211
  }
103
212
  else if ("RaydiumCpmmSwap" in ev) {
104
213
  tryFill(program_ids_js_1.RAYDIUM_CPMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumCpmmSwapAccounts)(ev.RaydiumCpmmSwap, g));
@@ -15,6 +15,26 @@ function fillPumpfunTradeAccounts(e, get) {
15
15
  e[key] = get(idx);
16
16
  }
17
17
  };
18
+ if (get(16) === "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" && accountAtMatchesMint(1)) {
19
+ set("global", 0);
20
+ set("mint", 1);
21
+ set("quote_mint", 2);
22
+ set("token_program", 3);
23
+ set("quote_token_program", 4);
24
+ set("bonding_curve", 5);
25
+ set("associated_bonding_curve", 6);
26
+ set("associated_quote_bonding_curve", 7);
27
+ set("user", 8);
28
+ set("associated_user", 9);
29
+ set("associated_quote_user", 10);
30
+ set("user_volume_accumulator", 11);
31
+ set("fee_config", 12);
32
+ set("buyback_fee_recipient", 13);
33
+ set("system_program", 14);
34
+ set("event_authority", 15);
35
+ set("program", 16);
36
+ return;
37
+ }
18
38
  const isV2 = e.ix_name === "buy_v2" ||
19
39
  e.ix_name === "sell_v2" ||
20
40
  e.ix_name === "buy_exact_quote_in_v2" ||
@@ -106,16 +126,14 @@ function fillPumpfunTradeAccounts(e, get) {
106
126
  }
107
127
  function fillPumpfunCreateAccounts(e, get) {
108
128
  const zero = Z();
109
- if (get(15) === "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P") {
110
- fillPumpfunCreateV2Accounts(e, get);
111
- return;
129
+ const accounts = e;
130
+ for (const [field, index] of Object.entries({ mint: 0, mint_authority: 1, bonding_curve: 2,
131
+ associated_bonding_curve: 3, global: 4, user: 7, system_program: 8, token_program: 9,
132
+ associated_token_program: 10, event_authority: 12, program: 13 })) {
133
+ const key = field;
134
+ if (!accounts[key] || accounts[key] === zero)
135
+ accounts[field] = get(index);
112
136
  }
113
- if (!e.mint || e.mint === zero)
114
- e.mint = get(0);
115
- if (!e.bonding_curve || e.bonding_curve === zero)
116
- e.bonding_curve = get(2);
117
- if (!e.user || e.user === zero)
118
- e.user = get(7);
119
137
  }
120
138
  function fillPumpfunCreateV2Accounts(e, get) {
121
139
  const zero = Z();
@@ -153,13 +171,6 @@ function fillPumpfunCreateV2Accounts(e, get) {
153
171
  e.event_authority = get(14);
154
172
  if (!e.program || e.program === zero)
155
173
  e.program = get(15);
156
- if (!e.quote_mint || e.quote_mint === zero || e.quote_mint === "So11111111111111111111111111111111111111111") {
157
- e.quote_mint = get(16);
158
- }
159
- if (!e.quote_vault || e.quote_vault === zero)
160
- e.quote_vault = get(17);
161
- if (!e.quote_token_program || e.quote_token_program === zero)
162
- e.quote_token_program = get(18);
163
174
  if (!e.ix_name || e.ix_name === "create")
164
175
  e.ix_name = "create_v2";
165
176
  }
@@ -1,5 +1,7 @@
1
1
  /** PumpSwap 账户填充 */
2
2
  import type { PumpSwapBuyEvent, PumpSwapCreatePoolEvent, PumpSwapLiquidityAdded, PumpSwapLiquidityRemoved, PumpSwapSellEvent, PumpSwapTradeEvent } from "./dex_event.js";
3
+ /** The boost layout has no user ATAs or fee accounts. Preserve decoded values. */
4
+ export declare function fillPumpswapBoostBuyAccounts(e: PumpSwapBuyEvent, get: (i: number) => string): void;
3
5
  export declare function fillPumpswapBuyAccounts(e: PumpSwapBuyEvent, get: (i: number) => string): void;
4
6
  export declare function fillPumpswapSellAccounts(e: PumpSwapSellEvent, get: (i: number) => string): void;
5
7
  export declare function fillPumpswapCreatePoolAccounts(e: PumpSwapCreatePoolEvent, get: (i: number) => string): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fillPumpswapBoostBuyAccounts = fillPumpswapBoostBuyAccounts;
3
4
  exports.fillPumpswapBuyAccounts = fillPumpswapBuyAccounts;
4
5
  exports.fillPumpswapSellAccounts = fillPumpswapSellAccounts;
5
6
  exports.fillPumpswapCreatePoolAccounts = fillPumpswapCreatePoolAccounts;
@@ -8,6 +9,16 @@ exports.fillPumpswapLiquidityAddedAccounts = fillPumpswapLiquidityAddedAccounts;
8
9
  exports.fillPumpswapLiquidityRemovedAccounts = fillPumpswapLiquidityRemovedAccounts;
9
10
  const dex_event_js_1 = require("./dex_event.js");
10
11
  const Z = () => (0, dex_event_js_1.defaultPubkey)();
12
+ const TOKEN_PROGRAMS = new Set([
13
+ "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
14
+ "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
15
+ ]);
16
+ function isCompactTrade(get) {
17
+ // Index 16 is the program in both legacy and compact layouts.
18
+ return (get(16) === "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA" &&
19
+ TOKEN_PROGRAMS.has(get(9)) &&
20
+ TOKEN_PROGRAMS.has(get(10)));
21
+ }
11
22
  function fillPumpswapTradeCommon(e, get) {
12
23
  const zero = Z();
13
24
  if (!e.pool || e.pool === zero)
@@ -30,10 +41,21 @@ function fillPumpswapTradeCommon(e, get) {
30
41
  if (!e.pool_quote_token_account || e.pool_quote_token_account === zero) {
31
42
  e.pool_quote_token_account = get(8);
32
43
  }
44
+ if (isCompactTrade(get)) {
45
+ if (!e.base_token_program || e.base_token_program === zero)
46
+ e.base_token_program = get(9);
47
+ if (!e.quote_token_program || e.quote_token_program === zero)
48
+ e.quote_token_program = get(10);
49
+ if (!e.fee_recipient_quote_token_account ||
50
+ e.fee_recipient_quote_token_account === zero)
51
+ e.fee_recipient_quote_token_account = get(14);
52
+ return;
53
+ }
33
54
  if (!e.protocol_fee_recipient || e.protocol_fee_recipient === zero) {
34
55
  e.protocol_fee_recipient = get(9);
35
56
  }
36
- if (!e.protocol_fee_recipient_token_account || e.protocol_fee_recipient_token_account === zero) {
57
+ if (!e.protocol_fee_recipient_token_account ||
58
+ e.protocol_fee_recipient_token_account === zero) {
37
59
  e.protocol_fee_recipient_token_account = get(10);
38
60
  }
39
61
  if (!e.base_token_program || e.base_token_program === zero)
@@ -42,12 +64,33 @@ function fillPumpswapTradeCommon(e, get) {
42
64
  e.quote_token_program = get(12);
43
65
  if (!e.coin_creator_vault_ata || e.coin_creator_vault_ata === zero)
44
66
  e.coin_creator_vault_ata = get(17);
45
- if (!e.coin_creator_vault_authority || e.coin_creator_vault_authority === zero) {
67
+ if (!e.coin_creator_vault_authority ||
68
+ e.coin_creator_vault_authority === zero) {
46
69
  e.coin_creator_vault_authority = get(18);
47
70
  }
48
71
  }
72
+ /** The boost layout has no user ATAs or fee accounts. Preserve decoded values. */
73
+ function fillPumpswapBoostBuyAccounts(e, get) {
74
+ const zero = Z();
75
+ const roles = {
76
+ pool: 0,
77
+ base_mint: 3,
78
+ quote_mint: 4,
79
+ pool_base_token_account: 5,
80
+ pool_quote_token_account: 6,
81
+ base_token_program: 9,
82
+ quote_token_program: 10,
83
+ };
84
+ for (const [field, index] of Object.entries(roles)) {
85
+ const key = field;
86
+ if (!e[key] || e[key] === zero)
87
+ e[key] = get(index);
88
+ }
89
+ }
49
90
  function fillPumpswapBuyAccounts(e, get) {
50
91
  fillPumpswapTradeCommon(e, get);
92
+ if (isCompactTrade(get))
93
+ return;
51
94
  const zero = Z();
52
95
  const a26 = get(26);
53
96
  if (a26 && a26 !== zero) {
@@ -55,7 +98,8 @@ function fillPumpswapBuyAccounts(e, get) {
55
98
  e.pool_v2 = get(24);
56
99
  if (!e.fee_recipient || e.fee_recipient === zero)
57
100
  e.fee_recipient = get(25);
58
- if (!e.fee_recipient_quote_token_account || e.fee_recipient_quote_token_account === zero) {
101
+ if (!e.fee_recipient_quote_token_account ||
102
+ e.fee_recipient_quote_token_account === zero) {
59
103
  e.fee_recipient_quote_token_account = a26;
60
104
  }
61
105
  return;
@@ -66,7 +110,8 @@ function fillPumpswapBuyAccounts(e, get) {
66
110
  e.pool_v2 = get(23);
67
111
  if (!e.fee_recipient || e.fee_recipient === zero)
68
112
  e.fee_recipient = get(24);
69
- if (!e.fee_recipient_quote_token_account || e.fee_recipient_quote_token_account === zero) {
113
+ if (!e.fee_recipient_quote_token_account ||
114
+ e.fee_recipient_quote_token_account === zero) {
70
115
  e.fee_recipient_quote_token_account = a25;
71
116
  }
72
117
  return;
@@ -76,6 +121,8 @@ function fillPumpswapBuyAccounts(e, get) {
76
121
  }
77
122
  function fillPumpswapSellAccounts(e, get) {
78
123
  fillPumpswapTradeCommon(e, get);
124
+ if (isCompactTrade(get))
125
+ return;
79
126
  const zero = Z();
80
127
  const a25 = get(25);
81
128
  if (a25 && a25 !== zero) {
@@ -83,7 +130,8 @@ function fillPumpswapSellAccounts(e, get) {
83
130
  e.pool_v2 = get(23);
84
131
  if (!e.fee_recipient || e.fee_recipient === zero)
85
132
  e.fee_recipient = get(24);
86
- if (!e.fee_recipient_quote_token_account || e.fee_recipient_quote_token_account === zero) {
133
+ if (!e.fee_recipient_quote_token_account ||
134
+ e.fee_recipient_quote_token_account === zero) {
87
135
  e.fee_recipient_quote_token_account = a25;
88
136
  }
89
137
  return;
@@ -94,7 +142,8 @@ function fillPumpswapSellAccounts(e, get) {
94
142
  e.pool_v2 = get(21);
95
143
  if (!e.fee_recipient || e.fee_recipient === zero)
96
144
  e.fee_recipient = get(22);
97
- if (!e.fee_recipient_quote_token_account || e.fee_recipient_quote_token_account === zero) {
145
+ if (!e.fee_recipient_quote_token_account ||
146
+ e.fee_recipient_quote_token_account === zero) {
98
147
  e.fee_recipient_quote_token_account = a23;
99
148
  }
100
149
  return;
@@ -57,11 +57,15 @@ function fillRaydiumClmmIncreaseLiquidityAccounts(e, get) {
57
57
  const zero = Z();
58
58
  if (!e.user || e.user === zero)
59
59
  e.user = get(0);
60
+ if (!e.pool || e.pool === zero)
61
+ e.pool = get(2);
60
62
  }
61
63
  function fillRaydiumClmmDecreaseLiquidityAccounts(e, get) {
62
64
  const zero = Z();
63
65
  if (!e.user || e.user === zero)
64
66
  e.user = get(0);
67
+ if (!e.pool || e.pool === zero)
68
+ e.pool = get(3);
65
69
  }
66
70
  function fillRaydiumCpmmSwapAccounts(e, get) {
67
71
  const zero = Z();