@hashspan/core 0.8.0 → 0.9.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 +32 -17
- package/dist/index.cjs +305 -19
- package/dist/index.d.cts +174 -28
- package/dist/index.d.mts +174 -28
- package/dist/index.mjs +292 -20
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ const ATTR_GEN_AI_AGENT_NAME = "gen_ai.agent.name";
|
|
|
5
5
|
/**
|
|
6
6
|
* Agent identity as GenAI attributes. A field set in the static identity always wins; Baggage, which a remote caller
|
|
7
7
|
* can set, only fills fields it leaves unset, and is not read at all with `fromBaggage` false
|
|
8
|
-
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
8
|
+
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0011-agent-identity-precedence.md).
|
|
9
9
|
*/
|
|
10
10
|
function agentAttributes(ctx, identity, fromBaggage = true) {
|
|
11
11
|
const baggage = fromBaggage ? propagation.getBaggage(ctx) : void 0;
|
|
@@ -21,7 +21,7 @@ function agentAttributes(ctx, identity, fromBaggage = true) {
|
|
|
21
21
|
/**
|
|
22
22
|
* Attribute keys emitted by hashspan.
|
|
23
23
|
*
|
|
24
|
-
* Stability: development. See https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
24
|
+
* Stability: development. See https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/semconv.md for
|
|
25
25
|
* definitions and value types. These names are a public contract: changes follow the deprecation policy in AGENTS.md.
|
|
26
26
|
*/
|
|
27
27
|
const ATTR_BLOCKCHAIN_SYSTEM = "blockchain.system";
|
|
@@ -32,6 +32,12 @@ const ATTR_BLOCKCHAIN_TX_FROM = "blockchain.tx.from";
|
|
|
32
32
|
const ATTR_BLOCKCHAIN_TX_TO = "blockchain.tx.to";
|
|
33
33
|
const ATTR_BLOCKCHAIN_TX_VALUE = "blockchain.tx.value";
|
|
34
34
|
const ATTR_BLOCKCHAIN_TX_NONCE = "blockchain.tx.nonce";
|
|
35
|
+
/** Number of EIP-7702 authorizations a type 4 transaction carries. */
|
|
36
|
+
const ATTR_BLOCKCHAIN_TX_AUTHORIZATION_COUNT = "blockchain.tx.authorization.count";
|
|
37
|
+
/** Delegated contract address of each well-formed EIP-7702 authorization, per the address mode; at most 64. */
|
|
38
|
+
const ATTR_BLOCKCHAIN_TX_AUTHORIZATION_ADDRESSES = "blockchain.tx.authorization.addresses";
|
|
39
|
+
/** Chain id of each well-formed EIP-7702 authorization, aligned with the addresses; 0 means every chain. */
|
|
40
|
+
const ATTR_BLOCKCHAIN_TX_AUTHORIZATION_CHAIN_IDS = "blockchain.tx.authorization.chain_ids";
|
|
35
41
|
const ATTR_BLOCKCHAIN_TX_STATUS = "blockchain.tx.status";
|
|
36
42
|
const ATTR_BLOCKCHAIN_TX_GAS_USED = "blockchain.tx.gas.used";
|
|
37
43
|
const ATTR_BLOCKCHAIN_TX_EFFECTIVE_GAS_PRICE = "blockchain.tx.effective_gas_price";
|
|
@@ -45,12 +51,12 @@ const ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_NAME = "blockchain.contract.function.nam
|
|
|
45
51
|
const ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_SELECTOR = "blockchain.contract.function.selector";
|
|
46
52
|
/**
|
|
47
53
|
* Opt-in: decoded call arguments as a JSON array. See
|
|
48
|
-
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
54
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0004-privacy-defaults.md.
|
|
49
55
|
*/
|
|
50
56
|
const ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_ARGUMENTS = "blockchain.contract.function.arguments";
|
|
51
57
|
/**
|
|
52
58
|
* Payments settled on chain by a party other than the agent, e.g. an x402 facilitator. See
|
|
53
|
-
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
59
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0013-x402-payments.md.
|
|
54
60
|
*/
|
|
55
61
|
const ATTR_BLOCKCHAIN_PAYMENT_PROTOCOL = "blockchain.payment.protocol";
|
|
56
62
|
const ATTR_BLOCKCHAIN_PAYMENT_PAYER = "blockchain.payment.payer";
|
|
@@ -63,7 +69,7 @@ const ATTR_BLOCKCHAIN_PAYMENT_SETTLED_AMOUNT = "blockchain.payment.settled_amoun
|
|
|
63
69
|
/**
|
|
64
70
|
* Whether the settlement transaction's receipt carries the payment, as checked by the adapter; absent when no check
|
|
65
71
|
* was possible. See
|
|
66
|
-
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
72
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0017-x402-payment-verification.md.
|
|
67
73
|
*/
|
|
68
74
|
const ATTR_BLOCKCHAIN_PAYMENT_VERIFIED = "blockchain.payment.verified";
|
|
69
75
|
/** x402's own payment fields. */
|
|
@@ -71,7 +77,7 @@ const ATTR_X402_SCHEME = "x402.scheme";
|
|
|
71
77
|
const ATTR_X402_RESOURCE = "x402.resource";
|
|
72
78
|
/**
|
|
73
79
|
* User operations of ERC-4337 smart accounts. See
|
|
74
|
-
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
80
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0021-user-operations.md.
|
|
75
81
|
*/
|
|
76
82
|
const ATTR_BLOCKCHAIN_USER_OPERATION_HASH = "blockchain.user_operation.hash";
|
|
77
83
|
const ATTR_BLOCKCHAIN_USER_OPERATION_SENDER = "blockchain.user_operation.sender";
|
|
@@ -84,12 +90,31 @@ const ATTR_BLOCKCHAIN_USER_OPERATION_GAS_USED = "blockchain.user_operation.gas.u
|
|
|
84
90
|
const ATTR_BLOCKCHAIN_USER_OPERATION_GAS_COST = "blockchain.user_operation.gas.cost";
|
|
85
91
|
const ATTR_BLOCKCHAIN_USER_OPERATION_PAYMASTER = "blockchain.user_operation.paymaster";
|
|
86
92
|
/**
|
|
93
|
+
* The batch id the wallet returned, truncated after 256 characters. See
|
|
94
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0022-call-batches.md.
|
|
95
|
+
*/
|
|
96
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_ID = "blockchain.call_batch.id";
|
|
97
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_SENDER = "blockchain.call_batch.sender";
|
|
98
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_CALL_COUNT = "blockchain.call_batch.call_count";
|
|
99
|
+
/** The outcome of a batch from chain data: `success`, `reverted` or `partially_reverted`. */
|
|
100
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_STATUS = "blockchain.call_batch.status";
|
|
101
|
+
/** The EIP-5792 status code of the batch as the wallet reported it, e.g. 200 confirmed or 500 reverted; spans only. */
|
|
102
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_STATUS_CODE = "blockchain.call_batch.status_code";
|
|
103
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_ATOMIC = "blockchain.call_batch.atomic";
|
|
104
|
+
/** Hashes of the transactions whose receipts the wallet reported for the batch. */
|
|
105
|
+
const ATTR_BLOCKCHAIN_CALL_BATCH_TRANSACTION_HASHES = "blockchain.call_batch.transaction_hashes";
|
|
106
|
+
/**
|
|
87
107
|
* Metrics only: what a send, confirmation or fee sample is about. Recorded as `user_operation` on samples of user
|
|
88
|
-
* operations, and absent on those of transactions.
|
|
108
|
+
* operations and `call_batch` on those of call batches, and absent on those of transactions.
|
|
89
109
|
*/
|
|
90
110
|
const ATTR_BLOCKCHAIN_OPERATION_SUBJECT = "blockchain.operation.subject";
|
|
91
111
|
/** Values for {@link ATTR_BLOCKCHAIN_OPERATION_SUBJECT}. */
|
|
92
112
|
const BLOCKCHAIN_OPERATION_SUBJECT_VALUE_USER_OPERATION = "user_operation";
|
|
113
|
+
const BLOCKCHAIN_OPERATION_SUBJECT_VALUE_CALL_BATCH = "call_batch";
|
|
114
|
+
/** Values for {@link ATTR_BLOCKCHAIN_CALL_BATCH_STATUS}. */
|
|
115
|
+
const BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_SUCCESS = "success";
|
|
116
|
+
const BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_REVERTED = "reverted";
|
|
117
|
+
const BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_PARTIALLY_REVERTED = "partially_reverted";
|
|
93
118
|
/** Values for {@link ATTR_BLOCKCHAIN_SYSTEM}. */
|
|
94
119
|
const BLOCKCHAIN_SYSTEM_VALUE_EVM = "evm";
|
|
95
120
|
/** Values for {@link ATTR_BLOCKCHAIN_OPERATION_NAME}. */
|
|
@@ -108,7 +133,7 @@ const BLOCKCHAIN_TX_STATUS_VALUE_REVERTED = "reverted";
|
|
|
108
133
|
/**
|
|
109
134
|
* @deprecated No longer recorded: a confirm span that gave up waiting records `error.type` `timeout` and no
|
|
110
135
|
* `blockchain.tx.status`. The constant is removed in 1.0. See
|
|
111
|
-
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
136
|
+
* https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0016-timeout-is-an-observer-outcome.md.
|
|
112
137
|
*/
|
|
113
138
|
const BLOCKCHAIN_TX_STATUS_VALUE_TIMEOUT = "timeout";
|
|
114
139
|
const BLOCKCHAIN_TX_STATUS_VALUE_REPLACED = "replaced";
|
|
@@ -331,7 +356,7 @@ function resolveAddressFormatter(option) {
|
|
|
331
356
|
hash: void 0
|
|
332
357
|
};
|
|
333
358
|
switch (mode) {
|
|
334
|
-
case "raw": return formatter((address) => address, false);
|
|
359
|
+
case "raw": return formatter((address) => address.toLowerCase(), false);
|
|
335
360
|
case "off": return OFF_ADDRESS_FORMATTER;
|
|
336
361
|
case "hashed": {
|
|
337
362
|
const hashFn = hash ?? defaultHash();
|
|
@@ -355,6 +380,8 @@ const ADDRESS_LENGTH = 42;
|
|
|
355
380
|
*/
|
|
356
381
|
const MAX_HEX_LENGTH = 66;
|
|
357
382
|
const MAX_MESSAGE_LENGTH = 256;
|
|
383
|
+
/** A URL in free text: `scheme://` up to the next whitespace, quote or bracket; the bounded scheme keeps it linear. */
|
|
384
|
+
const URL_IN_TEXT = /\b[A-Za-z][A-Za-z0-9+.-]{0,31}:\/\/[^\s"'<>()[\]{}]+/g;
|
|
358
385
|
/**
|
|
359
386
|
* Rewrites every address in `text` with the address mode (`<address>` when it records none). In `off` and `hashed`
|
|
360
387
|
* mode, hex values longer than an address become `<hex>`, because they can embed one.
|
|
@@ -366,11 +393,12 @@ function formatAddressesIn(text, formatAddress) {
|
|
|
366
393
|
});
|
|
367
394
|
}
|
|
368
395
|
/**
|
|
369
|
-
* First line of an error message with
|
|
370
|
-
*
|
|
396
|
+
* First line of an error message with URLs cut to their origin (an RPC URL can carry an API key in its path or
|
|
397
|
+
* query), addresses per address mode and longer hex data (such as calldata) replaced by `<hex>`. Best effort: other
|
|
398
|
+
* free text is kept, so the redaction hook still runs on the result.
|
|
371
399
|
*/
|
|
372
400
|
function sanitizeErrorMessage(message, formatAddress) {
|
|
373
|
-
const sanitized = formatAddressesIn(message.split("\n", 1)[0]?.trim() ?? "", formatAddress).replace(HEX, (hex) => hex.length > MAX_HEX_LENGTH ? "<hex>" : hex);
|
|
401
|
+
const sanitized = formatAddressesIn((message.split("\n", 1)[0]?.trim() ?? "").replace(URL_IN_TEXT, (url) => hidesUserInfo(url) ? "<url>" : originOf(url) ?? "<url>"), formatAddress).replace(HEX, (hex) => hex.length > MAX_HEX_LENGTH ? "<hex>" : hex);
|
|
374
402
|
return sanitized.length > MAX_MESSAGE_LENGTH ? `${sanitized.slice(0, MAX_MESSAGE_LENGTH)}...` : sanitized;
|
|
375
403
|
}
|
|
376
404
|
const MAX_ARGUMENTS_LENGTH = 4096;
|
|
@@ -473,7 +501,16 @@ function paymentResourceOf(resource, mode) {
|
|
|
473
501
|
if (mode === "off" || hidesUserInfo(resource)) return void 0;
|
|
474
502
|
const recorded = mode === "path" ? sanitizeResource(resource) : originOf(resource);
|
|
475
503
|
if (recorded === void 0) return void 0;
|
|
476
|
-
return recorded
|
|
504
|
+
return cutAt(recorded, MAX_RESOURCE_LENGTH);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* `text` cut to `max` characters, followed by `...`. A hex value that the cut splits is dropped whole: the part left
|
|
508
|
+
* is shorter than an address, so the address mode, applied later, would no longer recognise it as one.
|
|
509
|
+
*/
|
|
510
|
+
function cutAt(text, max) {
|
|
511
|
+
if (text.length <= max) return text;
|
|
512
|
+
const head = text.slice(0, max);
|
|
513
|
+
return `${/^[0-9a-fA-F]/.test(text.slice(max)) ? head.replace(/0[xX][0-9a-fA-F]*$/, "") : head}...`;
|
|
477
514
|
}
|
|
478
515
|
/** Longest `x402.resource` recorded; the value comes from the server that asks for the payment. */
|
|
479
516
|
const MAX_RESOURCE_LENGTH = 512;
|
|
@@ -507,7 +544,7 @@ function sanitizeResource(resource) {
|
|
|
507
544
|
}
|
|
508
545
|
//#endregion
|
|
509
546
|
//#region src/version.ts
|
|
510
|
-
const VERSION = "0.
|
|
547
|
+
const VERSION = "0.9.0";
|
|
511
548
|
//#endregion
|
|
512
549
|
//#region src/tracker.ts
|
|
513
550
|
const INSTRUMENTATION_NAME = "@hashspan/core";
|
|
@@ -532,12 +569,20 @@ const NON_SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
|
532
569
|
ATTR_BLOCKCHAIN_PAYMENT_VERIFIED,
|
|
533
570
|
ATTR_BLOCKCHAIN_USER_OPERATION_HASH,
|
|
534
571
|
ATTR_BLOCKCHAIN_USER_OPERATION_SUCCESS,
|
|
572
|
+
ATTR_BLOCKCHAIN_CALL_BATCH_ID,
|
|
573
|
+
ATTR_BLOCKCHAIN_CALL_BATCH_STATUS,
|
|
535
574
|
ATTR_ERROR_TYPE,
|
|
536
575
|
ATTR_EXCEPTION_TYPE
|
|
537
576
|
]);
|
|
538
577
|
const TX_HASH = /^0x[0-9a-fA-F]{64}$/;
|
|
539
578
|
const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
540
579
|
const ZERO_ADDRESS = /^0x0{40}$/;
|
|
580
|
+
/** The value of an own data property of `target`; undefined for an accessor, so no getter of the caller runs. */
|
|
581
|
+
function ownValue(target, key) {
|
|
582
|
+
if (typeof target !== "object" || target === null) return void 0;
|
|
583
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
584
|
+
return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
|
|
585
|
+
}
|
|
541
586
|
/** A non-negative integer that fits in 256 bits. */
|
|
542
587
|
const AMOUNT = /^(0|[1-9][0-9]{0,77})$/;
|
|
543
588
|
/** A `0x` hex quantity of at most 256 bits, as JSON-RPC encodes integers. */
|
|
@@ -546,6 +591,18 @@ const MAX_UINT256 = 2n ** 256n - 1n;
|
|
|
546
591
|
const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
|
|
547
592
|
/** `error.type` of a wait that gave up: a confirmation or a payment whose outcome was never learned. */
|
|
548
593
|
const OBSERVER_TIMEOUT = "timeout";
|
|
594
|
+
/** `error.type` of a call batch that failed without being included (EIP-5792 status 400). */
|
|
595
|
+
const CALL_BATCH_FAILED = "failed";
|
|
596
|
+
/** A call batch id: `0x`-prefixed hex of at most 8194 characters, the bound EIP-5792 sets. */
|
|
597
|
+
const CALL_BATCH_ID = /^0x[0-9a-fA-F]{1,8192}$/;
|
|
598
|
+
/** Longest call batch id recorded as an attribute. */
|
|
599
|
+
const MAX_CALL_BATCH_ID_ATTRIBUTE_LENGTH = 256;
|
|
600
|
+
/** Most transaction hashes recorded for one call batch. */
|
|
601
|
+
const MAX_CALL_BATCH_TRANSACTION_HASHES = 64;
|
|
602
|
+
/** Most EIP-7702 authorizations listed on a send span; the count covers all of them. */
|
|
603
|
+
const MAX_AUTHORIZATIONS = 64;
|
|
604
|
+
/** EIP-5792 status code of a batch that is still pending. */
|
|
605
|
+
const CALL_BATCH_PENDING = 100;
|
|
549
606
|
const PAYMENT_STATUSES = /* @__PURE__ */ new Set([
|
|
550
607
|
BLOCKCHAIN_PAYMENT_STATUS_VALUE_SETTLED,
|
|
551
608
|
BLOCKCHAIN_PAYMENT_STATUS_VALUE_PENDING,
|
|
@@ -583,6 +640,16 @@ const NOOP_USER_OPERATION_CONFIRM = {
|
|
|
583
640
|
timeout: () => {},
|
|
584
641
|
fail: () => {}
|
|
585
642
|
};
|
|
643
|
+
const noopCallBatchSend = (parent) => ({
|
|
644
|
+
context: parent,
|
|
645
|
+
end: () => {},
|
|
646
|
+
fail: () => {}
|
|
647
|
+
});
|
|
648
|
+
const NOOP_CALL_BATCH_CONFIRM = {
|
|
649
|
+
end: () => {},
|
|
650
|
+
timeout: () => {},
|
|
651
|
+
fail: () => {}
|
|
652
|
+
};
|
|
586
653
|
/** Runs `fn`, logging instead of throwing: instrumentation must never break the caller. */
|
|
587
654
|
function safely(what, fn, fallback) {
|
|
588
655
|
try {
|
|
@@ -626,7 +693,6 @@ function amount(value) {
|
|
|
626
693
|
const text = typeof value === "bigint" ? value.toString() : value;
|
|
627
694
|
return typeof text === "string" && AMOUNT.test(text) ? text : void 0;
|
|
628
695
|
}
|
|
629
|
-
/** The `error.type` for a failure: an adapter's override when it is a short identifier, else the class name. */
|
|
630
696
|
/** A finite number, an `HrTime` pair or a `Date`: what the deprecated positional `endTime` argument takes. */
|
|
631
697
|
function isTimeInput(value) {
|
|
632
698
|
if (typeof value === "number") return Number.isFinite(value);
|
|
@@ -658,6 +724,7 @@ function handleOptions(second, third) {
|
|
|
658
724
|
return {};
|
|
659
725
|
}
|
|
660
726
|
}
|
|
727
|
+
/** The `error.type` for a failure: an adapter's override when it is a short identifier, else the class name. */
|
|
661
728
|
function reportedErrorType(error, options) {
|
|
662
729
|
const override = options?.errorType;
|
|
663
730
|
if (override === void 0) return errorType(error);
|
|
@@ -665,6 +732,14 @@ function reportedErrorType(error, options) {
|
|
|
665
732
|
diag.debug("hashspan: ignoring an error type that is not a short identifier");
|
|
666
733
|
return errorType(error);
|
|
667
734
|
}
|
|
735
|
+
/** A call batch id the tracker keys and records. */
|
|
736
|
+
function isCallBatchId(id) {
|
|
737
|
+
return typeof id === "string" && CALL_BATCH_ID.test(id);
|
|
738
|
+
}
|
|
739
|
+
/** Whether `status` says the batch is still pending: its wait resolved before an outcome. */
|
|
740
|
+
function isPendingCallBatch(status) {
|
|
741
|
+
return status?.statusCode === CALL_BATCH_PENDING;
|
|
742
|
+
}
|
|
668
743
|
/**
|
|
669
744
|
* Joins the confirm span for `hash` in `registry`, opening it with `open` for the first handle; undefined when the
|
|
670
745
|
* key recently got a receipt. A receipt from any handle ends the span; a timeout or failure only ends it when it is the
|
|
@@ -703,7 +778,7 @@ function joinConfirm(registry, chainId, hash, open) {
|
|
|
703
778
|
}
|
|
704
779
|
/**
|
|
705
780
|
* Creates a tracker that records transactions as `send` and `confirm` spans, and payments as `payment` spans, with
|
|
706
|
-
* `@opentelemetry/api` (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
781
|
+
* `@opentelemetry/api` (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/semconv.md). It makes
|
|
707
782
|
* no network calls; the caller passes hashes and receipts. Its methods and handles never throw: failures are logged
|
|
708
783
|
* via `diag`, and a method that fails returns a handle that records nothing.
|
|
709
784
|
*/
|
|
@@ -727,6 +802,14 @@ function createTxTracker(options = {}) {
|
|
|
727
802
|
ttlMs: options.linkTtlMs ?? DEFAULT_LINK_TTL_MS,
|
|
728
803
|
maxEntries: options.maxTrackedTransactions ?? DEFAULT_MAX_TRACKED
|
|
729
804
|
});
|
|
805
|
+
const callBatchLinks = new LinkStore({
|
|
806
|
+
ttlMs: options.linkTtlMs ?? DEFAULT_LINK_TTL_MS,
|
|
807
|
+
maxEntries: options.maxTrackedTransactions ?? DEFAULT_MAX_TRACKED
|
|
808
|
+
});
|
|
809
|
+
const callBatchConfirmations = new ConfirmRegistry({
|
|
810
|
+
ttlMs: options.linkTtlMs ?? DEFAULT_LINK_TTL_MS,
|
|
811
|
+
maxEntries: options.maxTrackedTransactions ?? DEFAULT_MAX_TRACKED
|
|
812
|
+
});
|
|
730
813
|
const txMetrics = createTxMetrics(options.meterProvider, INSTRUMENTATION_NAME, VERSION);
|
|
731
814
|
/** Attributes of a metric: low-cardinality only, never an address, hash or agent identity. */
|
|
732
815
|
const metricAttributes = (chainId, extra = {}) => ({
|
|
@@ -739,6 +822,11 @@ function createTxTracker(options = {}) {
|
|
|
739
822
|
[ATTR_BLOCKCHAIN_OPERATION_SUBJECT]: BLOCKCHAIN_OPERATION_SUBJECT_VALUE_USER_OPERATION,
|
|
740
823
|
...extra
|
|
741
824
|
});
|
|
825
|
+
/** Metric attributes of a call batch sample. */
|
|
826
|
+
const callBatchMetricAttributes = (chainId, extra = {}) => metricAttributes(chainId, {
|
|
827
|
+
[ATTR_BLOCKCHAIN_OPERATION_SUBJECT]: BLOCKCHAIN_OPERATION_SUBJECT_VALUE_CALL_BATCH,
|
|
828
|
+
...extra
|
|
829
|
+
});
|
|
742
830
|
const secondsSince = (startMs, endTime) => (toEpochMs(endTime) - startMs) / 1e3;
|
|
743
831
|
let tracer;
|
|
744
832
|
const getTracer = () => {
|
|
@@ -764,7 +852,7 @@ function createTxTracker(options = {}) {
|
|
|
764
852
|
/**
|
|
765
853
|
* Exception event attributes for `error`, per the error message mode. The error object itself is never handed to
|
|
766
854
|
* the SDK: its message and stack can carry addresses and calldata
|
|
767
|
-
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
855
|
+
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0006-error-privacy.md).
|
|
768
856
|
*/
|
|
769
857
|
const exceptionAttributes = (type, error) => {
|
|
770
858
|
const attributes = { [ATTR_EXCEPTION_TYPE]: type };
|
|
@@ -819,6 +907,28 @@ function createTxTracker(options = {}) {
|
|
|
819
907
|
const formatted = formatAddress(address);
|
|
820
908
|
if (formatted !== void 0) attributes[key] = formatted;
|
|
821
909
|
};
|
|
910
|
+
/**
|
|
911
|
+
* Records an EIP-7702 authorization list: its length, and for each well-formed entry (an address and a non-negative
|
|
912
|
+
* integer chain id, read from own data properties only) its address per the address mode and its chain id, at most
|
|
913
|
+
* {@link MAX_AUTHORIZATIONS}. The two lists stay aligned: an entry is listed in both or in neither.
|
|
914
|
+
*/
|
|
915
|
+
const setAuthorizations = (attributes, list) => {
|
|
916
|
+
if (!Array.isArray(list) || list.length === 0) return;
|
|
917
|
+
attributes[ATTR_BLOCKCHAIN_TX_AUTHORIZATION_COUNT] = list.length;
|
|
918
|
+
const addresses = [];
|
|
919
|
+
const chainIds = [];
|
|
920
|
+
for (const entry of list.slice(0, MAX_AUTHORIZATIONS)) {
|
|
921
|
+
const address = ownValue(entry, "address");
|
|
922
|
+
const chainId = ownValue(entry, "chainId");
|
|
923
|
+
if (typeof address !== "string" || !ADDRESS.test(address)) continue;
|
|
924
|
+
if (typeof chainId !== "number" || !Number.isSafeInteger(chainId) || chainId < 0) continue;
|
|
925
|
+
const formatted = formatAddress(address);
|
|
926
|
+
if (formatted !== void 0) addresses.push(formatted);
|
|
927
|
+
chainIds.push(chainId);
|
|
928
|
+
}
|
|
929
|
+
if (addresses.length > 0) attributes[ATTR_BLOCKCHAIN_TX_AUTHORIZATION_ADDRESSES] = addresses;
|
|
930
|
+
if (chainIds.length > 0) attributes[ATTR_BLOCKCHAIN_TX_AUTHORIZATION_CHAIN_IDS] = chainIds;
|
|
931
|
+
};
|
|
822
932
|
/** Records `address` only if it is one: payment and user operation addresses come from remote parties. */
|
|
823
933
|
const setRemoteAddress = (attributes, key, address) => {
|
|
824
934
|
if (typeof address === "string" && ADDRESS.test(address)) setAddress(attributes, key, address);
|
|
@@ -836,6 +946,11 @@ function createTxTracker(options = {}) {
|
|
|
836
946
|
setAddress(attributes, ATTR_BLOCKCHAIN_TX_TO, input.to);
|
|
837
947
|
if (input.value !== void 0) attributes[ATTR_BLOCKCHAIN_TX_VALUE] = input.value.toString();
|
|
838
948
|
if (input.nonce !== void 0) attributes[ATTR_BLOCKCHAIN_TX_NONCE] = input.nonce;
|
|
949
|
+
try {
|
|
950
|
+
setAuthorizations(attributes, input.authorizations);
|
|
951
|
+
} catch (error) {
|
|
952
|
+
diag.debug(`hashspan: could not record authorizations (${errorType(error)})`);
|
|
953
|
+
}
|
|
839
954
|
if (input.functionName !== void 0) attributes[ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_NAME] = input.functionName;
|
|
840
955
|
if (input.functionSelector !== void 0) attributes[ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_SELECTOR] = input.functionSelector;
|
|
841
956
|
if (options.recordFunctionArguments === true && input.functionArguments !== void 0) try {
|
|
@@ -956,7 +1071,7 @@ function createTxTracker(options = {}) {
|
|
|
956
1071
|
};
|
|
957
1072
|
/**
|
|
958
1073
|
* Ends `shared` with `receipt`, attributing it to the transaction that was mined
|
|
959
|
-
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.
|
|
1074
|
+
* (https://github.com/selimaytac/hashspan/blob/@hashspan/core@0.9.0/docs/adr/0008-replaced-transactions.md).
|
|
960
1075
|
*/
|
|
961
1076
|
const endWithReceipt = (chainId, hash, shared, receipt, endTime) => {
|
|
962
1077
|
const mined = receipt.transactionHash;
|
|
@@ -1192,13 +1307,170 @@ function createTxTracker(options = {}) {
|
|
|
1192
1307
|
}
|
|
1193
1308
|
};
|
|
1194
1309
|
};
|
|
1310
|
+
const startCallBatchSend = (input, parentCtx) => {
|
|
1311
|
+
const parent = parentCtx ?? context.active();
|
|
1312
|
+
const { chainId } = input;
|
|
1313
|
+
const attributes = baseAttributes(chainId, BLOCKCHAIN_OPERATION_NAME_VALUE_SEND, parent);
|
|
1314
|
+
setRemoteAddress(attributes, ATTR_BLOCKCHAIN_CALL_BATCH_SENDER, input.sender);
|
|
1315
|
+
const callCount = smallQuantity(input.callCount);
|
|
1316
|
+
if (callCount !== void 0) attributes[ATTR_BLOCKCHAIN_CALL_BATCH_CALL_COUNT] = callCount;
|
|
1317
|
+
const span = getTracer().startSpan(`send ${chainId}`, {
|
|
1318
|
+
kind: SpanKind.CLIENT,
|
|
1319
|
+
attributes: redact(attributes),
|
|
1320
|
+
...input.startTime !== void 0 ? { startTime: input.startTime } : {}
|
|
1321
|
+
}, parent);
|
|
1322
|
+
const finish = finisher(span);
|
|
1323
|
+
const startMs = toEpochMs(input.startTime);
|
|
1324
|
+
const recordSend = (endTime, errorType) => txMetrics.sendDuration(secondsSince(startMs, endTime), callBatchMetricAttributes(chainId, errorType === void 0 ? {} : { [ATTR_ERROR_TYPE]: errorType }));
|
|
1325
|
+
return {
|
|
1326
|
+
context: trace.setSpan(parent, span),
|
|
1327
|
+
end: (result, second) => {
|
|
1328
|
+
const { endTime } = handleOptions(second);
|
|
1329
|
+
finish("record call batch id", () => {
|
|
1330
|
+
const id = result?.id;
|
|
1331
|
+
if (!isCallBatchId(id)) {
|
|
1332
|
+
diag.debug("hashspan: ending a send span without a valid call batch id");
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
const sent = {
|
|
1336
|
+
spanContext: span.spanContext(),
|
|
1337
|
+
parent
|
|
1338
|
+
};
|
|
1339
|
+
callBatchLinks.set(chainId, id, sent);
|
|
1340
|
+
const hashes = result.transactionHashes;
|
|
1341
|
+
if (Array.isArray(hashes)) {
|
|
1342
|
+
for (const hash of hashes) if (typeof hash === "string" && TX_HASH.test(hash) && !/^0x0+$/.test(hash)) links.set(chainId, hash, sent);
|
|
1343
|
+
}
|
|
1344
|
+
span.setAttributes(redact({ [ATTR_BLOCKCHAIN_CALL_BATCH_ID]: id.slice(0, MAX_CALL_BATCH_ID_ATTRIBUTE_LENGTH) }));
|
|
1345
|
+
recordSend(endTime);
|
|
1346
|
+
}, endTime);
|
|
1347
|
+
},
|
|
1348
|
+
fail: (error, second) => {
|
|
1349
|
+
const read = handleOptions(second);
|
|
1350
|
+
finish("record call batch send failure", () => recordSend(read.endTime, markError(span, reportedErrorType(error, read), error, errorType(error))), read.endTime);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
};
|
|
1354
|
+
/** Attributes of a call batch status. Its values come from a wallet: what is malformed is left out. */
|
|
1355
|
+
const callBatchStatusAttributes = (status) => {
|
|
1356
|
+
const attributes = {};
|
|
1357
|
+
const code = smallQuantity(status.statusCode);
|
|
1358
|
+
if (code !== void 0) attributes[ATTR_BLOCKCHAIN_CALL_BATCH_STATUS_CODE] = code;
|
|
1359
|
+
const atomic = status.atomic;
|
|
1360
|
+
if (typeof atomic === "boolean") attributes[ATTR_BLOCKCHAIN_CALL_BATCH_ATOMIC] = atomic;
|
|
1361
|
+
const receipts = status.receipts;
|
|
1362
|
+
if (Array.isArray(receipts)) {
|
|
1363
|
+
const hashes = [];
|
|
1364
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1365
|
+
let block;
|
|
1366
|
+
for (const receipt of receipts) {
|
|
1367
|
+
const hash = receipt?.transactionHash;
|
|
1368
|
+
if (typeof hash === "string" && TX_HASH.test(hash) && !seen.has(hash.toLowerCase()) && hashes.length < MAX_CALL_BATCH_TRANSACTION_HASHES) {
|
|
1369
|
+
seen.add(hash.toLowerCase());
|
|
1370
|
+
hashes.push(hash);
|
|
1371
|
+
}
|
|
1372
|
+
const number = smallQuantity(receipt?.blockNumber);
|
|
1373
|
+
if (number !== void 0 && (block === void 0 || number > block)) block = number;
|
|
1374
|
+
}
|
|
1375
|
+
if (hashes.length > 0) attributes[ATTR_BLOCKCHAIN_CALL_BATCH_TRANSACTION_HASHES] = hashes;
|
|
1376
|
+
if (block !== void 0) attributes[ATTR_BLOCKCHAIN_BLOCK_NUMBER] = block;
|
|
1377
|
+
}
|
|
1378
|
+
return attributes;
|
|
1379
|
+
};
|
|
1380
|
+
/**
|
|
1381
|
+
* The outcome of an EIP-5792 status code (ADR 0022): `blockchain.call_batch.status` for outcomes from chain data,
|
|
1382
|
+
* `error.type` for the rest; a code the spec does not define, or none, is `_OTHER`.
|
|
1383
|
+
*/
|
|
1384
|
+
const callBatchOutcome = (code) => {
|
|
1385
|
+
switch (code) {
|
|
1386
|
+
case 200: return { status: BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_SUCCESS };
|
|
1387
|
+
case 400: return { errorType: CALL_BATCH_FAILED };
|
|
1388
|
+
case 500: return {
|
|
1389
|
+
status: BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_REVERTED,
|
|
1390
|
+
errorType: BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_REVERTED
|
|
1391
|
+
};
|
|
1392
|
+
case 600: return {
|
|
1393
|
+
status: BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_PARTIALLY_REVERTED,
|
|
1394
|
+
errorType: BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_PARTIALLY_REVERTED
|
|
1395
|
+
};
|
|
1396
|
+
default: return { errorType: ERROR_TYPE_VALUE_OTHER };
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
/** Opens the confirm span of a call batch. */
|
|
1400
|
+
const openCallBatchConfirm = (input, parentCtx) => {
|
|
1401
|
+
const { chainId, id } = input;
|
|
1402
|
+
const sent = callBatchLinks.get(chainId, id);
|
|
1403
|
+
const active = context.active();
|
|
1404
|
+
const parent = parentCtx ?? (trace.getSpan(active) ? active : sent?.parent ?? active);
|
|
1405
|
+
const attributes = baseAttributes(chainId, BLOCKCHAIN_OPERATION_NAME_VALUE_CONFIRM, parent);
|
|
1406
|
+
attributes[ATTR_BLOCKCHAIN_CALL_BATCH_ID] = id.slice(0, MAX_CALL_BATCH_ID_ATTRIBUTE_LENGTH);
|
|
1407
|
+
const span = getTracer().startSpan(`confirm ${chainId}`, {
|
|
1408
|
+
kind: SpanKind.CLIENT,
|
|
1409
|
+
attributes: redact(attributes),
|
|
1410
|
+
links: sent ? [{ context: sent.spanContext }] : [],
|
|
1411
|
+
...input.startTime !== void 0 ? { startTime: input.startTime } : {}
|
|
1412
|
+
}, parent);
|
|
1413
|
+
const finish = finisher(span);
|
|
1414
|
+
const startMs = toEpochMs(input.startTime);
|
|
1415
|
+
const recordConfirmation = (endTime, outcome) => txMetrics.confirmationDuration(secondsSince(startMs, endTime), callBatchMetricAttributes(chainId, outcome));
|
|
1416
|
+
return {
|
|
1417
|
+
active: 0,
|
|
1418
|
+
ended: false,
|
|
1419
|
+
status: (status, endTime) => finish("record call batch status", () => {
|
|
1420
|
+
const attributes = callBatchStatusAttributes(status ?? {});
|
|
1421
|
+
if (isPendingCallBatch(status)) {
|
|
1422
|
+
span.setAttributes(redact(attributes));
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
const outcome = callBatchOutcome(status?.statusCode);
|
|
1426
|
+
if (outcome.status !== void 0) attributes[ATTR_BLOCKCHAIN_CALL_BATCH_STATUS] = outcome.status;
|
|
1427
|
+
span.setAttributes(redact(attributes));
|
|
1428
|
+
if (outcome.errorType !== void 0) markError(span, outcome.errorType);
|
|
1429
|
+
recordConfirmation(endTime, outcome.status !== void 0 ? { [ATTR_BLOCKCHAIN_CALL_BATCH_STATUS]: outcome.status } : { [ATTR_ERROR_TYPE]: outcome.errorType });
|
|
1430
|
+
}, endTime),
|
|
1431
|
+
timeout: (endTime) => finish("record call batch confirmation timeout", () => recordConfirmation(endTime, { [ATTR_ERROR_TYPE]: markError(span, OBSERVER_TIMEOUT) }), endTime),
|
|
1432
|
+
fail: (error, read) => finish("record call batch confirmation failure", () => recordConfirmation(read.endTime, { [ATTR_ERROR_TYPE]: markError(span, reportedErrorType(error, read), error, errorType(error)) }), read.endTime)
|
|
1433
|
+
};
|
|
1434
|
+
};
|
|
1435
|
+
const startCallBatchConfirm = (input, parentCtx) => {
|
|
1436
|
+
const { chainId, id } = input;
|
|
1437
|
+
if (!isCallBatchId(id)) {
|
|
1438
|
+
diag.debug("hashspan: not confirming a call batch without a valid id");
|
|
1439
|
+
return NOOP_CALL_BATCH_CONFIRM;
|
|
1440
|
+
}
|
|
1441
|
+
const claim = joinConfirm(callBatchConfirmations, chainId, id, () => openCallBatchConfirm(input, parentCtx));
|
|
1442
|
+
if (!claim) return NOOP_CALL_BATCH_CONFIRM;
|
|
1443
|
+
const { shared } = claim;
|
|
1444
|
+
return {
|
|
1445
|
+
end: (status, second) => {
|
|
1446
|
+
const { endTime } = handleOptions(second);
|
|
1447
|
+
if (isPendingCallBatch(status)) {
|
|
1448
|
+
claim.withdraw(() => shared.status(status, endTime));
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (!claim.receive()) return;
|
|
1452
|
+
callBatchConfirmations.settle(chainId, id, shared);
|
|
1453
|
+
shared.status(status, endTime);
|
|
1454
|
+
},
|
|
1455
|
+
timeout: (second) => {
|
|
1456
|
+
const { endTime } = handleOptions(second);
|
|
1457
|
+
claim.withdraw(() => shared.timeout(endTime));
|
|
1458
|
+
},
|
|
1459
|
+
fail: (error, second) => {
|
|
1460
|
+
const read = handleOptions(second);
|
|
1461
|
+
claim.withdraw(() => shared.fail(error, read));
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
};
|
|
1195
1465
|
return {
|
|
1196
1466
|
startSend: (input, parent) => safely("start send span", () => startSend(input, parent), noopSend(parent ?? context.active())),
|
|
1197
1467
|
startConfirm: (input, parent) => safely("start confirm span", () => startConfirm(input, parent), NOOP_CONFIRM),
|
|
1198
1468
|
startPayment: (input, parent) => safely("start payment span", () => startPayment(input, parent), NOOP_PAYMENT),
|
|
1199
1469
|
startUserOperationSend: (input, parent) => safely("start user operation send span", () => startUserOperationSend(input, parent), noopUserOperationSend(parent ?? context.active())),
|
|
1200
|
-
startUserOperationConfirm: (input, parent) => safely("start user operation confirm span", () => startUserOperationConfirm(input, parent), NOOP_USER_OPERATION_CONFIRM)
|
|
1470
|
+
startUserOperationConfirm: (input, parent) => safely("start user operation confirm span", () => startUserOperationConfirm(input, parent), NOOP_USER_OPERATION_CONFIRM),
|
|
1471
|
+
startCallBatchSend: (input, parent) => safely("start call batch send span", () => startCallBatchSend(input, parent), noopCallBatchSend(parent ?? context.active())),
|
|
1472
|
+
startCallBatchConfirm: (input, parent) => safely("start call batch confirm span", () => startCallBatchConfirm(input, parent), NOOP_CALL_BATCH_CONFIRM)
|
|
1201
1473
|
};
|
|
1202
1474
|
}
|
|
1203
1475
|
//#endregion
|
|
1204
|
-
export { ATTR_BLOCKCHAIN_BLOCK_NUMBER, ATTR_BLOCKCHAIN_CHAIN_ID, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_ARGUMENTS, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_NAME, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_SELECTOR, ATTR_BLOCKCHAIN_OPERATION_NAME, ATTR_BLOCKCHAIN_OPERATION_SUBJECT, ATTR_BLOCKCHAIN_PAYMENT_AMOUNT, ATTR_BLOCKCHAIN_PAYMENT_ASSET, ATTR_BLOCKCHAIN_PAYMENT_PAYER, ATTR_BLOCKCHAIN_PAYMENT_PROTOCOL, ATTR_BLOCKCHAIN_PAYMENT_RECIPIENT, ATTR_BLOCKCHAIN_PAYMENT_SETTLED_AMOUNT, ATTR_BLOCKCHAIN_PAYMENT_STATUS, ATTR_BLOCKCHAIN_PAYMENT_VERIFIED, ATTR_BLOCKCHAIN_SYSTEM, ATTR_BLOCKCHAIN_TX_EFFECTIVE_GAS_PRICE, ATTR_BLOCKCHAIN_TX_FEE, ATTR_BLOCKCHAIN_TX_FROM, ATTR_BLOCKCHAIN_TX_GAS_USED, ATTR_BLOCKCHAIN_TX_HASH, ATTR_BLOCKCHAIN_TX_L1_FEE, ATTR_BLOCKCHAIN_TX_NONCE, ATTR_BLOCKCHAIN_TX_REPLACEMENT_HASH, ATTR_BLOCKCHAIN_TX_REPLACEMENT_REASON, ATTR_BLOCKCHAIN_TX_REVERT_REASON, ATTR_BLOCKCHAIN_TX_STATUS, ATTR_BLOCKCHAIN_TX_TO, ATTR_BLOCKCHAIN_TX_VALUE, ATTR_BLOCKCHAIN_USER_OPERATION_CALL_COUNT, ATTR_BLOCKCHAIN_USER_OPERATION_ENTRY_POINT, ATTR_BLOCKCHAIN_USER_OPERATION_GAS_COST, ATTR_BLOCKCHAIN_USER_OPERATION_GAS_USED, ATTR_BLOCKCHAIN_USER_OPERATION_HASH, ATTR_BLOCKCHAIN_USER_OPERATION_NONCE, ATTR_BLOCKCHAIN_USER_OPERATION_PAYMASTER, ATTR_BLOCKCHAIN_USER_OPERATION_SENDER, ATTR_BLOCKCHAIN_USER_OPERATION_SUCCESS, ATTR_ERROR_TYPE, ATTR_GEN_AI_AGENT_ID, ATTR_GEN_AI_AGENT_NAME, ATTR_X402_RESOURCE, ATTR_X402_SCHEME, BLOCKCHAIN_OPERATION_NAME_VALUE_CONFIRM, BLOCKCHAIN_OPERATION_NAME_VALUE_PAYMENT, BLOCKCHAIN_OPERATION_NAME_VALUE_SEND, BLOCKCHAIN_OPERATION_SUBJECT_VALUE_USER_OPERATION, BLOCKCHAIN_PAYMENT_PROTOCOL_VALUE_X402, BLOCKCHAIN_PAYMENT_STATUS_VALUE_FAILED, BLOCKCHAIN_PAYMENT_STATUS_VALUE_PENDING, BLOCKCHAIN_PAYMENT_STATUS_VALUE_SETTLED, BLOCKCHAIN_SYSTEM_VALUE_EVM, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_CANCELLED, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_REPLACED, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_REPRICED, BLOCKCHAIN_TX_STATUS_VALUE_REPLACED, BLOCKCHAIN_TX_STATUS_VALUE_REVERTED, BLOCKCHAIN_TX_STATUS_VALUE_SUCCESS, BLOCKCHAIN_TX_STATUS_VALUE_TIMEOUT, ERROR_TYPE_VALUE_OTHER, METRIC_BLOCKCHAIN_CLIENT_CONFIRMATION_DURATION, METRIC_BLOCKCHAIN_CLIENT_FEE, METRIC_BLOCKCHAIN_CLIENT_SEND_DURATION, VERSION, createTxTracker };
|
|
1476
|
+
export { ATTR_BLOCKCHAIN_BLOCK_NUMBER, ATTR_BLOCKCHAIN_CALL_BATCH_ATOMIC, ATTR_BLOCKCHAIN_CALL_BATCH_CALL_COUNT, ATTR_BLOCKCHAIN_CALL_BATCH_ID, ATTR_BLOCKCHAIN_CALL_BATCH_SENDER, ATTR_BLOCKCHAIN_CALL_BATCH_STATUS, ATTR_BLOCKCHAIN_CALL_BATCH_STATUS_CODE, ATTR_BLOCKCHAIN_CALL_BATCH_TRANSACTION_HASHES, ATTR_BLOCKCHAIN_CHAIN_ID, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_ARGUMENTS, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_NAME, ATTR_BLOCKCHAIN_CONTRACT_FUNCTION_SELECTOR, ATTR_BLOCKCHAIN_OPERATION_NAME, ATTR_BLOCKCHAIN_OPERATION_SUBJECT, ATTR_BLOCKCHAIN_PAYMENT_AMOUNT, ATTR_BLOCKCHAIN_PAYMENT_ASSET, ATTR_BLOCKCHAIN_PAYMENT_PAYER, ATTR_BLOCKCHAIN_PAYMENT_PROTOCOL, ATTR_BLOCKCHAIN_PAYMENT_RECIPIENT, ATTR_BLOCKCHAIN_PAYMENT_SETTLED_AMOUNT, ATTR_BLOCKCHAIN_PAYMENT_STATUS, ATTR_BLOCKCHAIN_PAYMENT_VERIFIED, ATTR_BLOCKCHAIN_SYSTEM, ATTR_BLOCKCHAIN_TX_AUTHORIZATION_ADDRESSES, ATTR_BLOCKCHAIN_TX_AUTHORIZATION_CHAIN_IDS, ATTR_BLOCKCHAIN_TX_AUTHORIZATION_COUNT, ATTR_BLOCKCHAIN_TX_EFFECTIVE_GAS_PRICE, ATTR_BLOCKCHAIN_TX_FEE, ATTR_BLOCKCHAIN_TX_FROM, ATTR_BLOCKCHAIN_TX_GAS_USED, ATTR_BLOCKCHAIN_TX_HASH, ATTR_BLOCKCHAIN_TX_L1_FEE, ATTR_BLOCKCHAIN_TX_NONCE, ATTR_BLOCKCHAIN_TX_REPLACEMENT_HASH, ATTR_BLOCKCHAIN_TX_REPLACEMENT_REASON, ATTR_BLOCKCHAIN_TX_REVERT_REASON, ATTR_BLOCKCHAIN_TX_STATUS, ATTR_BLOCKCHAIN_TX_TO, ATTR_BLOCKCHAIN_TX_VALUE, ATTR_BLOCKCHAIN_USER_OPERATION_CALL_COUNT, ATTR_BLOCKCHAIN_USER_OPERATION_ENTRY_POINT, ATTR_BLOCKCHAIN_USER_OPERATION_GAS_COST, ATTR_BLOCKCHAIN_USER_OPERATION_GAS_USED, ATTR_BLOCKCHAIN_USER_OPERATION_HASH, ATTR_BLOCKCHAIN_USER_OPERATION_NONCE, ATTR_BLOCKCHAIN_USER_OPERATION_PAYMASTER, ATTR_BLOCKCHAIN_USER_OPERATION_SENDER, ATTR_BLOCKCHAIN_USER_OPERATION_SUCCESS, ATTR_ERROR_TYPE, ATTR_GEN_AI_AGENT_ID, ATTR_GEN_AI_AGENT_NAME, ATTR_X402_RESOURCE, ATTR_X402_SCHEME, BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_PARTIALLY_REVERTED, BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_REVERTED, BLOCKCHAIN_CALL_BATCH_STATUS_VALUE_SUCCESS, BLOCKCHAIN_OPERATION_NAME_VALUE_CONFIRM, BLOCKCHAIN_OPERATION_NAME_VALUE_PAYMENT, BLOCKCHAIN_OPERATION_NAME_VALUE_SEND, BLOCKCHAIN_OPERATION_SUBJECT_VALUE_CALL_BATCH, BLOCKCHAIN_OPERATION_SUBJECT_VALUE_USER_OPERATION, BLOCKCHAIN_PAYMENT_PROTOCOL_VALUE_X402, BLOCKCHAIN_PAYMENT_STATUS_VALUE_FAILED, BLOCKCHAIN_PAYMENT_STATUS_VALUE_PENDING, BLOCKCHAIN_PAYMENT_STATUS_VALUE_SETTLED, BLOCKCHAIN_SYSTEM_VALUE_EVM, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_CANCELLED, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_REPLACED, BLOCKCHAIN_TX_REPLACEMENT_REASON_VALUE_REPRICED, BLOCKCHAIN_TX_STATUS_VALUE_REPLACED, BLOCKCHAIN_TX_STATUS_VALUE_REVERTED, BLOCKCHAIN_TX_STATUS_VALUE_SUCCESS, BLOCKCHAIN_TX_STATUS_VALUE_TIMEOUT, ERROR_TYPE_VALUE_OTHER, METRIC_BLOCKCHAIN_CLIENT_CONFIRMATION_DURATION, METRIC_BLOCKCHAIN_CLIENT_FEE, METRIC_BLOCKCHAIN_CLIENT_SEND_DURATION, VERSION, createTxTracker };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hashspan/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://hashspan.dev",
|
|
8
8
|
"bugs": {
|
|
9
9
|
"url": "https://github.com/selimaytac/hashspan/issues"
|
|
10
10
|
},
|