sol-parser-sdk 0.5.14 → 0.5.16

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 (108) hide show
  1. package/NATIVE_ALIGNMENT.md +312 -0
  2. package/NATIVE_DAMM_FACTORY_ALIGNMENT_20261004.md +16 -0
  3. package/NATIVE_DAMM_FACTORY_EVIDENCE_20261004.json +55 -0
  4. package/NATIVE_MIGRATION.md +38 -0
  5. package/NATIVE_PUMPFUN_NATIVE_DEBIT_ALIGNMENT_20261004.md +18 -0
  6. package/NATIVE_PUMPFUN_NATIVE_DEBIT_EVIDENCE_20261004.json +57 -0
  7. package/NATIVE_PUMPFUN_SETTLEMENT_ALIGNMENT_20261004.md +11 -0
  8. package/NATIVE_PUMPFUN_SETTLEMENT_EVIDENCE_20261004.json +70 -0
  9. package/README.md +24 -1
  10. package/README_CN.md +21 -1
  11. package/dist/accounts/mod.js +7 -0
  12. package/dist/accounts/pumpfun.js +17 -0
  13. package/dist/accounts/pumpswap.js +18 -3
  14. package/dist/core/account_dispatcher_rpc.js +24 -4
  15. package/dist/core/account_fill_meteora.d.ts +1 -1
  16. package/dist/core/account_fill_meteora.js +12 -1
  17. package/dist/core/account_fill_raydium.js +12 -2
  18. package/dist/core/account_fill_raydium_launchlab.js +54 -0
  19. package/dist/core/clock.js +1 -1
  20. package/dist/core/common_filler_rpc.d.ts +2 -2
  21. package/dist/core/common_filler_rpc.js +66 -0
  22. package/dist/core/dex_event.d.ts +157 -0
  23. package/dist/core/metadata.d.ts +9 -5
  24. package/dist/core/metadata.js +28 -4
  25. package/dist/core/unified_parser.d.ts +7 -7
  26. package/dist/grpc/block_meta.d.ts +9 -0
  27. package/dist/grpc/block_meta.js +26 -0
  28. package/dist/grpc/client.d.ts +24 -9
  29. package/dist/grpc/client.js +129 -67
  30. package/dist/grpc/geyser_connect.d.ts +3 -3
  31. package/dist/grpc/geyser_connect.js +13 -15
  32. package/dist/grpc/log_instr_dedup.js +6 -0
  33. package/dist/grpc/native_client.d.ts +26 -0
  34. package/dist/grpc/native_client.js +101 -0
  35. package/dist/grpc/order_buffer.d.ts +1 -1
  36. package/dist/grpc/order_buffer.js +10 -9
  37. package/dist/grpc/program_ids.js +2 -0
  38. package/dist/grpc/protocol/LICENSE +202 -0
  39. package/dist/grpc/protocol/NOTICE +4 -0
  40. package/dist/grpc/protocol/geyser.d.ts +342 -0
  41. package/dist/grpc/protocol/geyser.js +37 -0
  42. package/dist/grpc/protocol/geyser.proto +326 -0
  43. package/dist/grpc/protocol/solana-storage.d.ts +139 -0
  44. package/dist/grpc/protocol/solana-storage.js +14 -0
  45. package/dist/grpc/protocol/solana-storage.proto +151 -0
  46. package/dist/grpc/rpc_to_grpc.d.ts +1 -1
  47. package/dist/grpc/subscribe_builder.d.ts +5 -3
  48. package/dist/grpc/subscribe_builder.js +11 -3
  49. package/dist/grpc/transaction_meta.d.ts +1 -1
  50. package/dist/grpc/types.d.ts +8 -8
  51. package/dist/grpc/types.js +15 -2
  52. package/dist/grpc/yellowstone_parse.d.ts +3 -3
  53. package/dist/grpc/yellowstone_parse.js +6 -8
  54. package/dist/grpc/yellowstone_transaction_adapter.d.ts +1 -1
  55. package/dist/index.d.ts +11 -1
  56. package/dist/index.js +23 -5
  57. package/dist/instr/inner.d.ts +2 -2
  58. package/dist/instr/inner.js +1 -1
  59. package/dist/instr/meteora_damm_ix.d.ts +1 -1
  60. package/dist/instr/meteora_damm_ix.js +41 -79
  61. package/dist/instr/meteora_dlmm_ix.d.ts +1 -1
  62. package/dist/instr/meteora_dlmm_ix.js +10 -0
  63. package/dist/instr/meteora_pools_ix.d.ts +1 -1
  64. package/dist/instr/mod.d.ts +1 -1
  65. package/dist/instr/orca_whirlpool_ix.d.ts +1 -1
  66. package/dist/instr/pump_fees_ix.d.ts +1 -1
  67. package/dist/instr/pumpfun_ix.d.ts +1 -1
  68. package/dist/instr/pumpfun_ix.js +16 -0
  69. package/dist/instr/pumpswap_ix.d.ts +1 -1
  70. package/dist/instr/pumpswap_ix.js +13 -5
  71. package/dist/instr/raydium_amm_v4_ix.d.ts +1 -1
  72. package/dist/instr/raydium_amm_v4_ix.js +9 -5
  73. package/dist/instr/raydium_clmm_ix.d.ts +1 -1
  74. package/dist/instr/raydium_cpmm_ix.d.ts +1 -1
  75. package/dist/instr/raydium_launchlab_ix.d.ts +1 -1
  76. package/dist/instr/raydium_launchlab_ix.js +62 -2
  77. package/dist/instr/utils.d.ts +2 -2
  78. package/dist/instr/utils.js +2 -7
  79. package/dist/liquidity_snapshot.d.ts +54 -0
  80. package/dist/liquidity_snapshot.js +85 -0
  81. package/dist/logs/meteora_damm.d.ts +17 -1
  82. package/dist/logs/meteora_damm.js +386 -12
  83. package/dist/logs/meteora_dlmm.d.ts +1 -1
  84. package/dist/logs/meteora_dlmm.js +10 -0
  85. package/dist/logs/optimized_matcher.d.ts +3 -3
  86. package/dist/logs/optimized_matcher.js +35 -1
  87. package/dist/logs/program_log_discriminators.d.ts +5 -0
  88. package/dist/logs/program_log_discriminators.js +5 -0
  89. package/dist/logs/pump.js +10 -0
  90. package/dist/logs/pump_amm.js +22 -1
  91. package/dist/logs/raydium_launchlab.js +19 -1
  92. package/dist/rpc_transaction.d.ts +4 -3
  93. package/dist/rpc_transaction.js +3 -2
  94. package/dist/shredstream/client.js +3 -7
  95. package/dist/shredstream/entries_decode.js +9 -85
  96. package/dist/shredstream/instruction_parse.d.ts +3 -3
  97. package/dist/shredstream/proto_types.d.ts +1 -1
  98. package/dist/shredstream/wire_to_shred_tx.d.ts +1 -1
  99. package/dist/shredstream/wire_to_shred_tx.js +9 -44
  100. package/dist/simulation_route.d.ts +6 -0
  101. package/dist/simulation_route.js +242 -0
  102. package/dist/stonkfun_registry.d.ts +30 -0
  103. package/dist/stonkfun_registry.js +137 -0
  104. package/dist/transaction_route.d.ts +84 -0
  105. package/dist/transaction_route.js +477 -0
  106. package/dist/wire_transaction.d.ts +35 -0
  107. package/dist/wire_transaction.js +191 -0
  108. package/package.json +7 -4
@@ -0,0 +1,70 @@
1
+ {
2
+ "date": "2026-10-04",
3
+ "overall_alignment_complete": false,
4
+ "broadcasts": 0,
5
+ "hot_path_rpc_calls": 0,
6
+ "rust_baseline": {
7
+ "trade": "5.0.6",
8
+ "parser": "0.7.7"
9
+ },
10
+ "current_pumpfun_fee_oracle": {
11
+ "package": "@pump-fun/pump-sdk",
12
+ "version": "2.0.0",
13
+ "vectors_per_language": 240,
14
+ "runtime_dependency": false
15
+ },
16
+ "simulations": {
17
+ "direct_sol": {
18
+ "wire_bytes": 1044,
19
+ "err": null,
20
+ "evidence": "examples/fixtures/pumpfun_direct_sol_simulations_20261004.json"
21
+ },
22
+ "funded_wsol": {
23
+ "wire_bytes": 1238,
24
+ "wire_sha256": "76b18c71a930080a4c937483ed1ab670e7ade2188cfef6cf1d00ec8a1538adfd",
25
+ "err": null,
26
+ "actual_wsol_debit": "10000",
27
+ "verified_asset_payment": true,
28
+ "evidence": "examples/fixtures/pumpfun_settled_funded_wsol_evidence_20261004.json",
29
+ "cross_language_wire_match": [
30
+ "go",
31
+ "nodejs",
32
+ "python"
33
+ ]
34
+ }
35
+ },
36
+ "verification": {
37
+ "full_suites_before_final_added_regressions": {
38
+ "trade_nodejs": 3326,
39
+ "parser_nodejs": 213,
40
+ "parser_nodejs_skipped": 8,
41
+ "trade_python": 3406,
42
+ "parser_python": 199,
43
+ "go_trade": "go test ./... passed",
44
+ "go_parser": "go test ./... passed"
45
+ },
46
+ "final_targeted": {
47
+ "trade_nodejs": 8,
48
+ "trade_python": 12,
49
+ "parser_nodejs_simulation": 47,
50
+ "parser_python_simulation": 49,
51
+ "go_parser_failed_intent_and_mainnet_corpus": "passed"
52
+ },
53
+ "go_vet": "both passed",
54
+ "go_race": "both full suites passed",
55
+ "node_trade_types_and_build": "passed",
56
+ "node_trade_example_types": "passed",
57
+ "node_parser_types": "passed",
58
+ "installed_wheel_verified_wire": "passed",
59
+ "installed_npm_public_api_verified_wire": "passed",
60
+ "six_repo_diff_check": "passed"
61
+ },
62
+ "not_verified": [
63
+ "current PumpFun funded sell simulation",
64
+ "native-quote PumpFun multi-hop settlement (explicitly rejected)",
65
+ "non-native USDC/stock PumpFun mainnet simulations",
66
+ "legacy low-level builder current-chain compatibility",
67
+ "SWQOS online V1 broadcast compatibility",
68
+ "full Rust public API/field alignment matrix and remaining lifecycle acceptance"
69
+ ]
70
+ }
package/README.md CHANGED
@@ -44,6 +44,19 @@
44
44
 
45
45
  ## Release notes
46
46
 
47
+ ### v0.5.16
48
+
49
+ - Adds native gRPC lifecycle and block metadata support, instruction-level route analysis and StonkFun registry/snapshot examples.
50
+ - Improves exact metadata serialization, account matching and wire transaction bounds validation.
51
+ - Includes native alignment evidence and simulation route fixtures. These language releases do not yet implement the new CPMM creator-fee collection event API.
52
+
53
+ ### v0.5.15
54
+
55
+ - Syncs with Rust `sol-parser-sdk` **0.7.3**, including the current PumpFun, PumpSwap, Pump Fees, and Meteora DAMM v2 protocol surfaces.
56
+ - Keeps existing optional DLMM mint/user-token fields and PumpFun balance snapshot fields aligned with the Rust 0.6.4–0.6.6 field model.
57
+ - Adds creator-fee and holder-reward fields across PumpFun/PumpSwap instruction, log, account, gRPC, and JSON event paths.
58
+ - Rejects truncated known PumpSwap trade and CreatePool tails, and prevents PumpSwap-only fields from leaking into PumpFun CreateV2 payloads.
59
+
47
60
  ### v0.5.14
48
61
 
49
62
  - Upgrades the Yellowstone client to `@triton-one/yellowstone-grpc` 7.0.0 with its native Rust N-API transport.
@@ -83,7 +96,7 @@
83
96
  **From npm**
84
97
 
85
98
  ```bash
86
- npm install sol-parser-sdk@0.5.14
99
+ npm install sol-parser-sdk@0.5.16
87
100
  ```
88
101
 
89
102
  **From source** (folder may be named `sol-parser-sdk-ts` in a monorepo)
@@ -321,3 +334,13 @@ npm run check:migration # parity checks; needs build
321
334
  ## License
322
335
 
323
336
  MIT — https://github.com/0xfnzero/sol-parser-sdk-nodejs
337
+
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.
341
+
342
+
343
+ 实时 parser → trade 接入使用 Yellowstone **gRPC**;见 [gRPC 缓存接入与三语言示例](examples/GRPC_CACHE.md)。此路径不使用 WebSocket,报价和构建热路径不调用 RPC。
344
+
345
+
346
+ [本轮原生对齐 API 迁移](NATIVE_MIGRATION.md)(实施中,尚未发布)。
package/README_CN.md CHANGED
@@ -44,6 +44,19 @@
44
44
 
45
45
  ## 发布说明
46
46
 
47
+ ### v0.5.16
48
+
49
+ - Adds native gRPC lifecycle and block metadata support, instruction-level route analysis and StonkFun registry/snapshot examples.
50
+ - Improves exact metadata serialization, account matching and wire transaction bounds validation.
51
+ - Includes native alignment evidence and simulation route fixtures. These language releases do not yet implement the new CPMM creator-fee collection event API.
52
+
53
+ ### v0.5.15
54
+
55
+ - 对齐 Rust sol-parser-sdk **0.7.3**,覆盖当前 PumpFun、PumpSwap、Pump Fees 与 Meteora DAMM v2 协议字段。
56
+ - DLMM Swap 上下文字段(`token_x/y_mint`、`user_token_in/out`、`min_amount_out`)、PumpFun 可选 pre/post SOL/token 余额、Raydium LaunchLab quote/global/platform 账户上下文与 Rust 对齐。
57
+ - 在 PumpFun/PumpSwap instruction、log、account、gRPC 与 JSON 事件链路中补齐 creator fee 和 holder reward 字段。
58
+ - 拒绝 PumpSwap trade 与 CreatePool 已知字段的截断尾部,并避免 PumpSwap 专属字段进入 PumpFun CreateV2 payload。
59
+
47
60
  ### v0.5.14
48
61
 
49
62
  - 将 Yellowstone 客户端升级到 `@triton-one/yellowstone-grpc` 7.0.0,使用其原生 Rust N-API 传输层。
@@ -83,7 +96,7 @@
83
96
  **npm**
84
97
 
85
98
  ```bash
86
- npm install sol-parser-sdk@0.5.14
99
+ npm install sol-parser-sdk@0.5.16
87
100
  ```
88
101
 
89
102
  **源码**(monorepo 里目录可能是 `sol-parser-sdk-ts`)
@@ -314,3 +327,10 @@ npm run check:migration # 对齐与校验,需先 build
314
327
  ## 许可证
315
328
 
316
329
  MIT — https://github.com/0xfnzero/sol-parser-sdk-nodejs
330
+
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.
334
+
335
+
336
+ [本轮原生对齐 API 迁移](NATIVE_MIGRATION.md)(实施中,尚未发布)。
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rpcResolveUserWalletPubkey = exports.userWalletPubkeyForOnchainAccount = exports.hasDiscriminator = exports.isOrcaWhirlpoolsConfigAccount = exports.isOrcaFeeTierAccount = exports.isOrcaTickArrayAccount = exports.isOrcaPositionAccount = exports.isOrcaWhirlpoolAccount = exports.isRaydiumCpmmPoolStateAccount = exports.isRaydiumCpmmAmmConfigAccount = exports.isRaydiumClmmTickArrayStateAccount = exports.isRaydiumClmmPoolStateAccount = exports.isRaydiumClmmAmmConfigAccount = exports.parseOrcaWhirlpoolsConfig = exports.parseOrcaFeeTier = exports.parseOrcaTickArray = exports.parseOrcaPosition = exports.parseOrcaWhirlpool = exports.parseOrcaWhirlpoolAccount = exports.parseRaydiumCpmmPoolState = exports.parseRaydiumCpmmAmmConfig = exports.parseRaydiumCpmmAccount = exports.parseRaydiumClmmTickArrayState = exports.parseRaydiumClmmPoolState = exports.parseRaydiumClmmAmmConfig = exports.parseRaydiumClmmAccount = exports.isPoolAccount = exports.isGlobalConfigAccount = exports.parsePumpswapAccount = exports.parsePumpswapPool = exports.parsePumpswapGlobalConfig = exports.isPumpfunUserVolumeAccumulatorAccount = exports.isPumpfunGlobalVolumeAccumulatorAccount = exports.isPumpfunSharingConfigAccount = exports.isPumpfunFeeConfigAccount = exports.isPumpfunBondingCurveAccount = exports.isPumpfunGlobalAccount = exports.parsePumpfunAccount = exports.parsePumpfunUserVolumeAccumulator = exports.parsePumpfunGlobalVolumeAccumulator = exports.parsePumpfunSharingConfig = exports.parsePumpfunFeeConfig = exports.parsePumpfunBondingCurve = exports.parsePumpfunGlobal = exports.parseTokenAccount = exports.isNonceAccount = exports.parseNonceAccount = void 0;
4
4
  exports.parseAccountUnified = parseAccountUnified;
5
+ const liquidity_snapshot_js_1 = require("../liquidity_snapshot.js");
5
6
  const types_js_1 = require("../grpc/types.js");
6
7
  const program_ids_js_1 = require("../instr/program_ids.js");
7
8
  const nonce_js_1 = require("./nonce.js");
@@ -86,6 +87,7 @@ const ACCOUNT_EVENT_TYPES = [
86
87
  "AccountOrcaTickArray",
87
88
  "AccountOrcaFeeTier",
88
89
  "AccountOrcaWhirlpoolsConfig",
90
+ "AccountLiquiditySnapshot",
89
91
  ];
90
92
  function filterParsedEvent(ev, eventTypeFilter) {
91
93
  if (!ev || !eventTypeFilter)
@@ -101,6 +103,11 @@ function parseAccountUnified(account, metadata, eventTypeFilter) {
101
103
  if (!shouldParse)
102
104
  return null;
103
105
  }
106
+ if (!eventTypeFilter || eventTypeFilter.shouldInclude('AccountLiquiditySnapshot')) {
107
+ const snapshot = (0, liquidity_snapshot_js_1.parseLiquidityAccount)(account, metadata);
108
+ if (snapshot)
109
+ return { LiquidityAccountSnapshot: snapshot };
110
+ }
104
111
  if (account.owner === program_ids_js_1.PUMPSWAP_PROGRAM_ID) {
105
112
  if (!eventTypeFilter ||
106
113
  eventTypeFilter.shouldInclude("AccountPumpSwapGlobalConfig") ||
@@ -20,6 +20,8 @@ const GLOBAL_DISC = Uint8Array.from([167, 232, 232, 177, 200, 108, 114, 127]);
20
20
  const GLOBAL_BODY = 1037;
21
21
  const BONDING_CURVE_DISC = Uint8Array.from([23, 183, 248, 55, 96, 216, 172, 96]);
22
22
  const BONDING_CURVE_BODY = 107;
23
+ const BONDING_CURVE_CREATOR_FEE_BODY = 116;
24
+ const BONDING_CURVE_HOLDER_REWARD_BODY = 117;
23
25
  const FEE_CONFIG_DISC = Uint8Array.from([143, 52, 146, 187, 219, 123, 76, 155]);
24
26
  const GLOBAL_VOLUME_ACCUMULATOR_DISC = Uint8Array.from([202, 42, 246, 43, 142, 190, 30, 255]);
25
27
  const SHARING_CONFIG_DISC = Uint8Array.from([216, 74, 9, 0, 56, 140, 93, 75]);
@@ -250,6 +252,12 @@ function parsePumpfunGlobal(account, metadata) {
250
252
  function parsePumpfunBondingCurve(account, metadata) {
251
253
  if (account.data.length < 8 + BONDING_CURVE_BODY)
252
254
  return null;
255
+ const bodyLength = account.data.length - 8;
256
+ if (bodyLength !== BONDING_CURVE_BODY &&
257
+ bodyLength !== BONDING_CURVE_CREATOR_FEE_BODY &&
258
+ bodyLength < BONDING_CURVE_HOLDER_REWARD_BODY) {
259
+ return null;
260
+ }
253
261
  if (!isPumpfunBondingCurveAccount(account.data))
254
262
  return null;
255
263
  const d = account.data.subarray(8);
@@ -296,6 +304,12 @@ function parsePumpfunBondingCurve(account, metadata) {
296
304
  const quote_mint = (0, binary_js_1.readPubkey)(d, o);
297
305
  if (quote_mint === null)
298
306
  return null;
307
+ o += 32;
308
+ const creator_fee_bps = (0, binary_js_1.readU64LE)(d, o) ?? 0n;
309
+ o += 8;
310
+ const can_edit_creator_fee = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
311
+ o += 1;
312
+ const is_holder_reward = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
299
313
  const bonding_curve = {
300
314
  virtual_token_reserves,
301
315
  virtual_quote_reserves,
@@ -307,6 +321,9 @@ function parsePumpfunBondingCurve(account, metadata) {
307
321
  is_mayhem_mode,
308
322
  is_cashback_coin,
309
323
  quote_mint,
324
+ creator_fee_bps,
325
+ can_edit_creator_fee,
326
+ is_holder_reward,
310
327
  };
311
328
  const ev = {
312
329
  metadata,
@@ -12,7 +12,9 @@ const GLOBAL_DISC = Uint8Array.from([149, 8, 156, 202, 160, 252, 176, 217]);
12
12
  const POOL_DISC = Uint8Array.from([241, 154, 109, 4, 17, 177, 109, 188]);
13
13
  const GLOBAL_BODY = 634;
14
14
  const POOL_LEGACY_BODY = 244;
15
- const POOL_BODY = 253;
15
+ const POOL_BOOST_BODY = 253;
16
+ const POOL_CREATOR_FEE_BODY = 262;
17
+ const POOL_BODY = 263;
16
18
  function isGlobalConfigAccount(data) {
17
19
  return (0, utils_js_1.hasDiscriminator)(data, GLOBAL_DISC);
18
20
  }
@@ -106,7 +108,11 @@ function parsePumpswapGlobalConfig(account, metadata) {
106
108
  function parsePumpswapPool(account, metadata) {
107
109
  if (account.data.length < 8 + POOL_LEGACY_BODY)
108
110
  return null;
109
- if (account.data.length !== 8 + POOL_LEGACY_BODY && account.data.length < 8 + POOL_BODY) {
111
+ const bodyLength = account.data.length - 8;
112
+ if (bodyLength !== POOL_LEGACY_BODY &&
113
+ bodyLength !== POOL_BOOST_BODY &&
114
+ bodyLength !== POOL_CREATOR_FEE_BODY &&
115
+ bodyLength < POOL_BODY) {
110
116
  return null;
111
117
  }
112
118
  if (!isPoolAccount(account.data))
@@ -162,12 +168,18 @@ function parsePumpswapPool(account, metadata) {
162
168
  return null;
163
169
  o += 1;
164
170
  let virtual_quote_reserves = 0n;
165
- if (d.length >= POOL_BODY) {
171
+ if (d.length >= POOL_BOOST_BODY) {
166
172
  const virtual = (0, binary_js_1.readU128LE)(d, o);
167
173
  if (virtual === null)
168
174
  return null;
169
175
  virtual_quote_reserves = BigInt.asIntN(128, virtual);
170
176
  }
177
+ o += 16;
178
+ const creator_fee_bps = (0, binary_js_1.readU64LE)(d, o) ?? 0n;
179
+ o += 8;
180
+ const can_edit_creator_fee = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
181
+ o += 1;
182
+ const is_holder_reward = ((0, binary_js_1.readU8)(d, o) ?? 0) !== 0;
171
183
  const pool = {
172
184
  pool_bump,
173
185
  index,
@@ -182,6 +194,9 @@ function parsePumpswapPool(account, metadata) {
182
194
  is_mayhem_mode: mayhem !== 0,
183
195
  is_cashback_coin: cashback !== 0,
184
196
  virtual_quote_reserves,
197
+ creator_fee_bps,
198
+ can_edit_creator_fee,
199
+ is_holder_reward,
185
200
  };
186
201
  const ev = {
187
202
  metadata,
@@ -9,7 +9,27 @@ const account_fill_raydium_js_1 = require("./account_fill_raydium.js");
9
9
  const account_fill_orca_js_1 = require("./account_fill_orca.js");
10
10
  const account_fill_raydium_launchlab_js_1 = require("./account_fill_raydium_launchlab.js");
11
11
  const account_fill_meteora_js_1 = require("./account_fill_meteora.js");
12
- function tryFill(programId, programInvokes, message, meta, resolver, fn) {
12
+ function tryFill(programId, programInvokes, message, meta, resolver, fn, anchor, unambiguous = false) {
13
+ if (anchor || unambiguous) {
14
+ const hasAnchor = anchor && anchor.pool && anchor.pool !== "11111111111111111111111111111111";
15
+ if (!hasAnchor && !unambiguous)
16
+ return;
17
+ let selected = null;
18
+ for (const invocation of programInvokes.get(programId) ?? []) {
19
+ const candidate = (0, rpc_invoke_map_js_1.makeInvokeAccountGetter)(resolver, invocation, message, meta);
20
+ if (!candidate || (hasAnchor && candidate(anchor.index) !== anchor.pool))
21
+ continue;
22
+ // One pool can be traded by multiple users within the same transaction.
23
+ // Without an invocation position, keep missing context instead of guessing.
24
+ if (selected &&
25
+ Array.from({ length: 18 }, (_, i) => i).some((i) => selected(i) !== candidate(i)))
26
+ return;
27
+ selected = candidate;
28
+ }
29
+ if (selected)
30
+ fn(selected);
31
+ return;
32
+ }
13
33
  const invoke = (0, rpc_invoke_map_js_1.findMaxAccountsInvoke)(programId, programInvokes, message, meta);
14
34
  if (!invoke)
15
35
  return;
@@ -93,7 +113,7 @@ function fillAccountsFromTransactionDataRpc(ev, message, meta, programInvokes, r
93
113
  tryFill(program_ids_js_1.RAYDIUM_CPMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumCpmmInitializeAccounts)(ev.RaydiumCpmmInitialize, g));
94
114
  }
95
115
  else if ("RaydiumAmmV4Swap" in ev) {
96
- tryFill(program_ids_js_1.RAYDIUM_AMM_V4_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumAmmV4SwapAccounts)(ev.RaydiumAmmV4Swap, g));
116
+ tryFill(program_ids_js_1.RAYDIUM_AMM_V4_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumAmmV4SwapAccounts)(ev.RaydiumAmmV4Swap, g), { pool: ev.RaydiumAmmV4Swap.amm, index: 1 }, true);
97
117
  }
98
118
  else if ("RaydiumAmmV4Deposit" in ev) {
99
119
  tryFill(program_ids_js_1.RAYDIUM_AMM_V4_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_js_1.fillRaydiumAmmV4DepositAccounts)(ev.RaydiumAmmV4Deposit, g));
@@ -147,9 +167,9 @@ function fillAccountsFromTransactionDataRpc(ev, message, meta, programInvokes, r
147
167
  tryFill(program_ids_js_1.METEORA_DLMM_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_meteora_js_1.fillMeteoraDlmmRemoveLiquidityAccounts)(ev.MeteoraDlmmRemoveLiquidity, g));
148
168
  }
149
169
  else if ("RaydiumLaunchlabTrade" in ev) {
150
- tryFill(program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_launchlab_js_1.fillRaydiumLaunchlabTradeAccounts)(ev.RaydiumLaunchlabTrade, g));
170
+ tryFill(program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_launchlab_js_1.fillRaydiumLaunchlabTradeAccounts)(ev.RaydiumLaunchlabTrade, g), { pool: ev.RaydiumLaunchlabTrade.pool_state, index: 4 });
151
171
  }
152
172
  else if ("RaydiumLaunchlabPoolCreate" in ev) {
153
- tryFill(program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_launchlab_js_1.fillRaydiumLaunchlabPoolCreateAccounts)(ev.RaydiumLaunchlabPoolCreate, g));
173
+ tryFill(program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID, programInvokes, message, meta, resolver, (g) => (0, account_fill_raydium_launchlab_js_1.fillRaydiumLaunchlabPoolCreateAccounts)(ev.RaydiumLaunchlabPoolCreate, g), { pool: ev.RaydiumLaunchlabPoolCreate.pool_state, index: 5 });
154
174
  }
155
175
  }
@@ -10,6 +10,6 @@ export declare function fillMeteoraDammV2RemoveLiquidityAccounts(_e: MeteoraDamm
10
10
  export declare function fillMeteoraPoolsSwapAccounts(_e: MeteoraPoolsSwapEvent, _get: (i: number) => string): void;
11
11
  export declare function fillMeteoraPoolsAddLiquidityAccounts(_e: MeteoraPoolsAddLiquidityEvent, _get: (i: number) => string): void;
12
12
  export declare function fillMeteoraPoolsRemoveLiquidityAccounts(_e: MeteoraPoolsRemoveLiquidityEvent, _get: (i: number) => string): void;
13
- export declare function fillMeteoraDlmmSwapAccounts(_e: MeteoraDlmmSwapEvent, _get: (i: number) => string): void;
13
+ export declare function fillMeteoraDlmmSwapAccounts(e: MeteoraDlmmSwapEvent, get: (i: number) => string): void;
14
14
  export declare function fillMeteoraDlmmAddLiquidityAccounts(_e: MeteoraDlmmAddLiquidityEvent, _get: (i: number) => string): void;
15
15
  export declare function fillMeteoraDlmmRemoveLiquidityAccounts(_e: MeteoraDlmmRemoveLiquidityEvent, _get: (i: number) => string): void;
@@ -12,6 +12,7 @@ exports.fillMeteoraPoolsRemoveLiquidityAccounts = fillMeteoraPoolsRemoveLiquidit
12
12
  exports.fillMeteoraDlmmSwapAccounts = fillMeteoraDlmmSwapAccounts;
13
13
  exports.fillMeteoraDlmmAddLiquidityAccounts = fillMeteoraDlmmAddLiquidityAccounts;
14
14
  exports.fillMeteoraDlmmRemoveLiquidityAccounts = fillMeteoraDlmmRemoveLiquidityAccounts;
15
+ const dex_event_js_1 = require("./dex_event.js");
15
16
  /** 预留:gRPC+meta 全量路径若需从 account_keys 补 vault,应对齐 cp_amm `swap` 账户顺序(IDL 中 vault/mint/token program 下标) */
16
17
  function fillMeteoraDammV2SwapAccounts(_e, _get) { }
17
18
  function fillMeteoraDammV2CreatePositionAccounts(_e, _get) { }
@@ -22,6 +23,16 @@ function fillMeteoraDammV2RemoveLiquidityAccounts(_e, _get) { }
22
23
  function fillMeteoraPoolsSwapAccounts(_e, _get) { }
23
24
  function fillMeteoraPoolsAddLiquidityAccounts(_e, _get) { }
24
25
  function fillMeteoraPoolsRemoveLiquidityAccounts(_e, _get) { }
25
- function fillMeteoraDlmmSwapAccounts(_e, _get) { }
26
+ function fillMeteoraDlmmSwapAccounts(e, get) {
27
+ const zero = (0, dex_event_js_1.defaultPubkey)();
28
+ if (!e.user_token_in || e.user_token_in === zero)
29
+ e.user_token_in = get(4);
30
+ if (!e.user_token_out || e.user_token_out === zero)
31
+ e.user_token_out = get(5);
32
+ if (!e.token_x_mint || e.token_x_mint === zero)
33
+ e.token_x_mint = get(6);
34
+ if (!e.token_y_mint || e.token_y_mint === zero)
35
+ e.token_y_mint = get(7);
36
+ }
26
37
  function fillMeteoraDlmmAddLiquidityAccounts(_e, _get) { }
27
38
  function fillMeteoraDlmmRemoveLiquidityAccounts(_e, _get) { }
@@ -86,9 +86,19 @@ function fillRaydiumCpmmInitializeAccounts(e, get) {
86
86
  e.pool = get(3);
87
87
  }
88
88
  function fillRaydiumAmmV4SwapAccounts(e, get) {
89
- const zero = Z();
90
- if (!e.amm || e.amm === zero)
89
+ const empty = (v) => !v || v === Z();
90
+ if (empty(e.amm))
91
91
  e.amm = get(1);
92
+ const modern = empty(get(8)) && !empty(get(7));
93
+ if (modern) {
94
+ for (const [field, index] of [['token_program', 0], ['amm_authority', 2], ['pool_coin_token_account', 3], ['pool_pc_token_account', 4], ['user_source_token_account', 5], ['user_destination_token_account', 6], ['user_source_owner', 7]]) {
95
+ if (empty(e[field]))
96
+ e[field] = get(index);
97
+ }
98
+ }
99
+ else if (empty(e.user_source_owner)) {
100
+ e.user_source_owner = empty(get(17)) ? get(16) : get(17);
101
+ }
92
102
  }
93
103
  function fillRaydiumAmmV4DepositAccounts(e, get) {
94
104
  const zero = Z();
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fillRaydiumLaunchlabTradeAccounts = fillRaydiumLaunchlabTradeAccounts;
4
4
  exports.fillRaydiumLaunchlabPoolCreateAccounts = fillRaydiumLaunchlabPoolCreateAccounts;
5
5
  const dex_event_js_1 = require("./dex_event.js");
6
+ const program_ids_js_1 = require("../instr/program_ids.js");
6
7
  const Z = () => (0, dex_event_js_1.defaultPubkey)();
7
8
  function fillRaydiumLaunchlabTradeAccounts(e, get) {
8
9
  const zero = Z();
@@ -10,6 +11,32 @@ function fillRaydiumLaunchlabTradeAccounts(e, get) {
10
11
  e.user = get(0);
11
12
  if (!e.pool_state || e.pool_state === zero)
12
13
  e.pool_state = get(4);
14
+ if (!e.global_config || e.global_config === zero)
15
+ e.global_config = get(2);
16
+ if (!e.platform_config || e.platform_config === zero)
17
+ e.platform_config = get(3);
18
+ if (!e.user_base_token || e.user_base_token === zero)
19
+ e.user_base_token = get(5);
20
+ if (!e.user_quote_token || e.user_quote_token === zero)
21
+ e.user_quote_token = get(6);
22
+ if (!e.base_vault || e.base_vault === zero)
23
+ e.base_vault = get(7);
24
+ if (!e.quote_vault || e.quote_vault === zero)
25
+ e.quote_vault = get(8);
26
+ if (!e.base_mint || e.base_mint === zero)
27
+ e.base_mint = get(9);
28
+ if (!e.quote_mint || e.quote_mint === zero)
29
+ e.quote_mint = get(10);
30
+ if (!e.base_token_program || e.base_token_program === zero)
31
+ e.base_token_program = get(11);
32
+ if (!e.quote_token_program || e.quote_token_program === zero)
33
+ e.quote_token_program = get(12);
34
+ if (!e.system_program || e.system_program === zero)
35
+ e.system_program = get(15);
36
+ if (!e.platform_associated_account || e.platform_associated_account === zero)
37
+ e.platform_associated_account = get(16);
38
+ if (!e.creator_associated_account || e.creator_associated_account === zero)
39
+ e.creator_associated_account = get(17);
13
40
  }
14
41
  function fillRaydiumLaunchlabPoolCreateAccounts(e, get) {
15
42
  const zero = Z();
@@ -17,4 +44,31 @@ function fillRaydiumLaunchlabPoolCreateAccounts(e, get) {
17
44
  e.pool_state = get(5);
18
45
  if (!e.creator || e.creator === zero)
19
46
  e.creator = get(1);
47
+ if (!e.payer || e.payer === zero)
48
+ e.payer = get(0);
49
+ if (!e.global_config || e.global_config === zero)
50
+ e.global_config = get(2);
51
+ if (!e.platform_config || e.platform_config === zero)
52
+ e.platform_config = get(3);
53
+ if (!e.base_mint || e.base_mint === zero)
54
+ e.base_mint = get(6);
55
+ if (!e.quote_mint || e.quote_mint === zero)
56
+ e.quote_mint = get(7);
57
+ if (!e.base_vault || e.base_vault === zero)
58
+ e.base_vault = get(8);
59
+ if (!e.quote_vault || e.quote_vault === zero)
60
+ e.quote_vault = get(9);
61
+ const tokenProgramIndices = get(17) === program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID
62
+ ? [11, 12]
63
+ : get(14) === program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID
64
+ ? [10, 11]
65
+ : null;
66
+ if (!tokenProgramIndices)
67
+ return;
68
+ if (!e.base_token_program || e.base_token_program === zero) {
69
+ e.base_token_program = get(tokenProgramIndices[0]);
70
+ }
71
+ if (!e.quote_token_program || e.quote_token_program === zero) {
72
+ e.quote_token_program = get(tokenProgramIndices[1]);
73
+ }
20
74
  }
@@ -12,7 +12,7 @@ function nowUs() {
12
12
  exports.nowMicros = nowUs;
13
13
  /** 与 Rust `now_nanos` 同语义:墙钟纳秒(`Date` 精度为毫秒,纳秒位为推算值) */
14
14
  function nowNanos() {
15
- return BigInt(Math.floor(Date.now() * 1_000_000));
15
+ return BigInt(Date.now()) * 1000000n;
16
16
  }
17
17
  /** 与 Rust `elapsed_micros_since` 一致 */
18
18
  function elapsedMicrosSince(startUs) {
@@ -1,6 +1,6 @@
1
- /** RPC / web3 路径补充字段(如 PumpSwap fees 指令 → `is_pump_pool`) */
1
+ /** RPC / web3 路径补充字段(如 PumpSwap fees 指令 → `is_pump_pool`,PumpFun 余额) */
2
2
  import type { DexEvent } from "./dex_event.js";
3
- import type { InvokePair } from "./rpc_invoke_map.js";
3
+ import { type InvokePair } from "./rpc_invoke_map.js";
4
4
  import type { Message, MessageV0 } from "@solana/web3.js";
5
5
  import type { ConfirmedTransactionMeta } from "@solana/web3.js";
6
6
  export declare function fillDataRpc(ev: DexEvent, message: Message | MessageV0, meta: ConfirmedTransactionMeta | null, programInvokes: Map<string, InvokePair[]>): void;
@@ -1,9 +1,75 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fillDataRpc = fillDataRpc;
4
+ const dex_event_js_1 = require("./dex_event.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");
7
+ function findAccountIndex(resolver, account) {
8
+ const zero = (0, dex_event_js_1.defaultPubkey)();
9
+ if (!account || account === zero)
10
+ return null;
11
+ for (let i = 0; i < resolver.length; i++) {
12
+ if (resolver.get(i)?.toBase58() === account)
13
+ return i;
14
+ }
15
+ return null;
16
+ }
17
+ function tokenBalanceRawAmount(amount) {
18
+ if (amount == null || amount === "")
19
+ return null;
20
+ try {
21
+ return BigInt(amount);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ function fillPumpfunTradeBalances(trade, message, meta) {
28
+ if (!meta)
29
+ return;
30
+ const resolver = (0, rpc_invoke_map_js_1.getAccountKeyResolver)(message, meta);
31
+ const userIndex = findAccountIndex(resolver, trade.user);
32
+ if (userIndex !== null) {
33
+ trade.pre_sol_balance =
34
+ meta.preBalances[userIndex] !== undefined ? BigInt(meta.preBalances[userIndex]) : undefined;
35
+ trade.post_sol_balance =
36
+ meta.postBalances[userIndex] !== undefined ? BigInt(meta.postBalances[userIndex]) : undefined;
37
+ }
38
+ const associated = trade.associated_user;
39
+ if (!associated || associated === (0, dex_event_js_1.defaultPubkey)())
40
+ return;
41
+ const preBalances = meta.preTokenBalances ?? [];
42
+ const postBalances = meta.postTokenBalances ?? [];
43
+ const matchIndex = [...preBalances, ...postBalances].find((b) => {
44
+ const key = resolver.get(b.accountIndex);
45
+ return key?.toBase58() === associated;
46
+ })?.accountIndex;
47
+ if (matchIndex === undefined)
48
+ return;
49
+ const pre = preBalances.find((b) => b.accountIndex === matchIndex);
50
+ const post = postBalances.find((b) => b.accountIndex === matchIndex);
51
+ const preAmt = tokenBalanceRawAmount(pre?.uiTokenAmount?.amount);
52
+ const postAmt = tokenBalanceRawAmount(post?.uiTokenAmount?.amount);
53
+ if (preAmt !== null || postAmt !== null) {
54
+ trade.pre_token_balance = preAmt ?? 0n;
55
+ trade.post_token_balance = postAmt ?? 0n;
56
+ }
57
+ }
58
+ function pumpfunTradeFromEvent(ev) {
59
+ if ("PumpFunTrade" in ev)
60
+ return ev.PumpFunTrade;
61
+ if ("PumpFunBuy" in ev)
62
+ return ev.PumpFunBuy;
63
+ if ("PumpFunSell" in ev)
64
+ return ev.PumpFunSell;
65
+ if ("PumpFunBuyExactSolIn" in ev)
66
+ return ev.PumpFunBuyExactSolIn;
67
+ return null;
68
+ }
6
69
  function fillDataRpc(ev, message, meta, programInvokes) {
70
+ const trade = pumpfunTradeFromEvent(ev);
71
+ if (trade)
72
+ fillPumpfunTradeBalances(trade, message, meta);
7
73
  const list = programInvokes.get(program_ids_js_1.PUMPSWAP_FEES_PROGRAM_ID);
8
74
  const last = list?.[list.length - 1];
9
75
  if (!last)