@thesight/sdk 0.3.8 → 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.
- package/dist/index.cjs +133 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -15
- package/dist/index.d.ts +0 -15
- package/dist/index.js +119 -152
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
IdlResolver: () =>
|
|
23
|
+
IdlResolver: () => import_core5.IdlResolver,
|
|
24
24
|
InstrumentedConnection: () => InstrumentedConnection,
|
|
25
25
|
SightSpanExporter: () => SightSpanExporter,
|
|
26
26
|
buildDsn: () => buildDsn,
|
|
@@ -30,15 +30,93 @@ __export(index_exports, {
|
|
|
30
30
|
});
|
|
31
31
|
module.exports = __toCommonJS(index_exports);
|
|
32
32
|
var import_web3 = require("@solana/web3.js");
|
|
33
|
-
var
|
|
34
|
-
var import_core3 = require("@thesight/core");
|
|
33
|
+
var import_api4 = require("@opentelemetry/api");
|
|
35
34
|
var import_core4 = require("@thesight/core");
|
|
36
35
|
|
|
37
|
-
// src/
|
|
36
|
+
// src/enrichment.ts
|
|
38
37
|
var import_api = require("@opentelemetry/api");
|
|
38
|
+
var import_core = require("@thesight/core");
|
|
39
|
+
var SOLANA_CU_BUDGET = 2e5;
|
|
40
|
+
var DEFAULT_ENRICHMENT_TIMEOUT_MS = 3e4;
|
|
41
|
+
var DEFAULT_ENRICHMENT_POLL_MS = 500;
|
|
42
|
+
async function pollForTransaction(getTransaction, signature, commitment, deadline, basePollMs) {
|
|
43
|
+
let attempt = 0;
|
|
44
|
+
while (Date.now() < deadline) {
|
|
45
|
+
try {
|
|
46
|
+
const tx = await getTransaction(signature, {
|
|
47
|
+
commitment,
|
|
48
|
+
maxSupportedTransactionVersion: 0
|
|
49
|
+
});
|
|
50
|
+
if (tx) return tx;
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
attempt++;
|
|
54
|
+
const waitMs = Math.min(basePollMs * Math.pow(1.5, attempt - 1), 2e3);
|
|
55
|
+
await sleep(waitMs);
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function attachTxDetailsToSpan(span, txDetails) {
|
|
60
|
+
span.setAttribute("solana.tx.status", txDetails.meta?.err ? "failed" : "confirmed");
|
|
61
|
+
span.setAttribute("solana.tx.slot", txDetails.slot);
|
|
62
|
+
const fee = txDetails.meta?.fee;
|
|
63
|
+
if (fee !== void 0) span.setAttribute("solana.tx.fee_lamports", fee);
|
|
64
|
+
const cuUsed = txDetails.meta?.computeUnitsConsumed;
|
|
65
|
+
if (cuUsed !== void 0 && cuUsed !== null) {
|
|
66
|
+
span.setAttribute("solana.tx.cu_used", Number(cuUsed));
|
|
67
|
+
span.setAttribute("solana.tx.cu_budget", SOLANA_CU_BUDGET);
|
|
68
|
+
span.setAttribute(
|
|
69
|
+
"solana.tx.cu_utilization",
|
|
70
|
+
parseFloat((Number(cuUsed) / SOLANA_CU_BUDGET * 100).toFixed(1))
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function attachParsedLogsToSpan(span, logs, resolver) {
|
|
75
|
+
const { cpiTree } = (0, import_core.parseLogs)({ logs });
|
|
76
|
+
await (0, import_core.enrichTree)(cpiTree, resolver);
|
|
77
|
+
const attributions = (0, import_core.flatAttributions)(cpiTree);
|
|
78
|
+
for (const attr of attributions) {
|
|
79
|
+
span.addEvent("cpi.invoke", {
|
|
80
|
+
"cpi.program": attr.programName ?? attr.programId,
|
|
81
|
+
"cpi.instruction": attr.instructionName ?? "unknown",
|
|
82
|
+
"cpi.depth": attr.depth,
|
|
83
|
+
"cpi.cu_consumed": attr.cuConsumed,
|
|
84
|
+
"cpi.cu_self": attr.cuSelf,
|
|
85
|
+
"cpi.percentage": parseFloat(attr.percentage.toFixed(2))
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const root = cpiTree.roots[0];
|
|
89
|
+
if (root) {
|
|
90
|
+
if (root.programName) span.setAttribute("solana.tx.program", root.programName);
|
|
91
|
+
if (root.instructionName) span.setAttribute("solana.tx.instruction", root.instructionName);
|
|
92
|
+
}
|
|
93
|
+
return cpiTree;
|
|
94
|
+
}
|
|
95
|
+
function finalizeSpan(span, txDetails, startTime) {
|
|
96
|
+
if (!txDetails) {
|
|
97
|
+
span.setAttribute("solana.tx.status", "timeout");
|
|
98
|
+
span.setAttribute("solana.tx.enrichment_ms", Date.now() - startTime);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
span.setAttribute("solana.tx.enrichment_ms", Date.now() - startTime);
|
|
102
|
+
if (txDetails.meta?.err) {
|
|
103
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR });
|
|
104
|
+
} else {
|
|
105
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function sleep(ms) {
|
|
109
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/index.ts
|
|
113
|
+
var import_core5 = require("@thesight/core");
|
|
114
|
+
|
|
115
|
+
// src/init.ts
|
|
116
|
+
var import_api2 = require("@opentelemetry/api");
|
|
39
117
|
|
|
40
118
|
// src/exporter.ts
|
|
41
|
-
var
|
|
119
|
+
var import_core2 = require("@opentelemetry/core");
|
|
42
120
|
|
|
43
121
|
// src/dsn.ts
|
|
44
122
|
function parseDsn(dsn) {
|
|
@@ -91,7 +169,7 @@ var SightSpanExporter = class {
|
|
|
91
169
|
}
|
|
92
170
|
async export(spans, resultCallback) {
|
|
93
171
|
if (this.shuttingDown) {
|
|
94
|
-
resultCallback({ code:
|
|
172
|
+
resultCallback({ code: import_core2.ExportResultCode.FAILED, error: new Error("Exporter is shut down") });
|
|
95
173
|
return;
|
|
96
174
|
}
|
|
97
175
|
const chunks = [];
|
|
@@ -102,10 +180,10 @@ var SightSpanExporter = class {
|
|
|
102
180
|
for (const chunk of chunks) {
|
|
103
181
|
await this.sendChunk(chunk);
|
|
104
182
|
}
|
|
105
|
-
resultCallback({ code:
|
|
183
|
+
resultCallback({ code: import_core2.ExportResultCode.SUCCESS });
|
|
106
184
|
} catch (err) {
|
|
107
185
|
resultCallback({
|
|
108
|
-
code:
|
|
186
|
+
code: import_core2.ExportResultCode.FAILED,
|
|
109
187
|
error: err instanceof Error ? err : new Error(String(err))
|
|
110
188
|
});
|
|
111
189
|
}
|
|
@@ -139,8 +217,8 @@ var SightSpanExporter = class {
|
|
|
139
217
|
const attr = span.attributes;
|
|
140
218
|
const resource2 = span.resource.attributes;
|
|
141
219
|
const serviceName = typeof resource2["service.name"] === "string" ? resource2["service.name"] : void 0;
|
|
142
|
-
const startTimeMs = (0,
|
|
143
|
-
const endTimeMs = (0,
|
|
220
|
+
const startTimeMs = (0, import_core2.hrTimeToMilliseconds)(span.startTime);
|
|
221
|
+
const endTimeMs = (0, import_core2.hrTimeToMilliseconds)(span.endTime);
|
|
144
222
|
const durationMs = Math.max(0, endTimeMs - startTimeMs);
|
|
145
223
|
const out = {
|
|
146
224
|
traceId: span.spanContext().traceId,
|
|
@@ -250,7 +328,7 @@ function initSight(config) {
|
|
|
250
328
|
_lastTier1Error = tier1Err;
|
|
251
329
|
}
|
|
252
330
|
try {
|
|
253
|
-
const proxy =
|
|
331
|
+
const proxy = import_api2.trace.getTracerProvider();
|
|
254
332
|
const delegate = proxy?.getDelegate?.() ?? proxy;
|
|
255
333
|
if (delegate && typeof delegate.addSpanProcessor === "function") {
|
|
256
334
|
const processor2 = new SightInlineProcessor(
|
|
@@ -260,7 +338,7 @@ function initSight(config) {
|
|
|
260
338
|
);
|
|
261
339
|
delegate.addSpanProcessor(processor2);
|
|
262
340
|
return {
|
|
263
|
-
tracer:
|
|
341
|
+
tracer: import_api2.trace.getTracer("@thesight/sdk"),
|
|
264
342
|
mode: "piggyback",
|
|
265
343
|
shutdown: async () => {
|
|
266
344
|
await processor2.shutdown();
|
|
@@ -282,7 +360,7 @@ function initSight(config) {
|
|
|
282
360
|
}
|
|
283
361
|
}
|
|
284
362
|
return {
|
|
285
|
-
tracer:
|
|
363
|
+
tracer: import_api2.trace.getTracer("@thesight/sdk"),
|
|
286
364
|
mode: "api_only",
|
|
287
365
|
shutdown: async () => {
|
|
288
366
|
}
|
|
@@ -332,68 +410,40 @@ var SightInlineProcessor = class {
|
|
|
332
410
|
};
|
|
333
411
|
|
|
334
412
|
// src/track.ts
|
|
335
|
-
var
|
|
336
|
-
var
|
|
413
|
+
var import_api3 = require("@opentelemetry/api");
|
|
414
|
+
var import_core3 = require("@thesight/core");
|
|
337
415
|
async function trackSolanaTransaction(opts) {
|
|
338
416
|
const tracerName = opts.serviceName ?? "@thesight/sdk";
|
|
339
|
-
const tracer = opts.tracer ??
|
|
340
|
-
const span = tracer.startSpan("solana.trackTransaction", {},
|
|
417
|
+
const tracer = opts.tracer ?? import_api3.trace.getTracer(tracerName);
|
|
418
|
+
const span = tracer.startSpan("solana.trackTransaction", {}, import_api3.context.active());
|
|
341
419
|
span.setAttribute("solana.tx.signature", opts.signature);
|
|
342
420
|
const start = Date.now();
|
|
343
|
-
const deadline = start + (opts.timeoutMs ??
|
|
421
|
+
const deadline = start + (opts.timeoutMs ?? DEFAULT_ENRICHMENT_TIMEOUT_MS);
|
|
344
422
|
const commitment = opts.commitment ?? "confirmed";
|
|
345
|
-
const basePoll = opts.pollIntervalMs ??
|
|
423
|
+
const basePoll = opts.pollIntervalMs ?? DEFAULT_ENRICHMENT_POLL_MS;
|
|
346
424
|
const resolver = opts.idlResolver ?? buildResolverFromIdls(opts.idls);
|
|
347
425
|
try {
|
|
348
|
-
const txDetails = await
|
|
426
|
+
const txDetails = await pollForTransaction(
|
|
427
|
+
(sig, pollOpts) => opts.connection.getTransaction(sig, pollOpts),
|
|
428
|
+
opts.signature,
|
|
429
|
+
commitment,
|
|
430
|
+
deadline,
|
|
431
|
+
basePoll
|
|
432
|
+
);
|
|
349
433
|
if (!txDetails) {
|
|
350
|
-
span
|
|
351
|
-
span.setAttribute("solana.tx.enrichment_ms", Date.now() - start);
|
|
434
|
+
finalizeSpan(span, null, start);
|
|
352
435
|
return;
|
|
353
436
|
}
|
|
354
|
-
span
|
|
355
|
-
span.setAttribute("solana.tx.slot", txDetails.slot);
|
|
356
|
-
const fee = txDetails.meta?.fee;
|
|
357
|
-
if (fee !== void 0) span.setAttribute("solana.tx.fee_lamports", fee);
|
|
358
|
-
const cuUsed = txDetails.meta?.computeUnitsConsumed;
|
|
359
|
-
if (cuUsed !== void 0 && cuUsed !== null) {
|
|
360
|
-
span.setAttribute("solana.tx.cu_used", Number(cuUsed));
|
|
361
|
-
span.setAttribute("solana.tx.cu_budget", 2e5);
|
|
362
|
-
span.setAttribute(
|
|
363
|
-
"solana.tx.cu_utilization",
|
|
364
|
-
parseFloat((Number(cuUsed) / 2e5 * 100).toFixed(1))
|
|
365
|
-
);
|
|
366
|
-
}
|
|
437
|
+
attachTxDetailsToSpan(span, txDetails);
|
|
367
438
|
const logs = txDetails.meta?.logMessages ?? [];
|
|
368
439
|
if (logs.length > 0) {
|
|
369
|
-
|
|
370
|
-
await (0, import_core2.enrichTree)(cpiTree, resolver);
|
|
371
|
-
for (const attr of (0, import_core2.flatAttributions)(cpiTree)) {
|
|
372
|
-
span.addEvent("cpi.invoke", {
|
|
373
|
-
"cpi.program": attr.programName ?? attr.programId,
|
|
374
|
-
"cpi.instruction": attr.instructionName ?? "unknown",
|
|
375
|
-
"cpi.depth": attr.depth,
|
|
376
|
-
"cpi.cu_consumed": attr.cuConsumed,
|
|
377
|
-
"cpi.cu_self": attr.cuSelf,
|
|
378
|
-
"cpi.percentage": parseFloat(attr.percentage.toFixed(2))
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
const root = cpiTree.roots[0];
|
|
382
|
-
if (root) {
|
|
383
|
-
if (root.programName) span.setAttribute("solana.tx.program", root.programName);
|
|
384
|
-
if (root.instructionName) span.setAttribute("solana.tx.instruction", root.instructionName);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
span.setAttribute("solana.tx.enrichment_ms", Date.now() - start);
|
|
388
|
-
if (txDetails.meta?.err) {
|
|
389
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
390
|
-
} else {
|
|
391
|
-
span.setStatus({ code: import_api2.SpanStatusCode.OK });
|
|
440
|
+
await attachParsedLogsToSpan(span, logs, resolver);
|
|
392
441
|
}
|
|
442
|
+
finalizeSpan(span, txDetails, start);
|
|
393
443
|
} catch (err) {
|
|
394
444
|
span.recordException(err instanceof Error ? err : new Error(String(err)));
|
|
395
445
|
span.setStatus({
|
|
396
|
-
code:
|
|
446
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
397
447
|
message: err instanceof Error ? err.message : String(err)
|
|
398
448
|
});
|
|
399
449
|
} finally {
|
|
@@ -401,27 +451,10 @@ async function trackSolanaTransaction(opts) {
|
|
|
401
451
|
}
|
|
402
452
|
}
|
|
403
453
|
function buildResolverFromIdls(idls) {
|
|
404
|
-
const resolver = new
|
|
454
|
+
const resolver = new import_core3.IdlResolver();
|
|
405
455
|
if (idls) resolver.registerMany(idls);
|
|
406
456
|
return resolver;
|
|
407
457
|
}
|
|
408
|
-
async function pollGetTransaction(connection, signature, commitment, deadline, basePollMs) {
|
|
409
|
-
let attempt = 0;
|
|
410
|
-
while (Date.now() < deadline) {
|
|
411
|
-
try {
|
|
412
|
-
const tx = await connection.getTransaction(signature, {
|
|
413
|
-
commitment,
|
|
414
|
-
maxSupportedTransactionVersion: 0
|
|
415
|
-
});
|
|
416
|
-
if (tx) return tx;
|
|
417
|
-
} catch {
|
|
418
|
-
}
|
|
419
|
-
attempt++;
|
|
420
|
-
const waitMs = Math.min(basePollMs * Math.pow(1.5, attempt - 1), 2e3);
|
|
421
|
-
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
422
|
-
}
|
|
423
|
-
return null;
|
|
424
|
-
}
|
|
425
458
|
|
|
426
459
|
// src/index.ts
|
|
427
460
|
var InstrumentedConnection = class extends import_web3.Connection {
|
|
@@ -438,7 +471,9 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
438
471
|
enrichmentTimeoutMs,
|
|
439
472
|
enrichmentPollIntervalMs,
|
|
440
473
|
disableAutoSpan,
|
|
441
|
-
commitment
|
|
474
|
+
// Note: commitment is intentionally NOT destructured out. It must
|
|
475
|
+
// pass through to super() via connectionConfig so the parent
|
|
476
|
+
// Connection uses it for RPC calls (preflight, blockhash, etc.).
|
|
442
477
|
...connectionConfig
|
|
443
478
|
} = config2 ?? {};
|
|
444
479
|
super(endpoint, connectionConfig);
|
|
@@ -447,17 +482,17 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
447
482
|
idlRpcEndpoint,
|
|
448
483
|
skipIdlResolution,
|
|
449
484
|
allowOnChainIdlFetch,
|
|
450
|
-
enrichmentTimeoutMs: enrichmentTimeoutMs ??
|
|
451
|
-
enrichmentPollIntervalMs: enrichmentPollIntervalMs ??
|
|
485
|
+
enrichmentTimeoutMs: enrichmentTimeoutMs ?? DEFAULT_ENRICHMENT_TIMEOUT_MS,
|
|
486
|
+
enrichmentPollIntervalMs: enrichmentPollIntervalMs ?? DEFAULT_ENRICHMENT_POLL_MS,
|
|
452
487
|
disableAutoSpan,
|
|
453
|
-
commitment
|
|
488
|
+
commitment: config2?.commitment
|
|
454
489
|
};
|
|
455
|
-
this.idlResolver = new
|
|
490
|
+
this.idlResolver = new import_core4.IdlResolver({
|
|
456
491
|
rpcEndpoint: idlRpcEndpoint ?? endpoint,
|
|
457
492
|
allowOnChainFetch: allowOnChainIdlFetch ?? false
|
|
458
493
|
});
|
|
459
494
|
if (idls) this.idlResolver.registerMany(idls);
|
|
460
|
-
this.tracer = tracer ??
|
|
495
|
+
this.tracer = tracer ?? import_api4.trace.getTracer("@thesight/sdk");
|
|
461
496
|
}
|
|
462
497
|
/**
|
|
463
498
|
* Register an IDL for a single program. Convenience forwarder for the
|
|
@@ -489,7 +524,7 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
489
524
|
if (this.sightConfig.disableAutoSpan) {
|
|
490
525
|
return super.sendRawTransaction(rawTransaction, options);
|
|
491
526
|
}
|
|
492
|
-
const span = this.tracer.startSpan("solana.sendRawTransaction", {},
|
|
527
|
+
const span = this.tracer.startSpan("solana.sendRawTransaction", {}, import_api4.context.active());
|
|
493
528
|
const submitStart = Date.now();
|
|
494
529
|
let signature;
|
|
495
530
|
try {
|
|
@@ -500,7 +535,7 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
500
535
|
span.setAttribute("solana.tx.status", "failed");
|
|
501
536
|
span.recordException(err instanceof Error ? err : new Error(String(err)));
|
|
502
537
|
span.setStatus({
|
|
503
|
-
code:
|
|
538
|
+
code: import_api4.SpanStatusCode.ERROR,
|
|
504
539
|
message: err instanceof Error ? err.message : String(err)
|
|
505
540
|
});
|
|
506
541
|
span.end();
|
|
@@ -524,30 +559,30 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
524
559
|
*/
|
|
525
560
|
async enrichSpanInBackground(span, signature, submitStart) {
|
|
526
561
|
const enrichStart = Date.now();
|
|
527
|
-
const deadline = enrichStart + (this.sightConfig.enrichmentTimeoutMs ??
|
|
562
|
+
const deadline = enrichStart + (this.sightConfig.enrichmentTimeoutMs ?? DEFAULT_ENRICHMENT_TIMEOUT_MS);
|
|
528
563
|
const commitment = this.sightConfig.commitment ?? "confirmed";
|
|
529
|
-
const basePollMs = this.sightConfig.enrichmentPollIntervalMs ??
|
|
564
|
+
const basePollMs = this.sightConfig.enrichmentPollIntervalMs ?? DEFAULT_ENRICHMENT_POLL_MS;
|
|
530
565
|
try {
|
|
531
|
-
const txDetails = await
|
|
566
|
+
const txDetails = await pollForTransaction(
|
|
567
|
+
(sig, opts) => super.getTransaction(sig, opts),
|
|
568
|
+
signature,
|
|
569
|
+
commitment,
|
|
570
|
+
deadline,
|
|
571
|
+
basePollMs
|
|
572
|
+
);
|
|
532
573
|
if (!txDetails) {
|
|
533
|
-
span
|
|
534
|
-
span.setAttribute("solana.tx.enrichment_ms", Date.now() - submitStart);
|
|
574
|
+
finalizeSpan(span, null, submitStart);
|
|
535
575
|
span.end();
|
|
536
576
|
return;
|
|
537
577
|
}
|
|
538
|
-
|
|
578
|
+
attachTxDetailsToSpan(span, txDetails);
|
|
539
579
|
if (!this.sightConfig.skipIdlResolution) {
|
|
540
580
|
const logs = txDetails.meta?.logMessages ?? [];
|
|
541
581
|
if (logs.length > 0) {
|
|
542
|
-
await
|
|
582
|
+
await attachParsedLogsToSpan(span, logs, this.idlResolver);
|
|
543
583
|
}
|
|
544
584
|
}
|
|
545
|
-
span
|
|
546
|
-
if (txDetails.meta?.err) {
|
|
547
|
-
span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
|
|
548
|
-
} else {
|
|
549
|
-
span.setStatus({ code: import_api3.SpanStatusCode.OK });
|
|
550
|
-
}
|
|
585
|
+
finalizeSpan(span, txDetails, submitStart);
|
|
551
586
|
} catch (err) {
|
|
552
587
|
span.recordException(err instanceof Error ? err : new Error(String(err)));
|
|
553
588
|
span.setAttribute(
|
|
@@ -558,75 +593,7 @@ var InstrumentedConnection = class extends import_web3.Connection {
|
|
|
558
593
|
span.end();
|
|
559
594
|
}
|
|
560
595
|
}
|
|
561
|
-
/**
|
|
562
|
-
* Poll `getTransaction(signature)` until either the on-chain record is
|
|
563
|
-
* returned or the deadline passes. Exponential backoff (1.5x) capped at
|
|
564
|
-
* 2 seconds to balance responsiveness against RPC load.
|
|
565
|
-
*/
|
|
566
|
-
async pollForTransaction(signature, commitment, deadline, basePollMs) {
|
|
567
|
-
let attempt = 0;
|
|
568
|
-
while (Date.now() < deadline) {
|
|
569
|
-
try {
|
|
570
|
-
const tx = await super.getTransaction(signature, {
|
|
571
|
-
commitment,
|
|
572
|
-
maxSupportedTransactionVersion: 0
|
|
573
|
-
});
|
|
574
|
-
if (tx) return tx;
|
|
575
|
-
} catch {
|
|
576
|
-
}
|
|
577
|
-
attempt++;
|
|
578
|
-
const waitMs = Math.min(basePollMs * Math.pow(1.5, attempt - 1), 2e3);
|
|
579
|
-
await sleep(waitMs);
|
|
580
|
-
}
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
/** Attach the flat fields (slot, fee, CU, status) from a tx response to a span. */
|
|
584
|
-
attachTxDetailsToSpan(span, txDetails) {
|
|
585
|
-
span.setAttribute("solana.tx.status", txDetails.meta?.err ? "failed" : "confirmed");
|
|
586
|
-
span.setAttribute("solana.tx.slot", txDetails.slot);
|
|
587
|
-
const fee = txDetails.meta?.fee;
|
|
588
|
-
if (fee !== void 0) span.setAttribute("solana.tx.fee_lamports", fee);
|
|
589
|
-
const cuUsed = txDetails.meta?.computeUnitsConsumed;
|
|
590
|
-
if (cuUsed !== void 0 && cuUsed !== null) {
|
|
591
|
-
span.setAttribute("solana.tx.cu_used", Number(cuUsed));
|
|
592
|
-
span.setAttribute("solana.tx.cu_budget", 2e5);
|
|
593
|
-
span.setAttribute(
|
|
594
|
-
"solana.tx.cu_utilization",
|
|
595
|
-
parseFloat((Number(cuUsed) / 2e5 * 100).toFixed(1))
|
|
596
|
-
);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* Parse program logs into a CPI tree, enrich with registered IDLs, and
|
|
601
|
-
* emit one `cpi.invoke` event per invocation onto the span. Root
|
|
602
|
-
* program/instruction names are copied onto span attributes so dashboards
|
|
603
|
-
* can filter by them without walking events.
|
|
604
|
-
*/
|
|
605
|
-
async attachParsedLogsToSpan(span, logs) {
|
|
606
|
-
const { cpiTree } = (0, import_core3.parseLogs)({ logs });
|
|
607
|
-
await (0, import_core3.enrichTree)(cpiTree, this.idlResolver);
|
|
608
|
-
const attributions = (0, import_core3.flatAttributions)(cpiTree);
|
|
609
|
-
for (const attr of attributions) {
|
|
610
|
-
span.addEvent("cpi.invoke", {
|
|
611
|
-
"cpi.program": attr.programName ?? attr.programId,
|
|
612
|
-
"cpi.instruction": attr.instructionName ?? "unknown",
|
|
613
|
-
"cpi.depth": attr.depth,
|
|
614
|
-
"cpi.cu_consumed": attr.cuConsumed,
|
|
615
|
-
"cpi.cu_self": attr.cuSelf,
|
|
616
|
-
"cpi.percentage": parseFloat(attr.percentage.toFixed(2))
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
const root = cpiTree.roots[0];
|
|
620
|
-
if (root) {
|
|
621
|
-
if (root.programName) span.setAttribute("solana.tx.program", root.programName);
|
|
622
|
-
if (root.instructionName) span.setAttribute("solana.tx.instruction", root.instructionName);
|
|
623
|
-
}
|
|
624
|
-
return cpiTree;
|
|
625
|
-
}
|
|
626
596
|
};
|
|
627
|
-
function sleep(ms) {
|
|
628
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
629
|
-
}
|
|
630
597
|
// Annotate the CommonJS export names for ESM import in node:
|
|
631
598
|
0 && (module.exports = {
|
|
632
599
|
IdlResolver,
|