crypto-aio 0.1.0 → 0.2.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.
Files changed (163) hide show
  1. package/CHANGELOG.md +151 -1
  2. package/README.md +32 -12
  3. package/dist/adapters/evm/builder.js +64 -4
  4. package/dist/adapters/evm/builder.js.map +1 -1
  5. package/dist/adapters/evm/decode.js +6 -1
  6. package/dist/adapters/evm/decode.js.map +1 -1
  7. package/dist/adapters/evm/ethers-client.js +4 -0
  8. package/dist/adapters/evm/ethers-client.js.map +1 -1
  9. package/dist/adapters/evm/fees.d.ts +24 -0
  10. package/dist/adapters/evm/fees.js +47 -4
  11. package/dist/adapters/evm/fees.js.map +1 -1
  12. package/dist/adapters/evm/index.d.ts +1 -1
  13. package/dist/adapters/evm/index.js +2 -1
  14. package/dist/adapters/evm/index.js.map +1 -1
  15. package/dist/adapters/evm/network.d.ts +5 -0
  16. package/dist/adapters/evm/network.js +21 -2
  17. package/dist/adapters/evm/network.js.map +1 -1
  18. package/dist/adapters/evm/plugin.d.ts +5 -6
  19. package/dist/adapters/evm/plugin.js +50 -2
  20. package/dist/adapters/evm/plugin.js.map +1 -1
  21. package/dist/adapters/evm/proofs.js +17 -5
  22. package/dist/adapters/evm/proofs.js.map +1 -1
  23. package/dist/adapters/evm/reader.d.ts +18 -0
  24. package/dist/adapters/evm/reader.js +34 -0
  25. package/dist/adapters/evm/reader.js.map +1 -1
  26. package/dist/adapters/evm/tokens.d.ts +3 -0
  27. package/dist/adapters/evm/tokens.js.map +1 -1
  28. package/dist/adapters/evm/types.d.ts +10 -0
  29. package/dist/adapters/evm/types.js.map +1 -1
  30. package/dist/adapters/evm/web3-client.d.ts +6 -3
  31. package/dist/adapters/evm/web3-client.js +19 -2
  32. package/dist/adapters/evm/web3-client.js.map +1 -1
  33. package/dist/adapters/solana/builder.js +29 -18
  34. package/dist/adapters/solana/builder.js.map +1 -1
  35. package/dist/adapters/solana/fees.d.ts +12 -3
  36. package/dist/adapters/solana/fees.js +13 -4
  37. package/dist/adapters/solana/fees.js.map +1 -1
  38. package/dist/adapters/solana/message.d.ts +15 -0
  39. package/dist/adapters/solana/message.js +120 -0
  40. package/dist/adapters/solana/message.js.map +1 -0
  41. package/dist/adapters/solana/plugin.js +4 -1
  42. package/dist/adapters/solana/plugin.js.map +1 -1
  43. package/dist/adapters/solana/types.d.ts +8 -5
  44. package/dist/adapters/solana/types.js.map +1 -1
  45. package/dist/adapters/solana/web3.js +10 -32
  46. package/dist/adapters/solana/web3.js.map +1 -1
  47. package/dist/adapters/ton/proofs.js +18 -76
  48. package/dist/adapters/ton/proofs.js.map +1 -1
  49. package/dist/adapters/ton/reader.d.ts +45 -4
  50. package/dist/adapters/ton/reader.js +200 -5
  51. package/dist/adapters/ton/reader.js.map +1 -1
  52. package/dist/adapters/ton/trace.d.ts +26 -0
  53. package/dist/adapters/ton/trace.js +35 -9
  54. package/dist/adapters/ton/trace.js.map +1 -1
  55. package/dist/adapters/tron/abi.d.ts +2 -0
  56. package/dist/adapters/tron/abi.js +2 -0
  57. package/dist/adapters/tron/abi.js.map +1 -1
  58. package/dist/adapters/tron/builder.js +20 -4
  59. package/dist/adapters/tron/builder.js.map +1 -1
  60. package/dist/adapters/tron/decode.d.ts +2 -0
  61. package/dist/adapters/tron/decode.js +1 -1
  62. package/dist/adapters/tron/decode.js.map +1 -1
  63. package/dist/adapters/tron/proofs.js +1 -0
  64. package/dist/adapters/tron/proofs.js.map +1 -1
  65. package/dist/adapters/tron/reader.d.ts +10 -0
  66. package/dist/adapters/tron/reader.js +17 -0
  67. package/dist/adapters/tron/reader.js.map +1 -1
  68. package/dist/adapters/tron/tokens.d.ts +2 -0
  69. package/dist/adapters/tron/tokens.js.map +1 -1
  70. package/dist/adapters/utxo/builder.js +1 -1
  71. package/dist/adapters/utxo/builder.js.map +1 -1
  72. package/dist/adapters/utxo/chains.js +2 -1
  73. package/dist/adapters/utxo/chains.js.map +1 -1
  74. package/dist/adapters/utxo/context.d.ts +6 -0
  75. package/dist/adapters/utxo/context.js +8 -1
  76. package/dist/adapters/utxo/context.js.map +1 -1
  77. package/dist/adapters/utxo/decode.d.ts +8 -0
  78. package/dist/adapters/utxo/decode.js +36 -0
  79. package/dist/adapters/utxo/decode.js.map +1 -1
  80. package/dist/adapters/utxo/driver.js +5 -0
  81. package/dist/adapters/utxo/driver.js.map +1 -1
  82. package/dist/adapters/utxo/esplora.d.ts +23 -2
  83. package/dist/adapters/utxo/esplora.js +49 -2
  84. package/dist/adapters/utxo/esplora.js.map +1 -1
  85. package/dist/adapters/utxo/proofs.d.ts +15 -6
  86. package/dist/adapters/utxo/proofs.js +185 -47
  87. package/dist/adapters/utxo/proofs.js.map +1 -1
  88. package/dist/adapters/utxo/rawblock.d.ts +46 -0
  89. package/dist/adapters/utxo/rawblock.js +159 -0
  90. package/dist/adapters/utxo/rawblock.js.map +1 -0
  91. package/dist/adapters/utxo/rawtx.d.ts +14 -0
  92. package/dist/adapters/utxo/rawtx.js +44 -14
  93. package/dist/adapters/utxo/rawtx.js.map +1 -1
  94. package/dist/core/blockchain/handle.d.ts +6 -27
  95. package/dist/core/blockchain/handle.js +112 -112
  96. package/dist/core/blockchain/handle.js.map +1 -1
  97. package/dist/core/config/types.d.ts +15 -0
  98. package/dist/core/config/types.js.map +1 -1
  99. package/dist/core/container/container.d.ts +1 -8
  100. package/dist/core/container/container.js +42 -8
  101. package/dist/core/container/container.js.map +1 -1
  102. package/dist/core/driver/types.d.ts +34 -1
  103. package/dist/core/driver/types.js.map +1 -1
  104. package/dist/core/errors/codes.d.ts +10 -0
  105. package/dist/core/errors/codes.js +4 -0
  106. package/dist/core/errors/codes.js.map +1 -1
  107. package/dist/core/lifecycle/engine-rules.d.ts +3 -4
  108. package/dist/core/lifecycle/engine-rules.js +16 -6
  109. package/dist/core/lifecycle/engine-rules.js.map +1 -1
  110. package/dist/core/lifecycle/engine.d.ts +2 -0
  111. package/dist/core/lifecycle/engine.js +19 -1
  112. package/dist/core/lifecycle/engine.js.map +1 -1
  113. package/dist/core/lifecycle/evaluate.js +9 -4
  114. package/dist/core/lifecycle/evaluate.js.map +1 -1
  115. package/dist/core/lifecycle/monitor.js +16 -6
  116. package/dist/core/lifecycle/monitor.js.map +1 -1
  117. package/dist/core/lifecycle/reconcile.d.ts +1 -1
  118. package/dist/core/lifecycle/reconcile.js +1 -1
  119. package/dist/core/lifecycle/reconcile.js.map +1 -1
  120. package/dist/core/lifecycle/workers.d.ts +9 -3
  121. package/dist/core/lifecycle/workers.js +32 -14
  122. package/dist/core/lifecycle/workers.js.map +1 -1
  123. package/dist/core/model/ids.d.ts +1 -0
  124. package/dist/core/model/ids.js +1 -0
  125. package/dist/core/model/ids.js.map +1 -1
  126. package/dist/core/model/ordering.d.ts +8 -0
  127. package/dist/core/model/ordering.js.map +1 -1
  128. package/dist/core/model/transaction.d.ts +7 -0
  129. package/dist/core/model/transaction.js.map +1 -1
  130. package/dist/core/observe/scanner.js +3 -0
  131. package/dist/core/observe/scanner.js.map +1 -1
  132. package/dist/core/signing/wallet.js +8 -0
  133. package/dist/core/signing/wallet.js.map +1 -1
  134. package/dist/core/store/format.d.ts +20 -0
  135. package/dist/core/store/format.js +86 -0
  136. package/dist/core/store/format.js.map +1 -0
  137. package/dist/core/store/memory.js +2 -2
  138. package/dist/core/store/memory.js.map +1 -1
  139. package/dist/core/store/types.d.ts +15 -3
  140. package/dist/core/store/types.js +2 -0
  141. package/dist/core/store/types.js.map +1 -1
  142. package/dist/core/transport/http-transport.js +21 -13
  143. package/dist/core/transport/http-transport.js.map +1 -1
  144. package/dist/core/transport/types.d.ts +16 -1
  145. package/dist/core/transport/types.js.map +1 -1
  146. package/dist/core/util/json.d.ts +7 -1
  147. package/dist/core/util/json.js +13 -4
  148. package/dist/core/util/json.js.map +1 -1
  149. package/dist/core/util/names.d.ts +6 -0
  150. package/dist/core/util/names.js +10 -0
  151. package/dist/core/util/names.js.map +1 -1
  152. package/dist/index.d.ts +2 -1
  153. package/dist/index.js +4 -2
  154. package/dist/index.js.map +1 -1
  155. package/dist/testing/contracts/operations.js +20 -1
  156. package/dist/testing/contracts/operations.js.map +1 -1
  157. package/dist/testing/env.d.ts +5 -0
  158. package/dist/testing/env.js +1 -1
  159. package/dist/testing/env.js.map +1 -1
  160. package/dist/testing/faulty-store.d.ts +2 -0
  161. package/dist/testing/faulty-store.js +5 -0
  162. package/dist/testing/faulty-store.js.map +1 -1
  163. package/package.json +17 -7
@@ -21,6 +21,15 @@ export interface TransportOptions {
21
21
  readonly timeoutMs?: number;
22
22
  readonly maxLagBlocks?: number;
23
23
  readonly proofQuorum?: number;
24
+ /**
25
+ * Whether proofs go on, from fewer endpoints, once endpoints drop out of the proof
26
+ * quorum's count (their probes or requests failing for three health refreshes in a
27
+ * row). By default (`false`) a proof still needs `proofQuorum` endpoints, capped only by
28
+ * the endpoints configured, so it waits for the dropped ones and one endpoint left can
29
+ * never prove alone. `true` caps it by the endpoints still counted, down to one: proofs
30
+ * keep going through an outage, but the one endpoint left decides alone.
31
+ */
32
+ readonly degradedProofs?: boolean;
24
33
  readonly failureThreshold?: number;
25
34
  readonly openMs?: number;
26
35
  readonly healthIntervalMs?: number;
@@ -76,7 +85,13 @@ export interface HttpRequest {
76
85
  readonly query?: Readonly<Record<string, string>>;
77
86
  readonly body?: unknown;
78
87
  readonly headers?: Readonly<Record<string, string>>;
79
- readonly responseType?: 'json' | 'text';
88
+ /**
89
+ * How a 2xx answer is returned (default `'json'`): parsed JSON, the body as text, or its
90
+ * bytes unchanged as a `Uint8Array` (`'bytes'`, for a binary answer such as a serialized
91
+ * block, which text decoding would corrupt). Every type is read under
92
+ * `maxResponseBytes`; an error answer is read as text for its details whatever the type.
93
+ */
94
+ readonly responseType?: 'json' | 'text' | 'bytes';
80
95
  /**
81
96
  * Low-cardinality template label used for event and log method fields instead of the
82
97
  * raw path, e.g. `'/address/:address/utxo'`. Must contain no identifiers (addresses,
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/transport/types.ts"],"names":[],"mappings":";;;AAyJA,uFAAuF;AAC1E,QAAA,kBAAkB,GAAG,sCAAsC,CAAC","sourcesContent":["import type { Secret } from '../secret/secret';\n\nexport type RetryClass = 'safe' | 'ambiguous-on-failure' | 'never-auto';\nexport type RequestPurpose = 'read' | 'monitor' | 'proof' | 'broadcast';\n\nexport interface EndpointConfig {\n readonly name?: string;\n readonly url: string | Secret<string>;\n readonly kind?: 'rpc' | 'indexer';\n readonly headers?: Readonly<Record<string, string | Secret<string>>>;\n readonly priority?: number;\n readonly rateLimit?: { readonly rps: number; readonly burst?: number };\n readonly timeoutMs?: number;\n}\n\nexport interface TransportOptions {\n readonly fetch?: typeof fetch;\n readonly maxAttempts?: number;\n readonly baseDelayMs?: number;\n readonly maxDelayMs?: number;\n readonly timeoutMs?: number;\n readonly maxLagBlocks?: number;\n readonly proofQuorum?: number;\n readonly failureThreshold?: number;\n readonly openMs?: number;\n readonly healthIntervalMs?: number;\n /**\n * The most bytes one answer may carry (default 64 MiB). A longer answer, by its declared\n * length or as it arrives, is cancelled and fails as a retryable `PROVIDER_UNAVAILABLE`,\n * so one endpoint can never make a call hold unbounded memory.\n */\n readonly maxResponseBytes?: number;\n}\n\nexport interface CallOptions {\n readonly retry?: RetryClass;\n readonly purpose?: RequestPurpose;\n /**\n * Independent endpoints that must agree; `'proof'` uses `proofQuorum`, capped by the\n * endpoints the quorum counts. A proof quorum (`'proof'` under any purpose, or any quorum\n * for a monitor or proof purpose) with probes configured counts every endpoint not proven\n * mismatched until three health refreshes in a row, at most one per `healthIntervalMs`,\n * fail its probes or find its requests failing (its circuit breaker not closed), even\n * while it cannot answer, so a shortfall decides nothing (a retryable\n * `PROVIDER_UNAVAILABLE`); any other quorum counts the usable endpoints. An endpoint out\n * of a proof quorum's count never answers toward the read: while its circuit breaker is\n * half-open it is tried alongside the others (the read waits for that trial, up to its\n * timeout, unless the endpoint has no rate-limit token free), and its disagreement or\n * refusal can only block the read. In a proof quorum, a definitive error decides only when\n * every endpoint asked returns an equivalent one: the same error code, HTTP status and\n * JSON-RPC code, and for a JSON-RPC code each server defines (-32000 to -32099, and\n * -32603) the same message. Otherwise the read is a retryable `PROVIDER_INCONSISTENT`.\n */\n readonly quorum?: number | 'proof';\n /**\n * The part of each endpoint's result that must agree under `quorum` (default: the whole\n * result). Lets a caller compare consensus facts only, e.g. a block's number, hash and\n * parent hash, not fields that node implementations format differently. The call still\n * resolves with the first endpoint's whole result. A key that throws on any result counts\n * as a disagreement (a retryable `PROVIDER_INCONSISTENT`).\n */\n readonly quorumKey?: (result: unknown) => unknown;\n /**\n * Parse JSON answers with exact integers: an integer outside the safe range becomes a\n * `bigint` instead of a rounded number (`rpc`, `rpcRaw` and `http`; health probes always\n * parse plainly). A quorum key sees the revived values.\n */\n readonly exactIntegers?: boolean;\n /** Send to this many endpoints concurrently (raw-transaction broadcasts). */\n readonly fanout?: number;\n readonly signal?: AbortSignal;\n readonly timeoutMs?: number;\n}\n\nexport interface HttpRequest {\n readonly method: 'GET' | 'POST';\n readonly path: string;\n readonly query?: Readonly<Record<string, string>>;\n readonly body?: unknown;\n readonly headers?: Readonly<Record<string, string>>;\n readonly responseType?: 'json' | 'text';\n /**\n * Low-cardinality template label used for event and log method fields instead of the\n * raw path, e.g. `'/address/:address/utxo'`. Must contain no identifiers (addresses,\n * hashes, ids). When omitted, events fall back to the bare HTTP method.\n */\n readonly route?: string;\n}\n\n/** Single-attempt calls against one specific endpoint (used by health probes). */\nexport interface EndpointCall {\n rpc<T = unknown>(method: string, params?: unknown): Promise<T>;\n http<T = unknown>(request: HttpRequest): Promise<T>;\n}\n\nexport interface HealthProbes {\n readonly identity?: (call: EndpointCall) => Promise<string>;\n readonly expectedIdentity?: string;\n readonly height?: (call: EndpointCall) => Promise<bigint>;\n}\n\nexport type EndpointState =\n 'healthy' | 'lagging' | 'open' | 'half-open' | 'disabled' | 'unknown';\n\nexport interface EndpointStatus {\n readonly id: string;\n readonly kind: 'rpc' | 'indexer';\n readonly state: EndpointState;\n readonly failures: number;\n readonly height?: bigint;\n readonly lag?: bigint;\n readonly latencyMs?: number;\n readonly reason?: string;\n}\n\nexport interface Transport {\n readonly id: string;\n rpc<T = unknown>(method: string, params?: unknown, options?: CallOptions): Promise<T>;\n /** Posts an arbitrary JSON-RPC payload (single or batch) and returns the parsed body. */\n rpcRaw(payload: unknown, options?: CallOptions): Promise<unknown>;\n http<T = unknown>(request: HttpRequest, options?: CallOptions): Promise<T>;\n /** fetch-compatible function for SDKs; only `PLACEHOLDER_ORIGIN` URLs are accepted. */\n createFetch(\n classify?: (url: URL, init: RequestInit | undefined) => CallOptions,\n ): typeof fetch;\n setProbes(probes: HealthProbes): void;\n /** Whether any health probe (`identity` and/or `height`) has ever been configured via\n * `setProbes`. A transport with none configured can never mark an endpoint 'healthy' or\n * 'lagging' — its endpoints stay 'unknown' forever, which callers like `Blockchain.ready()`\n * treat as acceptable only in that case. */\n hasProbes(): boolean;\n refreshHealth(signal?: AbortSignal): Promise<void>;\n ensureFreshHealth(signal?: AbortSignal): Promise<void>;\n status(): EndpointStatus[];\n /**\n * Highest verified block height: a high-water mark (the stale-view guard of monitors\n * and scanners). It drops in two cases only: a height taken before an identity probe\n * existed stops counting once its endpoint turns out to serve another network, and a\n * peak that no verified endpoint comes within `maxLagBlocks` of for three health\n * refreshes in a row falls back to the verified best, so one forged far-future head\n * cannot keep every view stale until restart.\n */\n highestHeight(): bigint | undefined;\n /**\n * The lag tolerance in effect (`TransportOptions.maxLagBlocks`). The driver pool\n * resolves it in this order: the chain's `maxLagBlocks` config, else the root\n * `transport.maxLagBlocks`, else the plugin network's own, else the built-in default.\n * An endpoint further behind is lagging, and a view further behind `highestHeight()` is\n * stale.\n */\n readonly maxLagBlocks: number;\n}\n\n/** SDKs are configured with this origin; the transport maps it onto real endpoints. */\nexport const PLACEHOLDER_ORIGIN = 'https://transport.crypto-aio.invalid';\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/transport/types.ts"],"names":[],"mappings":";;;AAwKA,uFAAuF;AAC1E,QAAA,kBAAkB,GAAG,sCAAsC,CAAC","sourcesContent":["import type { Secret } from '../secret/secret';\n\nexport type RetryClass = 'safe' | 'ambiguous-on-failure' | 'never-auto';\nexport type RequestPurpose = 'read' | 'monitor' | 'proof' | 'broadcast';\n\nexport interface EndpointConfig {\n readonly name?: string;\n readonly url: string | Secret<string>;\n readonly kind?: 'rpc' | 'indexer';\n readonly headers?: Readonly<Record<string, string | Secret<string>>>;\n readonly priority?: number;\n readonly rateLimit?: { readonly rps: number; readonly burst?: number };\n readonly timeoutMs?: number;\n}\n\nexport interface TransportOptions {\n readonly fetch?: typeof fetch;\n readonly maxAttempts?: number;\n readonly baseDelayMs?: number;\n readonly maxDelayMs?: number;\n readonly timeoutMs?: number;\n readonly maxLagBlocks?: number;\n readonly proofQuorum?: number;\n /**\n * Whether proofs go on, from fewer endpoints, once endpoints drop out of the proof\n * quorum's count (their probes or requests failing for three health refreshes in a\n * row). By default (`false`) a proof still needs `proofQuorum` endpoints, capped only by\n * the endpoints configured, so it waits for the dropped ones and one endpoint left can\n * never prove alone. `true` caps it by the endpoints still counted, down to one: proofs\n * keep going through an outage, but the one endpoint left decides alone.\n */\n readonly degradedProofs?: boolean;\n readonly failureThreshold?: number;\n readonly openMs?: number;\n readonly healthIntervalMs?: number;\n /**\n * The most bytes one answer may carry (default 64 MiB). A longer answer, by its declared\n * length or as it arrives, is cancelled and fails as a retryable `PROVIDER_UNAVAILABLE`,\n * so one endpoint can never make a call hold unbounded memory.\n */\n readonly maxResponseBytes?: number;\n}\n\nexport interface CallOptions {\n readonly retry?: RetryClass;\n readonly purpose?: RequestPurpose;\n /**\n * Independent endpoints that must agree; `'proof'` uses `proofQuorum`, capped by the\n * endpoints the quorum counts. A proof quorum (`'proof'` under any purpose, or any quorum\n * for a monitor or proof purpose) with probes configured counts every endpoint not proven\n * mismatched until three health refreshes in a row, at most one per `healthIntervalMs`,\n * fail its probes or find its requests failing (its circuit breaker not closed), even\n * while it cannot answer, so a shortfall decides nothing (a retryable\n * `PROVIDER_UNAVAILABLE`); any other quorum counts the usable endpoints. An endpoint out\n * of a proof quorum's count never answers toward the read: while its circuit breaker is\n * half-open it is tried alongside the others (the read waits for that trial, up to its\n * timeout, unless the endpoint has no rate-limit token free), and its disagreement or\n * refusal can only block the read. In a proof quorum, a definitive error decides only when\n * every endpoint asked returns an equivalent one: the same error code, HTTP status and\n * JSON-RPC code, and for a JSON-RPC code each server defines (-32000 to -32099, and\n * -32603) the same message. Otherwise the read is a retryable `PROVIDER_INCONSISTENT`.\n */\n readonly quorum?: number | 'proof';\n /**\n * The part of each endpoint's result that must agree under `quorum` (default: the whole\n * result). Lets a caller compare consensus facts only, e.g. a block's number, hash and\n * parent hash, not fields that node implementations format differently. The call still\n * resolves with the first endpoint's whole result. A key that throws on any result counts\n * as a disagreement (a retryable `PROVIDER_INCONSISTENT`).\n */\n readonly quorumKey?: (result: unknown) => unknown;\n /**\n * Parse JSON answers with exact integers: an integer outside the safe range becomes a\n * `bigint` instead of a rounded number (`rpc`, `rpcRaw` and `http`; health probes always\n * parse plainly). A quorum key sees the revived values.\n */\n readonly exactIntegers?: boolean;\n /** Send to this many endpoints concurrently (raw-transaction broadcasts). */\n readonly fanout?: number;\n readonly signal?: AbortSignal;\n readonly timeoutMs?: number;\n}\n\nexport interface HttpRequest {\n readonly method: 'GET' | 'POST';\n readonly path: string;\n readonly query?: Readonly<Record<string, string>>;\n readonly body?: unknown;\n readonly headers?: Readonly<Record<string, string>>;\n /**\n * How a 2xx answer is returned (default `'json'`): parsed JSON, the body as text, or its\n * bytes unchanged as a `Uint8Array` (`'bytes'`, for a binary answer such as a serialized\n * block, which text decoding would corrupt). Every type is read under\n * `maxResponseBytes`; an error answer is read as text for its details whatever the type.\n */\n readonly responseType?: 'json' | 'text' | 'bytes';\n /**\n * Low-cardinality template label used for event and log method fields instead of the\n * raw path, e.g. `'/address/:address/utxo'`. Must contain no identifiers (addresses,\n * hashes, ids). When omitted, events fall back to the bare HTTP method.\n */\n readonly route?: string;\n}\n\n/** Single-attempt calls against one specific endpoint (used by health probes). */\nexport interface EndpointCall {\n rpc<T = unknown>(method: string, params?: unknown): Promise<T>;\n http<T = unknown>(request: HttpRequest): Promise<T>;\n}\n\nexport interface HealthProbes {\n readonly identity?: (call: EndpointCall) => Promise<string>;\n readonly expectedIdentity?: string;\n readonly height?: (call: EndpointCall) => Promise<bigint>;\n}\n\nexport type EndpointState =\n 'healthy' | 'lagging' | 'open' | 'half-open' | 'disabled' | 'unknown';\n\nexport interface EndpointStatus {\n readonly id: string;\n readonly kind: 'rpc' | 'indexer';\n readonly state: EndpointState;\n readonly failures: number;\n readonly height?: bigint;\n readonly lag?: bigint;\n readonly latencyMs?: number;\n readonly reason?: string;\n}\n\nexport interface Transport {\n readonly id: string;\n rpc<T = unknown>(method: string, params?: unknown, options?: CallOptions): Promise<T>;\n /** Posts an arbitrary JSON-RPC payload (single or batch) and returns the parsed body. */\n rpcRaw(payload: unknown, options?: CallOptions): Promise<unknown>;\n http<T = unknown>(request: HttpRequest, options?: CallOptions): Promise<T>;\n /** fetch-compatible function for SDKs; only `PLACEHOLDER_ORIGIN` URLs are accepted. */\n createFetch(\n classify?: (url: URL, init: RequestInit | undefined) => CallOptions,\n ): typeof fetch;\n setProbes(probes: HealthProbes): void;\n /** Whether any health probe (`identity` and/or `height`) has ever been configured via\n * `setProbes`. A transport with none configured can never mark an endpoint 'healthy' or\n * 'lagging' — its endpoints stay 'unknown' forever, which callers like `Blockchain.ready()`\n * treat as acceptable only in that case. */\n hasProbes(): boolean;\n refreshHealth(signal?: AbortSignal): Promise<void>;\n ensureFreshHealth(signal?: AbortSignal): Promise<void>;\n status(): EndpointStatus[];\n /**\n * Highest verified block height: a high-water mark (the stale-view guard of monitors\n * and scanners). It drops in two cases only: a height taken before an identity probe\n * existed stops counting once its endpoint turns out to serve another network, and a\n * peak that no verified endpoint comes within `maxLagBlocks` of for three health\n * refreshes in a row falls back to the verified best, so one forged far-future head\n * cannot keep every view stale until restart.\n */\n highestHeight(): bigint | undefined;\n /**\n * The lag tolerance in effect (`TransportOptions.maxLagBlocks`). The driver pool\n * resolves it in this order: the chain's `maxLagBlocks` config, else the root\n * `transport.maxLagBlocks`, else the plugin network's own, else the built-in default.\n * An endpoint further behind is lagging, and a view further behind `highestHeight()` is\n * stale.\n */\n readonly maxLagBlocks: number;\n}\n\n/** SDKs are configured with this origin; the transport maps it onto real endpoints. */\nexport const PLACEHOLDER_ORIGIN = 'https://transport.crypto-aio.invalid';\n"]}
@@ -24,6 +24,12 @@ export declare function quorumJson(value: unknown): string;
24
24
  */
25
25
  export declare function parseJson(text: string, exactIntegers?: boolean): unknown;
26
26
  export declare function sha256Hex(input: string | Uint8Array): string;
27
- /** JSON that round-trips bigint and Uint8Array (for external store implementations). */
27
+ /**
28
+ * JSON that round-trips bigint and Uint8Array (for external store implementations). Bytes
29
+ * are read from the holder, not from the replacer's value: `toJSON` runs first, and a
30
+ * Node.js `Buffer` (a Uint8Array, which the memory store keeps as bytes) would otherwise
31
+ * arrive as `{ type: 'Buffer', data }` and read back as a plain object. The check is by tag,
32
+ * as `clone` does, so bytes from another realm are bytes too.
33
+ */
28
34
  export declare function stringifyTagged(value: unknown): string;
29
35
  export declare function parseTagged<T = unknown>(text: string): T;
@@ -138,13 +138,22 @@ function parseJson(text, exactIntegers = false) {
138
138
  function sha256Hex(input) {
139
139
  return (0, utils_1.bytesToHex)((0, sha256_1.sha256)(typeof input === 'string' ? (0, utils_1.utf8ToBytes)(input) : input));
140
140
  }
141
- /** JSON that round-trips bigint and Uint8Array (for external store implementations). */
141
+ /**
142
+ * JSON that round-trips bigint and Uint8Array (for external store implementations). Bytes
143
+ * are read from the holder, not from the replacer's value: `toJSON` runs first, and a
144
+ * Node.js `Buffer` (a Uint8Array, which the memory store keeps as bytes) would otherwise
145
+ * arrive as `{ type: 'Buffer', data }` and read back as a plain object. The check is by tag,
146
+ * as `clone` does, so bytes from another realm are bytes too.
147
+ */
142
148
  function stringifyTagged(value) {
143
- return JSON.stringify(value, (_key, v) => {
149
+ return JSON.stringify(value, function (key, v) {
150
+ const raw = this[key];
151
+ if (Object.prototype.toString.call(raw) === '[object Uint8Array]') {
152
+ // A plain copy: the hex encoder checks its argument with `instanceof`.
153
+ return { $bytes: (0, bytes_1.toHex)(new Uint8Array(raw)) };
154
+ }
144
155
  if (typeof v === 'bigint')
145
156
  return { $bigint: v.toString() };
146
- if (v instanceof Uint8Array)
147
- return { $bytes: (0, bytes_1.toHex)(v) };
148
157
  return v;
149
158
  });
150
159
  }
@@ -1 +1 @@
1
- {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/core/util/json.ts"],"names":[],"mappings":"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","sourcesContent":["import { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\nimport { fromHex, toHex } from './bytes';\n\n/**\n * Deterministic JSON for hashing: object keys sorted, `undefined` properties omitted,\n * bigint → `{\"$bigint\":\"<decimal>\"}`, Uint8Array → `{\"$bytes\":\"<hex>\"}`.\n */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalize(value, new WeakSet()));\n}\n\nfunction canonicalize(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null) return null;\n switch (typeof value) {\n case 'string':\n case 'boolean':\n return value;\n case 'number':\n if (!Number.isFinite(value))\n throw new TypeError('canonicalJson: non-finite number');\n return value;\n case 'bigint':\n return { $bigint: value.toString() };\n case 'undefined':\n return undefined;\n case 'object':\n break;\n default:\n throw new TypeError(`canonicalJson: unsupported type ${typeof value}`);\n }\n if (value instanceof Uint8Array) return { $bytes: toHex(value) };\n if (seen.has(value)) throw new TypeError('canonicalJson: circular structure');\n seen.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((item) => {\n const c = canonicalize(item, seen);\n return c === undefined ? null : c;\n });\n }\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) {\n const toJSON = (value as { toJSON?: () => unknown }).toJSON;\n if (typeof toJSON === 'function') return canonicalize(toJSON.call(value), seen);\n throw new TypeError('canonicalJson: only plain objects are supported');\n }\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n const c = canonicalize((value as Record<string, unknown>)[key], seen);\n if (c !== undefined) out[key] = c;\n }\n return out;\n } finally {\n seen.delete(value);\n }\n}\n\n/**\n * Deterministic JSON for comparing quorum answers, which no two different values\n * share. `canonicalJson` writes a bigint as `{\"$bigint\":…}` and bytes as `{\"$bytes\":…}`, the\n * same text as a plain object with that key, so one endpoint's object could agree with\n * another's bigint; it also drops a `__proto__` key. Here every plain-object key that starts\n * with `$` gains one more `$`, and `__proto__` becomes `$__proto__`, before tagging, so no\n * two keys become one and no plain object's key is ever `$bigint` or `$bytes`.\n * `canonicalJson` itself is unchanged: the intent hash depends on it.\n */\nexport function quorumJson(value: unknown): string {\n return canonicalJson(escapeKeys(value, new WeakSet()));\n}\n\n/** `value` with the keys of its plain objects escaped as `quorumJson` describes. */\nfunction escapeKeys(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== 'object' || value instanceof Uint8Array)\n return value;\n if (seen.has(value)) throw new TypeError('canonicalJson: circular structure');\n seen.add(value);\n try {\n if (Array.isArray(value)) return value.map((item) => escapeKeys(item, seen));\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) {\n // As canonicalJson reads it: its toJSON() value, or (without one) a TypeError there.\n const toJSON = (value as { toJSON?: () => unknown }).toJSON;\n return typeof toJSON === 'function' ? escapeKeys(toJSON.call(value), seen) : value;\n }\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const escaped = key.startsWith('$') || key === '__proto__' ? `$${key}` : key;\n out[escaped] = escapeKeys((value as Record<string, unknown>)[key], seen);\n }\n return out;\n } finally {\n seen.delete(value);\n }\n}\n\n/** The longest integer literal `parseJson` revives, in digits without the sign. */\nconst MAX_EXACT_DIGITS = 80;\n\n/**\n * `JSON.parse`, optionally exact for integers: with `exactIntegers`, every integer\n * literal outside the safe range becomes a `bigint` read from its source text (Node ≥ 22\n * `JSON.parse` source text access), so a u64 amount is never rounded. Safe integers,\n * fractions and exponents stay numbers, so answers keep their shape for ordinary values.\n * With the flag, an integer literal longer than 80 digits (sign excluded) is malformed and\n * throws a `SyntaxError`, as `JSON.parse` does: no amount is that long (u256 has 78 digits),\n * and `BigInt()` of a multi-megabyte literal would take seconds.\n */\nexport function parseJson(text: string, exactIntegers = false): unknown {\n // A run of 16 digits is the shortest literal that can leave the safe range; without one,\n // the reviver (about 7 times slower on large bodies) cannot change anything.\n if (!exactIntegers || !/\\d{16}/.test(text)) return JSON.parse(text);\n return JSON.parse(\n text,\n (_key: string, value: unknown, context?: { readonly source?: string }) => {\n const source = context?.source;\n if (\n typeof value !== 'number' ||\n Number.isSafeInteger(value) ||\n source === undefined ||\n !/^-?\\d+$/.test(source)\n )\n return value;\n const digits = source.startsWith('-') ? source.length - 1 : source.length;\n if (digits > MAX_EXACT_DIGITS)\n throw new SyntaxError(`integer literal longer than ${MAX_EXACT_DIGITS} digits`);\n return BigInt(source);\n },\n );\n}\n\nexport function sha256Hex(input: string | Uint8Array): string {\n return bytesToHex(sha256(typeof input === 'string' ? utf8ToBytes(input) : input));\n}\n\n/** JSON that round-trips bigint and Uint8Array (for external store implementations). */\nexport function stringifyTagged(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) => {\n if (typeof v === 'bigint') return { $bigint: v.toString() };\n if (v instanceof Uint8Array) return { $bytes: toHex(v) };\n return v;\n });\n}\n\nexport function parseTagged<T = unknown>(text: string): T {\n return JSON.parse(text, (_key, v: unknown) => {\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n const o = v as Record<string, unknown>;\n if (Object.keys(o).length === 1) {\n if (typeof o.$bigint === 'string') return BigInt(o.$bigint);\n if (typeof o.$bytes === 'string') return fromHex(o.$bytes);\n }\n }\n return v;\n }) as T;\n}\n"]}
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/core/util/json.ts"],"names":[],"mappings":"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","sourcesContent":["import { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\nimport { fromHex, toHex } from './bytes';\n\n/**\n * Deterministic JSON for hashing: object keys sorted, `undefined` properties omitted,\n * bigint → `{\"$bigint\":\"<decimal>\"}`, Uint8Array → `{\"$bytes\":\"<hex>\"}`.\n */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalize(value, new WeakSet()));\n}\n\nfunction canonicalize(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null) return null;\n switch (typeof value) {\n case 'string':\n case 'boolean':\n return value;\n case 'number':\n if (!Number.isFinite(value))\n throw new TypeError('canonicalJson: non-finite number');\n return value;\n case 'bigint':\n return { $bigint: value.toString() };\n case 'undefined':\n return undefined;\n case 'object':\n break;\n default:\n throw new TypeError(`canonicalJson: unsupported type ${typeof value}`);\n }\n if (value instanceof Uint8Array) return { $bytes: toHex(value) };\n if (seen.has(value)) throw new TypeError('canonicalJson: circular structure');\n seen.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((item) => {\n const c = canonicalize(item, seen);\n return c === undefined ? null : c;\n });\n }\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) {\n const toJSON = (value as { toJSON?: () => unknown }).toJSON;\n if (typeof toJSON === 'function') return canonicalize(toJSON.call(value), seen);\n throw new TypeError('canonicalJson: only plain objects are supported');\n }\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n const c = canonicalize((value as Record<string, unknown>)[key], seen);\n if (c !== undefined) out[key] = c;\n }\n return out;\n } finally {\n seen.delete(value);\n }\n}\n\n/**\n * Deterministic JSON for comparing quorum answers, which no two different values\n * share. `canonicalJson` writes a bigint as `{\"$bigint\":…}` and bytes as `{\"$bytes\":…}`, the\n * same text as a plain object with that key, so one endpoint's object could agree with\n * another's bigint; it also drops a `__proto__` key. Here every plain-object key that starts\n * with `$` gains one more `$`, and `__proto__` becomes `$__proto__`, before tagging, so no\n * two keys become one and no plain object's key is ever `$bigint` or `$bytes`.\n * `canonicalJson` itself is unchanged: the intent hash depends on it.\n */\nexport function quorumJson(value: unknown): string {\n return canonicalJson(escapeKeys(value, new WeakSet()));\n}\n\n/** `value` with the keys of its plain objects escaped as `quorumJson` describes. */\nfunction escapeKeys(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== 'object' || value instanceof Uint8Array)\n return value;\n if (seen.has(value)) throw new TypeError('canonicalJson: circular structure');\n seen.add(value);\n try {\n if (Array.isArray(value)) return value.map((item) => escapeKeys(item, seen));\n const proto: unknown = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) {\n // As canonicalJson reads it: its toJSON() value, or (without one) a TypeError there.\n const toJSON = (value as { toJSON?: () => unknown }).toJSON;\n return typeof toJSON === 'function' ? escapeKeys(toJSON.call(value), seen) : value;\n }\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const escaped = key.startsWith('$') || key === '__proto__' ? `$${key}` : key;\n out[escaped] = escapeKeys((value as Record<string, unknown>)[key], seen);\n }\n return out;\n } finally {\n seen.delete(value);\n }\n}\n\n/** The longest integer literal `parseJson` revives, in digits without the sign. */\nconst MAX_EXACT_DIGITS = 80;\n\n/**\n * `JSON.parse`, optionally exact for integers: with `exactIntegers`, every integer\n * literal outside the safe range becomes a `bigint` read from its source text (Node ≥ 22\n * `JSON.parse` source text access), so a u64 amount is never rounded. Safe integers,\n * fractions and exponents stay numbers, so answers keep their shape for ordinary values.\n * With the flag, an integer literal longer than 80 digits (sign excluded) is malformed and\n * throws a `SyntaxError`, as `JSON.parse` does: no amount is that long (u256 has 78 digits),\n * and `BigInt()` of a multi-megabyte literal would take seconds.\n */\nexport function parseJson(text: string, exactIntegers = false): unknown {\n // A run of 16 digits is the shortest literal that can leave the safe range; without one,\n // the reviver (about 7 times slower on large bodies) cannot change anything.\n if (!exactIntegers || !/\\d{16}/.test(text)) return JSON.parse(text);\n return JSON.parse(\n text,\n (_key: string, value: unknown, context?: { readonly source?: string }) => {\n const source = context?.source;\n if (\n typeof value !== 'number' ||\n Number.isSafeInteger(value) ||\n source === undefined ||\n !/^-?\\d+$/.test(source)\n )\n return value;\n const digits = source.startsWith('-') ? source.length - 1 : source.length;\n if (digits > MAX_EXACT_DIGITS)\n throw new SyntaxError(`integer literal longer than ${MAX_EXACT_DIGITS} digits`);\n return BigInt(source);\n },\n );\n}\n\nexport function sha256Hex(input: string | Uint8Array): string {\n return bytesToHex(sha256(typeof input === 'string' ? utf8ToBytes(input) : input));\n}\n\n/**\n * JSON that round-trips bigint and Uint8Array (for external store implementations). Bytes\n * are read from the holder, not from the replacer's value: `toJSON` runs first, and a\n * Node.js `Buffer` (a Uint8Array, which the memory store keeps as bytes) would otherwise\n * arrive as `{ type: 'Buffer', data }` and read back as a plain object. The check is by tag,\n * as `clone` does, so bytes from another realm are bytes too.\n */\nexport function stringifyTagged(value: unknown): string {\n return JSON.stringify(value, function (this: unknown, key: string, v: unknown) {\n const raw = (this as Record<string, unknown>)[key];\n if (Object.prototype.toString.call(raw) === '[object Uint8Array]') {\n // A plain copy: the hex encoder checks its argument with `instanceof`.\n return { $bytes: toHex(new Uint8Array(raw as Uint8Array)) };\n }\n if (typeof v === 'bigint') return { $bigint: v.toString() };\n return v;\n });\n}\n\nexport function parseTagged<T = unknown>(text: string): T {\n return JSON.parse(text, (_key, v: unknown) => {\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n const o = v as Record<string, unknown>;\n if (Object.keys(o).length === 1) {\n if (typeof o.$bigint === 'string') return BigInt(o.$bigint);\n if (typeof o.$bytes === 'string') return fromHex(o.$bytes);\n }\n }\n return v;\n }) as T;\n}\n"]}
@@ -19,3 +19,9 @@ export declare function unknownName(what: string, accepted: Iterable<string>): s
19
19
  * library, such as a capability name), else `unshown`.
20
20
  */
21
21
  export declare function knownName(value: unknown, known: readonly string[], unshown: string): string;
22
+ /**
23
+ * Whether a caller's text can serve as a store key as it is: well-formed Unicode without
24
+ * U+0000. A database may refuse U+0000 (PostgreSQL does), and a driver may replace a lone
25
+ * surrogate with U+FFFD, so two different keys would become one.
26
+ */
27
+ export declare function storableText(text: string): boolean;
@@ -11,6 +11,7 @@ exports.MAX_LISTED_NAMES = void 0;
11
11
  exports.listNames = listNames;
12
12
  exports.unknownName = unknownName;
13
13
  exports.knownName = knownName;
14
+ exports.storableText = storableText;
14
15
  /** At most this many accepted names are listed; the rest are counted. */
15
16
  exports.MAX_LISTED_NAMES = 12;
16
17
  /** `'a'`, `'a' and 'b'`, `'a', 'b' and 'c'`, or `'a', …, 'l' and 3 more`: sorted, unique. */
@@ -43,4 +44,13 @@ function unknownName(what, accepted) {
43
44
  function knownName(value, known, unshown) {
44
45
  return typeof value === 'string' && known.includes(value) ? `'${value}'` : unshown;
45
46
  }
47
+ const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
48
+ /**
49
+ * Whether a caller's text can serve as a store key as it is: well-formed Unicode without
50
+ * U+0000. A database may refuse U+0000 (PostgreSQL does), and a driver may replace a lone
51
+ * surrogate with U+FFFD, so two different keys would become one.
52
+ */
53
+ function storableText(text) {
54
+ return !text.includes('\u0000') && !LONE_SURROGATE.test(text);
55
+ }
46
56
  //# sourceMappingURL=names.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"names.js","sourceRoot":"","sources":["../../../src/core/util/names.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAMH,8BAOC;AAMD,kCAMC;AAMD,8BAMC;AAnCD,yEAAyE;AAC5D,QAAA,gBAAgB,GAAG,EAAE,CAAC;AAEnC,6FAA6F;AAC7F,SAAgB,SAAS,CAAC,KAAuB;IAC/C,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAC5D,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAW,EAAE,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,IAAY,EAAE,QAA0B;IAClE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,IAAI,sBAAsB,CAAC;IACrE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACpB,OAAO,WAAW,IAAI,+BAA+B,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1E,OAAO,WAAW,IAAI,4BAA4B,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS,CACvB,KAAc,EACd,KAAwB,EACxB,OAAe;IAEf,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AACrF,CAAC","sourcesContent":["/**\n * How an error names something the caller typed (a chain, network,\n * library, provider, wallet, signer, scheme, asset alias, option key or capability). What a\n * caller typed may be a pasted secret, so an error never repeats it, at any length: it lists\n * the names that would have been accepted instead, which the library or the caller's own\n * configuration defined.\n */\n\n/** At most this many accepted names are listed; the rest are counted. */\nexport const MAX_LISTED_NAMES = 12;\n\n/** `'a'`, `'a' and 'b'`, `'a', 'b' and 'c'`, or `'a', …, 'l' and 3 more`: sorted, unique. */\nexport function listNames(names: Iterable<string>): string {\n const sorted = [...new Set(names)].sort();\n const shown = sorted.slice(0, MAX_LISTED_NAMES).map((name) => `'${name}'`);\n const rest = sorted.length - shown.length;\n if (rest > 0) return `${shown.join(', ')} and ${rest} more`;\n if (shown.length <= 1) return shown.join('');\n return `${shown.slice(0, -1).join(', ')} and ${shown.at(-1) as string}`;\n}\n\n/**\n * The text of a refusal of an unknown `what`, listing the accepted names and never the\n * caller's: `unknown network; the accepted names are 'mainnet' and 'sepolia'`.\n */\nexport function unknownName(what: string, accepted: Iterable<string>): string {\n const names = [...new Set(accepted)];\n if (names.length === 0) return `unknown ${what}; none is configured`;\n if (names.length === 1)\n return `unknown ${what}; the only accepted name is ${listNames(names)}`;\n return `unknown ${what}; the accepted names are ${listNames(names)}`;\n}\n\n/**\n * A value as an error may show it: quoted when it is one of `known` (a fixed word of this\n * library, such as a capability name), else `unshown`.\n */\nexport function knownName(\n value: unknown,\n known: readonly string[],\n unshown: string,\n): string {\n return typeof value === 'string' && known.includes(value) ? `'${value}'` : unshown;\n}\n"]}
1
+ {"version":3,"file":"names.js","sourceRoot":"","sources":["../../../src/core/util/names.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAMH,8BAOC;AAMD,kCAMC;AAMD,8BAMC;AAUD,oCAEC;AA/CD,yEAAyE;AAC5D,QAAA,gBAAgB,GAAG,EAAE,CAAC;AAEnC,6FAA6F;AAC7F,SAAgB,SAAS,CAAC,KAAuB;IAC/C,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAC5D,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAW,EAAE,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,IAAY,EAAE,QAA0B;IAClE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,IAAI,sBAAsB,CAAC;IACrE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACpB,OAAO,WAAW,IAAI,+BAA+B,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1E,OAAO,WAAW,IAAI,4BAA4B,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS,CACvB,KAAc,EACd,KAAwB,EACxB,OAAe;IAEf,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AACrF,CAAC;AAED,MAAM,cAAc,GAClB,wEAAwE,CAAC;AAE3E;;;;GAIG;AACH,SAAgB,YAAY,CAAC,IAAY;IACvC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC","sourcesContent":["/**\n * How an error names something the caller typed (a chain, network,\n * library, provider, wallet, signer, scheme, asset alias, option key or capability). What a\n * caller typed may be a pasted secret, so an error never repeats it, at any length: it lists\n * the names that would have been accepted instead, which the library or the caller's own\n * configuration defined.\n */\n\n/** At most this many accepted names are listed; the rest are counted. */\nexport const MAX_LISTED_NAMES = 12;\n\n/** `'a'`, `'a' and 'b'`, `'a', 'b' and 'c'`, or `'a', …, 'l' and 3 more`: sorted, unique. */\nexport function listNames(names: Iterable<string>): string {\n const sorted = [...new Set(names)].sort();\n const shown = sorted.slice(0, MAX_LISTED_NAMES).map((name) => `'${name}'`);\n const rest = sorted.length - shown.length;\n if (rest > 0) return `${shown.join(', ')} and ${rest} more`;\n if (shown.length <= 1) return shown.join('');\n return `${shown.slice(0, -1).join(', ')} and ${shown.at(-1) as string}`;\n}\n\n/**\n * The text of a refusal of an unknown `what`, listing the accepted names and never the\n * caller's: `unknown network; the accepted names are 'mainnet' and 'sepolia'`.\n */\nexport function unknownName(what: string, accepted: Iterable<string>): string {\n const names = [...new Set(accepted)];\n if (names.length === 0) return `unknown ${what}; none is configured`;\n if (names.length === 1)\n return `unknown ${what}; the only accepted name is ${listNames(names)}`;\n return `unknown ${what}; the accepted names are ${listNames(names)}`;\n}\n\n/**\n * A value as an error may show it: quoted when it is one of `known` (a fixed word of this\n * library, such as a capability name), else `unshown`.\n */\nexport function knownName(\n value: unknown,\n known: readonly string[],\n unshown: string,\n): string {\n return typeof value === 'string' && known.includes(value) ? `'${value}'` : unshown;\n}\n\nconst LONE_SURROGATE =\n /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/;\n\n/**\n * Whether a caller's text can serve as a store key as it is: well-formed Unicode without\n * U+0000. A database may refuse U+0000 (PostgreSQL does), and a driver may replace a lone\n * surrogate with U+FFFD, so two different keys would become one.\n */\nexport function storableText(text: string): boolean {\n return !text.includes('\\u0000') && !LONE_SURROGATE.test(text);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ export type { ChainId, ChainRegistry, ExtOf, FamilyOf, FamilyRegistry, KnownLibr
34
34
  export type { DriverIntent, DriverOutput, IntentSummary, StoredIntent, TransferIntent, TransferOutputInput, } from './core/model/intent';
35
35
  export { mutuallyExclusive } from './core/model/ordering';
36
36
  export type { OrderingData, OrderingKind } from './core/model/ordering';
37
- export type { AttemptIdKind, AttemptRef, Block, BlockRef, Decoding, Evidence, Finality, RawTx, ResolvedTransfer, SignedTx, Transaction, Transfer, TransferSource, TxState, TxStatus, UnresolvedTransfer, UnsignedTx, } from './core/model/transaction';
37
+ export type { AttemptIdKind, AttemptRef, Block, BlockRef, Decoding, Evidence, Finality, RawTx, ResolvedTransfer, SignedTx, Transaction, Transfer, TransferSource, TxFailure, TxState, TxStatus, UnresolvedTransfer, UnsignedTx, } from './core/model/transaction';
38
38
  export type { AioOptions, ChainDefaults, HandleConfig, HandleOptions, Hooks, LifecycleOptions, ProviderConfig, ProviderRef, ScopeOptions, WalletConfig, } from './core/config/types';
39
39
  export type { TransferOptions } from './core/lifecycle/engine';
40
40
  export type { ConfirmationResult, RecoveryReport, TxStatusEvent, WaitOptions, WorkerOptions, } from './core/lifecycle/monitor';
@@ -47,6 +47,7 @@ export type { AssetRegistration } from './core/registry/assets';
47
47
  export { BUILTIN_SCHEMES } from './core/registry/schemes';
48
48
  export type { SignatureScheme, VerifyInput } from './core/registry/schemes';
49
49
  export { MemoryCursorStore, MemoryLockManager, MemoryOperationStore, MemorySequenceStore, createMemoryStores, } from './core/store/memory';
50
+ export { OPERATION_FORMAT } from './core/store/format';
50
51
  export { CLEARABLE_FIELDS, DATA_CLASSIFICATION, NON_TERMINAL_STATES, OPERATION_PATCH_KEYS, TERMINAL_STATES, isTerminal, } from './core/store/types';
51
52
  export type { AttemptObservation, AttemptPurpose, AttemptRecord, ClearableField, CreateResult, CursorStore, DataClass, ExecutionContext, Fence, Lease, LockManager, NewOperation, OperationClaim, OperationFilter, OperationPatch, OperationRecord, OperationState, OperationStore, ScanCursor, SequenceState, SequenceStore, StoredCursor, Stores, } from './core/store/types';
52
53
  export { parseTagged, stringifyTagged } from './core/util/json';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PLACEHOLDER_ORIGIN = exports.stringifyTagged = exports.parseTagged = exports.isTerminal = exports.TERMINAL_STATES = exports.OPERATION_PATCH_KEYS = exports.NON_TERMINAL_STATES = exports.DATA_CLASSIFICATION = exports.CLEARABLE_FIELDS = exports.createMemoryStores = exports.MemorySequenceStore = exports.MemoryOperationStore = exports.MemoryLockManager = exports.MemoryCursorStore = exports.BUILTIN_SCHEMES = exports.mutuallyExclusive = exports.Library = exports.feeTotal = exports.explorerUrl = exports.KNOWN_CAPABILITIES = exports.parseAssetId = exports.assetId = exports.Amount = exports.Address = exports.deriveXpubChild = exports.callbackSigner = exports.localSigner = exports.redactUrl = exports.redactDeep = exports.secret = exports.reveal = exports.isSecret = exports.Secret = exports.REDACTED = exports.isCryptoAioError = exports.createError = exports.ValidationError = exports.UnsupportedCapabilityError = exports.TimeoutError = exports.StateError = exports.SigningError = exports.ProviderError = exports.CryptoAioError = exports.ConfigError = exports.ChainError = exports.ERROR_CODES = exports.defaultContainer = exports.configure = exports.CryptoAio = exports.Blockchain = void 0;
4
- exports.noopLogger = exports.createLogger = void 0;
3
+ exports.stringifyTagged = exports.parseTagged = exports.isTerminal = exports.TERMINAL_STATES = exports.OPERATION_PATCH_KEYS = exports.NON_TERMINAL_STATES = exports.DATA_CLASSIFICATION = exports.CLEARABLE_FIELDS = exports.OPERATION_FORMAT = exports.createMemoryStores = exports.MemorySequenceStore = exports.MemoryOperationStore = exports.MemoryLockManager = exports.MemoryCursorStore = exports.BUILTIN_SCHEMES = exports.mutuallyExclusive = exports.Library = exports.feeTotal = exports.explorerUrl = exports.KNOWN_CAPABILITIES = exports.parseAssetId = exports.assetId = exports.Amount = exports.Address = exports.deriveXpubChild = exports.callbackSigner = exports.localSigner = exports.redactUrl = exports.redactDeep = exports.secret = exports.reveal = exports.isSecret = exports.Secret = exports.REDACTED = exports.isCryptoAioError = exports.createError = exports.ValidationError = exports.UnsupportedCapabilityError = exports.TimeoutError = exports.StateError = exports.SigningError = exports.ProviderError = exports.CryptoAioError = exports.ConfigError = exports.ChainError = exports.ERROR_CODES = exports.defaultContainer = exports.configure = exports.CryptoAio = exports.Blockchain = void 0;
4
+ exports.noopLogger = exports.createLogger = exports.PLACEHOLDER_ORIGIN = void 0;
5
5
  /**
6
6
  * `crypto-aio`: the container (`CryptoAio`), the handle (`Blockchain`), the domain model,
7
7
  * errors, signers, stores and the extension points for chain family plugins.
@@ -90,6 +90,8 @@ Object.defineProperty(exports, "MemoryLockManager", { enumerable: true, get: fun
90
90
  Object.defineProperty(exports, "MemoryOperationStore", { enumerable: true, get: function () { return memory_1.MemoryOperationStore; } });
91
91
  Object.defineProperty(exports, "MemorySequenceStore", { enumerable: true, get: function () { return memory_1.MemorySequenceStore; } });
92
92
  Object.defineProperty(exports, "createMemoryStores", { enumerable: true, get: function () { return memory_1.createMemoryStores; } });
93
+ var format_1 = require("./core/store/format");
94
+ Object.defineProperty(exports, "OPERATION_FORMAT", { enumerable: true, get: function () { return format_1.OPERATION_FORMAT; } });
93
95
  var types_1 = require("./core/store/types");
94
96
  Object.defineProperty(exports, "CLEARABLE_FIELDS", { enumerable: true, get: function () { return types_1.CLEARABLE_FIELDS; } });
95
97
  Object.defineProperty(exports, "DATA_CLASSIFICATION", { enumerable: true, get: function () { return types_1.DATA_CLASSIFICATION; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA;;;;;GAKG;AACH,wDAA8D;AAC9D,kDAAkD;AAClD,qDAAwD;AACxD,kDAAkD;AAClD,mDAAoD;AACpD,mDAAoD;AACpD,wDAA8D;AAG9D,iGAAiG;AACjG,MAAM,eAAe,GAAsB;IACzC,IAAA,kBAAS,GAAE;IACX,IAAA,mBAAU,GAAE;IACZ,IAAA,mBAAU,GAAE;IACZ,IAAA,qBAAY,GAAE;IACd,IAAA,kBAAS,GAAE;IACX,IAAA,wBAAe,GAAE;CAClB,CAAC;AACF,IAAA,4BAAiB,EAAC,eAAe,CAAC,CAAC;AAEnC,eAAe;AACf,mDAAsD;AAA7C,oGAAA,UAAU,OAAA;AAEnB,wDAAuD;AAA9C,sGAAA,SAAS,OAAA;AAMlB,oDAAuE;AAA9D,oGAAA,SAAS,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAEpC,SAAS;AACT,6CAAkD;AAAzC,oGAAA,WAAW,OAAA;AAEpB,6CAY6B;AAX3B,mGAAA,UAAU,OAAA;AACV,oGAAA,WAAW,OAAA;AACX,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,qGAAA,YAAY,OAAA;AACZ,mGAAA,UAAU,OAAA;AACV,qGAAA,YAAY,OAAA;AACZ,mHAAA,0BAA0B,OAAA;AAC1B,wGAAA,eAAe,OAAA;AACf,oGAAA,WAAW,OAAA;AACX,yGAAA,gBAAgB,OAAA;AASlB,sBAAsB;AACtB,+CAAkF;AAAzE,kGAAA,QAAQ,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,gGAAA,MAAM,OAAA;AACnD,+CAA6D;AAApD,oGAAA,UAAU,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC9B,8CAAmD;AAA1C,oGAAA,WAAW,OAAA;AAQpB,oDAAyD;AAAhD,0GAAA,cAAc,OAAA;AAEvB,wCAAoD;AAA3C,qGAAA,eAAe,OAAA;AAexB,eAAe;AACf,gDAA+C;AAAtC,kGAAA,OAAO,OAAA;AAEhB,8CAA6C;AAApC,gGAAA,MAAM,OAAA;AAEf,4CAA2D;AAAlD,gGAAA,OAAO,OAAA;AAAE,qGAAA,YAAY,OAAA;AAQ9B,sDAA6D;AAApD,gHAAA,kBAAkB,OAAA;AAE3B,4CAAiD;AAAxC,oGAAA,WAAW,OAAA;AAOpB,wCAA4C;AAAnC,+FAAA,QAAQ,OAAA;AAUjB,wCAA2C;AAAlC,8FAAA,OAAO,OAAA;AAoBhB,kDAA0D;AAAjD,6GAAA,iBAAiB,OAAA;AA6F1B,mDAA0D;AAAjD,0GAAA,eAAe,OAAA;AAExB,8CAM6B;AAL3B,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AACjB,8GAAA,oBAAoB,OAAA;AACpB,6GAAA,mBAAmB,OAAA;AACnB,4GAAA,kBAAkB,OAAA;AAEpB,4CAO4B;AAN1B,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,6GAAA,oBAAoB,OAAA;AACpB,wGAAA,eAAe,OAAA;AACf,mGAAA,UAAU,OAAA;AA2BZ,yCAAgE;AAAvD,mGAAA,WAAW,OAAA;AAAE,uGAAA,eAAe,OAAA;AACrC,gDAA4D;AAAnD,2GAAA,kBAAkB,OAAA;AAe3B,+CAAgE;AAAvD,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA","sourcesContent":["/**\n * `crypto-aio`: the container (`CryptoAio`), the handle (`Blockchain`), the domain model,\n * errors, signers, stores and the extension points for chain family plugins.\n *\n * @module crypto-aio\n */\nimport { avalanchePlugin } from './adapters/avalanche/plugin';\nimport { evmPlugin } from './adapters/evm/plugin';\nimport { solanaPlugin } from './adapters/solana/plugin';\nimport { tonPlugin } from './adapters/ton/plugin';\nimport { tronPlugin } from './adapters/tron/plugin';\nimport { utxoPlugin } from './adapters/utxo/plugin';\nimport { setBuiltinPlugins } from './core/container/builtins';\nimport type { Plugin } from './core/registry/plugin';\n\n/** Built-in chain family plugins. Each family plugin module is SDK-free; drivers load lazily. */\nconst BUILTIN_PLUGINS: readonly Plugin[] = [\n evmPlugin(),\n utxoPlugin(),\n tronPlugin(),\n solanaPlugin(),\n tonPlugin(),\n avalanchePlugin(),\n];\nsetBuiltinPlugins(BUILTIN_PLUGINS);\n\n// Entry points\nexport { Blockchain } from './core/blockchain/handle';\nexport type { Balance, NetworkStatus } from './core/blockchain/handle';\nexport { CryptoAio } from './core/container/container';\nexport type {\n MonitorApi,\n OperationsApi,\n OperationsFilter,\n} from './core/container/container';\nexport { configure, defaultContainer } from './core/container/default';\n\n// Errors\nexport { ERROR_CODES } from './core/errors/codes';\nexport type { CodesOf, ErrorCategory, ErrorCode } from './core/errors/codes';\nexport {\n ChainError,\n ConfigError,\n CryptoAioError,\n ProviderError,\n SigningError,\n StateError,\n TimeoutError,\n UnsupportedCapabilityError,\n ValidationError,\n createError,\n isCryptoAioError,\n} from './core/errors/error';\nexport type {\n CryptoAioErrorOptions,\n ErrorContext,\n ErrorContextValue,\n SerializedError,\n} from './core/errors/error';\n\n// Secrets and signing\nexport { REDACTED, Secret, isSecret, reveal, secret } from './core/secret/secret';\nexport { redactDeep, redactUrl } from './core/secret/redact';\nexport { localSigner } from './core/signing/local';\nexport type {\n Curve,\n GenerateOptions,\n GeneratedSigner,\n LocalSignerOptions,\n MnemonicSignerOptions,\n} from './core/signing/local';\nexport { callbackSigner } from './core/signing/callback';\nexport type { CallbackSignerOptions } from './core/signing/callback';\nexport { deriveXpubChild } from './core/signing/hd';\nexport type { ExtendedKeyVersions } from './core/signing/hd';\nexport type { WalletHdOptions } from './core/signing/wallet';\nexport type {\n KeyRef,\n SignatureBundle,\n Signer,\n SignerTicket,\n SigningContext,\n SigningParams,\n SigningPurpose,\n SigningRequest,\n SigningResult,\n} from './core/signing/types';\n\n// Domain model\nexport { Address } from './core/model/address';\nexport type { AddressFormatter, NormalizedAddress } from './core/model/address';\nexport { Amount } from './core/model/amount';\nexport type { AmountInput } from './core/model/amount';\nexport { assetId, parseAssetId } from './core/model/asset';\nexport type {\n AssetId,\n AssetInfo,\n AssetMetadata,\n AssetRef,\n TokenRef,\n} from './core/model/asset';\nexport { KNOWN_CAPABILITIES } from './core/model/capability';\nexport type { Capability, KnownCapability } from './core/model/capability';\nexport { explorerUrl } from './core/model/chain';\nexport type {\n ChainInfo,\n FinalityPolicy,\n NativeAssetInfo,\n NetworkInfo,\n} from './core/model/chain';\nexport { feeTotal } from './core/model/fee';\nexport type {\n FeeBound,\n FeeCharge,\n FeeChargeDraft,\n FeeEstimate,\n FeeEstimateDraft,\n FeeOverride,\n FeeSpeed,\n} from './core/model/fee';\nexport { Library } from './core/model/ids';\nexport type {\n ChainId,\n ChainRegistry,\n ExtOf,\n FamilyOf,\n FamilyRegistry,\n KnownLibrary,\n LibraryOf,\n NativeClientMap,\n NetworkOf,\n} from './core/model/ids';\nexport type {\n DriverIntent,\n DriverOutput,\n IntentSummary,\n StoredIntent,\n TransferIntent,\n TransferOutputInput,\n} from './core/model/intent';\nexport { mutuallyExclusive } from './core/model/ordering';\nexport type { OrderingData, OrderingKind } from './core/model/ordering';\nexport type {\n AttemptIdKind,\n AttemptRef,\n Block,\n BlockRef,\n Decoding,\n Evidence,\n Finality,\n RawTx,\n ResolvedTransfer,\n SignedTx,\n Transaction,\n Transfer,\n TransferSource,\n TxState,\n TxStatus,\n UnresolvedTransfer,\n UnsignedTx,\n} from './core/model/transaction';\n\n// Configuration\nexport type {\n AioOptions,\n ChainDefaults,\n HandleConfig,\n HandleOptions,\n Hooks,\n LifecycleOptions,\n ProviderConfig,\n ProviderRef,\n ScopeOptions,\n WalletConfig,\n} from './core/config/types';\n\n// Lifecycle and observation\nexport type { TransferOptions } from './core/lifecycle/engine';\nexport type {\n ConfirmationResult,\n RecoveryReport,\n TxStatusEvent,\n WaitOptions,\n WorkerOptions,\n} from './core/lifecycle/monitor';\nexport type {\n AttemptView,\n OperationView,\n PreparedOperation,\n Submission,\n} from './core/lifecycle/views';\n// Type only; scanners come from `bc.scanner()`.\nexport type {\n Checkpoint,\n ScanEvent,\n ScanEventBody,\n Scanner,\n ScannerOptions,\n} from './core/observe/scanner';\n\n// Extension points: drivers, plugins, presets, schemes, stores, transport, events\nexport type {\n AdapterManifest,\n AddressCodec,\n AddressHistorySource,\n BlockSource,\n BroadcastResult,\n Broadcaster,\n BuildContext,\n ChainDriver,\n ChainReader,\n DisposableNativeClient,\n DriverBlock,\n DriverContext,\n DriverFactory,\n DriverLimits,\n DriverTransaction,\n DriverTransfer,\n DriverTxObservation,\n FinalityLevel,\n FundsCheck,\n PeerDependency,\n ProofSource,\n ReplacementPolicy,\n ScanFilter,\n SequenceSource,\n TxBuilder,\n WalletKey,\n WalletOptions,\n} from './core/driver/types';\nexport type { Plugin } from './core/registry/plugin';\nexport type { PresetInput, ProviderPreset } from './core/registry/providers';\nexport type { AssetRegistration } from './core/registry/assets';\nexport { BUILTIN_SCHEMES } from './core/registry/schemes';\nexport type { SignatureScheme, VerifyInput } from './core/registry/schemes';\nexport {\n MemoryCursorStore,\n MemoryLockManager,\n MemoryOperationStore,\n MemorySequenceStore,\n createMemoryStores,\n} from './core/store/memory';\nexport {\n CLEARABLE_FIELDS,\n DATA_CLASSIFICATION,\n NON_TERMINAL_STATES,\n OPERATION_PATCH_KEYS,\n TERMINAL_STATES,\n isTerminal,\n} from './core/store/types';\nexport type {\n AttemptObservation,\n AttemptPurpose,\n AttemptRecord,\n ClearableField,\n CreateResult,\n CursorStore,\n DataClass,\n ExecutionContext,\n Fence,\n Lease,\n LockManager,\n NewOperation,\n OperationClaim,\n OperationFilter,\n OperationPatch,\n OperationRecord,\n OperationState,\n OperationStore,\n ScanCursor,\n SequenceState,\n SequenceStore,\n StoredCursor,\n Stores,\n} from './core/store/types';\nexport { parseTagged, stringifyTagged } from './core/util/json';\nexport { PLACEHOLDER_ORIGIN } from './core/transport/types';\nexport type {\n CallOptions,\n EndpointCall,\n EndpointConfig,\n EndpointState,\n EndpointStatus,\n HealthProbes,\n HttpRequest,\n RequestPurpose,\n RetryClass,\n Transport,\n TransportOptions,\n} from './core/transport/types';\nexport type { AioEvent, AioEventName, AioEvents } from './core/events/types';\nexport { createLogger, noopLogger } from './core/events/logger';\nexport type { LogFields, LogLevel, LogWriter, Logger } from './core/events/logger';\nexport type { Clock } from './core/util/clock';\n\n// Chain families: SDK-free types. SDK client types are in `crypto-aio/avalanche`,\n// `crypto-aio/evm`, `crypto-aio/solana`, `crypto-aio/ton`, `crypto-aio/tron` and\n// `crypto-aio/utxo`.\nexport type { EvmExt, EvmFeeDetails, EvmFeeOverride } from './adapters/evm/types';\nexport type {\n TronExpiryOrdering,\n TronExt,\n TronFeeDetails,\n TronFeeOverride,\n TronResources,\n} from './adapters/tron/types';\nexport type {\n UtxoAddressType,\n UtxoExt,\n UtxoFeeDetails,\n UtxoFeeOverride,\n UtxoOutputType,\n UtxoSelectionPreview,\n UtxoSelectionRequest,\n UtxoUnspent,\n UtxoWalletOptions,\n} from './adapters/utxo/types';\nexport type {\n SolanaExpiryOrdering,\n SolanaExt,\n SolanaFeeDetails,\n SolanaFeeOverride,\n SolanaTokenAccount,\n} from './adapters/solana/types';\nexport type {\n TonExt,\n TonFeeDetails,\n TonFeeOverride,\n TonSeqnoOrdering,\n TonWalletIdentity,\n TonWalletVersion,\n} from './adapters/ton/types';\nexport type {\n AvalancheExt,\n AvalancheFeeDetails,\n AvalancheFeeOverride,\n AvalancheUnspent,\n AvalancheVm,\n} from './adapters/avalanche/types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA;;;;;GAKG;AACH,wDAA8D;AAC9D,kDAAkD;AAClD,qDAAwD;AACxD,kDAAkD;AAClD,mDAAoD;AACpD,mDAAoD;AACpD,wDAA8D;AAG9D,iGAAiG;AACjG,MAAM,eAAe,GAAsB;IACzC,IAAA,kBAAS,GAAE;IACX,IAAA,mBAAU,GAAE;IACZ,IAAA,mBAAU,GAAE;IACZ,IAAA,qBAAY,GAAE;IACd,IAAA,kBAAS,GAAE;IACX,IAAA,wBAAe,GAAE;CAClB,CAAC;AACF,IAAA,4BAAiB,EAAC,eAAe,CAAC,CAAC;AAEnC,eAAe;AACf,mDAAsD;AAA7C,oGAAA,UAAU,OAAA;AAEnB,wDAAuD;AAA9C,sGAAA,SAAS,OAAA;AAMlB,oDAAuE;AAA9D,oGAAA,SAAS,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAEpC,SAAS;AACT,6CAAkD;AAAzC,oGAAA,WAAW,OAAA;AAEpB,6CAY6B;AAX3B,mGAAA,UAAU,OAAA;AACV,oGAAA,WAAW,OAAA;AACX,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,qGAAA,YAAY,OAAA;AACZ,mGAAA,UAAU,OAAA;AACV,qGAAA,YAAY,OAAA;AACZ,mHAAA,0BAA0B,OAAA;AAC1B,wGAAA,eAAe,OAAA;AACf,oGAAA,WAAW,OAAA;AACX,yGAAA,gBAAgB,OAAA;AASlB,sBAAsB;AACtB,+CAAkF;AAAzE,kGAAA,QAAQ,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,gGAAA,MAAM,OAAA;AACnD,+CAA6D;AAApD,oGAAA,UAAU,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC9B,8CAAmD;AAA1C,oGAAA,WAAW,OAAA;AAQpB,oDAAyD;AAAhD,0GAAA,cAAc,OAAA;AAEvB,wCAAoD;AAA3C,qGAAA,eAAe,OAAA;AAexB,eAAe;AACf,gDAA+C;AAAtC,kGAAA,OAAO,OAAA;AAEhB,8CAA6C;AAApC,gGAAA,MAAM,OAAA;AAEf,4CAA2D;AAAlD,gGAAA,OAAO,OAAA;AAAE,qGAAA,YAAY,OAAA;AAQ9B,sDAA6D;AAApD,gHAAA,kBAAkB,OAAA;AAE3B,4CAAiD;AAAxC,oGAAA,WAAW,OAAA;AAOpB,wCAA4C;AAAnC,+FAAA,QAAQ,OAAA;AAUjB,wCAA2C;AAAlC,8FAAA,OAAO,OAAA;AAoBhB,kDAA0D;AAAjD,6GAAA,iBAAiB,OAAA;AA8F1B,mDAA0D;AAAjD,0GAAA,eAAe,OAAA;AAExB,8CAM6B;AAL3B,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AACjB,8GAAA,oBAAoB,OAAA;AACpB,6GAAA,mBAAmB,OAAA;AACnB,4GAAA,kBAAkB,OAAA;AAEpB,8CAAuD;AAA9C,0GAAA,gBAAgB,OAAA;AACzB,4CAO4B;AAN1B,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,6GAAA,oBAAoB,OAAA;AACpB,wGAAA,eAAe,OAAA;AACf,mGAAA,UAAU,OAAA;AA2BZ,yCAAgE;AAAvD,mGAAA,WAAW,OAAA;AAAE,uGAAA,eAAe,OAAA;AACrC,gDAA4D;AAAnD,2GAAA,kBAAkB,OAAA;AAe3B,+CAAgE;AAAvD,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA","sourcesContent":["/**\n * `crypto-aio`: the container (`CryptoAio`), the handle (`Blockchain`), the domain model,\n * errors, signers, stores and the extension points for chain family plugins.\n *\n * @module crypto-aio\n */\nimport { avalanchePlugin } from './adapters/avalanche/plugin';\nimport { evmPlugin } from './adapters/evm/plugin';\nimport { solanaPlugin } from './adapters/solana/plugin';\nimport { tonPlugin } from './adapters/ton/plugin';\nimport { tronPlugin } from './adapters/tron/plugin';\nimport { utxoPlugin } from './adapters/utxo/plugin';\nimport { setBuiltinPlugins } from './core/container/builtins';\nimport type { Plugin } from './core/registry/plugin';\n\n/** Built-in chain family plugins. Each family plugin module is SDK-free; drivers load lazily. */\nconst BUILTIN_PLUGINS: readonly Plugin[] = [\n evmPlugin(),\n utxoPlugin(),\n tronPlugin(),\n solanaPlugin(),\n tonPlugin(),\n avalanchePlugin(),\n];\nsetBuiltinPlugins(BUILTIN_PLUGINS);\n\n// Entry points\nexport { Blockchain } from './core/blockchain/handle';\nexport type { Balance, NetworkStatus } from './core/blockchain/handle';\nexport { CryptoAio } from './core/container/container';\nexport type {\n MonitorApi,\n OperationsApi,\n OperationsFilter,\n} from './core/container/container';\nexport { configure, defaultContainer } from './core/container/default';\n\n// Errors\nexport { ERROR_CODES } from './core/errors/codes';\nexport type { CodesOf, ErrorCategory, ErrorCode } from './core/errors/codes';\nexport {\n ChainError,\n ConfigError,\n CryptoAioError,\n ProviderError,\n SigningError,\n StateError,\n TimeoutError,\n UnsupportedCapabilityError,\n ValidationError,\n createError,\n isCryptoAioError,\n} from './core/errors/error';\nexport type {\n CryptoAioErrorOptions,\n ErrorContext,\n ErrorContextValue,\n SerializedError,\n} from './core/errors/error';\n\n// Secrets and signing\nexport { REDACTED, Secret, isSecret, reveal, secret } from './core/secret/secret';\nexport { redactDeep, redactUrl } from './core/secret/redact';\nexport { localSigner } from './core/signing/local';\nexport type {\n Curve,\n GenerateOptions,\n GeneratedSigner,\n LocalSignerOptions,\n MnemonicSignerOptions,\n} from './core/signing/local';\nexport { callbackSigner } from './core/signing/callback';\nexport type { CallbackSignerOptions } from './core/signing/callback';\nexport { deriveXpubChild } from './core/signing/hd';\nexport type { ExtendedKeyVersions } from './core/signing/hd';\nexport type { WalletHdOptions } from './core/signing/wallet';\nexport type {\n KeyRef,\n SignatureBundle,\n Signer,\n SignerTicket,\n SigningContext,\n SigningParams,\n SigningPurpose,\n SigningRequest,\n SigningResult,\n} from './core/signing/types';\n\n// Domain model\nexport { Address } from './core/model/address';\nexport type { AddressFormatter, NormalizedAddress } from './core/model/address';\nexport { Amount } from './core/model/amount';\nexport type { AmountInput } from './core/model/amount';\nexport { assetId, parseAssetId } from './core/model/asset';\nexport type {\n AssetId,\n AssetInfo,\n AssetMetadata,\n AssetRef,\n TokenRef,\n} from './core/model/asset';\nexport { KNOWN_CAPABILITIES } from './core/model/capability';\nexport type { Capability, KnownCapability } from './core/model/capability';\nexport { explorerUrl } from './core/model/chain';\nexport type {\n ChainInfo,\n FinalityPolicy,\n NativeAssetInfo,\n NetworkInfo,\n} from './core/model/chain';\nexport { feeTotal } from './core/model/fee';\nexport type {\n FeeBound,\n FeeCharge,\n FeeChargeDraft,\n FeeEstimate,\n FeeEstimateDraft,\n FeeOverride,\n FeeSpeed,\n} from './core/model/fee';\nexport { Library } from './core/model/ids';\nexport type {\n ChainId,\n ChainRegistry,\n ExtOf,\n FamilyOf,\n FamilyRegistry,\n KnownLibrary,\n LibraryOf,\n NativeClientMap,\n NetworkOf,\n} from './core/model/ids';\nexport type {\n DriverIntent,\n DriverOutput,\n IntentSummary,\n StoredIntent,\n TransferIntent,\n TransferOutputInput,\n} from './core/model/intent';\nexport { mutuallyExclusive } from './core/model/ordering';\nexport type { OrderingData, OrderingKind } from './core/model/ordering';\nexport type {\n AttemptIdKind,\n AttemptRef,\n Block,\n BlockRef,\n Decoding,\n Evidence,\n Finality,\n RawTx,\n ResolvedTransfer,\n SignedTx,\n Transaction,\n Transfer,\n TransferSource,\n TxFailure,\n TxState,\n TxStatus,\n UnresolvedTransfer,\n UnsignedTx,\n} from './core/model/transaction';\n\n// Configuration\nexport type {\n AioOptions,\n ChainDefaults,\n HandleConfig,\n HandleOptions,\n Hooks,\n LifecycleOptions,\n ProviderConfig,\n ProviderRef,\n ScopeOptions,\n WalletConfig,\n} from './core/config/types';\n\n// Lifecycle and observation\nexport type { TransferOptions } from './core/lifecycle/engine';\nexport type {\n ConfirmationResult,\n RecoveryReport,\n TxStatusEvent,\n WaitOptions,\n WorkerOptions,\n} from './core/lifecycle/monitor';\nexport type {\n AttemptView,\n OperationView,\n PreparedOperation,\n Submission,\n} from './core/lifecycle/views';\n// Type only; scanners come from `bc.scanner()`.\nexport type {\n Checkpoint,\n ScanEvent,\n ScanEventBody,\n Scanner,\n ScannerOptions,\n} from './core/observe/scanner';\n\n// Extension points: drivers, plugins, presets, schemes, stores, transport, events\nexport type {\n AdapterManifest,\n AddressCodec,\n AddressHistorySource,\n BlockSource,\n BroadcastResult,\n Broadcaster,\n BuildContext,\n ChainDriver,\n ChainReader,\n DisposableNativeClient,\n DriverBlock,\n DriverContext,\n DriverFactory,\n DriverLimits,\n DriverTransaction,\n DriverTransfer,\n DriverTxObservation,\n FinalityLevel,\n FundsCheck,\n PeerDependency,\n ProofSource,\n ReplacementPolicy,\n ScanFilter,\n SequenceSource,\n TxBuilder,\n WalletKey,\n WalletOptions,\n} from './core/driver/types';\nexport type { Plugin } from './core/registry/plugin';\nexport type { PresetInput, ProviderPreset } from './core/registry/providers';\nexport type { AssetRegistration } from './core/registry/assets';\nexport { BUILTIN_SCHEMES } from './core/registry/schemes';\nexport type { SignatureScheme, VerifyInput } from './core/registry/schemes';\nexport {\n MemoryCursorStore,\n MemoryLockManager,\n MemoryOperationStore,\n MemorySequenceStore,\n createMemoryStores,\n} from './core/store/memory';\nexport { OPERATION_FORMAT } from './core/store/format';\nexport {\n CLEARABLE_FIELDS,\n DATA_CLASSIFICATION,\n NON_TERMINAL_STATES,\n OPERATION_PATCH_KEYS,\n TERMINAL_STATES,\n isTerminal,\n} from './core/store/types';\nexport type {\n AttemptObservation,\n AttemptPurpose,\n AttemptRecord,\n ClearableField,\n CreateResult,\n CursorStore,\n DataClass,\n ExecutionContext,\n Fence,\n Lease,\n LockManager,\n NewOperation,\n OperationClaim,\n OperationFilter,\n OperationPatch,\n OperationRecord,\n OperationState,\n OperationStore,\n ScanCursor,\n SequenceState,\n SequenceStore,\n StoredCursor,\n Stores,\n} from './core/store/types';\nexport { parseTagged, stringifyTagged } from './core/util/json';\nexport { PLACEHOLDER_ORIGIN } from './core/transport/types';\nexport type {\n CallOptions,\n EndpointCall,\n EndpointConfig,\n EndpointState,\n EndpointStatus,\n HealthProbes,\n HttpRequest,\n RequestPurpose,\n RetryClass,\n Transport,\n TransportOptions,\n} from './core/transport/types';\nexport type { AioEvent, AioEventName, AioEvents } from './core/events/types';\nexport { createLogger, noopLogger } from './core/events/logger';\nexport type { LogFields, LogLevel, LogWriter, Logger } from './core/events/logger';\nexport type { Clock } from './core/util/clock';\n\n// Chain families: SDK-free types. SDK client types are in `crypto-aio/avalanche`,\n// `crypto-aio/evm`, `crypto-aio/solana`, `crypto-aio/ton`, `crypto-aio/tron` and\n// `crypto-aio/utxo`.\nexport type { EvmExt, EvmFeeDetails, EvmFeeOverride } from './adapters/evm/types';\nexport type {\n TronExpiryOrdering,\n TronExt,\n TronFeeDetails,\n TronFeeOverride,\n TronResources,\n} from './adapters/tron/types';\nexport type {\n UtxoAddressType,\n UtxoExt,\n UtxoFeeDetails,\n UtxoFeeOverride,\n UtxoOutputType,\n UtxoSelectionPreview,\n UtxoSelectionRequest,\n UtxoUnspent,\n UtxoWalletOptions,\n} from './adapters/utxo/types';\nexport type {\n SolanaExpiryOrdering,\n SolanaExt,\n SolanaFeeDetails,\n SolanaFeeOverride,\n SolanaTokenAccount,\n} from './adapters/solana/types';\nexport type {\n TonExt,\n TonFeeDetails,\n TonFeeOverride,\n TonSeqnoOrdering,\n TonWalletIdentity,\n TonWalletVersion,\n} from './adapters/ton/types';\nexport type {\n AvalancheExt,\n AvalancheFeeDetails,\n AvalancheFeeOverride,\n AvalancheUnspent,\n AvalancheVm,\n} from './adapters/avalanche/types';\n"]}
@@ -23,6 +23,7 @@ function sampleOperation(overrides = {}) {
23
23
  counter += 1;
24
24
  return {
25
25
  id: `op_contract_${counter}`,
26
+ format: 1,
26
27
  namespace: 'ns',
27
28
  idempotencyKey: `key-${counter}`,
28
29
  intentHash: 'hash',
@@ -154,6 +155,20 @@ function describeOperationStoreContract(api, create) {
154
155
  strict_1.default.equal(await operations.get('ns', 'missing'), null);
155
156
  strict_1.default.equal(await operations.getByKey('ns', 'missing'), null);
156
157
  });
158
+ api.it('keeps the record format of every record through each write', async () => {
159
+ // A future format is stored as it is: the core, not the store, decides what it reads.
160
+ const { operations } = await create();
161
+ for (const format of [1, 2]) {
162
+ const { record } = await operations.create(sampleOperation({ format }));
163
+ strict_1.default.equal(record.format, format);
164
+ const updated = await operations.update('ns', record.id, { state: 'prepared' }, 1);
165
+ strict_1.default.equal(updated.format, format);
166
+ const appended = await operations.appendAttempt('ns', record.id, sampleAttempt(`att_format_${format}_${record.id}`), {}, updated.version);
167
+ strict_1.default.equal(appended.format, format);
168
+ strict_1.default.equal((await operations.get('ns', record.id))?.format, format);
169
+ strict_1.default.equal((await operations.getByKey('ns', record.idempotencyKey))?.format, format);
170
+ }
171
+ });
157
172
  api.it('rejects create when the runtime input carries a store-owned field, storing nothing', async () => {
158
173
  const { operations } = await create();
159
174
  const forbidden = {
@@ -226,7 +241,7 @@ function describeOperationStoreContract(api, create) {
226
241
  const { operations } = await create();
227
242
  for (const [name, ordering] of exports.SAMPLE_ORDERINGS) {
228
243
  const { record } = await operations.create(sampleOperation());
229
- const sample = sampleAttempt('a1');
244
+ const sample = sampleAttempt(`a1-${record.id}`);
230
245
  const appended = await operations.appendAttempt('ns', record.id, { ...sample, ordering, unsigned: { ...sample.unsigned, ordering } }, { state: 'signed', reservation: ordering }, record.version);
231
246
  // Read back after the append, and again after a later write to the record.
232
247
  const stored = await operations.get('ns', record.id);
@@ -292,7 +307,9 @@ function describeOperationStoreContract(api, create) {
292
307
  blockHeight: 7n,
293
308
  blockHash: 'block-7',
294
309
  reason: 'transfer bounced',
310
+ failure: 'unevidenced',
295
311
  }, null);
312
+ strict_1.default.equal((await operations.getObservation('a3'))?.failure, 'unevidenced', 'an observation keeps what failed');
296
313
  await operations.putObservation({
297
314
  attemptId: 'a3',
298
315
  operationId: record.id,
@@ -300,12 +317,14 @@ function describeOperationStoreContract(api, create) {
300
317
  evidence: 'observed',
301
318
  confirmations: 0,
302
319
  reason: undefined,
320
+ failure: undefined,
303
321
  }, failed.version);
304
322
  const reread = await operations.getObservation('a3');
305
323
  strict_1.default.equal(reread?.state, 'pending');
306
324
  strict_1.default.equal(reread?.blockHeight, undefined);
307
325
  strict_1.default.equal(reread?.blockHash, undefined);
308
326
  strict_1.default.equal(reread?.reason, undefined);
327
+ strict_1.default.equal(reread?.failure, undefined);
309
328
  });
310
329
  api.it('claims due operations exclusively and fences stale workers', async () => {
311
330
  const { operations } = await create();