sol-parser-sdk 0.5.9 → 0.5.10

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.
@@ -7,7 +7,7 @@ exports.defaultGeyserConnectConfig = defaultGeyserConnectConfig;
7
7
  exports.geyserGrpcChannelOptions = geyserGrpcChannelOptions;
8
8
  exports.connectYellowstoneGeyser = connectYellowstoneGeyser;
9
9
  const yellowstone_grpc_1 = __importDefault(require("@triton-one/yellowstone-grpc"));
10
- /** 与 Rust `GeyserConnectConfig::default` 一致 */
10
+ /** 公共字段与 Rust `GeyserConnectConfig::default` 一致,并包含 Node gRPC 通道默认值。 */
11
11
  function defaultGeyserConnectConfig() {
12
12
  return {
13
13
  connectTimeoutMs: 8000,
@@ -15,6 +15,9 @@ function defaultGeyserConnectConfig() {
15
15
  xToken: undefined,
16
16
  keepAliveIntervalMs: 30_000,
17
17
  keepAliveTimeoutMs: 5000,
18
+ initialReconnectBackoffMs: 1000,
19
+ maxReconnectBackoffMs: 60_000,
20
+ flowControlWindowBytes: 1024 * 1024,
18
21
  };
19
22
  }
20
23
  /** 与 `ClientConfig` / `grpc.keepalive_*` 对齐,用于长连接抗 NAT/负载均衡 idle 断开 */
@@ -29,6 +32,9 @@ function geyserGrpcChannelOptions(config = defaultGeyserConnectConfig()) {
29
32
  "grpc.keepalive_timeout_ms": timeout,
30
33
  /** 无活跃 RPC 时仍发 keepalive,避免长时间仅订阅时被中间设备掐断 */
31
34
  "grpc.keepalive_permit_without_calls": 1,
35
+ "grpc.initial_reconnect_backoff_ms": config.initialReconnectBackoffMs,
36
+ "grpc.max_reconnect_backoff_ms": config.maxReconnectBackoffMs,
37
+ "grpc-node.flow_control_window": config.flowControlWindowBytes,
32
38
  };
33
39
  }
34
40
  /**
@@ -62,7 +62,7 @@ function nextOccurrence(base, counts) {
62
62
  counts.set(base, current + 1);
63
63
  return current;
64
64
  }
65
- function dedupeKey(ev, pumpfunLaneCounts) {
65
+ function dedupeKey(ev, occurrenceCounts) {
66
66
  const name = eventName(ev);
67
67
  const data = payload(ev);
68
68
  if (!data)
@@ -70,7 +70,7 @@ function dedupeKey(ev, pumpfunLaneCounts) {
70
70
  if (PUMPFUN_TRADE_NAMES.has(name)) {
71
71
  const lane = ixLane(data.ix_name);
72
72
  const base = `${data.mint}|${data.user}|${Boolean(data.is_buy)}|${lane}`;
73
- const occurrence = nextOccurrence(base, pumpfunLaneCounts);
73
+ const occurrence = nextOccurrence(`PumpFun|${base}`, occurrenceCounts);
74
74
  return `PumpFunTrade|${base}|${occurrence}`;
75
75
  }
76
76
  switch (name) {
@@ -98,12 +98,28 @@ function dedupeKey(ev, pumpfunLaneCounts) {
98
98
  return `PumpSwapLiquidityAdded|${data.pool}|${data.user}`;
99
99
  case "PumpSwapLiquidityRemoved":
100
100
  return `PumpSwapLiquidityRemoved|${data.pool}|${data.user}`;
101
- case "RaydiumClmmSwap":
102
- return `RaydiumClmmSwap|${data.pool_state}|${Boolean(data.zero_for_one)}`;
103
- case "RaydiumAmmV4Swap":
104
- return `RaydiumAmmV4Swap|${data.amm}`;
105
- case "MeteoraDlmmSwap":
106
- return `MeteoraDlmmSwap|${data.pool}|${data.from}|${Boolean(data.swap_for_y)}`;
101
+ case "RaydiumClmmSwap": {
102
+ const base = String(data.pool_state);
103
+ return `RaydiumClmmSwap|${base}|${nextOccurrence(`RaydiumClmm|${base}`, occurrenceCounts)}`;
104
+ }
105
+ case "RaydiumCpmmSwap": {
106
+ const base = String(data.pool_id);
107
+ return `RaydiumCpmmSwap|${base}|${nextOccurrence(`RaydiumCpmm|${base}`, occurrenceCounts)}`;
108
+ }
109
+ case "RaydiumAmmV4Swap": {
110
+ const base = data.max_amount_in !== 0n && data.max_amount_in !== 0
111
+ ? `out|${data.amount_out}`
112
+ : `in|${data.amount_in}`;
113
+ return `RaydiumAmmV4Swap|${base}|${nextOccurrence(`RaydiumAmmV4|${base}`, occurrenceCounts)}`;
114
+ }
115
+ case "OrcaWhirlpoolSwap": {
116
+ const base = String(data.whirlpool);
117
+ return `OrcaWhirlpoolSwap|${base}|${nextOccurrence(`OrcaWhirlpool|${base}`, occurrenceCounts)}`;
118
+ }
119
+ case "MeteoraDlmmSwap": {
120
+ const base = `${data.pool}|${data.from}|${Boolean(data.swap_for_y)}`;
121
+ return `MeteoraDlmmSwap|${base}|${nextOccurrence(`MeteoraDlmm|${base}`, occurrenceCounts)}`;
122
+ }
107
123
  default:
108
124
  return null;
109
125
  }
@@ -282,6 +298,8 @@ function mergeRaydiumAmmV4Swap(log, ix) {
282
298
  "serum_vault_signer",
283
299
  "user_source_token_account",
284
300
  "user_destination_token_account",
301
+ "user_source_owner",
302
+ "amm",
285
303
  ]) {
286
304
  fillString(log, key, ix);
287
305
  }
@@ -376,16 +394,16 @@ function mergeGrpcInstructionIntoLog(logEvent, ixEvent) {
376
394
  function dedupeLogInstructionEvents(logEvents, instructionEvents) {
377
395
  const out = [];
378
396
  const indexByKey = new Map();
379
- const logPumpfunLaneCounts = new Map();
380
- const ixPumpfunLaneCounts = new Map();
397
+ const logOccurrenceCounts = new Map();
398
+ const ixOccurrenceCounts = new Map();
381
399
  for (const ev of logEvents) {
382
- const key = dedupeKey(ev, logPumpfunLaneCounts);
400
+ const key = dedupeKey(ev, logOccurrenceCounts);
383
401
  if (key)
384
402
  indexByKey.set(key, out.length);
385
403
  out.push(ev);
386
404
  }
387
405
  for (const ev of instructionEvents) {
388
- const key = dedupeKey(ev, ixPumpfunLaneCounts);
406
+ const key = dedupeKey(ev, ixOccurrenceCounts);
389
407
  if (!key) {
390
408
  out.push(ev);
391
409
  continue;
@@ -98,16 +98,18 @@ export interface ClientConfig {
98
98
  keep_alive_interval_ms: number;
99
99
  keep_alive_timeout_ms: number;
100
100
  buffer_size: number;
101
+ /** Node gRPC HTTP/2 receive window. Larger values reduce stalls on bursty streams. */
102
+ flow_control_window_bytes?: number;
101
103
  order_mode: OrderMode;
102
104
  order_timeout_ms: number;
103
105
  micro_batch_us: number;
104
106
  }
105
- /** 与 Rust `grpc::config` 中 `StreamingConfig` 别名(即 `ClientConfig`)一致 */
107
+ /** 与 Rust `grpc::config` 中 `StreamingConfig` 别名一致,并包含可选 Node gRPC 参数。 */
106
108
  export type StreamingConfig = ClientConfig;
107
109
  export declare function defaultClientConfig(): ClientConfig;
108
- /** 与 Rust `ClientConfig::low_latency` 一致 */
110
+ /** Rust `ClientConfig::low_latency` 的 Node 调优版本,使用更小的 JS 对象队列。 */
109
111
  export declare function lowLatencyClientConfig(): ClientConfig;
110
- /** 与 Rust `ClientConfig::high_throughput` 一致 */
112
+ /** Rust `ClientConfig::high_throughput` 的 Node 调优版本,使用更小的 JS 对象队列。 */
111
113
  export declare function highThroughputClientConfig(): ClientConfig;
112
114
  export interface TransactionFilter {
113
115
  account_include: string[];
@@ -42,12 +42,13 @@ function defaultClientConfig() {
42
42
  keep_alive_interval_ms: 30000,
43
43
  keep_alive_timeout_ms: 5000,
44
44
  buffer_size: 8192,
45
+ flow_control_window_bytes: 1024 * 1024,
45
46
  order_mode: "Unordered",
46
47
  order_timeout_ms: 100,
47
48
  micro_batch_us: 100,
48
49
  };
49
50
  }
50
- /** 与 Rust `ClientConfig::low_latency` 一致 */
51
+ /** Rust `ClientConfig::low_latency` 的 Node 调优版本,使用更小的 JS 对象队列。 */
51
52
  function lowLatencyClientConfig() {
52
53
  return {
53
54
  enable_metrics: false,
@@ -60,12 +61,13 @@ function lowLatencyClientConfig() {
60
61
  keep_alive_interval_ms: 10_000,
61
62
  keep_alive_timeout_ms: 2000,
62
63
  buffer_size: 16384,
64
+ flow_control_window_bytes: 16 * 1024 * 1024,
63
65
  order_mode: "Unordered",
64
66
  order_timeout_ms: 50,
65
67
  micro_batch_us: 50,
66
68
  };
67
69
  }
68
- /** 与 Rust `ClientConfig::high_throughput` 一致 */
70
+ /** Rust `ClientConfig::high_throughput` 的 Node 调优版本,使用更小的 JS 对象队列。 */
69
71
  function highThroughputClientConfig() {
70
72
  return {
71
73
  enable_metrics: true,
@@ -78,6 +80,7 @@ function highThroughputClientConfig() {
78
80
  keep_alive_interval_ms: 60_000,
79
81
  keep_alive_timeout_ms: 10_000,
80
82
  buffer_size: 32768,
83
+ flow_control_window_bytes: 16 * 1024 * 1024,
81
84
  order_mode: "Unordered",
82
85
  order_timeout_ms: 200,
83
86
  micro_batch_us: 200,
package/dist/index.d.ts CHANGED
@@ -41,7 +41,7 @@ export { parseInstructionUnified, parsePumpfunInstruction, parsePumpswapInstruct
41
41
  /** Rust `instr` 根模块蛇形命名别名 */
42
42
  export { parse_instruction_unified, parse_pumpfun_instruction, parse_pumpswap_instruction, parse_meteora_damm_instruction, parse_meteora_dlmm_instruction, parse_meteora_pools_instruction, parse_pump_fees_instruction, } from "./instr/rust_aliases.js";
43
43
  export * as programIds from "./instr/program_ids.js";
44
- export { YellowstoneGrpc, type SubscribeCallbacks, type DexEventSubscription } from "./grpc/client.js";
44
+ export { YellowstoneGrpc, type SubscribeCallbacks, type DexEventSubscription, type SubscribeDexEventsOptions, type EventQueueOverflowStrategy, } from "./grpc/client.js";
45
45
  export { connectYellowstoneGeyser, defaultGeyserConnectConfig, geyserGrpcChannelOptions, type GeyserConnectConfig, } from "./grpc/geyser_connect.js";
46
46
  /** 与 Rust `sol_parser_sdk::grpc::event_parser` 模块对应 */
47
47
  export * as event_parser from "./grpc/event_parser.js";
@@ -48,7 +48,7 @@ function filterDexEvent(ev, filter) {
48
48
  ? (0, types_js_1.eventTypeFilterNormalizeDexEvent)(filter, ev)
49
49
  : null;
50
50
  }
51
- function pumpFeesEventDisc(disc) {
51
+ function eventCpiDiscriminator(disc) {
52
52
  if (bytesEq(disc, 0, EVENT_CPI_PREFIX))
53
53
  return (0, binary_js_1.readU64LE)(disc, 8);
54
54
  if (bytesEq(disc, 8, EVENT_CPI_SUFFIX))
@@ -116,14 +116,16 @@ const LOG = {
116
116
  METEORA_DAMM_INITIALIZE_POOL: [228, 50, 246, 85, 203, 66, 134, 37],
117
117
  METEORA_DAMM_CREATE_POSITION: [156, 15, 119, 198, 29, 181, 221, 55],
118
118
  METEORA_DAMM_CLOSE_POSITION: [20, 145, 144, 68, 143, 142, 214, 178],
119
- METEORA_DLMM_SWAP: [143, 190, 90, 218, 196, 30, 51, 222],
120
- METEORA_DLMM_ADD_LIQUIDITY: [181, 157, 89, 67, 143, 182, 52, 72],
121
- METEORA_DLMM_REMOVE_LIQUIDITY: [80, 85, 209, 72, 24, 206, 35, 178],
122
- METEORA_DLMM_INITIALIZE_POOL: [95, 180, 10, 172, 84, 174, 232, 40],
119
+ METEORA_DLMM_SWAP: [81, 108, 227, 190, 205, 208, 10, 196],
120
+ METEORA_DLMM_SWAP2: [46, 116, 82, 215, 148, 27, 84, 77],
121
+ METEORA_DLMM_ADD_LIQUIDITY: [31, 94, 125, 90, 227, 52, 61, 186],
122
+ METEORA_DLMM_REMOVE_LIQUIDITY: [116, 244, 97, 232, 103, 31, 152, 58],
123
+ METEORA_DLMM_INITIALIZE_POOL: [185, 74, 252, 125, 27, 215, 188, 111],
123
124
  METEORA_DLMM_INITIALIZE_BIN_ARRAY: [11, 18, 155, 194, 33, 115, 238, 119],
124
- METEORA_DLMM_CREATE_POSITION: [123, 233, 11, 43, 146, 180, 97, 119],
125
- METEORA_DLMM_CLOSE_POSITION: [94, 168, 102, 45, 59, 122, 137, 54],
126
- METEORA_DLMM_CLAIM_FEE: [152, 70, 208, 111, 104, 91, 44, 1],
125
+ METEORA_DLMM_CREATE_POSITION: [144, 142, 252, 84, 157, 53, 37, 121],
126
+ METEORA_DLMM_CLOSE_POSITION: [255, 196, 16, 107, 28, 202, 53, 128],
127
+ METEORA_DLMM_CLAIM_FEE: [75, 122, 154, 48, 140, 74, 123, 163],
128
+ METEORA_DLMM_CLAIM_FEE2: [232, 171, 242, 97, 58, 77, 35, 45],
127
129
  RAYDIUM_LAUNCHLAB_POOL_CREATE: [151, 215, 226, 9, 118, 161, 115, 174],
128
130
  RAYDIUM_LAUNCHLAB_TRADE: [189, 219, 127, 211, 78, 230, 97, 238],
129
131
  };
@@ -200,6 +202,28 @@ const IX = {
200
202
  [80, 85, 209, 72, 24, 206, 177, 108],
201
203
  [95, 180, 10, 172, 84, 174, 232, 40],
202
204
  ],
205
+ METEORA_DLMM: [
206
+ [181, 157, 89, 67, 143, 182, 52, 72],
207
+ [228, 162, 78, 28, 70, 219, 116, 115],
208
+ [169, 32, 79, 137, 136, 232, 70, 137],
209
+ [112, 191, 101, 171, 28, 144, 127, 187],
210
+ [123, 134, 81, 0, 49, 68, 98, 98],
211
+ [174, 90, 35, 115, 186, 40, 147, 226],
212
+ [35, 86, 19, 185, 78, 212, 75, 211],
213
+ [45, 154, 237, 210, 221, 15, 166, 92],
214
+ [73, 59, 36, 120, 237, 83, 108, 198],
215
+ [219, 192, 234, 71, 190, 191, 102, 80],
216
+ [143, 19, 242, 145, 213, 15, 104, 115],
217
+ [46, 82, 125, 146, 85, 141, 228, 153],
218
+ [80, 85, 209, 72, 24, 206, 177, 108],
219
+ [230, 215, 82, 127, 241, 101, 227, 146],
220
+ [248, 198, 158, 145, 225, 117, 135, 200],
221
+ [65, 75, 63, 76, 235, 91, 91, 136],
222
+ [250, 73, 101, 33, 38, 207, 75, 184],
223
+ [43, 215, 247, 132, 137, 60, 243, 81],
224
+ [56, 173, 230, 208, 173, 228, 156, 205],
225
+ [74, 98, 192, 214, 177, 51, 75, 51],
226
+ ],
203
227
  };
204
228
  function firstByteIn(data, allowed) {
205
229
  return data.length > 0 && allowed.includes(data[0]);
@@ -213,7 +237,7 @@ function normalInstructionDataMayParse(programId, data) {
213
237
  if (programId === program_ids_js_1.RAYDIUM_AMM_V4_PROGRAM_ID)
214
238
  return firstByteIn(data, [1, 3, 4, 7, 9, 11]);
215
239
  if (programId === program_ids_js_1.METEORA_DLMM_PROGRAM_ID)
216
- return firstByteIn(data, [0, 1, 2, 7, 8, 11, 13, 14]);
240
+ return headIn(data, IX.METEORA_DLMM);
217
241
  if (programId === program_ids_js_1.METEORA_DAMM_V2_PROGRAM_ID) {
218
242
  return discEq(data, LOG.METEORA_DAMM_INITIALIZE_POOL);
219
243
  }
@@ -243,7 +267,7 @@ function parseInnerCompiledInstructionIfSupported(data, accounts, signature, slo
243
267
  return (0, mod_js_1.parseInstructionUnified)(data, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs, filter, programId);
244
268
  }
245
269
  function parsePumpFeesInner(disc, data, metadata) {
246
- const eventDisc = pumpFeesEventDisc(disc);
270
+ const eventDisc = eventCpiDiscriminator(disc);
247
271
  if (eventDisc === null)
248
272
  return null;
249
273
  if (eventDisc === disc8(LOG.PUMP_FEES_CREATE_FEE_SHARING_CONFIG)) {
@@ -431,12 +455,10 @@ function parseInnerInstructionUnified(instructionData, accounts, signature, slot
431
455
  else if (programId === program_ids_js_1.METEORA_DLMM_PROGRAM_ID) {
432
456
  if (filter && !(0, types_js_1.eventTypeFilterIncludesMeteoraDlmm)(filter))
433
457
  return null;
434
- if (!discTailEq(disc, EVENT_CPI_SUFFIX))
458
+ const eventDisc = eventCpiDiscriminator(disc);
459
+ if (eventDisc === null)
435
460
  return null;
436
- const decoded = new Uint8Array(8 + data.length);
437
- decoded.set(disc.subarray(0, 8), 0);
438
- decoded.set(data, 8);
439
- ev = (0, meteora_dlmm_js_1.parseDlmmFromDecoded)(decoded, metadata);
461
+ ev = (0, meteora_dlmm_js_1.parseDlmmEventFromData)(eventDisc, data, metadata);
440
462
  }
441
463
  else if (programId === program_ids_js_1.RAYDIUM_LAUNCHLAB_PROGRAM_ID) {
442
464
  if (filter && !(0, types_js_1.eventTypeFilterIncludesRaydiumLaunchlab)(filter))
@@ -5,100 +5,157 @@ const dex_event_js_1 = require("../core/dex_event.js");
5
5
  const binary_js_1 = require("../util/binary.js");
6
6
  const utils_js_1 = require("./utils.js");
7
7
  const Z = (0, dex_event_js_1.defaultPubkey)();
8
+ function discEq(data, bytes) {
9
+ return data.length >= 8 && bytes.every((b, i) => data[i] === b);
10
+ }
11
+ const IX = {
12
+ ADD_LIQUIDITY: [181, 157, 89, 67, 143, 182, 52, 72],
13
+ ADD_LIQUIDITY2: [228, 162, 78, 28, 70, 219, 116, 115],
14
+ CLAIM_FEE: [169, 32, 79, 137, 136, 232, 70, 137],
15
+ CLAIM_FEE2: [112, 191, 101, 171, 28, 144, 127, 187],
16
+ CLOSE_POSITION: [123, 134, 81, 0, 49, 68, 98, 98],
17
+ CLOSE_POSITION2: [174, 90, 35, 115, 186, 40, 147, 226],
18
+ INITIALIZE_BIN_ARRAY: [35, 86, 19, 185, 78, 212, 75, 211],
19
+ INITIALIZE_LB_PAIR: [45, 154, 237, 210, 221, 15, 166, 92],
20
+ INITIALIZE_LB_PAIR2: [73, 59, 36, 120, 237, 83, 108, 198],
21
+ INITIALIZE_POSITION: [219, 192, 234, 71, 190, 191, 102, 80],
22
+ INITIALIZE_POSITION2: [143, 19, 242, 145, 213, 15, 104, 115],
23
+ INITIALIZE_POSITION_PDA: [46, 82, 125, 146, 85, 141, 228, 153],
24
+ REMOVE_LIQUIDITY: [80, 85, 209, 72, 24, 206, 177, 108],
25
+ REMOVE_LIQUIDITY2: [230, 215, 82, 127, 241, 101, 227, 146],
26
+ SWAP: [248, 198, 158, 145, 225, 117, 135, 200],
27
+ SWAP2: [65, 75, 63, 76, 235, 91, 91, 136],
28
+ SWAP_EXACT_OUT: [250, 73, 101, 33, 38, 207, 75, 184],
29
+ SWAP_EXACT_OUT2: [43, 215, 247, 132, 137, 60, 243, 81],
30
+ SWAP_WITH_PRICE_IMPACT: [56, 173, 230, 208, 173, 228, 156, 205],
31
+ SWAP_WITH_PRICE_IMPACT2: [74, 98, 192, 214, 177, 51, 75, 51],
32
+ };
8
33
  function parseMeteoraDlmmInstruction(instructionData, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs) {
9
- if (instructionData.length === 0)
10
- return null;
11
- const pool = (0, utils_js_1.getAccount)(accounts, 0);
12
- if (!pool)
34
+ if (instructionData.length < 8)
13
35
  return null;
14
36
  const metadata = (0, utils_js_1.ixMeta)(signature, slot, txIndex, blockTimeUs, grpcRecvUs);
15
- const kind = instructionData[0];
16
- if (kind === 0) {
17
- if (instructionData.length < 1 + 4 + 2)
37
+ const data = instructionData.subarray(8);
38
+ if (discEq(instructionData, IX.INITIALIZE_LB_PAIR)) {
39
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
40
+ if (!pool || data.length < 6)
18
41
  return null;
19
- const active_bin_id = (0, binary_js_1.readI32LE)(instructionData, 1);
20
- const bin_step = (0, binary_js_1.readU16LE)(instructionData, 5);
42
+ const active_bin_id = (0, binary_js_1.readI32LE)(data, 0);
43
+ const bin_step = (0, binary_js_1.readU16LE)(data, 4);
21
44
  if (active_bin_id === null || bin_step === null)
22
45
  return null;
23
46
  return {
24
47
  MeteoraDlmmInitializePool: {
25
48
  metadata,
26
49
  pool,
27
- creator: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
50
+ creator: (0, utils_js_1.getAccount)(accounts, 8) ?? Z,
28
51
  active_bin_id,
29
52
  bin_step,
30
53
  },
31
54
  };
32
55
  }
33
- if (kind === 1) {
34
- if (instructionData.length < 1 + 8)
56
+ if (discEq(instructionData, IX.INITIALIZE_LB_PAIR2)) {
57
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
58
+ if (!pool || data.length < 4)
59
+ return null;
60
+ return {
61
+ MeteoraDlmmInitializePool: {
62
+ metadata,
63
+ pool,
64
+ creator: (0, utils_js_1.getAccount)(accounts, 8) ?? Z,
65
+ active_bin_id: (0, binary_js_1.readI32LE)(data, 0) ?? 0,
66
+ bin_step: 0,
67
+ },
68
+ };
69
+ }
70
+ if (discEq(instructionData, IX.INITIALIZE_BIN_ARRAY)) {
71
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
72
+ if (!pool || data.length < 8)
35
73
  return null;
36
74
  return {
37
75
  MeteoraDlmmInitializeBinArray: {
38
76
  metadata,
39
77
  pool,
40
78
  bin_array: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
41
- index: (0, binary_js_1.readU64LE)(instructionData, 1) ?? 0n,
79
+ index: (0, binary_js_1.readI64LE)(data, 0) ?? 0n,
42
80
  },
43
81
  };
44
82
  }
45
- if (kind === 2) {
46
- if (instructionData.length < 1 + 32)
83
+ if (discEq(instructionData, IX.ADD_LIQUIDITY) || discEq(instructionData, IX.ADD_LIQUIDITY2)) {
84
+ const pool = (0, utils_js_1.getAccount)(accounts, 1);
85
+ if (!pool)
86
+ return null;
87
+ const senderIndex = discEq(instructionData, IX.ADD_LIQUIDITY2) ? 9 : 11;
88
+ const from = (0, utils_js_1.getAccount)(accounts, senderIndex);
89
+ if (!from)
47
90
  return null;
48
91
  return {
49
92
  MeteoraDlmmAddLiquidity: {
50
93
  metadata,
51
94
  pool,
52
- from: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
53
- position: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
95
+ from,
96
+ position: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
54
97
  amounts: [0n, 0n],
55
98
  active_bin_id: 0,
56
99
  },
57
100
  };
58
101
  }
59
- if (kind === 7) {
60
- if (instructionData.length < 1 + 32)
102
+ if (discEq(instructionData, IX.REMOVE_LIQUIDITY) || discEq(instructionData, IX.REMOVE_LIQUIDITY2)) {
103
+ const pool = (0, utils_js_1.getAccount)(accounts, 1);
104
+ if (!pool)
105
+ return null;
106
+ const senderIndex = discEq(instructionData, IX.REMOVE_LIQUIDITY2) ? 9 : 11;
107
+ const from = (0, utils_js_1.getAccount)(accounts, senderIndex);
108
+ if (!from)
61
109
  return null;
62
110
  return {
63
111
  MeteoraDlmmRemoveLiquidity: {
64
112
  metadata,
65
113
  pool,
66
- from: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
67
- position: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
114
+ from,
115
+ position: (0, utils_js_1.getAccount)(accounts, 0) ?? Z,
68
116
  amounts: [0n, 0n],
69
117
  active_bin_id: 0,
70
118
  },
71
119
  };
72
120
  }
73
- if (kind === 8) {
74
- if (instructionData.length < 1 + 4 + 4)
121
+ if (discEq(instructionData, IX.INITIALIZE_POSITION) ||
122
+ discEq(instructionData, IX.INITIALIZE_POSITION2) ||
123
+ discEq(instructionData, IX.INITIALIZE_POSITION_PDA)) {
124
+ if (data.length < 8)
125
+ return null;
126
+ const lower_bin_id = (0, binary_js_1.readI32LE)(data, 0);
127
+ const width = (0, binary_js_1.readI32LE)(data, 4);
128
+ if (lower_bin_id === null || width === null || width < 0)
75
129
  return null;
76
- const lower_bin_id = (0, binary_js_1.readI32LE)(instructionData, 1);
77
- const width = (0, binary_js_1.readU32LE)(instructionData, 5);
78
- if (lower_bin_id === null || width === null)
130
+ const pda = discEq(instructionData, IX.INITIALIZE_POSITION_PDA);
131
+ const position = (0, utils_js_1.getAccount)(accounts, pda ? 2 : 1);
132
+ const pool = (0, utils_js_1.getAccount)(accounts, pda ? 3 : 2);
133
+ const owner = (0, utils_js_1.getAccount)(accounts, pda ? 4 : 3);
134
+ if (!position || !pool || !owner)
79
135
  return null;
80
136
  return {
81
137
  MeteoraDlmmCreatePosition: {
82
138
  metadata,
83
139
  pool,
84
- position: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
85
- owner: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
140
+ position,
141
+ owner,
86
142
  lower_bin_id,
87
143
  width,
88
144
  },
89
145
  };
90
146
  }
91
- if (kind === 11) {
92
- if (instructionData.length < 1 + 8 + 8)
147
+ if (discEq(instructionData, IX.SWAP) || discEq(instructionData, IX.SWAP2)) {
148
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
149
+ if (!pool || data.length < 16)
93
150
  return null;
94
151
  return {
95
152
  MeteoraDlmmSwap: {
96
153
  metadata,
97
154
  pool,
98
- from: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
155
+ from: (0, utils_js_1.getAccount)(accounts, 10) ?? Z,
99
156
  start_bin_id: 0,
100
157
  end_bin_id: 0,
101
- amount_in: (0, binary_js_1.readU64LE)(instructionData, 1) ?? 0n,
158
+ amount_in: (0, binary_js_1.readU64LE)(data, 0) ?? 0n,
102
159
  amount_out: 0n,
103
160
  swap_for_y: false,
104
161
  fee: 0n,
@@ -108,25 +165,60 @@ function parseMeteoraDlmmInstruction(instructionData, accounts, signature, slot,
108
165
  },
109
166
  };
110
167
  }
111
- if (kind === 13) {
168
+ if (discEq(instructionData, IX.SWAP_EXACT_OUT) ||
169
+ discEq(instructionData, IX.SWAP_EXACT_OUT2) ||
170
+ discEq(instructionData, IX.SWAP_WITH_PRICE_IMPACT) ||
171
+ discEq(instructionData, IX.SWAP_WITH_PRICE_IMPACT2)) {
172
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
173
+ if (!pool || data.length < 8)
174
+ return null;
175
+ return {
176
+ MeteoraDlmmSwap: {
177
+ metadata,
178
+ pool,
179
+ from: (0, utils_js_1.getAccount)(accounts, 10) ?? Z,
180
+ start_bin_id: 0,
181
+ end_bin_id: 0,
182
+ amount_in: (0, binary_js_1.readU64LE)(data, 0) ?? 0n,
183
+ amount_out: discEq(instructionData, IX.SWAP_EXACT_OUT) || discEq(instructionData, IX.SWAP_EXACT_OUT2)
184
+ ? (0, binary_js_1.readU64LE)(data, 8) ?? 0n
185
+ : 0n,
186
+ swap_for_y: false,
187
+ fee: 0n,
188
+ protocol_fee: 0n,
189
+ fee_bps: 0n,
190
+ host_fee: 0n,
191
+ },
192
+ };
193
+ }
194
+ if (discEq(instructionData, IX.CLAIM_FEE) || discEq(instructionData, IX.CLAIM_FEE2)) {
195
+ const pool = (0, utils_js_1.getAccount)(accounts, 0);
196
+ const owner = (0, utils_js_1.getAccount)(accounts, discEq(instructionData, IX.CLAIM_FEE2) ? 2 : 4);
197
+ if (!pool || !owner)
198
+ return null;
112
199
  return {
113
200
  MeteoraDlmmClaimFee: {
114
201
  metadata,
115
202
  pool,
116
203
  position: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
117
- owner: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
204
+ owner,
118
205
  fee_x: 0n,
119
206
  fee_y: 0n,
120
207
  },
121
208
  };
122
209
  }
123
- if (kind === 14) {
210
+ if (discEq(instructionData, IX.CLOSE_POSITION) || discEq(instructionData, IX.CLOSE_POSITION2)) {
211
+ const position = (0, utils_js_1.getAccount)(accounts, 0);
212
+ const v2 = discEq(instructionData, IX.CLOSE_POSITION2);
213
+ const owner = (0, utils_js_1.getAccount)(accounts, v2 ? 1 : 4);
214
+ if (!position || !owner)
215
+ return null;
124
216
  return {
125
217
  MeteoraDlmmClosePosition: {
126
218
  metadata,
127
- pool,
128
- position: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
129
- owner: (0, utils_js_1.getAccount)(accounts, 2) ?? Z,
219
+ pool: v2 ? Z : (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
220
+ position,
221
+ owner,
130
222
  },
131
223
  };
132
224
  }
@@ -34,10 +34,11 @@ function parseOrcaWhirlpoolInstruction(instructionData, accounts, signature, slo
34
34
  return null;
35
35
  const input_amount = amount_specified_is_input ? amount : 0n;
36
36
  const output_amount = amount_specified_is_input ? other_threshold : amount;
37
+ const whirlpoolIndex = discEq(instructionData, DISC.SWAP_V2) ? 4 : 2;
37
38
  return {
38
39
  OrcaWhirlpoolSwap: {
39
40
  metadata: meta,
40
- whirlpool: (0, utils_js_1.getAccount)(accounts, 1) ?? Z,
41
+ whirlpool: (0, utils_js_1.getAccount)(accounts, whirlpoolIndex) ?? Z,
41
42
  a_to_b,
42
43
  pre_sqrt_price: sqrt_price_limit,
43
44
  post_sqrt_price: 0n,
@@ -94,6 +94,11 @@ function buyLike(data, accounts, meta, swapOrder) {
94
94
  ix_name: "",
95
95
  cashback_fee_basis_points: 0n,
96
96
  cashback: 0n,
97
+ buyback_fee_basis_points: 0n,
98
+ buyback_fee: 0n,
99
+ virtual_quote_reserves: 0n,
100
+ can_boost: false,
101
+ base_supply: 0n,
97
102
  is_pump_pool: false,
98
103
  base_mint: g(3),
99
104
  quote_mint: g(4),
@@ -157,6 +162,11 @@ function parsePumpswapInstruction(instructionData, accounts, signature, slot, tx
157
162
  coin_creator_fee: 0n,
158
163
  cashback_fee_basis_points: 0n,
159
164
  cashback: 0n,
165
+ buyback_fee_basis_points: 0n,
166
+ buyback_fee: 0n,
167
+ virtual_quote_reserves: 0n,
168
+ can_boost: false,
169
+ base_supply: 0n,
160
170
  is_pump_pool: false,
161
171
  base_mint: g(3),
162
172
  quote_mint: g(4),