sol-parser-sdk-nodejs 0.3.0 → 0.4.4

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 (114) hide show
  1. package/.env.example +24 -0
  2. package/README.md +100 -352
  3. package/README_CN.md +107 -253
  4. package/dist/accounts/mod.d.ts +3 -0
  5. package/dist/accounts/mod.js +18 -1
  6. package/dist/accounts/pumpfun.d.ts +6 -0
  7. package/dist/accounts/pumpfun.js +157 -0
  8. package/dist/accounts/rpc_wallet.d.ts +5 -0
  9. package/dist/accounts/rpc_wallet.js +18 -0
  10. package/dist/accounts/rust_aliases.d.ts +10 -0
  11. package/dist/accounts/rust_aliases.js +21 -0
  12. package/dist/accounts/wallet_resolve.d.ts +1 -0
  13. package/dist/accounts/wallet_resolve.js +28 -0
  14. package/dist/common/constants.d.ts +10 -0
  15. package/dist/common/constants.js +13 -0
  16. package/dist/core/account_dispatcher_rpc.js +26 -5
  17. package/dist/core/account_fill_meteora.d.ts +4 -2
  18. package/dist/core/account_fill_meteora.js +5 -2
  19. package/dist/core/account_fill_pumpfun.js +17 -0
  20. package/dist/core/account_pubkey_cache.d.ts +12 -0
  21. package/dist/core/account_pubkey_cache.js +26 -0
  22. package/dist/core/clock.d.ts +6 -0
  23. package/dist/core/clock.js +13 -0
  24. package/dist/core/dex_event.d.ts +172 -44
  25. package/dist/core/metadata.d.ts +1 -0
  26. package/dist/core/pumpfun_fee_enrich.d.ts +4 -0
  27. package/dist/core/pumpfun_fee_enrich.js +80 -0
  28. package/dist/core/unified_parser.d.ts +2 -2
  29. package/dist/core/unified_parser.js +8 -6
  30. package/dist/grpc/client.d.ts +32 -1
  31. package/dist/grpc/client.js +400 -64
  32. package/dist/grpc/event_parser.d.ts +6 -0
  33. package/dist/grpc/event_parser.js +15 -0
  34. package/dist/grpc/geyser_connect.d.ts +30 -0
  35. package/dist/grpc/geyser_connect.js +40 -0
  36. package/dist/grpc/log_instr_dedup.d.ts +2 -0
  37. package/dist/grpc/log_instr_dedup.js +330 -0
  38. package/dist/grpc/order_buffer.d.ts +27 -0
  39. package/dist/grpc/order_buffer.js +166 -0
  40. package/dist/grpc/program_ids.d.ts +26 -0
  41. package/dist/grpc/program_ids.js +55 -0
  42. package/dist/grpc/rpc_to_grpc.d.ts +18 -0
  43. package/dist/grpc/rpc_to_grpc.js +127 -0
  44. package/dist/grpc/subscribe_builder.d.ts +13 -0
  45. package/dist/grpc/subscribe_builder.js +66 -0
  46. package/dist/grpc/transaction_meta.d.ts +29 -0
  47. package/dist/grpc/transaction_meta.js +208 -0
  48. package/dist/grpc/types.d.ts +57 -2
  49. package/dist/grpc/types.js +199 -7
  50. package/dist/grpc/yellowstone_parse.d.ts +8 -1
  51. package/dist/grpc/yellowstone_parse.js +27 -11
  52. package/dist/index.d.ts +39 -8
  53. package/dist/index.js +184 -2
  54. package/dist/instr/bonk_ix.d.ts +4 -1
  55. package/dist/instr/bonk_ix.js +106 -27
  56. package/dist/instr/meteora_damm_ix.d.ts +4 -2
  57. package/dist/instr/meteora_damm_ix.js +248 -13
  58. package/dist/instr/mod.d.ts +1 -0
  59. package/dist/instr/mod.js +16 -3
  60. package/dist/instr/orca_whirlpool_ix.d.ts +4 -1
  61. package/dist/instr/orca_whirlpool_ix.js +45 -16
  62. package/dist/instr/program_ids.d.ts +7 -13
  63. package/dist/instr/program_ids.js +20 -15
  64. package/dist/instr/pump_fees_ix.d.ts +2 -0
  65. package/dist/instr/pump_fees_ix.js +166 -0
  66. package/dist/instr/pumpfun_ix.js +57 -0
  67. package/dist/instr/pumpswap_ix.d.ts +1 -1
  68. package/dist/instr/pumpswap_ix.js +78 -57
  69. package/dist/instr/raydium_amm_v4_ix.d.ts +1 -1
  70. package/dist/instr/raydium_amm_v4_ix.js +94 -28
  71. package/dist/instr/raydium_clmm_ix.d.ts +1 -1
  72. package/dist/instr/raydium_clmm_ix.js +84 -30
  73. package/dist/instr/raydium_cpmm_ix.d.ts +1 -1
  74. package/dist/instr/raydium_cpmm_ix.js +46 -12
  75. package/dist/instr/rust_aliases.d.ts +8 -0
  76. package/dist/instr/rust_aliases.js +16 -0
  77. package/dist/instr/utils.d.ts +1 -1
  78. package/dist/instr/utils.js +2 -1
  79. package/dist/logs/discriminator_lut.d.ts +19 -0
  80. package/dist/logs/discriminator_lut.js +62 -0
  81. package/dist/logs/meteora_damm.d.ts +3 -4
  82. package/dist/logs/meteora_damm.js +3 -369
  83. package/dist/logs/optimized_matcher.d.ts +2 -2
  84. package/dist/logs/optimized_matcher.js +123 -23
  85. package/dist/logs/program_log_discriminators.d.ts +10 -0
  86. package/dist/logs/program_log_discriminators.js +10 -0
  87. package/dist/logs/pump.d.ts +2 -0
  88. package/dist/logs/pump.js +51 -4
  89. package/dist/logs/pump_fees.d.ts +23 -0
  90. package/dist/logs/pump_fees.js +364 -0
  91. package/dist/logs/rust_aliases.d.ts +6 -0
  92. package/dist/logs/rust_aliases.js +13 -0
  93. package/dist/rpc_parser.d.ts +1 -0
  94. package/dist/rpc_parser.js +4 -1
  95. package/dist/rpc_transaction.d.ts +2 -0
  96. package/dist/rpc_transaction.js +14 -6
  97. package/dist/shredstream/alt_lookup.d.ts +9 -0
  98. package/dist/shredstream/alt_lookup.js +70 -0
  99. package/dist/shredstream/client.d.ts +62 -0
  100. package/dist/shredstream/client.js +399 -0
  101. package/dist/shredstream/config.d.ts +30 -0
  102. package/dist/shredstream/config.js +34 -0
  103. package/dist/shredstream/entries_decode.d.ts +28 -0
  104. package/dist/shredstream/entries_decode.js +251 -0
  105. package/dist/shredstream/index.d.ts +17 -0
  106. package/dist/shredstream/index.js +33 -0
  107. package/dist/shredstream/instruction_parse.d.ts +34 -0
  108. package/dist/shredstream/instruction_parse.js +49 -0
  109. package/dist/shredstream/proto_types.d.ts +9 -0
  110. package/dist/shredstream/proto_types.js +2 -0
  111. package/dist/shredstream/shredstream.proto +15 -0
  112. package/dist/shredstream/wire_to_shred_tx.d.ts +2 -0
  113. package/dist/shredstream/wire_to_shred_tx.js +59 -0
  114. package/package.json +28 -11
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePumpFeesInstruction = parsePumpFeesInstruction;
4
+ const metadata_js_1 = require("../core/metadata.js");
5
+ const dex_event_js_1 = require("../core/dex_event.js");
6
+ const binary_js_1 = require("../util/binary.js");
7
+ const pump_fees_js_1 = require("../logs/pump_fees.js");
8
+ const program_log_discriminators_js_1 = require("../logs/program_log_discriminators.js");
9
+ const CREATE_FEE_SHARING_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([195, 78, 86, 76, 111, 52, 251, 213]);
10
+ const INITIALIZE_FEE_CONFIG_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([62, 162, 20, 133, 121, 65, 145, 27]);
11
+ const RESET_FEE_SHARING_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([10, 2, 182, 95, 16, 127, 129, 186]);
12
+ const REVOKE_FEE_SHARING_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([18, 233, 158, 39, 185, 207, 58, 104]);
13
+ const TRANSFER_FEE_SHARING_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([202, 10, 75, 200, 164, 34, 210, 96]);
14
+ const UPDATE_ADMIN_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([161, 176, 40, 213, 60, 184, 179, 228]);
15
+ const UPDATE_FEE_CONFIG_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([104, 184, 103, 242, 88, 151, 107, 20]);
16
+ const UPDATE_FEE_SHARES_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([189, 13, 136, 99, 187, 164, 237, 35]);
17
+ const UPSERT_FEE_TIERS_IX = (0, program_log_discriminators_js_1.u64leDiscriminator)([227, 23, 150, 12, 77, 86, 94, 4]);
18
+ function account(accounts, index) {
19
+ return accounts[index] ?? null;
20
+ }
21
+ function accountOrDefault(accounts, index) {
22
+ return accounts[index] ?? (0, dex_event_js_1.defaultPubkey)();
23
+ }
24
+ function parsePumpFeesInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs) {
25
+ const disc = (0, binary_js_1.readDiscriminatorU64)(instructionData);
26
+ if (disc === null)
27
+ return null;
28
+ const metadata = (0, metadata_js_1.makeMetadata)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
29
+ if (disc === CREATE_FEE_SHARING_IX) {
30
+ const admin = account(accounts, 2);
31
+ const mint = account(accounts, 4);
32
+ if (!admin || !mint)
33
+ return null;
34
+ return {
35
+ PumpFeesCreateFeeSharingConfig: {
36
+ metadata,
37
+ timestamp: 0n,
38
+ mint,
39
+ bonding_curve: accountOrDefault(accounts, 7),
40
+ pool: account(accounts, 10) ?? undefined,
41
+ sharing_config: accountOrDefault(accounts, 5),
42
+ admin,
43
+ initial_shareholders: [],
44
+ status: "Active",
45
+ },
46
+ };
47
+ }
48
+ if (disc === UPDATE_FEE_SHARES_IX) {
49
+ const admin = account(accounts, 2);
50
+ const mint = account(accounts, 4);
51
+ const sharing_config = account(accounts, 5);
52
+ if (!admin || !mint || !sharing_config)
53
+ return null;
54
+ const shareholders = (0, pump_fees_js_1.readShareholdersVec)(instructionData, 8);
55
+ if (!shareholders || shareholders.next !== instructionData.length)
56
+ return null;
57
+ return {
58
+ PumpFeesUpdateFeeShares: {
59
+ metadata,
60
+ timestamp: 0n,
61
+ mint,
62
+ sharing_config,
63
+ admin,
64
+ bonding_curve: accountOrDefault(accounts, 6),
65
+ pump_creator_vault: accountOrDefault(accounts, 7),
66
+ new_shareholders: shareholders.value,
67
+ },
68
+ };
69
+ }
70
+ if (disc === INITIALIZE_FEE_CONFIG_IX) {
71
+ const admin = account(accounts, 0);
72
+ const fee_config = account(accounts, 1);
73
+ if (!admin || !fee_config)
74
+ return null;
75
+ return { PumpFeesInitializeFeeConfig: { metadata, timestamp: 0n, admin, fee_config } };
76
+ }
77
+ if (disc === RESET_FEE_SHARING_IX) {
78
+ const old_admin = account(accounts, 0);
79
+ const new_admin = account(accounts, 2);
80
+ const mint = account(accounts, 3);
81
+ const sharing_config = account(accounts, 4);
82
+ if (!old_admin || !new_admin || !mint || !sharing_config)
83
+ return null;
84
+ return {
85
+ PumpFeesResetFeeSharingConfig: {
86
+ metadata,
87
+ timestamp: 0n,
88
+ mint,
89
+ sharing_config,
90
+ old_admin,
91
+ old_shareholders: [],
92
+ new_admin,
93
+ new_shareholders: [],
94
+ },
95
+ };
96
+ }
97
+ if (disc === REVOKE_FEE_SHARING_IX) {
98
+ const admin = account(accounts, 0);
99
+ const mint = account(accounts, 2);
100
+ const sharing_config = account(accounts, 3);
101
+ if (!admin || !mint || !sharing_config)
102
+ return null;
103
+ return { PumpFeesRevokeFeeSharingAuthority: { metadata, timestamp: 0n, mint, sharing_config, admin } };
104
+ }
105
+ if (disc === TRANSFER_FEE_SHARING_IX) {
106
+ const old_admin = account(accounts, 0);
107
+ const mint = account(accounts, 2);
108
+ const sharing_config = account(accounts, 3);
109
+ const new_admin = account(accounts, 4);
110
+ if (!old_admin || !mint || !sharing_config || !new_admin)
111
+ return null;
112
+ return {
113
+ PumpFeesTransferFeeSharingAuthority: {
114
+ metadata,
115
+ timestamp: 0n,
116
+ mint,
117
+ sharing_config,
118
+ old_admin,
119
+ new_admin,
120
+ },
121
+ };
122
+ }
123
+ if (disc === UPDATE_ADMIN_IX) {
124
+ const old_admin = account(accounts, 0);
125
+ const new_admin = account(accounts, 2);
126
+ if (!old_admin || !new_admin)
127
+ return null;
128
+ return { PumpFeesUpdateAdmin: { metadata, timestamp: 0n, old_admin, new_admin } };
129
+ }
130
+ if (disc === UPDATE_FEE_CONFIG_IX) {
131
+ const fee_config = account(accounts, 0);
132
+ const admin = account(accounts, 1);
133
+ if (!fee_config || !admin)
134
+ return null;
135
+ const fee_tiers = (0, pump_fees_js_1.readFeeTiersVec)(instructionData, 8);
136
+ if (!fee_tiers)
137
+ return null;
138
+ const flat_fees = (0, pump_fees_js_1.readFeesAt)(instructionData, fee_tiers.next);
139
+ if (!flat_fees || flat_fees.next !== instructionData.length)
140
+ return null;
141
+ return {
142
+ PumpFeesUpdateFeeConfig: {
143
+ metadata,
144
+ timestamp: 0n,
145
+ admin,
146
+ fee_config,
147
+ fee_tiers: fee_tiers.value,
148
+ flat_fees: flat_fees.value,
149
+ },
150
+ };
151
+ }
152
+ if (disc === UPSERT_FEE_TIERS_IX) {
153
+ const fee_config = account(accounts, 0);
154
+ const admin = account(accounts, 1);
155
+ if (!fee_config || !admin)
156
+ return null;
157
+ const fee_tiers = (0, pump_fees_js_1.readFeeTiersVec)(instructionData, 8);
158
+ if (!fee_tiers)
159
+ return null;
160
+ const offset = (0, binary_js_1.readU8)(instructionData, fee_tiers.next);
161
+ if (offset === null || fee_tiers.next + 1 !== instructionData.length)
162
+ return null;
163
+ return { PumpFeesUpsertFeeTiers: { metadata, timestamp: 0n, admin, fee_config, fee_tiers: fee_tiers.value, offset } };
164
+ }
165
+ return null;
166
+ }
@@ -8,6 +8,9 @@ const Z = (0, dex_event_js_1.defaultPubkey)();
8
8
  const DISC = {
9
9
  CREATE: Uint8Array.from([24, 30, 200, 40, 5, 28, 7, 119]),
10
10
  CREATE_V2: Uint8Array.from([214, 144, 76, 236, 95, 139, 49, 180]),
11
+ BUY_V2: Uint8Array.from([184, 23, 238, 97, 103, 197, 211, 61]),
12
+ SELL_V2: Uint8Array.from([93, 246, 130, 60, 231, 233, 64, 178]),
13
+ BUY_EXACT_QUOTE_IN_V2: Uint8Array.from([194, 171, 28, 70, 104, 77, 91, 47]),
11
14
  MIGRATE_EVENT_LOG: Uint8Array.from([189, 233, 93, 185, 92, 148, 234, 148]),
12
15
  };
13
16
  function discEq(data, disc) {
@@ -29,6 +32,50 @@ function createNumericDefaults() {
29
32
  is_cashback_enabled: false,
30
33
  };
31
34
  }
35
+ function parsePumpfunTradeV2Instruction(ixName, data, accounts, metadata) {
36
+ const minAccounts = ixName === "sell_v2" ? 26 : 27;
37
+ if (accounts.length < minAccounts)
38
+ return null;
39
+ const first = data.length >= 8 ? (0, utils_js_1.readU64LE)(data, 0) ?? 0n : 0n;
40
+ const second = data.length >= 16 ? (0, utils_js_1.readU64LE)(data, 8) ?? 0n : 0n;
41
+ const tokenAmount = ixName === "buy_exact_quote_in_v2" ? second : first;
42
+ const solAmount = ixName === "buy_exact_quote_in_v2" ? first : second;
43
+ const trade = {
44
+ metadata,
45
+ mint: accounts[1] ?? Z,
46
+ bonding_curve: accounts[10] ?? Z,
47
+ user: accounts[13] ?? Z,
48
+ sol_amount: solAmount,
49
+ token_amount: tokenAmount,
50
+ fee_recipient: accounts[6] ?? Z,
51
+ is_buy: ixName !== "sell_v2",
52
+ is_created_buy: false,
53
+ timestamp: 0n,
54
+ virtual_sol_reserves: 0n,
55
+ virtual_token_reserves: 0n,
56
+ real_sol_reserves: 0n,
57
+ real_token_reserves: 0n,
58
+ fee_basis_points: 0n,
59
+ fee: 0n,
60
+ creator: Z,
61
+ creator_fee_basis_points: 0n,
62
+ creator_fee: 0n,
63
+ track_volume: false,
64
+ total_unclaimed_tokens: 0n,
65
+ total_claimed_tokens: 0n,
66
+ current_sol_volume: 0n,
67
+ last_update_timestamp: 0n,
68
+ ix_name: ixName,
69
+ mayhem_mode: false,
70
+ cashback_fee_basis_points: 0n,
71
+ cashback: 0n,
72
+ is_cashback_coin: false,
73
+ associated_bonding_curve: accounts[11] ?? Z,
74
+ token_program: accounts[3] ?? Z,
75
+ creator_vault: accounts[16] ?? Z,
76
+ };
77
+ return { PumpFunTrade: trade };
78
+ }
32
79
  function parsePumpfunInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs) {
33
80
  if (instructionData.length < 8)
34
81
  return null;
@@ -75,10 +122,20 @@ function parsePumpfunInstruction(instructionData, accounts, signature, slot, txI
75
122
  mayhem_token_vault: accounts[13] ?? Z,
76
123
  event_authority: accounts[14] ?? Z,
77
124
  program: accounts[15] ?? Z,
125
+ observed_fee_recipient: Z,
78
126
  ...createNumericDefaults(),
79
127
  };
80
128
  return { PumpFunCreateV2: ev };
81
129
  }
130
+ if (discEq(outer, DISC.BUY_V2)) {
131
+ return parsePumpfunTradeV2Instruction("buy_v2", data, accounts, meta);
132
+ }
133
+ if (discEq(outer, DISC.BUY_EXACT_QUOTE_IN_V2)) {
134
+ return parsePumpfunTradeV2Instruction("buy_exact_quote_in_v2", data, accounts, meta);
135
+ }
136
+ if (discEq(outer, DISC.SELL_V2)) {
137
+ return parsePumpfunTradeV2Instruction("sell_v2", data, accounts, meta);
138
+ }
82
139
  if (discEq(outer, DISC.CREATE)) {
83
140
  if (accounts.length < 8)
84
141
  return null;
@@ -2,4 +2,4 @@
2
2
  * PumpSwap 指令解析
3
3
  */
4
4
  import type { DexEvent } from "../core/dex_event.js";
5
- export declare function parsePumpswapInstruction(instructionData: Uint8Array, accounts: string[], signature: string, slot: number, txIndex: number, blockTimeUs: number | undefined): DexEvent | null;
5
+ export declare function parsePumpswapInstruction(instructionData: Uint8Array, accounts: string[], signature: string, slot: number, txIndex: number, blockTimeUs: number | undefined, grpcRecvUs?: number): DexEvent | null;
@@ -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;