sol-parser-sdk 0.5.9 → 0.5.11

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.
@@ -19,8 +19,31 @@ const rpc_invoke_map_js_1 = require("./core/rpc_invoke_map.js");
19
19
  const log_instr_dedup_js_1 = require("./grpc/log_instr_dedup.js");
20
20
  const inner_js_1 = require("./instr/inner.js");
21
21
  const mod_js_1 = require("./instr/mod.js");
22
+ const program_ids_js_1 = require("./instr/program_ids.js");
22
23
  const optimized_matcher_js_1 = require("./logs/optimized_matcher.js");
23
24
  const DEFAULT_PK = web3_js_1.PublicKey.default.toBase58();
25
+ const PUMPFUN_TRADE_EVENT_NAMES = new Set([
26
+ "PumpFunTrade",
27
+ "PumpFunBuy",
28
+ "PumpFunSell",
29
+ "PumpFunBuyExactSolIn",
30
+ ]);
31
+ const EVENT_CPI_PREFIX = Uint8Array.from([228, 69, 165, 46, 81, 203, 154, 29]);
32
+ const LEGACY_EVENT_CPI_SUFFIX = Uint8Array.from([155, 167, 108, 32, 122, 76, 173, 64]);
33
+ function bytesEqualAt(data, expected, offset) {
34
+ for (let i = 0; i < expected.length; i++) {
35
+ if (data[offset + i] !== expected[i])
36
+ return false;
37
+ }
38
+ return true;
39
+ }
40
+ function isDlmmEventCpi(programId, data) {
41
+ return programId === program_ids_js_1.METEORA_DLMM_PROGRAM_ID && data.length >= 16 && (bytesEqualAt(data, EVENT_CPI_PREFIX, 0) ||
42
+ bytesEqualAt(data, LEGACY_EVENT_CPI_SUFFIX, 8));
43
+ }
44
+ function isDlmmEvent(event) {
45
+ return eventName(event).startsWith("MeteoraDlmm");
46
+ }
24
47
  function eventName(ev) {
25
48
  return Object.keys(ev)[0] ?? "";
26
49
  }
@@ -224,35 +247,48 @@ function mergePumpSwapBuySellInstruction(base, inner) {
224
247
  fillStringIfEmpty(base, key, ix);
225
248
  }
226
249
  }
250
+ function mergeDlmmInstruction(baseName, base, inner) {
251
+ const context = baseName === "MeteoraDlmmInitializePool"
252
+ ? { creator: base.creator, active_bin_id: base.active_bin_id }
253
+ : baseName === "MeteoraDlmmCreatePosition"
254
+ ? { lower_bin_id: base.lower_bin_id, width: base.width }
255
+ : baseName === "MeteoraDlmmClosePosition"
256
+ ? { pool: base.pool }
257
+ : null;
258
+ Object.assign(base, inner);
259
+ if (context)
260
+ Object.assign(base, context);
261
+ }
227
262
  function mergeInstructionEvent(base, inner) {
228
263
  const baseName = eventName(base);
229
264
  const innerName = eventName(inner);
230
265
  const baseData = eventPayload(base);
231
266
  const innerData = eventPayload(inner);
232
267
  if (!baseData || !innerData)
233
- return;
234
- const pumpfunTradeNames = new Set([
235
- "PumpFunTrade",
236
- "PumpFunBuy",
237
- "PumpFunSell",
238
- "PumpFunBuyExactSolIn",
239
- ]);
240
- if (pumpfunTradeNames.has(baseName) && pumpfunTradeNames.has(innerName)) {
268
+ return false;
269
+ if (PUMPFUN_TRADE_EVENT_NAMES.has(baseName) && PUMPFUN_TRADE_EVENT_NAMES.has(innerName)) {
241
270
  mergePumpfunTradeInstruction(baseData, innerData);
242
- return;
271
+ return true;
243
272
  }
244
273
  if (baseName === "PumpFunCreateV2" && innerName === "PumpFunCreateV2") {
245
274
  mergePumpfunCreateV2Instruction(baseData, innerData);
246
- return;
275
+ return true;
247
276
  }
248
277
  if ((baseName === "PumpSwapBuy" && innerName === "PumpSwapBuy") ||
249
278
  (baseName === "PumpSwapSell" && innerName === "PumpSwapSell")) {
250
279
  mergePumpSwapBuySellInstruction(baseData, innerData);
251
- return;
280
+ return true;
252
281
  }
253
282
  if (baseName === innerName) {
254
- Object.assign(baseData, innerData);
283
+ if (baseName.startsWith("MeteoraDlmm")) {
284
+ mergeDlmmInstruction(baseName, baseData, innerData);
285
+ }
286
+ else {
287
+ Object.assign(baseData, innerData);
288
+ }
289
+ return true;
255
290
  }
291
+ return false;
256
292
  }
257
293
  function mergeInstructionEvents(events) {
258
294
  if (events.length === 0)
@@ -265,27 +301,71 @@ function mergeInstructionEvents(events) {
265
301
  return ak - bk;
266
302
  });
267
303
  const out = [];
268
- let pending = null;
304
+ let outerTarget = null;
305
+ const dlmmTargets = [];
269
306
  for (const item of events) {
270
307
  if (item.innerIdx === null) {
271
- if (pending)
272
- out.push(pending.event);
273
- pending = { outerIdx: item.outerIdx, event: item.event };
308
+ out.push(item.event);
309
+ const resultIdx = out.length - 1;
310
+ outerTarget = { outerIdx: item.outerIdx, resultIdx };
311
+ dlmmTargets.length = 0;
312
+ if (isDlmmEvent(item.event)) {
313
+ dlmmTargets.push({
314
+ outerIdx: item.outerIdx,
315
+ stackHeight: item.stackHeight,
316
+ resultIdx,
317
+ });
318
+ }
274
319
  continue;
275
320
  }
276
- if (pending && pending.outerIdx === item.outerIdx) {
277
- mergeInstructionEvent(pending.event, item.event);
321
+ if (item.isDlmmEventCpi) {
322
+ let merged = false;
323
+ for (let i = dlmmTargets.length - 1; i >= 0; i--) {
324
+ const target = dlmmTargets[i];
325
+ const directChild = target.stackHeight === undefined || item.stackHeight === undefined ||
326
+ item.stackHeight === target.stackHeight + 1;
327
+ if (target.outerIdx === item.outerIdx && directChild) {
328
+ dlmmTargets.length = i + 1;
329
+ merged = mergeInstructionEvent(out[target.resultIdx], item.event);
330
+ break;
331
+ }
332
+ }
333
+ if (!merged)
334
+ out.push(item.event);
335
+ continue;
336
+ }
337
+ let resultIdx = -1;
338
+ if (outerTarget && outerTarget.outerIdx === item.outerIdx &&
339
+ mergeInstructionEvent(out[outerTarget.resultIdx], item.event)) {
340
+ resultIdx = outerTarget.resultIdx;
278
341
  }
279
342
  else {
280
- if (pending) {
281
- out.push(pending.event);
282
- pending = null;
283
- }
284
343
  out.push(item.event);
344
+ resultIdx = out.length - 1;
345
+ }
346
+ if (isDlmmEvent(item.event)) {
347
+ if (item.stackHeight === undefined) {
348
+ dlmmTargets.length = 0;
349
+ }
350
+ else {
351
+ while (dlmmTargets.length > 0) {
352
+ const last = dlmmTargets[dlmmTargets.length - 1];
353
+ if (last.outerIdx !== item.outerIdx ||
354
+ (last.stackHeight !== undefined && last.stackHeight >= item.stackHeight)) {
355
+ dlmmTargets.pop();
356
+ }
357
+ else {
358
+ break;
359
+ }
360
+ }
361
+ }
362
+ dlmmTargets.push({
363
+ outerIdx: item.outerIdx,
364
+ stackHeight: item.stackHeight,
365
+ resultIdx,
366
+ });
285
367
  }
286
368
  }
287
- if (pending)
288
- out.push(pending.event);
289
369
  return out;
290
370
  }
291
371
  function resolveAccounts(resolver, indices) {
@@ -303,7 +383,13 @@ function parseOuterAndInnerInstructions(message, meta, signature, slot, txIndex,
303
383
  const accounts = resolveAccounts(resolver, ix.accountKeyIndexes);
304
384
  const ev = (0, mod_js_1.parseInstructionUnified)(data, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs, filter, programId);
305
385
  if (ev)
306
- indexedEvents.push({ outerIdx, innerIdx: null, event: ev });
386
+ indexedEvents.push({
387
+ outerIdx,
388
+ innerIdx: null,
389
+ stackHeight: 1,
390
+ isDlmmEventCpi: false,
391
+ event: ev,
392
+ });
307
393
  }
308
394
  const innerGroups = meta?.innerInstructions;
309
395
  if (!innerGroups)
@@ -318,7 +404,13 @@ function parseOuterAndInnerInstructions(message, meta, signature, slot, txIndex,
318
404
  const ev = (0, inner_js_1.parseInnerCompiledInstructionIfSupported)(data, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs, filter, programId) ??
319
405
  (0, inner_js_1.parseInnerInstructionUnified)(data, accounts, signature, slot, txIndex, blockTimeUs, grpcRecvUs, filter, programId, isCreatedBuy);
320
406
  if (ev)
321
- indexedEvents.push({ outerIdx: group.index, innerIdx, event: ev });
407
+ indexedEvents.push({
408
+ outerIdx: group.index,
409
+ innerIdx,
410
+ stackHeight: ix.stackHeight,
411
+ isDlmmEventCpi: isDlmmEventCpi(programId, data),
412
+ event: ev,
413
+ });
322
414
  }
323
415
  }
324
416
  return mergeInstructionEvents(indexedEvents);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sol-parser-sdk",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "High-performance Solana DEX event parser for Node.js/TypeScript (Yellowstone gRPC, log parsing)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,6 +31,7 @@
31
31
  "check:discriminator-lut": "tsx scripts/check-discriminator-lut.ts",
32
32
  "test": "vitest run",
33
33
  "check:migration": "npm run check:dex-events && npm run verify:discriminators && npm run check:discriminator-lut && npm run check:json-utils && npm run build",
34
+ "example:grpc:devtrades": "tsx examples/devtrades_low_latency.ts",
34
35
  "example:shredstream:subscribe": "tsx examples/shredstream_example.ts",
35
36
  "example:shredstream:pumpfun-json": "tsx examples/shredstream_pumpfun_json.ts",
36
37
  "example:shredstream": "tsx examples/shredstream_example.ts",