sol-parser-sdk-nodejs 0.3.0 → 0.4.0

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 (93) hide show
  1. package/.env.example +24 -0
  2. package/README.md +94 -352
  3. package/README_CN.md +101 -253
  4. package/dist/accounts/mod.d.ts +2 -0
  5. package/dist/accounts/mod.js +5 -1
  6. package/dist/accounts/rpc_wallet.d.ts +5 -0
  7. package/dist/accounts/rpc_wallet.js +18 -0
  8. package/dist/accounts/rust_aliases.d.ts +9 -0
  9. package/dist/accounts/rust_aliases.js +19 -0
  10. package/dist/accounts/wallet_resolve.d.ts +1 -0
  11. package/dist/accounts/wallet_resolve.js +28 -0
  12. package/dist/common/constants.d.ts +10 -0
  13. package/dist/common/constants.js +13 -0
  14. package/dist/core/account_dispatcher_rpc.js +26 -5
  15. package/dist/core/account_fill_meteora.d.ts +4 -2
  16. package/dist/core/account_fill_meteora.js +5 -2
  17. package/dist/core/account_pubkey_cache.d.ts +12 -0
  18. package/dist/core/account_pubkey_cache.js +26 -0
  19. package/dist/core/clock.d.ts +6 -0
  20. package/dist/core/clock.js +13 -0
  21. package/dist/core/dex_event.d.ts +25 -44
  22. package/dist/core/metadata.d.ts +1 -0
  23. package/dist/core/unified_parser.d.ts +2 -2
  24. package/dist/core/unified_parser.js +6 -6
  25. package/dist/grpc/client.d.ts +6 -0
  26. package/dist/grpc/client.js +121 -64
  27. package/dist/grpc/event_parser.d.ts +6 -0
  28. package/dist/grpc/event_parser.js +15 -0
  29. package/dist/grpc/geyser_connect.d.ts +30 -0
  30. package/dist/grpc/geyser_connect.js +40 -0
  31. package/dist/grpc/program_ids.d.ts +25 -0
  32. package/dist/grpc/program_ids.js +54 -0
  33. package/dist/grpc/rpc_to_grpc.d.ts +18 -0
  34. package/dist/grpc/rpc_to_grpc.js +127 -0
  35. package/dist/grpc/subscribe_builder.d.ts +13 -0
  36. package/dist/grpc/subscribe_builder.js +66 -0
  37. package/dist/grpc/transaction_meta.d.ts +29 -0
  38. package/dist/grpc/transaction_meta.js +208 -0
  39. package/dist/grpc/types.d.ts +53 -2
  40. package/dist/grpc/types.js +98 -7
  41. package/dist/grpc/yellowstone_parse.d.ts +5 -0
  42. package/dist/grpc/yellowstone_parse.js +15 -2
  43. package/dist/index.d.ts +36 -6
  44. package/dist/index.js +172 -2
  45. package/dist/instr/bonk_ix.d.ts +4 -1
  46. package/dist/instr/bonk_ix.js +106 -27
  47. package/dist/instr/meteora_damm_ix.d.ts +4 -2
  48. package/dist/instr/meteora_damm_ix.js +248 -13
  49. package/dist/instr/mod.js +7 -2
  50. package/dist/instr/orca_whirlpool_ix.d.ts +4 -1
  51. package/dist/instr/orca_whirlpool_ix.js +45 -16
  52. package/dist/instr/program_ids.d.ts +7 -13
  53. package/dist/instr/program_ids.js +19 -15
  54. package/dist/instr/pumpswap_ix.d.ts +1 -1
  55. package/dist/instr/pumpswap_ix.js +78 -57
  56. package/dist/instr/raydium_amm_v4_ix.d.ts +1 -1
  57. package/dist/instr/raydium_amm_v4_ix.js +94 -28
  58. package/dist/instr/raydium_clmm_ix.d.ts +1 -1
  59. package/dist/instr/raydium_clmm_ix.js +59 -26
  60. package/dist/instr/raydium_cpmm_ix.d.ts +1 -1
  61. package/dist/instr/raydium_cpmm_ix.js +46 -12
  62. package/dist/instr/rust_aliases.d.ts +7 -0
  63. package/dist/instr/rust_aliases.js +14 -0
  64. package/dist/instr/utils.d.ts +1 -1
  65. package/dist/instr/utils.js +2 -1
  66. package/dist/logs/discriminator_lut.d.ts +19 -0
  67. package/dist/logs/discriminator_lut.js +60 -0
  68. package/dist/logs/meteora_damm.d.ts +3 -4
  69. package/dist/logs/meteora_damm.js +3 -369
  70. package/dist/logs/optimized_matcher.d.ts +2 -2
  71. package/dist/logs/optimized_matcher.js +3 -3
  72. package/dist/logs/rust_aliases.d.ts +6 -0
  73. package/dist/logs/rust_aliases.js +13 -0
  74. package/dist/rpc_parser.d.ts +1 -0
  75. package/dist/rpc_parser.js +4 -1
  76. package/dist/shredstream/alt_lookup.d.ts +9 -0
  77. package/dist/shredstream/alt_lookup.js +70 -0
  78. package/dist/shredstream/client.d.ts +62 -0
  79. package/dist/shredstream/client.js +399 -0
  80. package/dist/shredstream/config.d.ts +30 -0
  81. package/dist/shredstream/config.js +34 -0
  82. package/dist/shredstream/entries_decode.d.ts +28 -0
  83. package/dist/shredstream/entries_decode.js +251 -0
  84. package/dist/shredstream/index.d.ts +17 -0
  85. package/dist/shredstream/index.js +33 -0
  86. package/dist/shredstream/instruction_parse.d.ts +34 -0
  87. package/dist/shredstream/instruction_parse.js +47 -0
  88. package/dist/shredstream/proto_types.d.ts +9 -0
  89. package/dist/shredstream/proto_types.js +2 -0
  90. package/dist/shredstream/shredstream.proto +15 -0
  91. package/dist/shredstream/wire_to_shred_tx.d.ts +2 -0
  92. package/dist/shredstream/wire_to_shred_tx.js +59 -0
  93. package/package.json +28 -11
@@ -27,6 +27,7 @@ function buyLike(data, accounts, meta, swapOrder) {
27
27
  ? [(0, utils_js_1.readU64LE)(data, 0) ?? 0n, (0, utils_js_1.readU64LE)(data, 8) ?? 0n]
28
28
  : [0n, 0n];
29
29
  const [base_amount_out, max_quote_amount_in] = swapOrder === "buy" ? [a0, a1] : [a1, a0];
30
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? ZP;
30
31
  const ev = {
31
32
  metadata: meta,
32
33
  timestamp: 0n,
@@ -43,13 +44,13 @@ function buyLike(data, accounts, meta, swapOrder) {
43
44
  protocol_fee: 0n,
44
45
  quote_amount_in_with_lp_fee: 0n,
45
46
  user_quote_amount_in: 0n,
46
- pool: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
47
- user: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
48
- user_base_token_account: (0, utils_js_1.getAccount)(accounts, 5) ?? Z,
49
- user_quote_token_account: (0, utils_js_1.getAccount)(accounts, 6) ?? Z,
50
- protocol_fee_recipient: (0, utils_js_1.getAccount)(accounts, 9) ?? Z,
51
- protocol_fee_recipient_token_account: (0, utils_js_1.getAccount)(accounts, 10) ?? Z,
52
- coin_creator: Z,
47
+ pool: g(0),
48
+ user: g(1),
49
+ user_base_token_account: g(5),
50
+ user_quote_token_account: g(6),
51
+ protocol_fee_recipient: g(9),
52
+ protocol_fee_recipient_token_account: g(10),
53
+ coin_creator: accounts.length > 16 ? g(16) : Z,
53
54
  coin_creator_fee_basis_points: 0n,
54
55
  coin_creator_fee: 0n,
55
56
  track_volume: false,
@@ -62,23 +63,23 @@ function buyLike(data, accounts, meta, swapOrder) {
62
63
  cashback_fee_basis_points: 0n,
63
64
  cashback: 0n,
64
65
  is_pump_pool: false,
65
- base_mint: ZP,
66
- quote_mint: ZP,
67
- pool_base_token_account: ZP,
68
- pool_quote_token_account: ZP,
69
- coin_creator_vault_ata: ZP,
70
- coin_creator_vault_authority: ZP,
71
- base_token_program: ZP,
72
- quote_token_program: ZP,
66
+ base_mint: g(3),
67
+ quote_mint: g(4),
68
+ pool_base_token_account: g(7),
69
+ pool_quote_token_account: g(8),
70
+ coin_creator_vault_ata: accounts.length > 17 ? g(17) : ZP,
71
+ coin_creator_vault_authority: accounts.length > 18 ? g(18) : ZP,
72
+ base_token_program: g(11),
73
+ quote_token_program: g(12),
73
74
  };
74
75
  return ev;
75
76
  }
76
- function parsePumpswapInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs) {
77
+ function parsePumpswapInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs = 0) {
77
78
  if (instructionData.length < 8)
78
79
  return null;
79
80
  const head = instructionData.subarray(0, 8);
80
81
  const data = instructionData.subarray(8);
81
- const meta = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, 0);
82
+ const meta = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
82
83
  if (discEq(head, PS.BUY)) {
83
84
  if (accounts.length < 13)
84
85
  return null;
@@ -95,6 +96,7 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
95
96
  const [base_amount_in, min_quote_amount_out] = data.length >= 16
96
97
  ? [(0, utils_js_1.readU64LE)(data, 0) ?? 0n, (0, utils_js_1.readU64LE)(data, 8) ?? 0n]
97
98
  : [0n, 0n];
99
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? ZP;
98
100
  const ev = {
99
101
  metadata: meta,
100
102
  timestamp: 0n,
@@ -111,39 +113,41 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
111
113
  protocol_fee: 0n,
112
114
  quote_amount_out_without_lp_fee: 0n,
113
115
  user_quote_amount_out: 0n,
114
- pool: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
115
- user: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
116
- user_base_token_account: (0, utils_js_1.getAccount)(accounts, 5) ?? Z,
117
- user_quote_token_account: (0, utils_js_1.getAccount)(accounts, 6) ?? Z,
118
- protocol_fee_recipient: (0, utils_js_1.getAccount)(accounts, 9) ?? Z,
119
- protocol_fee_recipient_token_account: (0, utils_js_1.getAccount)(accounts, 10) ?? Z,
120
- coin_creator: Z,
116
+ pool: g(0),
117
+ user: g(1),
118
+ user_base_token_account: g(5),
119
+ user_quote_token_account: g(6),
120
+ protocol_fee_recipient: g(9),
121
+ protocol_fee_recipient_token_account: g(10),
122
+ coin_creator: accounts.length > 16 ? g(16) : Z,
121
123
  coin_creator_fee_basis_points: 0n,
122
124
  coin_creator_fee: 0n,
123
125
  cashback_fee_basis_points: 0n,
124
126
  cashback: 0n,
125
127
  is_pump_pool: false,
126
- base_mint: ZP,
127
- quote_mint: ZP,
128
- pool_base_token_account: ZP,
129
- pool_quote_token_account: ZP,
130
- coin_creator_vault_ata: ZP,
131
- coin_creator_vault_authority: ZP,
132
- base_token_program: ZP,
133
- quote_token_program: ZP,
128
+ base_mint: g(3),
129
+ quote_mint: g(4),
130
+ pool_base_token_account: g(7),
131
+ pool_quote_token_account: g(8),
132
+ coin_creator_vault_ata: accounts.length > 17 ? g(17) : ZP,
133
+ coin_creator_vault_authority: accounts.length > 18 ? g(18) : ZP,
134
+ base_token_program: g(11),
135
+ quote_token_program: g(12),
134
136
  };
135
137
  return { PumpSwapSell: ev };
136
138
  }
137
139
  if (discEq(head, PS.CREATE_POOL)) {
138
- if (accounts.length < 5)
140
+ if (accounts.length < 8)
139
141
  return null;
142
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? Z;
140
143
  const ev = {
141
144
  metadata: meta,
142
145
  timestamp: 0n,
143
146
  index: 0,
144
- creator: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
145
- base_mint: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
146
- quote_mint: (0, utils_js_1.getAccount)(accounts, 3) ?? Z,
147
+ pool: g(0),
148
+ creator: g(2),
149
+ base_mint: g(3),
150
+ quote_mint: g(4),
147
151
  base_mint_decimals: 0,
148
152
  quote_mint_decimals: 0,
149
153
  base_amount_in: 0n,
@@ -154,11 +158,10 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
154
158
  initial_liquidity: 0n,
155
159
  lp_token_amount_out: 0n,
156
160
  pool_bump: 0,
157
- pool: Z,
158
- lp_mint: Z,
159
- user_base_token_account: Z,
160
- user_quote_token_account: Z,
161
- coin_creator: Z,
161
+ lp_mint: g(5),
162
+ user_base_token_account: g(6),
163
+ user_quote_token_account: g(7),
164
+ coin_creator: g(1),
162
165
  is_mayhem_mode: false,
163
166
  };
164
167
  return { PumpSwapCreatePool: ev };
@@ -166,12 +169,21 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
166
169
  if (discEq(head, PS.DEPOSIT)) {
167
170
  if (accounts.length < 8)
168
171
  return null;
172
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? Z;
173
+ let lp_out = 0n;
174
+ let max_base = 0n;
175
+ let max_quote = 0n;
176
+ if (data.length >= 24) {
177
+ lp_out = (0, utils_js_1.readU64LE)(data, 0) ?? 0n;
178
+ max_base = (0, utils_js_1.readU64LE)(data, 8) ?? 0n;
179
+ max_quote = (0, utils_js_1.readU64LE)(data, 16) ?? 0n;
180
+ }
169
181
  const ev = {
170
182
  metadata: meta,
171
183
  timestamp: 0n,
172
- lp_token_amount_out: 0n,
173
- max_base_amount_in: 0n,
174
- max_quote_amount_in: 0n,
184
+ lp_token_amount_out: lp_out,
185
+ max_base_amount_in: max_base,
186
+ max_quote_amount_in: max_quote,
175
187
  user_base_token_reserves: 0n,
176
188
  user_quote_token_reserves: 0n,
177
189
  pool_base_token_reserves: 0n,
@@ -179,23 +191,32 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
179
191
  base_amount_in: 0n,
180
192
  quote_amount_in: 0n,
181
193
  lp_mint_supply: 0n,
182
- pool: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
183
- user: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
184
- user_base_token_account: (0, utils_js_1.getAccount)(accounts, 4) ?? Z,
185
- user_quote_token_account: (0, utils_js_1.getAccount)(accounts, 5) ?? Z,
186
- user_pool_token_account: (0, utils_js_1.getAccount)(accounts, 6) ?? Z,
194
+ pool: g(0),
195
+ user: g(1),
196
+ user_base_token_account: g(4),
197
+ user_quote_token_account: g(5),
198
+ user_pool_token_account: g(6),
187
199
  };
188
200
  return { PumpSwapLiquidityAdded: ev };
189
201
  }
190
202
  if (discEq(head, PS.WITHDRAW)) {
191
203
  if (accounts.length < 8)
192
204
  return null;
205
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? Z;
206
+ let lp_in = 0n;
207
+ let min_base = 0n;
208
+ let min_quote = 0n;
209
+ if (data.length >= 24) {
210
+ lp_in = (0, utils_js_1.readU64LE)(data, 0) ?? 0n;
211
+ min_base = (0, utils_js_1.readU64LE)(data, 8) ?? 0n;
212
+ min_quote = (0, utils_js_1.readU64LE)(data, 16) ?? 0n;
213
+ }
193
214
  const ev = {
194
215
  metadata: meta,
195
216
  timestamp: 0n,
196
- lp_token_amount_in: 0n,
197
- min_base_amount_out: 0n,
198
- min_quote_amount_out: 0n,
217
+ lp_token_amount_in: lp_in,
218
+ min_base_amount_out: min_base,
219
+ min_quote_amount_out: min_quote,
199
220
  user_base_token_reserves: 0n,
200
221
  user_quote_token_reserves: 0n,
201
222
  pool_base_token_reserves: 0n,
@@ -203,11 +224,11 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
203
224
  base_amount_out: 0n,
204
225
  quote_amount_out: 0n,
205
226
  lp_mint_supply: 0n,
206
- pool: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
207
- user: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
208
- user_base_token_account: (0, utils_js_1.getAccount)(accounts, 4) ?? Z,
209
- user_quote_token_account: (0, utils_js_1.getAccount)(accounts, 5) ?? Z,
210
- user_pool_token_account: (0, utils_js_1.getAccount)(accounts, 6) ?? Z,
227
+ pool: g(0),
228
+ user: g(1),
229
+ user_base_token_account: g(4),
230
+ user_quote_token_account: g(5),
231
+ user_pool_token_account: g(6),
211
232
  };
212
233
  return { PumpSwapLiquidityRemoved: ev };
213
234
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Raydium AMM V4 指令解析
3
- * 注意:Raydium AMM V4 使用单字节 instruction discriminator
3
+ * 单字节 discriminator;Swap 账户顺序与链上 `SwapBaseIn`/`SwapBaseOut` 一致(18 个账户)。
4
4
  */
5
5
  import type { DexEvent } from "../core/dex_event.js";
6
6
  export declare function parseRaydiumAmmV4Instruction(instructionData: Uint8Array, accounts: string[], signature: string, slot: number, txIndex: number, blockTimeUs: number | undefined, grpcRecvUs: number): DexEvent | null;
@@ -4,43 +4,109 @@ exports.parseRaydiumAmmV4Instruction = parseRaydiumAmmV4Instruction;
4
4
  const dex_event_js_1 = require("../core/dex_event.js");
5
5
  const utils_js_1 = require("./utils.js");
6
6
  const Z = (0, dex_event_js_1.defaultPubkey)();
7
- // Raydium AMM V4 使用单字节指令类型
8
7
  const INSTR_TYPE = {
9
8
  SWAP_BASE_IN: 9,
10
9
  SWAP_BASE_OUT: 11,
11
10
  };
11
+ /** 指令内账户顺序(与 Raydium AMM V4 swap 一致) */
12
+ const SWAP = {
13
+ TOKEN_PROGRAM: 0,
14
+ AMM: 1,
15
+ AMM_AUTHORITY: 2,
16
+ AMM_OPEN_ORDERS: 3,
17
+ AMM_TARGET_ORDERS: 4,
18
+ POOL_COIN_TOKEN: 5,
19
+ POOL_PC_TOKEN: 6,
20
+ SERUM_PROGRAM: 7,
21
+ SERUM_MARKET: 8,
22
+ SERUM_BIDS: 9,
23
+ SERUM_ASKS: 10,
24
+ SERUM_EVENT_QUEUE: 11,
25
+ SERUM_COIN_VAULT: 12,
26
+ SERUM_PC_VAULT: 13,
27
+ SERUM_VAULT_SIGNER: 14,
28
+ USER_SOURCE_TOKEN: 15,
29
+ USER_DEST_TOKEN: 16,
30
+ USER_OWNER: 17,
31
+ };
32
+ function swapBaseInFromIx(instructionData, accounts, meta) {
33
+ if (instructionData.length < 1 + 8 + 8)
34
+ return null;
35
+ const amount_in = (0, utils_js_1.readU64LE)(instructionData, 1) ?? 0n;
36
+ const minimum_amount_out = (0, utils_js_1.readU64LE)(instructionData, 9) ?? 0n;
37
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? Z;
38
+ return {
39
+ RaydiumAmmV4Swap: {
40
+ metadata: meta,
41
+ amount_in,
42
+ minimum_amount_out,
43
+ max_amount_in: 0n,
44
+ amount_out: 0n,
45
+ token_program: g(SWAP.TOKEN_PROGRAM),
46
+ amm: g(SWAP.AMM),
47
+ amm_authority: g(SWAP.AMM_AUTHORITY),
48
+ amm_open_orders: g(SWAP.AMM_OPEN_ORDERS),
49
+ amm_target_orders: g(SWAP.AMM_TARGET_ORDERS),
50
+ pool_coin_token_account: g(SWAP.POOL_COIN_TOKEN),
51
+ pool_pc_token_account: g(SWAP.POOL_PC_TOKEN),
52
+ serum_program: g(SWAP.SERUM_PROGRAM),
53
+ serum_market: g(SWAP.SERUM_MARKET),
54
+ serum_bids: g(SWAP.SERUM_BIDS),
55
+ serum_asks: g(SWAP.SERUM_ASKS),
56
+ serum_event_queue: g(SWAP.SERUM_EVENT_QUEUE),
57
+ serum_coin_vault_account: g(SWAP.SERUM_COIN_VAULT),
58
+ serum_pc_vault_account: g(SWAP.SERUM_PC_VAULT),
59
+ serum_vault_signer: g(SWAP.SERUM_VAULT_SIGNER),
60
+ user_source_token_account: g(SWAP.USER_SOURCE_TOKEN),
61
+ user_destination_token_account: g(SWAP.USER_DEST_TOKEN),
62
+ user_source_owner: g(SWAP.USER_OWNER),
63
+ },
64
+ };
65
+ }
66
+ function swapBaseOutFromIx(instructionData, accounts, meta) {
67
+ if (instructionData.length < 1 + 8 + 8)
68
+ return null;
69
+ const max_amount_in = (0, utils_js_1.readU64LE)(instructionData, 1) ?? 0n;
70
+ const amount_out = (0, utils_js_1.readU64LE)(instructionData, 9) ?? 0n;
71
+ const g = (i) => (0, utils_js_1.getAccount)(accounts, i) ?? Z;
72
+ return {
73
+ RaydiumAmmV4Swap: {
74
+ metadata: meta,
75
+ amount_in: 0n,
76
+ minimum_amount_out: 0n,
77
+ max_amount_in,
78
+ amount_out,
79
+ token_program: g(SWAP.TOKEN_PROGRAM),
80
+ amm: g(SWAP.AMM),
81
+ amm_authority: g(SWAP.AMM_AUTHORITY),
82
+ amm_open_orders: g(SWAP.AMM_OPEN_ORDERS),
83
+ amm_target_orders: g(SWAP.AMM_TARGET_ORDERS),
84
+ pool_coin_token_account: g(SWAP.POOL_COIN_TOKEN),
85
+ pool_pc_token_account: g(SWAP.POOL_PC_TOKEN),
86
+ serum_program: g(SWAP.SERUM_PROGRAM),
87
+ serum_market: g(SWAP.SERUM_MARKET),
88
+ serum_bids: g(SWAP.SERUM_BIDS),
89
+ serum_asks: g(SWAP.SERUM_ASKS),
90
+ serum_event_queue: g(SWAP.SERUM_EVENT_QUEUE),
91
+ serum_coin_vault_account: g(SWAP.SERUM_COIN_VAULT),
92
+ serum_pc_vault_account: g(SWAP.SERUM_PC_VAULT),
93
+ serum_vault_signer: g(SWAP.SERUM_VAULT_SIGNER),
94
+ user_source_token_account: g(SWAP.USER_SOURCE_TOKEN),
95
+ user_destination_token_account: g(SWAP.USER_DEST_TOKEN),
96
+ user_source_owner: g(SWAP.USER_OWNER),
97
+ },
98
+ };
99
+ }
12
100
  function parseRaydiumAmmV4Instruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs) {
13
101
  if (instructionData.length < 1)
14
102
  return null;
15
103
  const instrType = instructionData[0];
16
104
  const meta = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
17
- if (instrType === INSTR_TYPE.SWAP_BASE_IN || instrType === INSTR_TYPE.SWAP_BASE_OUT) {
18
- return {
19
- RaydiumAmmV4Swap: {
20
- metadata: meta,
21
- amm: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
22
- user_source_owner: (0, utils_js_1.getAccount)(accounts, 17) ?? Z,
23
- amount_in: 0n,
24
- minimum_amount_out: 0n,
25
- max_amount_in: 0n,
26
- amount_out: 0n,
27
- token_program: Z,
28
- amm_authority: Z,
29
- amm_open_orders: Z,
30
- pool_coin_token_account: Z,
31
- pool_pc_token_account: Z,
32
- serum_program: Z,
33
- serum_market: Z,
34
- serum_bids: Z,
35
- serum_asks: Z,
36
- serum_event_queue: Z,
37
- serum_coin_vault_account: Z,
38
- serum_pc_vault_account: Z,
39
- serum_vault_signer: Z,
40
- user_source_token_account: Z,
41
- user_destination_token_account: Z,
42
- },
43
- };
105
+ if (instrType === INSTR_TYPE.SWAP_BASE_IN) {
106
+ return swapBaseInFromIx(instructionData, accounts, meta);
107
+ }
108
+ if (instrType === INSTR_TYPE.SWAP_BASE_OUT) {
109
+ return swapBaseOutFromIx(instructionData, accounts, meta);
44
110
  }
45
111
  return null;
46
112
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Raydium CLMM 指令解析
2
+ * Raydium CLMM 指令解析(与 Orca Whirlpool 同源 Anchor 布局:swap / 增减流动性)
3
3
  */
4
4
  import type { DexEvent } from "../core/dex_event.js";
5
5
  export declare function parseRaydiumClmmInstruction(instructionData: Uint8Array, accounts: string[], signature: string, slot: number, txIndex: number, blockTimeUs: number | undefined, grpcRecvUs: number): DexEvent | null;
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseRaydiumClmmInstruction = parseRaydiumClmmInstruction;
4
4
  const dex_event_js_1 = require("../core/dex_event.js");
5
+ const program_log_discriminators_js_1 = require("../logs/program_log_discriminators.js");
5
6
  const utils_js_1 = require("./utils.js");
6
7
  const Z = (0, dex_event_js_1.defaultPubkey)();
7
- // Discriminators (little-endian u64)
8
8
  const DISC = {
9
- SWAP: 14494794552504610216n, // disc8(248, 198, 158, 145, 225, 117, 135, 200)
10
- INCREASE_LIQUIDITY: 746211110853564037n, // disc8(133, 29, 89, 223, 69, 238, 176, 10)
11
- DECREASE_LIQUIDITY: 100389049586398241n, // disc8(160, 38, 208, 111, 104, 91, 44, 1)
12
- CREATE_POOL: 13543951572834378153n, // disc8(233, 146, 209, 142, 207, 104, 64, 188)
9
+ SWAP: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CLMM_SWAP,
10
+ INCREASE_LIQUIDITY: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CLMM_INCREASE_LIQUIDITY,
11
+ DECREASE_LIQUIDITY: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CLMM_DECREASE_LIQUIDITY,
12
+ CREATE_POOL: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CLMM_CREATE_POOL,
13
13
  };
14
14
  function discEq(data, disc) {
15
15
  if (data.length < 8)
@@ -17,22 +17,39 @@ function discEq(data, disc) {
17
17
  const v = (0, utils_js_1.readU64LE)(data, 0);
18
18
  return v === disc;
19
19
  }
20
+ /** Whirlpool 系 swap 指令账户:0 program, 1 authority, 2 pool, 3 user_ata_a, 4 vault_a, 5 user_ata_b, … */
21
+ const SWAP_ACC = {
22
+ POOL: 2,
23
+ SENDER: 1,
24
+ TOKEN_A_USER: 3,
25
+ TOKEN_B_USER: 5,
26
+ };
20
27
  function parseRaydiumClmmInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs) {
21
28
  if (instructionData.length < 8)
22
29
  return null;
23
30
  const meta = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
24
31
  if (discEq(instructionData, DISC.SWAP)) {
32
+ // Anchor swap:amount, other_amount_threshold, sqrt_price_limit(u128), amount_specified_is_input, a_to_b
33
+ if (instructionData.length < 42)
34
+ return null;
35
+ const amount = (0, utils_js_1.readU64LE)(instructionData, 8) ?? 0n;
36
+ const other = (0, utils_js_1.readU64LE)(instructionData, 16) ?? 0n;
37
+ const sqrt_limit = (0, utils_js_1.readU128LE)(instructionData, 24) ?? 0n;
38
+ const _amount_specified_is_input = (0, utils_js_1.readBool)(instructionData, 40);
39
+ const a_to_b = (0, utils_js_1.readBool)(instructionData, 41);
40
+ if (_amount_specified_is_input === null || a_to_b === null)
41
+ return null;
25
42
  return {
26
43
  RaydiumClmmSwap: {
27
44
  metadata: meta,
28
- pool_state: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
29
- sender: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
30
- token_account_0: Z,
31
- token_account_1: Z,
32
- amount_0: 0n,
33
- amount_1: 0n,
34
- zero_for_one: false,
35
- sqrt_price_x64: 0n,
45
+ pool_state: (0, utils_js_1.getAccount)(accounts, SWAP_ACC.POOL) ?? Z,
46
+ sender: (0, utils_js_1.getAccount)(accounts, SWAP_ACC.SENDER) ?? Z,
47
+ token_account_0: (0, utils_js_1.getAccount)(accounts, SWAP_ACC.TOKEN_A_USER) ?? Z,
48
+ token_account_1: (0, utils_js_1.getAccount)(accounts, SWAP_ACC.TOKEN_B_USER) ?? Z,
49
+ amount_0: amount,
50
+ amount_1: other,
51
+ zero_for_one: a_to_b,
52
+ sqrt_price_x64: sqrt_limit,
36
53
  liquidity: 0n,
37
54
  transfer_fee_0: 0n,
38
55
  transfer_fee_1: 0n,
@@ -41,43 +58,59 @@ function parseRaydiumClmmInstruction(instructionData, accounts, signature, slot,
41
58
  };
42
59
  }
43
60
  if (discEq(instructionData, DISC.INCREASE_LIQUIDITY)) {
61
+ // increase_liquidity_v2:liquidity (u128), token_max_a, token_max_b
62
+ if (instructionData.length < 8 + 16 + 8 + 8)
63
+ return null;
64
+ const liquidity = (0, utils_js_1.readU128LE)(instructionData, 8) ?? 0n;
65
+ const amount0_max = (0, utils_js_1.readU64LE)(instructionData, 24) ?? 0n;
66
+ const amount1_max = (0, utils_js_1.readU64LE)(instructionData, 32) ?? 0n;
44
67
  return {
45
68
  RaydiumClmmIncreaseLiquidity: {
46
69
  metadata: meta,
47
- pool: (0, utils_js_1.getAccount)(accounts, 3) ?? Z,
48
- position_nft_mint: Z,
70
+ pool: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
71
+ position_nft_mint: (0, utils_js_1.getAccount)(accounts, 3) ?? Z,
49
72
  user: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
50
- liquidity: 0n,
51
- amount0_max: 0n,
52
- amount1_max: 0n,
73
+ liquidity,
74
+ amount0_max,
75
+ amount1_max,
53
76
  },
54
77
  };
55
78
  }
56
79
  if (discEq(instructionData, DISC.DECREASE_LIQUIDITY)) {
80
+ // decrease_liquidity:liquidity (u128), token_min_a, token_min_b
81
+ if (instructionData.length < 8 + 16 + 8 + 8)
82
+ return null;
83
+ const liquidity = (0, utils_js_1.readU128LE)(instructionData, 8) ?? 0n;
84
+ const amount0_min = (0, utils_js_1.readU64LE)(instructionData, 24) ?? 0n;
85
+ const amount1_min = (0, utils_js_1.readU64LE)(instructionData, 32) ?? 0n;
57
86
  return {
58
87
  RaydiumClmmDecreaseLiquidity: {
59
88
  metadata: meta,
60
- pool: (0, utils_js_1.getAccount)(accounts, 3) ?? Z,
61
- position_nft_mint: Z,
89
+ pool: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
90
+ position_nft_mint: (0, utils_js_1.getAccount)(accounts, 3) ?? Z,
62
91
  user: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
63
- liquidity: 0n,
64
- amount0_min: 0n,
65
- amount1_min: 0n,
92
+ liquidity,
93
+ amount0_min,
94
+ amount1_min,
66
95
  },
67
96
  };
68
97
  }
69
98
  if (discEq(instructionData, DISC.CREATE_POOL)) {
99
+ if (instructionData.length < 8 + 16 + 8)
100
+ return null;
101
+ const sqrt_price_x64 = (0, utils_js_1.readU128LE)(instructionData, 8) ?? 0n;
102
+ const open_time = (0, utils_js_1.readU64LE)(instructionData, 24) ?? 0n;
70
103
  return {
71
104
  RaydiumClmmCreatePool: {
72
105
  metadata: meta,
73
106
  pool: (0, utils_js_1.getAccount)(accounts, 4) ?? Z,
74
- creator: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
75
107
  token_0_mint: Z,
76
108
  token_1_mint: Z,
77
109
  tick_spacing: 0,
78
110
  fee_rate: 0,
79
- sqrt_price_x64: 0n,
80
- open_time: 0n,
111
+ creator: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
112
+ sqrt_price_x64,
113
+ open_time,
81
114
  },
82
115
  };
83
116
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Raydium CPMM 指令解析
2
+ * Raydium CPMM 指令解析(Anchor:8 字节 discriminator + Borsh 参数)
3
3
  */
4
4
  import type { DexEvent } from "../core/dex_event.js";
5
5
  export declare function parseRaydiumCpmmInstruction(instructionData: Uint8Array, accounts: string[], signature: string, slot: number, txIndex: number, blockTimeUs: number | undefined, grpcRecvUs: number): DexEvent | null;
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseRaydiumCpmmInstruction = parseRaydiumCpmmInstruction;
4
4
  const dex_event_js_1 = require("../core/dex_event.js");
5
+ const program_log_discriminators_js_1 = require("../logs/program_log_discriminators.js");
5
6
  const utils_js_1 = require("./utils.js");
6
7
  const Z = (0, dex_event_js_1.defaultPubkey)();
7
- // Discriminators (little-endian u64)
8
8
  const DISC = {
9
- SWAP: 16066630856980634287n, // disc8(143, 190, 90, 218, 196, 30, 51, 222)
10
- DEPOSIT: 13142033090605164850n, // disc8(242, 35, 198, 137, 82, 225, 242, 182)
11
- WITHDRAW: 2464928621593348407n, // disc8(183, 18, 70, 156, 148, 109, 161, 34)
9
+ SWAP_BASE_IN: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CPMM_SWAP_BASE_IN,
10
+ SWAP_BASE_OUT: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CPMM_SWAP_BASE_OUT,
11
+ DEPOSIT: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CPMM_DEPOSIT,
12
+ WITHDRAW: program_log_discriminators_js_1.PROGRAM_LOG_DISC.RAYDIUM_CPMM_WITHDRAW,
12
13
  };
13
14
  function discEq(data, disc) {
14
15
  if (data.length < 8)
@@ -20,12 +21,16 @@ function parseRaydiumCpmmInstruction(instructionData, accounts, signature, slot,
20
21
  if (instructionData.length < 8)
21
22
  return null;
22
23
  const meta = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
23
- if (discEq(instructionData, DISC.SWAP)) {
24
+ if (discEq(instructionData, DISC.SWAP_BASE_IN)) {
25
+ if (instructionData.length < 8 + 8 + 8)
26
+ return null;
27
+ const amount_in = (0, utils_js_1.readU64LE)(instructionData, 8) ?? 0n;
28
+ const minimum_amount_out = (0, utils_js_1.readU64LE)(instructionData, 16) ?? 0n;
24
29
  return {
25
30
  RaydiumCpmmSwap: {
26
31
  metadata: meta,
27
32
  pool_id: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
28
- input_amount: 0n,
33
+ input_amount: amount_in,
29
34
  output_amount: 0n,
30
35
  input_vault_before: 0n,
31
36
  output_vault_before: 0n,
@@ -35,27 +40,56 @@ function parseRaydiumCpmmInstruction(instructionData, accounts, signature, slot,
35
40
  },
36
41
  };
37
42
  }
43
+ if (discEq(instructionData, DISC.SWAP_BASE_OUT)) {
44
+ if (instructionData.length < 8 + 8 + 8)
45
+ return null;
46
+ const max_amount_in = (0, utils_js_1.readU64LE)(instructionData, 8) ?? 0n;
47
+ const amount_out = (0, utils_js_1.readU64LE)(instructionData, 16) ?? 0n;
48
+ return {
49
+ RaydiumCpmmSwap: {
50
+ metadata: meta,
51
+ pool_id: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
52
+ input_amount: max_amount_in,
53
+ output_amount: amount_out,
54
+ input_vault_before: 0n,
55
+ output_vault_before: 0n,
56
+ input_transfer_fee: 0n,
57
+ output_transfer_fee: 0n,
58
+ base_input: false,
59
+ },
60
+ };
61
+ }
38
62
  if (discEq(instructionData, DISC.DEPOSIT)) {
63
+ if (instructionData.length < 8 + 8 + 8 + 8)
64
+ return null;
65
+ const lp_token_amount = (0, utils_js_1.readU64LE)(instructionData, 8) ?? 0n;
66
+ const token0_amount = (0, utils_js_1.readU64LE)(instructionData, 16) ?? 0n;
67
+ const token1_amount = (0, utils_js_1.readU64LE)(instructionData, 24) ?? 0n;
39
68
  return {
40
69
  RaydiumCpmmDeposit: {
41
70
  metadata: meta,
42
71
  pool: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
43
72
  user: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
44
- lp_token_amount: 0n,
45
- token0_amount: 0n,
46
- token1_amount: 0n,
73
+ lp_token_amount,
74
+ token0_amount,
75
+ token1_amount,
47
76
  },
48
77
  };
49
78
  }
50
79
  if (discEq(instructionData, DISC.WITHDRAW)) {
80
+ if (instructionData.length < 8 + 8 + 8 + 8)
81
+ return null;
82
+ const lp_token_amount = (0, utils_js_1.readU64LE)(instructionData, 8) ?? 0n;
83
+ const token0_amount = (0, utils_js_1.readU64LE)(instructionData, 16) ?? 0n;
84
+ const token1_amount = (0, utils_js_1.readU64LE)(instructionData, 24) ?? 0n;
51
85
  return {
52
86
  RaydiumCpmmWithdraw: {
53
87
  metadata: meta,
54
88
  pool: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
55
89
  user: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
56
- lp_token_amount: 0n,
57
- token0_amount: 0n,
58
- token1_amount: 0n,
90
+ lp_token_amount,
91
+ token0_amount,
92
+ token1_amount,
59
93
  },
60
94
  };
61
95
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Rust `instr` 根模块 re-export 的蛇形命名(与 `parse_pumpfun_instruction` 等对应)。
3
+ */
4
+ export { parseInstructionUnified as parse_instruction_unified } from "./mod.js";
5
+ export { parsePumpfunInstruction as parse_pumpfun_instruction } from "./pumpfun_ix.js";
6
+ export { parsePumpswapInstruction as parse_pumpswap_instruction } from "./pumpswap_ix.js";
7
+ export { parseMeteoraDammInstruction as parse_meteora_damm_instruction } from "./meteora_damm_ix.js";
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parse_meteora_damm_instruction = exports.parse_pumpswap_instruction = exports.parse_pumpfun_instruction = exports.parse_instruction_unified = void 0;
4
+ /**
5
+ * Rust `instr` 根模块 re-export 的蛇形命名(与 `parse_pumpfun_instruction` 等对应)。
6
+ */
7
+ var mod_js_1 = require("./mod.js");
8
+ Object.defineProperty(exports, "parse_instruction_unified", { enumerable: true, get: function () { return mod_js_1.parseInstructionUnified; } });
9
+ var pumpfun_ix_js_1 = require("./pumpfun_ix.js");
10
+ Object.defineProperty(exports, "parse_pumpfun_instruction", { enumerable: true, get: function () { return pumpfun_ix_js_1.parsePumpfunInstruction; } });
11
+ var pumpswap_ix_js_1 = require("./pumpswap_ix.js");
12
+ Object.defineProperty(exports, "parse_pumpswap_instruction", { enumerable: true, get: function () { return pumpswap_ix_js_1.parsePumpswapInstruction; } });
13
+ var meteora_damm_ix_js_1 = require("./meteora_damm_ix.js");
14
+ Object.defineProperty(exports, "parse_meteora_damm_instruction", { enumerable: true, get: function () { return meteora_damm_ix_js_1.parseMeteoraDammInstruction; } });