@hashspan/core 0.1.0 → 0.3.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/README.md +16 -6
- package/dist/index.cjs +26 -11
- package/dist/index.d.cts +21 -3
- package/dist/index.d.mts +21 -3
- package/dist/index.mjs +26 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Transaction lifecycle tracing for the on-chain actions of AI agents, built on Op
|
|
|
9
9
|
revert reason. It carries a span link to its `send` span.
|
|
10
10
|
|
|
11
11
|
The core is library-agnostic and read-only: it never signs, sends or fetches anything. Adapters such as
|
|
12
|
-
[`@hashspan/viem`](https://github.com/selimaytac/hashspan/tree/
|
|
12
|
+
[`@hashspan/viem`](https://github.com/selimaytac/hashspan/tree/@hashspan/core@0.3.0/packages/viem) call it for you. Use the core directly to instrument any other send path.
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
@@ -17,7 +17,9 @@ The core is library-agnostic and read-only: it never signs, sends or fetches any
|
|
|
17
17
|
npm install @hashspan/core @opentelemetry/api
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
`@opentelemetry/api` is the only peer dependency. Bring your own OpenTelemetry SDK and exporter.
|
|
20
|
+
`@opentelemetry/api` is the only peer dependency. Bring your own OpenTelemetry SDK and exporter. Requires Node.js 22.3
|
|
21
|
+
or later; in other runtimes, `hashed` address mode needs a custom `hash` function and otherwise records no addresses,
|
|
22
|
+
with a `diag` warning.
|
|
21
23
|
|
|
22
24
|
## Usage
|
|
23
25
|
|
|
@@ -55,9 +57,13 @@ confirm.end({
|
|
|
55
57
|
share one confirm span. A receipt from any of them ends it; a timeout or failure ends it once every caller gave up.
|
|
56
58
|
End every handle you start, since an open handle keeps the shared span open.
|
|
57
59
|
|
|
60
|
+
`send.fail(error, endTime, { errorType })` records a library's machine-readable error code as `error.type` instead
|
|
61
|
+
of the error's class name, if it is a short identifier (`[A-Za-z0-9_.-]`, at most 64 characters); `exception.type`
|
|
62
|
+
stays the class name.
|
|
63
|
+
|
|
58
64
|
Both calls accept an explicit parent `Context` as a second argument. An integration that learns about a call only
|
|
59
65
|
after it started can record it after the fact: pass `startTime` in the input and the end time as the last argument
|
|
60
|
-
of the handle method, e.g. `send.end(hash, endTime)` ([ADR 0009](https://github.com/selimaytac/hashspan/blob/
|
|
66
|
+
of the handle method, e.g. `send.end(hash, endTime)` ([ADR 0009](https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.3.0/docs/adr/0009-telemetry-off-the-call-path.md)). Every method is safe to call: failures inside
|
|
61
67
|
the instrumentation are reported through `diag` and never thrown into your code.
|
|
62
68
|
|
|
63
69
|
## Options
|
|
@@ -66,9 +72,10 @@ the instrumentation are reported through `diag` and never thrown into your code.
|
|
|
66
72
|
|---|---|---|
|
|
67
73
|
| `tracerProvider` | global provider | Tracer provider to use |
|
|
68
74
|
| `address` | `'raw'` | `'raw'`, `'hashed'`, `'off'`, or `{ mode: 'hashed', hash: (address) => string }` |
|
|
69
|
-
| `errorMessages` | `'off'` | What failed spans record about the error: `'off'` (type only), `'sanitized'` (first line, addresses per `address` mode, calldata removed; in `hashed` and `off` mode any hex longer than an address) or `'raw'` (full message and stack trace) |
|
|
75
|
+
| `errorMessages` | `'off'` | What failed spans record about the error: `'off'` (type only), `'sanitized'` (first line, addresses per `address` mode, calldata removed; in `hashed` and `off` mode any hex longer than an address) or `'raw'` (full message and stack trace). `'raw'` can record RPC URLs that include API keys, as some libraries put the request URL in the message; `'sanitized'` keeps only the first line (viem puts the URL on a later line), which is best effort. See [ADR 0006](https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.3.0/docs/adr/0006-error-privacy.md) |
|
|
70
76
|
| `recordFunctionArguments` | `false` | Record `functionArguments` as a JSON array in `blockchain.contract.function.arguments`: bigints as decimal strings, addresses per `address` mode (longer hex values become `<hex>` in `hashed` and `off` mode), at most 4096 characters. Reads only own enumerable data properties: `toJSON()` and getters are never called, so a `Date` records as `{}`; a Proxy's traps still run |
|
|
71
|
-
| `agent` | none |
|
|
77
|
+
| `agent` | none | Agent `{ id, name }`; a field set here always wins, unset fields come from the Baggage entries `gen_ai.agent.id` / `gen_ai.agent.name` |
|
|
78
|
+
| `agentFromBaggage` | `true` | Read agent identity fields that `agent` leaves unset from Baggage; set to `false` in services that accept requests from outside their trust boundary |
|
|
72
79
|
| `redact` | none | `(attributes) => attributes`, runs last on every attribute set, including exception event attributes; if it throws, only non-sensitive identifiers are kept |
|
|
73
80
|
| `linkTtlMs` | `600000` | How long a sent transaction can be linked from its confirmation |
|
|
74
81
|
| `maxTrackedTransactions` | `10000` | Upper bound on transactions kept for linking |
|
|
@@ -79,7 +86,7 @@ Chain id, transaction hash, sender/recipient (per `address` mode), value, nonce,
|
|
|
79
86
|
on confirmation, status, block number, gas used, effective gas price, L1 fee, total fee and revert reason. Decoded
|
|
80
87
|
call arguments are recorded only with `recordFunctionArguments`, and error messages only with `errorMessages`.
|
|
81
88
|
Attribute definitions:
|
|
82
|
-
[docs/semconv.md](https://github.com/selimaytac/hashspan/blob/
|
|
89
|
+
[docs/semconv.md](https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.3.0/docs/semconv.md).
|
|
83
90
|
|
|
84
91
|
## Privacy notes
|
|
85
92
|
|
|
@@ -92,6 +99,9 @@ Attribute definitions:
|
|
|
92
99
|
party APIs. Put only identifiers there that may leave your system, such as an opaque agent id. For identifiers
|
|
93
100
|
that must stay internal, use the tracker's static `agent` option instead, which is recorded on spans but never
|
|
94
101
|
propagated, or strip the entries before outbound calls.
|
|
102
|
+
- **Inbound Baggage can claim an identity.** A caller can send Baggage entries with any agent id. A field set in the
|
|
103
|
+
`agent` option cannot be overridden that way; to ignore identity from Baggage entirely, set `agentFromBaggage: false`
|
|
104
|
+
([ADR 0011](https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.3.0/docs/adr/0011-agent-identity-precedence.md)).
|
|
95
105
|
- The redaction hook (`redact`) runs last on every attribute set and on exception attributes; use it for anything
|
|
96
106
|
else your policy forbids.
|
|
97
107
|
|
package/dist/index.cjs
CHANGED
|
@@ -3,11 +3,14 @@ let _opentelemetry_api = require("@opentelemetry/api");
|
|
|
3
3
|
//#region src/agent.ts
|
|
4
4
|
const ATTR_GEN_AI_AGENT_ID = "gen_ai.agent.id";
|
|
5
5
|
const ATTR_GEN_AI_AGENT_NAME = "gen_ai.agent.name";
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Agent identity as GenAI attributes. A field set in the static identity always wins; Baggage, which a remote caller
|
|
8
|
+
* can set, only fills fields it leaves unset, and is not read at all with `fromBaggage` false (docs/adr/0011).
|
|
9
|
+
*/
|
|
10
|
+
function agentAttributes(ctx, identity, fromBaggage = true) {
|
|
11
|
+
const baggage = fromBaggage ? _opentelemetry_api.propagation.getBaggage(ctx) : void 0;
|
|
12
|
+
const id = identity?.id ?? baggage?.getEntry("gen_ai.agent.id")?.value;
|
|
13
|
+
const name = identity?.name ?? baggage?.getEntry("gen_ai.agent.name")?.value;
|
|
11
14
|
const attributes = {};
|
|
12
15
|
if (id !== void 0) attributes[ATTR_GEN_AI_AGENT_ID] = id;
|
|
13
16
|
if (name !== void 0) attributes[ATTR_GEN_AI_AGENT_NAME] = name;
|
|
@@ -299,7 +302,7 @@ function resolveErrorMessageMode(mode) {
|
|
|
299
302
|
}
|
|
300
303
|
//#endregion
|
|
301
304
|
//#region src/version.ts
|
|
302
|
-
const VERSION = "0.
|
|
305
|
+
const VERSION = "0.3.0";
|
|
303
306
|
//#endregion
|
|
304
307
|
//#region src/tracker.ts
|
|
305
308
|
const INSTRUMENTATION_NAME = "@hashspan/core";
|
|
@@ -354,6 +357,15 @@ function toInt(value) {
|
|
|
354
357
|
function errorType(error) {
|
|
355
358
|
return error instanceof Error && error.name ? error.name : ERROR_TYPE_VALUE_OTHER;
|
|
356
359
|
}
|
|
360
|
+
const ERROR_TYPE_OVERRIDE = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
361
|
+
/** The `error.type` for a failure: an adapter's override when it is a short identifier, else the class name. */
|
|
362
|
+
function reportedErrorType(error, options) {
|
|
363
|
+
const override = options?.errorType;
|
|
364
|
+
if (override === void 0) return errorType(error);
|
|
365
|
+
if (typeof override === "string" && ERROR_TYPE_OVERRIDE.test(override)) return override;
|
|
366
|
+
_opentelemetry_api.diag.debug("hashspan: ignoring an error type that is not a short identifier");
|
|
367
|
+
return errorType(error);
|
|
368
|
+
}
|
|
357
369
|
function createTxTracker(options = {}) {
|
|
358
370
|
const links = new LinkStore({
|
|
359
371
|
ttlMs: options.linkTtlMs ?? DEFAULT_LINK_TTL_MS,
|
|
@@ -403,12 +415,15 @@ function createTxTracker(options = {}) {
|
|
|
403
415
|
if (error instanceof Error && error.stack) attributes[ATTR_EXCEPTION_STACKTRACE] = error.stack;
|
|
404
416
|
return attributes;
|
|
405
417
|
};
|
|
406
|
-
/**
|
|
407
|
-
|
|
418
|
+
/**
|
|
419
|
+
* Error names are free text too: they follow the address mode and pass through the redaction hook.
|
|
420
|
+
* `exceptionName` is the class name for `exception.type` when `errorName` is an adapter's error type.
|
|
421
|
+
*/
|
|
422
|
+
const markError = (span, errorName, error, exceptionName = errorName) => {
|
|
408
423
|
const type = formatAddressesIn(errorName, formatAddress);
|
|
409
424
|
let message;
|
|
410
425
|
if (error !== void 0) {
|
|
411
|
-
const exception = redact(exceptionAttributes(
|
|
426
|
+
const exception = redact(exceptionAttributes(formatAddressesIn(exceptionName, formatAddress), error));
|
|
412
427
|
span.addEvent(EXCEPTION_EVENT, exception);
|
|
413
428
|
const recorded = exception[ATTR_EXCEPTION_MESSAGE];
|
|
414
429
|
if (typeof recorded === "string") message = recorded;
|
|
@@ -443,7 +458,7 @@ function createTxTracker(options = {}) {
|
|
|
443
458
|
[ATTR_BLOCKCHAIN_SYSTEM]: "evm",
|
|
444
459
|
[ATTR_BLOCKCHAIN_CHAIN_ID]: chainId,
|
|
445
460
|
[ATTR_BLOCKCHAIN_OPERATION_NAME]: operation,
|
|
446
|
-
...agentAttributes(ctx, options.agent)
|
|
461
|
+
...agentAttributes(ctx, options.agent, options.agentFromBaggage !== false)
|
|
447
462
|
});
|
|
448
463
|
const startSend = (input, parentCtx) => {
|
|
449
464
|
const parent = parentCtx ?? _opentelemetry_api.context.active();
|
|
@@ -473,7 +488,7 @@ function createTxTracker(options = {}) {
|
|
|
473
488
|
});
|
|
474
489
|
span.setAttributes(redact({ [ATTR_BLOCKCHAIN_TX_HASH]: hash }));
|
|
475
490
|
}, endTime),
|
|
476
|
-
fail: (error, endTime) => finish("record send failure", () => markError(span,
|
|
491
|
+
fail: (error, endTime, options) => finish("record send failure", () => markError(span, reportedErrorType(error, options), error, errorType(error)), endTime)
|
|
477
492
|
};
|
|
478
493
|
};
|
|
479
494
|
const receiptAttributes = (receipt) => {
|
package/dist/index.d.cts
CHANGED
|
@@ -38,8 +38,17 @@ interface TxTrackerOptions {
|
|
|
38
38
|
* text; addresses in them follow the address mode and the redaction hook runs on them.
|
|
39
39
|
*/
|
|
40
40
|
recordFunctionArguments?: boolean | undefined;
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Agent identity. A field set here always wins; fields left unset are taken from the Baggage entries
|
|
43
|
+
* `gen_ai.agent.id` / `gen_ai.agent.name` unless `agentFromBaggage` is false (docs/adr/0011).
|
|
44
|
+
*/
|
|
42
45
|
agent?: AgentIdentity | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Read agent identity fields that `agent` leaves unset from Baggage. Default: true. Baggage travels with requests
|
|
48
|
+
* between services, so a remote caller can set it; services that accept requests from outside their trust boundary
|
|
49
|
+
* should set this to false.
|
|
50
|
+
*/
|
|
51
|
+
agentFromBaggage?: boolean | undefined;
|
|
43
52
|
/**
|
|
44
53
|
* Runs last on every attribute set and returns the attributes to record.
|
|
45
54
|
* If it throws, only non-sensitive identifiers (system, chain id, operation, hash) are recorded.
|
|
@@ -73,7 +82,16 @@ interface SendHandle {
|
|
|
73
82
|
/** Ends the send span successfully once the transaction hash is known; `endTime` defaults to now. */
|
|
74
83
|
end(hash: string, endTime?: TimeInput): void;
|
|
75
84
|
/** Ends the send span with an error (signing, simulation or broadcast failure); `endTime` defaults to now. */
|
|
76
|
-
fail(error: unknown, endTime?: TimeInput): void;
|
|
85
|
+
fail(error: unknown, endTime?: TimeInput, options?: FailOptions): void;
|
|
86
|
+
}
|
|
87
|
+
interface FailOptions {
|
|
88
|
+
/**
|
|
89
|
+
* `error.type` to record instead of the error's class name, for adapters whose library reports a stable,
|
|
90
|
+
* machine-readable error code (for example a wallet API's error type). Recorded only if it matches
|
|
91
|
+
* `/^[A-Za-z0-9_.-]{1,64}$/`, so that the attribute keeps a bounded set of values; otherwise the class name is
|
|
92
|
+
* recorded. `exception.type` is always the class name.
|
|
93
|
+
*/
|
|
94
|
+
errorType?: string | undefined;
|
|
77
95
|
}
|
|
78
96
|
interface ConfirmInput {
|
|
79
97
|
chainId: number;
|
|
@@ -187,4 +205,4 @@ export declare function createTxTracker(options?: TxTrackerOptions): TxTracker;
|
|
|
187
205
|
//#region src/version.d.ts
|
|
188
206
|
export declare const VERSION: string;
|
|
189
207
|
//#endregion
|
|
190
|
-
export type { AddressMode, AddressOptions, AgentIdentity, ConfirmHandle, ConfirmInput, ErrorMessageMode, ReceiptLike, ReplacementReason, SendHandle, SendInput, TxTracker, TxTrackerOptions };
|
|
208
|
+
export type { AddressMode, AddressOptions, AgentIdentity, ConfirmHandle, ConfirmInput, ErrorMessageMode, FailOptions, ReceiptLike, ReplacementReason, SendHandle, SendInput, TxTracker, TxTrackerOptions };
|
package/dist/index.d.mts
CHANGED
|
@@ -38,8 +38,17 @@ interface TxTrackerOptions {
|
|
|
38
38
|
* text; addresses in them follow the address mode and the redaction hook runs on them.
|
|
39
39
|
*/
|
|
40
40
|
recordFunctionArguments?: boolean | undefined;
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Agent identity. A field set here always wins; fields left unset are taken from the Baggage entries
|
|
43
|
+
* `gen_ai.agent.id` / `gen_ai.agent.name` unless `agentFromBaggage` is false (docs/adr/0011).
|
|
44
|
+
*/
|
|
42
45
|
agent?: AgentIdentity | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Read agent identity fields that `agent` leaves unset from Baggage. Default: true. Baggage travels with requests
|
|
48
|
+
* between services, so a remote caller can set it; services that accept requests from outside their trust boundary
|
|
49
|
+
* should set this to false.
|
|
50
|
+
*/
|
|
51
|
+
agentFromBaggage?: boolean | undefined;
|
|
43
52
|
/**
|
|
44
53
|
* Runs last on every attribute set and returns the attributes to record.
|
|
45
54
|
* If it throws, only non-sensitive identifiers (system, chain id, operation, hash) are recorded.
|
|
@@ -73,7 +82,16 @@ interface SendHandle {
|
|
|
73
82
|
/** Ends the send span successfully once the transaction hash is known; `endTime` defaults to now. */
|
|
74
83
|
end(hash: string, endTime?: TimeInput): void;
|
|
75
84
|
/** Ends the send span with an error (signing, simulation or broadcast failure); `endTime` defaults to now. */
|
|
76
|
-
fail(error: unknown, endTime?: TimeInput): void;
|
|
85
|
+
fail(error: unknown, endTime?: TimeInput, options?: FailOptions): void;
|
|
86
|
+
}
|
|
87
|
+
interface FailOptions {
|
|
88
|
+
/**
|
|
89
|
+
* `error.type` to record instead of the error's class name, for adapters whose library reports a stable,
|
|
90
|
+
* machine-readable error code (for example a wallet API's error type). Recorded only if it matches
|
|
91
|
+
* `/^[A-Za-z0-9_.-]{1,64}$/`, so that the attribute keeps a bounded set of values; otherwise the class name is
|
|
92
|
+
* recorded. `exception.type` is always the class name.
|
|
93
|
+
*/
|
|
94
|
+
errorType?: string | undefined;
|
|
77
95
|
}
|
|
78
96
|
interface ConfirmInput {
|
|
79
97
|
chainId: number;
|
|
@@ -187,4 +205,4 @@ export declare function createTxTracker(options?: TxTrackerOptions): TxTracker;
|
|
|
187
205
|
//#region src/version.d.ts
|
|
188
206
|
export declare const VERSION: string;
|
|
189
207
|
//#endregion
|
|
190
|
-
export type { AddressMode, AddressOptions, AgentIdentity, ConfirmHandle, ConfirmInput, ErrorMessageMode, ReceiptLike, ReplacementReason, SendHandle, SendInput, TxTracker, TxTrackerOptions };
|
|
208
|
+
export type { AddressMode, AddressOptions, AgentIdentity, ConfirmHandle, ConfirmInput, ErrorMessageMode, FailOptions, ReceiptLike, ReplacementReason, SendHandle, SendInput, TxTracker, TxTrackerOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -2,11 +2,14 @@ import { SpanKind, SpanStatusCode, context, diag, propagation, trace } from "@op
|
|
|
2
2
|
//#region src/agent.ts
|
|
3
3
|
const ATTR_GEN_AI_AGENT_ID = "gen_ai.agent.id";
|
|
4
4
|
const ATTR_GEN_AI_AGENT_NAME = "gen_ai.agent.name";
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Agent identity as GenAI attributes. A field set in the static identity always wins; Baggage, which a remote caller
|
|
7
|
+
* can set, only fills fields it leaves unset, and is not read at all with `fromBaggage` false (docs/adr/0011).
|
|
8
|
+
*/
|
|
9
|
+
function agentAttributes(ctx, identity, fromBaggage = true) {
|
|
10
|
+
const baggage = fromBaggage ? propagation.getBaggage(ctx) : void 0;
|
|
11
|
+
const id = identity?.id ?? baggage?.getEntry("gen_ai.agent.id")?.value;
|
|
12
|
+
const name = identity?.name ?? baggage?.getEntry("gen_ai.agent.name")?.value;
|
|
10
13
|
const attributes = {};
|
|
11
14
|
if (id !== void 0) attributes[ATTR_GEN_AI_AGENT_ID] = id;
|
|
12
15
|
if (name !== void 0) attributes[ATTR_GEN_AI_AGENT_NAME] = name;
|
|
@@ -298,7 +301,7 @@ function resolveErrorMessageMode(mode) {
|
|
|
298
301
|
}
|
|
299
302
|
//#endregion
|
|
300
303
|
//#region src/version.ts
|
|
301
|
-
const VERSION = "0.
|
|
304
|
+
const VERSION = "0.3.0";
|
|
302
305
|
//#endregion
|
|
303
306
|
//#region src/tracker.ts
|
|
304
307
|
const INSTRUMENTATION_NAME = "@hashspan/core";
|
|
@@ -353,6 +356,15 @@ function toInt(value) {
|
|
|
353
356
|
function errorType(error) {
|
|
354
357
|
return error instanceof Error && error.name ? error.name : ERROR_TYPE_VALUE_OTHER;
|
|
355
358
|
}
|
|
359
|
+
const ERROR_TYPE_OVERRIDE = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
360
|
+
/** The `error.type` for a failure: an adapter's override when it is a short identifier, else the class name. */
|
|
361
|
+
function reportedErrorType(error, options) {
|
|
362
|
+
const override = options?.errorType;
|
|
363
|
+
if (override === void 0) return errorType(error);
|
|
364
|
+
if (typeof override === "string" && ERROR_TYPE_OVERRIDE.test(override)) return override;
|
|
365
|
+
diag.debug("hashspan: ignoring an error type that is not a short identifier");
|
|
366
|
+
return errorType(error);
|
|
367
|
+
}
|
|
356
368
|
function createTxTracker(options = {}) {
|
|
357
369
|
const links = new LinkStore({
|
|
358
370
|
ttlMs: options.linkTtlMs ?? DEFAULT_LINK_TTL_MS,
|
|
@@ -402,12 +414,15 @@ function createTxTracker(options = {}) {
|
|
|
402
414
|
if (error instanceof Error && error.stack) attributes[ATTR_EXCEPTION_STACKTRACE] = error.stack;
|
|
403
415
|
return attributes;
|
|
404
416
|
};
|
|
405
|
-
/**
|
|
406
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Error names are free text too: they follow the address mode and pass through the redaction hook.
|
|
419
|
+
* `exceptionName` is the class name for `exception.type` when `errorName` is an adapter's error type.
|
|
420
|
+
*/
|
|
421
|
+
const markError = (span, errorName, error, exceptionName = errorName) => {
|
|
407
422
|
const type = formatAddressesIn(errorName, formatAddress);
|
|
408
423
|
let message;
|
|
409
424
|
if (error !== void 0) {
|
|
410
|
-
const exception = redact(exceptionAttributes(
|
|
425
|
+
const exception = redact(exceptionAttributes(formatAddressesIn(exceptionName, formatAddress), error));
|
|
411
426
|
span.addEvent(EXCEPTION_EVENT, exception);
|
|
412
427
|
const recorded = exception[ATTR_EXCEPTION_MESSAGE];
|
|
413
428
|
if (typeof recorded === "string") message = recorded;
|
|
@@ -442,7 +457,7 @@ function createTxTracker(options = {}) {
|
|
|
442
457
|
[ATTR_BLOCKCHAIN_SYSTEM]: "evm",
|
|
443
458
|
[ATTR_BLOCKCHAIN_CHAIN_ID]: chainId,
|
|
444
459
|
[ATTR_BLOCKCHAIN_OPERATION_NAME]: operation,
|
|
445
|
-
...agentAttributes(ctx, options.agent)
|
|
460
|
+
...agentAttributes(ctx, options.agent, options.agentFromBaggage !== false)
|
|
446
461
|
});
|
|
447
462
|
const startSend = (input, parentCtx) => {
|
|
448
463
|
const parent = parentCtx ?? context.active();
|
|
@@ -472,7 +487,7 @@ function createTxTracker(options = {}) {
|
|
|
472
487
|
});
|
|
473
488
|
span.setAttributes(redact({ [ATTR_BLOCKCHAIN_TX_HASH]: hash }));
|
|
474
489
|
}, endTime),
|
|
475
|
-
fail: (error, endTime) => finish("record send failure", () => markError(span,
|
|
490
|
+
fail: (error, endTime, options) => finish("record send failure", () => markError(span, reportedErrorType(error, options), error, errorType(error)), endTime)
|
|
476
491
|
};
|
|
477
492
|
};
|
|
478
493
|
const receiptAttributes = (receipt) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hashspan/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Transaction lifecycle tracing for on-chain actions of AI agents, built on OpenTelemetry.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Selim Aytac",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@opentelemetry/sdk-trace-node": "^2.11.0"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|
|
60
|
-
"node": ">=
|
|
60
|
+
"node": ">=22.3.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsdown",
|