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
@@ -28,10 +28,15 @@ function evaluateOperation(op, observations) {
28
28
  if (reverted) {
29
29
  return {
30
30
  state: 'failed',
31
- error: {
32
- code: 'TX_REVERTED',
33
- message: 'the transaction was included but failed on chain',
34
- },
31
+ error: of(reverted)?.failure === 'unevidenced'
32
+ ? {
33
+ code: 'TX_UNEVIDENCED',
34
+ message: 'the transaction executed, but shows no transfer to the recipient: check the chain before paying again',
35
+ }
36
+ : {
37
+ code: 'TX_REVERTED',
38
+ message: 'the transaction was included but failed on chain',
39
+ },
35
40
  winner: reverted,
36
41
  };
37
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../../src/core/lifecycle/evaluate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CodesOf } from '../errors/codes';\nimport type {\n AttemptObservation,\n AttemptRecord,\n OperationRecord,\n OperationState,\n} from '../store/types';\n\nexport interface Evaluation {\n readonly state: OperationState;\n readonly outcome?: 'executed' | 'cancelled';\n readonly error?: { readonly code: CodesOf<'chain'>; readonly message: string };\n /** The Attempt whose proven result decided the Operation. */\n readonly winner?: AttemptRecord;\n}\n\nconst PROVEN_DEAD = new Set(['rejected', 'replaced', 'expired']);\n\n/**\n * Pure: derives the Operation state from its Attempts' observations.\n * Every terminal verdict rests on `proven` evidence only: an executed or reverted Attempt\n * proven in finalized state, or every Attempt proven dead (rejected, replaced, expired).\n * Observed-only states (`dropped`, `refused`, absence, an unfinalized block) never end it.\n */\nexport function evaluateOperation(\n op: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n): Evaluation {\n if (op.attempts.length === 0) return { state: op.state };\n const of = (attempt: AttemptRecord) => observations.get(attempt.id);\n const provenAs = (attempt: AttemptRecord, state: string) => {\n const o = of(attempt);\n return o?.evidence === 'proven' && o.state === state;\n };\n const executed = op.attempts.find((a) => provenAs(a, 'final'));\n if (executed) {\n return {\n state: 'final',\n outcome: executed.purpose === 'cancel' ? 'cancelled' : 'executed',\n winner: executed,\n };\n }\n const reverted = op.attempts.find((a) => provenAs(a, 'failed'));\n if (reverted) {\n return {\n state: 'failed',\n error: {\n code: 'TX_REVERTED',\n message: 'the transaction was included but failed on chain',\n },\n winner: reverted,\n };\n }\n const all = op.attempts.map(of);\n if (all.every((o) => o?.evidence === 'proven' && PROVEN_DEAD.has(o.state))) {\n if (all.some((o) => o?.state === 'expired')) {\n return {\n state: 'expired',\n error: {\n code: 'TX_EXPIRED',\n message: 'the transaction expired without being included',\n },\n };\n }\n if (all.every((o) => o?.state === 'rejected')) {\n return {\n state: 'failed',\n error: { code: 'TX_REJECTED', message: 'every attempt was rejected as invalid' },\n };\n }\n return {\n state: 'failed',\n error: {\n code: 'TX_REPLACED',\n message: 'the ordering slot was consumed by another transaction',\n },\n };\n }\n if (all.some((o) => o?.state === 'included' || o?.state === 'failed'))\n return { state: 'included' };\n const visible = all.some((o) => o?.state === 'mempool');\n if (op.state === 'stalled' && !visible) return { state: 'stalled' };\n if (op.state === 'signed' && !visible) return { state: 'signed' };\n return { state: 'submitted' };\n}\n"]}
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../../src/core/lifecycle/evaluate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CodesOf } from '../errors/codes';\nimport type {\n AttemptObservation,\n AttemptRecord,\n OperationRecord,\n OperationState,\n} from '../store/types';\n\nexport interface Evaluation {\n readonly state: OperationState;\n readonly outcome?: 'executed' | 'cancelled';\n readonly error?: { readonly code: CodesOf<'chain'>; readonly message: string };\n /** The Attempt whose proven result decided the Operation. */\n readonly winner?: AttemptRecord;\n}\n\nconst PROVEN_DEAD = new Set(['rejected', 'replaced', 'expired']);\n\n/**\n * Pure: derives the Operation state from its Attempts' observations.\n * Every terminal verdict rests on `proven` evidence only: an executed or reverted Attempt\n * proven in finalized state, or every Attempt proven dead (rejected, replaced, expired).\n * Observed-only states (`dropped`, `refused`, absence, an unfinalized block) never end it.\n */\nexport function evaluateOperation(\n op: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n): Evaluation {\n if (op.attempts.length === 0) return { state: op.state };\n const of = (attempt: AttemptRecord) => observations.get(attempt.id);\n const provenAs = (attempt: AttemptRecord, state: string) => {\n const o = of(attempt);\n return o?.evidence === 'proven' && o.state === state;\n };\n const executed = op.attempts.find((a) => provenAs(a, 'final'));\n if (executed) {\n return {\n state: 'final',\n outcome: executed.purpose === 'cancel' ? 'cancelled' : 'executed',\n winner: executed,\n };\n }\n const reverted = op.attempts.find((a) => provenAs(a, 'failed'));\n if (reverted) {\n return {\n state: 'failed',\n error:\n of(reverted)?.failure === 'unevidenced'\n ? {\n code: 'TX_UNEVIDENCED',\n message:\n 'the transaction executed, but shows no transfer to the recipient: check the chain before paying again',\n }\n : {\n code: 'TX_REVERTED',\n message: 'the transaction was included but failed on chain',\n },\n winner: reverted,\n };\n }\n const all = op.attempts.map(of);\n if (all.every((o) => o?.evidence === 'proven' && PROVEN_DEAD.has(o.state))) {\n if (all.some((o) => o?.state === 'expired')) {\n return {\n state: 'expired',\n error: {\n code: 'TX_EXPIRED',\n message: 'the transaction expired without being included',\n },\n };\n }\n if (all.every((o) => o?.state === 'rejected')) {\n return {\n state: 'failed',\n error: { code: 'TX_REJECTED', message: 'every attempt was rejected as invalid' },\n };\n }\n return {\n state: 'failed',\n error: {\n code: 'TX_REPLACED',\n message: 'the ordering slot was consumed by another transaction',\n },\n };\n }\n if (all.some((o) => o?.state === 'included' || o?.state === 'failed'))\n return { state: 'included' };\n const visible = all.some((o) => o?.state === 'mempool');\n if (op.state === 'stalled' && !visible) return { state: 'stalled' };\n if (op.state === 'signed' && !visible) return { state: 'signed' };\n return { state: 'submitted' };\n}\n"]}
@@ -279,6 +279,7 @@ class Monitor {
279
279
  // Why an included transaction failed, as the driver's fixed text; any earlier
280
280
  // reason (a refusal, an old failure) is cleared otherwise.
281
281
  reason: seen.success === false ? seen.reason : undefined,
282
+ failure: seen.success === false ? (seen.failure ?? 'reverted') : undefined,
282
283
  firstSeenAt: current?.firstSeenAt ?? now,
283
284
  lastSeenAt: now,
284
285
  };
@@ -304,6 +305,7 @@ class Monitor {
304
305
  blockHeight: undefined,
305
306
  confirmations: 0,
306
307
  reason: undefined,
308
+ failure: undefined,
307
309
  };
308
310
  patch =
309
311
  seen.seen === 'mempool'
@@ -364,7 +366,7 @@ class Monitor {
364
366
  blockHash: proof.blockHash,
365
367
  txHash: proof.txHash,
366
368
  confirmations: depth(head, proof.blockHeight),
367
- reason: failureReason(proof),
369
+ ...failureOf(proof),
368
370
  };
369
371
  }
370
372
  /**
@@ -413,7 +415,7 @@ class Monitor {
413
415
  blockHeight: proof.blockHeight,
414
416
  blockHash: proof.blockHash,
415
417
  txHash: proof.txHash,
416
- reason: failureReason(proof),
418
+ ...failureOf(proof),
417
419
  };
418
420
  }
419
421
  return { state: deadSlot ? 'replaced' : 'expired', evidence: 'proven' };
@@ -422,7 +424,12 @@ class Monitor {
422
424
  return { state: 'replaced', evidence: 'observed' };
423
425
  }
424
426
  if (current?.state === 'refused') {
425
- return { state: 'refused', evidence: 'observed', reason: current.reason };
427
+ return {
428
+ state: 'refused',
429
+ evidence: 'observed',
430
+ reason: current.reason,
431
+ failure: undefined,
432
+ };
426
433
  }
427
434
  const since = current?.lastSeenAt ?? current?.lastBroadcastAt ?? attempt.createdAt;
428
435
  const dropped = now - since >= this.deps.lifecycle().droppedGracePeriodMs;
@@ -446,6 +453,7 @@ class Monitor {
446
453
  evidence: 'proven',
447
454
  replacedBy: winner.ref.id,
448
455
  reason: undefined,
456
+ failure: undefined,
449
457
  });
450
458
  }
451
459
  }
@@ -596,11 +604,13 @@ function depth(head, height) {
596
604
  return d > 0n ? Number(d) : 0;
597
605
  }
598
606
  /**
599
- * A proven failure's fixed reason; a success clears any earlier reason. Drivers give a
607
+ * A proven failure's fixed reason and what failed; a success clears both. Drivers give a
600
608
  * fixed text because a node's own text can carry addresses or amounts; the stored reason
601
609
  * is sensitive data, and no event carries it.
602
610
  */
603
- function failureReason(proof) {
604
- return proof.success ? undefined : proof.reason;
611
+ function failureOf(proof) {
612
+ return proof.success
613
+ ? { reason: undefined, failure: undefined }
614
+ : { reason: proof.reason, failure: proof.failure ?? 'reverted' };
605
615
  }
606
616
  //# sourceMappingURL=monitor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../src/core/lifecycle/monitor.ts"],"names":[],"mappings":"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","sourcesContent":["import { statusFromObservation } from '../blockchain/mapping';\nimport type { ResolvedSelection } from '../config/types';\nimport type { ProofSource } from '../driver/types';\nimport {\n ChainError,\n StateError,\n TimeoutError,\n ValidationError,\n isCryptoAioError,\n type SerializedError,\n} from '../errors/error';\nimport type { EventBus } from '../events/bus';\nimport type { Logger } from '../events/logger';\nimport type { TxStatus } from '../model/transaction';\nimport {\n isTerminal,\n type AttemptObservation,\n type AttemptRecord,\n type ClearableField,\n type Fence,\n type OperationPatch,\n type OperationRecord,\n type Stores,\n} from '../store/types';\nimport { isStaleView } from '../transport/stale-view';\nimport type { Clock } from '../util/clock';\nimport {\n PRE_SIGNING_STATES,\n errorCode,\n rehydrateError,\n type OperationEngine,\n type OperationTarget,\n type ReadTarget,\n type ResolvedLifecycle,\n} from './engine';\nimport { evaluateOperation } from './evaluate';\nimport {\n loadObservations,\n writeObservation,\n type ObservationDeps,\n type ObservationPatch,\n} from './observations';\nimport { statusOf, type OperationView } from './views';\nimport { Workers, type RecoveryReport, type WorkerOptions } from './workers';\n\nexport interface WaitOptions {\n /** Default: the handle's `confirmations`. Ignored when `finality: 'final'`. */\n readonly confirmations?: number;\n readonly finality?: 'included' | 'final';\n readonly timeoutMs?: number;\n readonly pollIntervalMs?: number;\n readonly signal?: AbortSignal;\n}\n\nexport interface ConfirmationResult {\n readonly status: TxStatus;\n readonly operation?: OperationView;\n}\n\nexport interface TxStatusEvent {\n readonly status: TxStatus;\n readonly operation?: OperationView;\n}\n\nexport type { RecoveryReport, WorkerOptions } from './workers';\n\n/**\n * Rebuilds the wallet-bound target of a stored Operation (from its `context`); `undefined`\n * (or a rejection) when it cannot be resolved any more, e.g. its wallet config is gone.\n */\nexport type TargetResolver = (\n op: OperationRecord,\n) => Promise<OperationTarget | undefined>;\n\n/** Rebuilds the signer-free read target of a stored Operation; see `TargetResolver`. */\nexport type ReadResolver = (op: OperationRecord) => Promise<ReadTarget | undefined>;\n\nexport interface MonitorDeps {\n readonly engine: OperationEngine;\n readonly stores: Stores;\n readonly events: EventBus;\n readonly clock: Clock;\n readonly log: Logger;\n readonly namespace: string;\n readonly lifecycle: () => ResolvedLifecycle;\n /**\n * Every check, worker pass and recovery read runs on this target (no wallet), so a\n * signer rotated out of config or a hung `getPublicKey` never stalls monitoring.\n */\n readonly resolveRead: ReadResolver;\n /**\n * Resolved lazily, only for the writes that need a wallet-bound target: the\n * all-rejected verdict, nonce reconciliation and recovery's resend (none of them signs).\n * Known gap: for the all-rejected verdict this resolution is bounded neither by the\n * pass `signal` nor by a per-pass cache, so each such Operation of a pass can wait up\n * to `lifecycle.signTimeoutMs` for a wallet whose resolution keeps failing.\n */\n readonly resolveTarget: TargetResolver;\n}\n\ninterface Snapshot {\n readonly status: TxStatus;\n readonly record?: OperationRecord;\n}\n\nconst SETTLED = new Set(['final', 'failed', 'rejected', 'replaced', 'expired']);\nconst UNKNOWN: TxStatus = {\n state: 'unknown',\n evidence: 'observed',\n confirmations: 0,\n finality: 'none',\n};\n\n/** Proven and settled: nothing observed later may overwrite it. */\nfunction isSettled(observation: AttemptObservation | null | undefined): boolean {\n return observation?.evidence === 'proven' && SETTLED.has(observation.state);\n}\n\n/**\n * Watches Attempts on chain and moves their Operation on evidence.\n * Observed data (a single endpoint's view, absence, `dropped`, `refused`, an unfinalized\n * block) only ever produces non-terminal states; a terminal state needs `proven` evidence\n * (finalized data confirmed by quorum proof reads). A stale view decides nothing.\n */\nexport class Monitor {\n /** The worker loop and recovery, over this monitor's checks. */\n readonly #workers: Workers;\n\n constructor(private readonly deps: MonitorDeps) {\n this.#workers = new Workers(deps, {\n checkPass: (target, op, fence, signal) =>\n this.#checkPass(target, op, fence, signal),\n check: (target, op, fence, signal) => this.check(target, op, fence, signal),\n find: (ref) => this.find(ref),\n });\n }\n\n private get observationDeps(): ObservationDeps {\n return {\n operations: this.deps.stores.operations,\n events: this.deps.events,\n namespace: this.deps.namespace,\n };\n }\n\n /** Finds a managed Operation by id, Attempt ref or observed canonical tx hash. */\n async find(ref: string): Promise<OperationRecord | null> {\n const store = this.deps.stores.operations;\n return (\n (await store.get(this.deps.namespace, ref)) ??\n (await store.findByRef(this.deps.namespace, ref))\n );\n }\n\n /**\n * One evaluation pass: observe live Attempts, persist observations, apply the transition.\n * `signal` is checked before every read, so an aborted pass stops after at most the\n * read in flight; it then throws the signal's reason and decides nothing further.\n */\n async check(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<OperationRecord> {\n return (await this.#checkPass(target, op, fence, signal)).record;\n }\n\n /** `check`, also telling whether the view was stale (it then decided nothing). */\n async #checkPass(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<{ readonly record: OperationRecord; readonly stale: boolean }> {\n if (isTerminal(op.state) || PRE_SIGNING_STATES.has(op.state))\n return { record: op, stale: false };\n const { pooled } = target;\n signal?.throwIfAborted();\n await pooled.transport.ensureFreshHealth(signal);\n signal?.throwIfAborted();\n const [head, finalized] = await Promise.all([\n pooled.driver.reader.getBlockHeight(),\n pooled.driver.reader.getFinalizedHeight(),\n ]);\n if (isStaleView(pooled.transport, head)) return { record: op, stale: true };\n const observations = new Map<string, AttemptObservation>();\n for (const attempt of op.attempts) {\n try {\n observations.set(\n attempt.id,\n await this.observeAttempt(target, op, attempt, head, finalized, signal),\n );\n } catch (error) {\n if (signal?.aborted || !isCryptoAioError(error) || !error.retryable) throw error;\n const current = await this.deps.stores.operations.getObservation(attempt.id);\n if (current) observations.set(attempt.id, current);\n }\n }\n return {\n record: await this.applyEvaluation(op, observations, fence, signal),\n stale: false,\n };\n }\n\n /** Current status of a managed Operation (after a check) or of an arbitrary transaction id. */\n async status(target: ReadTarget, ref: string, signal?: AbortSignal): Promise<Snapshot> {\n let record = await this.find(ref);\n if (!record) return { status: await this.rawStatus(target, ref) };\n assertSameNetwork(target.selection, record);\n if (!isTerminal(record.state) && !PRE_SIGNING_STATES.has(record.state)) {\n try {\n record = await this.check(target, record, undefined, signal);\n } catch (error) {\n if (signal?.aborted || !isCryptoAioError(error) || !error.retryable) throw error;\n }\n }\n const observations = await loadObservations(this.deps.stores.operations, record);\n return { status: this.bestStatus(record, observations), record };\n }\n\n /**\n * Polls until the wanted status: `confirmations` (default: the handle's) or, with\n * `finality: 'final'`, proven finality for a managed Operation and observed finality for\n * a transaction it does not manage. The caller's `signal` and the deadline bound\n * every pass and sleep; a pass stops after at most the read in flight.\n */\n async waitFor(\n target: ReadTarget,\n ref: string,\n options: WaitOptions = {},\n ): Promise<Snapshot> {\n const { signal } = options;\n if (signal?.aborted) throw signal.reason;\n const lifecycle = this.deps.lifecycle();\n const deadline =\n this.deps.clock.now() + (options.timeoutMs ?? lifecycle.waitTimeoutMs);\n const poll = options.pollIntervalMs ?? lifecycle.pollIntervalMs;\n const wanted = options.confirmations ?? target.selection.confirmations;\n const wantFinal = options.finality === 'final';\n let last: Snapshot | undefined;\n const stopped = (): unknown =>\n signal?.aborted\n ? signal.reason\n : new TimeoutError(\n 'TIMEOUT',\n 'the transaction was not confirmed before the timeout',\n {\n context: last?.record ? { operationId: last.record.id } : {},\n },\n );\n // One signal for every pass and sleep: the caller's abort or the deadline.\n const bound = new AbortController();\n const finished = new AbortController();\n const onAbort = () => bound.abort();\n signal?.addEventListener('abort', onAbort, { once: true });\n this.deps.clock\n .sleep(Math.max(0, deadline - this.deps.clock.now()), finished.signal)\n .then(onAbort, () => undefined);\n try {\n for (;;) {\n if (bound.signal.aborted || this.deps.clock.now() >= deadline) throw stopped();\n let snapshot: Snapshot | undefined;\n try {\n snapshot = await this.status(target, ref, bound.signal);\n } catch (error) {\n if (bound.signal.aborted) throw stopped();\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n }\n if (snapshot) {\n last = snapshot;\n const { status, record } = snapshot;\n if (record?.state === 'final') return snapshot;\n if (record && (record.state === 'failed' || record.state === 'expired')) {\n throw rehydrateError(record.error ?? this.defaultError(record), record.id);\n }\n if (record?.state === 'abandoned') {\n throw new StateError(\n 'INVALID_TRANSITION',\n `operation '${record.id}' was abandoned`,\n );\n }\n if (!record && status.state === 'failed' && status.finality === 'final') {\n throw new ChainError(\n 'TX_REVERTED',\n 'the transaction was included but failed on chain',\n );\n }\n const reached = wantFinal\n ? status.state === 'final' || unmanagedFinal(snapshot)\n : status.state === 'final' ||\n (status.state === 'included' && status.confirmations >= wanted);\n if (reached) return snapshot;\n }\n try {\n await this.deps.clock.sleep(poll, bound.signal);\n } catch {\n throw stopped();\n }\n }\n } finally {\n finished.abort();\n signal?.removeEventListener('abort', onAbort);\n }\n }\n\n /**\n * Yields each status change until the Operation is terminal, or until a transaction\n * it does not manage reaches observed finality, whether it succeeded or reverted. Ends\n * quietly when `signal` aborts.\n */\n async *watch(\n target: ReadTarget,\n ref: string,\n options: { readonly pollIntervalMs?: number; readonly signal?: AbortSignal } = {},\n ): AsyncGenerator<Snapshot> {\n const { signal } = options;\n const poll = options.pollIntervalMs ?? this.deps.lifecycle().pollIntervalMs;\n let last = '';\n while (!signal?.aborted) {\n let snapshot: Snapshot | undefined;\n try {\n snapshot = await this.status(target, ref, signal);\n } catch (error) {\n if (signal?.aborted) return;\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n }\n if (snapshot) {\n const { status, record } = snapshot;\n const key = [\n status.state,\n status.evidence,\n status.confirmations,\n status.blockHash ?? '',\n record?.state ?? '',\n ].join('|');\n if (key !== last) {\n last = key;\n yield snapshot;\n }\n if (record ? isTerminal(record.state) : unmanagedFinal(snapshot)) return;\n }\n try {\n await this.deps.clock.sleep(poll, signal);\n } catch {\n return;\n }\n }\n }\n\n // ---- workers and recovery ------------------------------------------------------------\n\n /** One worker pass (see `Workers.runOnce`); resolves to how many Operations it claimed. */\n runOnce(options: {\n readonly workerId: string;\n readonly batch?: number;\n readonly signal?: AbortSignal;\n }): Promise<number> {\n return this.#workers.runOnce(options);\n }\n\n /** Runs worker passes until `signal` aborts (see `Workers.start`). */\n start(options: WorkerOptions = {}): Promise<void> {\n return this.#workers.start(options);\n }\n\n /** Startup recovery for this namespace; it never signs (see `Workers.recover`). */\n recover(options: { readonly signal?: AbortSignal } = {}): Promise<RecoveryReport> {\n return this.#workers.recover(options);\n }\n\n // ---- observation ---------------------------------------------------------------------\n\n private async observeAttempt(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n head: bigint,\n finalized: bigint,\n signal?: AbortSignal,\n ): Promise<AttemptObservation> {\n const current = await this.deps.stores.operations.getObservation(attempt.id);\n if (current && isSettled(current)) return current;\n const { driver } = target.pooled;\n const from = op.intent.from;\n const now = this.deps.clock.now();\n signal?.throwIfAborted();\n const seen = await driver.reader.observe(attempt.ref, attempt.ordering, from);\n signal?.throwIfAborted();\n let reorgedFrom: string | undefined;\n let patch: ObservationPatch;\n if (seen.seen === 'block' && seen.blockHeight !== undefined) {\n // The transaction is in another block than recorded: its old block was orphaned, once\n // the quorum confirms it; one endpoint's other block alone decides nothing.\n if (\n current?.blockHash !== undefined &&\n seen.blockHash !== undefined &&\n current.blockHash !== seen.blockHash\n ) {\n if (!(await this.orphaned(target, current))) return current;\n signal?.throwIfAborted();\n reorgedFrom = current.blockHash;\n }\n patch = {\n state: seen.success === false ? 'failed' : 'included',\n evidence: 'observed',\n confirmations: depth(head, seen.blockHeight),\n blockHeight: seen.blockHeight,\n blockHash: seen.blockHash,\n ...(seen.txHash !== undefined ? { txHash: seen.txHash } : {}),\n // Why an included transaction failed, as the driver's fixed text; any earlier\n // reason (a refusal, an old failure) is cleared otherwise.\n reason: seen.success === false ? seen.reason : undefined,\n firstSeenAt: current?.firstSeenAt ?? now,\n lastSeenAt: now,\n };\n if (seen.blockHeight <= finalized)\n patch = await this.proveFinal(target, op, attempt, patch, head, signal);\n } else {\n if (current?.blockHash !== undefined) {\n // Absence (or a mempool sighting) of an included transaction is not evidence of a\n // reorg by itself: a lagging or inconsistent endpoint shows the same. Only a\n // quorum-served different block at the recorded height proves it; otherwise decide\n // nothing.\n if (!(await this.orphaned(target, current))) return current;\n signal?.throwIfAborted();\n reorgedFrom = current.blockHash;\n }\n // Out of a block, an earlier failure's reason no longer applies (a refusal keeps\n // its own, below). Clearing relies on `putObservation` replacing the whole record,\n // a key set to `undefined` being absent.\n const cleared: ObservationPatch = {\n blockHash: undefined,\n blockHeight: undefined,\n confirmations: 0,\n reason: undefined,\n };\n patch =\n seen.seen === 'mempool'\n ? {\n ...cleared,\n state: 'mempool',\n evidence: 'observed',\n firstSeenAt: current?.firstSeenAt ?? now,\n lastSeenAt: now,\n }\n : {\n ...cleared,\n ...(await this.whenAbsent(target, op, attempt, current, now, signal)),\n };\n }\n // This patch was derived from `current`; when another writer changed the\n // observation meanwhile (possibly with stronger evidence), keep theirs and decide nothing.\n let applied = false;\n const saved = await writeObservation(\n this.observationDeps,\n attempt,\n op.id,\n (stored) => {\n applied = (stored?.version ?? null) === (current?.version ?? null);\n return applied ? patch : undefined;\n },\n );\n if (!applied) return saved;\n if (reorgedFrom !== undefined) this.#reorged(op, attempt, reorgedFrom);\n if (\n saved.state === 'dropped' &&\n attempt.id === op.activeAttemptId &&\n op.state !== 'stalled'\n ) {\n signal?.throwIfAborted();\n await this.#rebroadcastDropped(target, op, attempt, saved, now, signal);\n }\n return saved;\n }\n\n /**\n * A block at or below the finalized height becomes `final`/`failed` + `proven` only when\n * the quorum proof confirms it. A retryable proof failure (e.g. PROVIDER_INCONSISTENT)\n * decides nothing: the observed patch is kept.\n */\n private async proveFinal(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n patch: ObservationPatch,\n head: bigint,\n signal?: AbortSignal,\n ): Promise<ObservationPatch> {\n let proof: Awaited<ReturnType<ProofSource['includedFinal']>>;\n signal?.throwIfAborted();\n try {\n proof = await target.pooled.driver.proofs.includedFinal(\n attempt.ref,\n attempt.ordering,\n op.intent.from,\n );\n } catch (error) {\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n return patch;\n }\n if (!proof.included) return patch;\n return {\n ...patch,\n state: proof.success ? 'final' : 'failed',\n evidence: 'proven',\n blockHeight: proof.blockHeight,\n blockHash: proof.blockHash,\n txHash: proof.txHash,\n confirmations: depth(head, proof.blockHeight),\n reason: failureReason(proof),\n };\n }\n\n /**\n * Whether the block recorded for `observation` is no longer the one at its height.\n * Only the quorum-served hash decides; a disagreement or other retryable failure, or no\n * block at that height yet, decides nothing (`false`).\n */\n private async orphaned(\n target: ReadTarget,\n observation: AttemptObservation,\n ): Promise<boolean> {\n const { blockHeight, blockHash } = observation;\n if (blockHeight === undefined || blockHash === undefined) return false;\n let canonical: string | null;\n try {\n canonical = await target.pooled.driver.proofs.blockHash(blockHeight, 'latest');\n } catch (error) {\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n return false;\n }\n return canonical !== null && canonical !== blockHash;\n }\n\n /** The transaction is not visible anywhere we can see: only finalized proofs may declare it dead. */\n private async whenAbsent(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n current: AttemptObservation | null,\n now: number,\n signal?: AbortSignal,\n ): Promise<ObservationPatch> {\n const { proofs } = target.pooled.driver;\n const read = <T>(work: () => Promise<T>): Promise<T> => {\n signal?.throwIfAborted();\n return work();\n };\n // The built ordering (never the reservation, whose seqno `validUntil`\n // the driver may have replaced while building).\n const ordering = attempt.ordering;\n const from = op.intent.from;\n const slotted =\n ordering.kind === 'nonce' ||\n ordering.kind === 'seqno' ||\n ordering.kind === 'inputs';\n const expiring = ordering.kind === 'expiry' || ordering.kind === 'seqno';\n const deadSlot =\n slotted && (await read(() => proofs.slotConsumed(ordering, from, 'finalized')));\n const deadExpiry =\n !deadSlot && expiring && (await read(() => proofs.expired(ordering)));\n if (deadSlot || deadExpiry) {\n const proof = await read(() => proofs.includedFinal(attempt.ref, ordering, from));\n if (proof.included) {\n return {\n state: proof.success ? 'final' : 'failed',\n evidence: 'proven',\n blockHeight: proof.blockHeight,\n blockHash: proof.blockHash,\n txHash: proof.txHash,\n reason: failureReason(proof),\n };\n }\n return { state: deadSlot ? 'replaced' : 'expired', evidence: 'proven' };\n }\n if (slotted && (await read(() => proofs.slotConsumed(ordering, from, 'latest')))) {\n return { state: 'replaced', evidence: 'observed' };\n }\n if (current?.state === 'refused') {\n return { state: 'refused', evidence: 'observed', reason: current.reason };\n }\n const since = current?.lastSeenAt ?? current?.lastBroadcastAt ?? attempt.createdAt;\n const dropped = now - since >= this.deps.lifecycle().droppedGracePeriodMs;\n return { state: dropped ? 'dropped' : 'pending', evidence: 'observed' };\n }\n\n private async applyEvaluation(\n op: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<OperationRecord> {\n const evaluation = evaluateOperation(op, observations);\n const { winner } = evaluation;\n if (winner) {\n // The winner consumed the ordering slot: every other Attempt is proven replaced by it.\n // As in `whenAbsent`, a proven `replaced` carries no reason: a refusal's no longer\n // applies.\n const linked = (o: AttemptObservation | null | undefined) =>\n isSettled(o) && !(o?.state === 'replaced' && o.replacedBy === undefined);\n for (const attempt of op.attempts) {\n if (attempt.id === winner.id || linked(observations.get(attempt.id))) continue;\n await writeObservation(this.observationDeps, attempt, op.id, (stored) =>\n linked(stored)\n ? undefined\n : {\n state: 'replaced',\n evidence: 'proven',\n replacedBy: winner.ref.id,\n reason: undefined,\n },\n );\n }\n }\n // Failing an all-rejected Operation releases its nonce, so the engine applies it\n // under the address lease; the monitor never makes a reservation-holding transition.\n if (evaluation.error?.code === 'TX_REJECTED')\n return this.failRejected(op, signal, fence);\n const terminal = isTerminal(evaluation.state);\n // A read-only pass (no fence) writes the Operation only when its state, outcome\n // or error changes, never just to schedule it: a version bump would make a concurrent\n // engine write (e.g. right after a broadcast) lose its compare-and-set. Scheduling\n // (`nextCheckAt`) belongs to fenced workers and to engine transitions.\n const changed =\n evaluation.state !== op.state ||\n (evaluation.outcome !== undefined && evaluation.outcome !== op.outcome) ||\n (evaluation.error !== undefined && evaluation.error.code !== op.error?.code);\n if (!changed && !fence) return op;\n const clear: ClearableField[] = [];\n if (terminal) clear.push('nextCheckAt');\n if (op.state === 'stalled' && evaluation.state !== 'stalled' && !evaluation.error)\n clear.push('error');\n const patch: OperationPatch = {\n ...(evaluation.state !== op.state ? { state: evaluation.state } : {}),\n ...(evaluation.outcome ? { outcome: evaluation.outcome } : {}),\n ...(evaluation.error\n ? {\n error: new ChainError(evaluation.error.code, evaluation.error.message, {\n context: { operationId: op.id },\n }).toJSON(),\n }\n : {}),\n ...(fence && !terminal\n ? { nextCheckAt: this.deps.clock.now() + this.deps.lifecycle().pollIntervalMs }\n : {}),\n ...(clear.length > 0 ? { clear } : {}),\n };\n return this.deps.engine.update(op, patch, fence);\n }\n\n /**\n * Hands the all-rejected verdict to the engine: an unfenced pass (`tryOnce`) tries the\n * lease once, a fenced one waits `acquireTimeoutMs`, and either wait is bounded by the\n * pass `signal` (the caller's abort and, in `waitFor`, its deadline). A fenced pass's\n * terminal write carries its claim `fence`, so a worker whose claim was taken over writes\n * nothing. An unresolvable target leaves the Operation non-terminal.\n */\n private async failRejected(\n op: OperationRecord,\n signal: AbortSignal | undefined,\n fence: Fence | undefined,\n ): Promise<OperationRecord> {\n let target: OperationTarget | undefined;\n let failure: unknown;\n try {\n target = await this.deps.resolveTarget(op);\n } catch (error) {\n failure = error;\n }\n if (!target) {\n this.deps.log.warn('cannot resolve the target to fail a rejected operation', {\n operationId: op.id,\n code: errorCode(failure),\n });\n return op;\n }\n // Every unfenced pass (`getTransactionStatus`, `watch`, `waitFor`), signalled or not,\n // tries the lease once: a busy lease leaves the Operation for a later pass. Only a\n // fenced worker pass waits `acquireTimeoutMs`.\n return this.deps.engine.failRejected(target, op, {\n signal,\n ...(fence ? { fence } : { acquireTimeoutMs: 0 }),\n });\n }\n\n private bestStatus(\n record: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n ): TxStatus {\n const all = record.attempts\n .map((a) => observations.get(a.id))\n .filter((o): o is AttemptObservation => o !== undefined);\n const chosen =\n all.find(\n (o) => o.state === 'final' || (o.state === 'failed' && o.evidence === 'proven'),\n ) ??\n all\n .filter((o) => o.state === 'included' || o.state === 'failed')\n .sort((a, b) => b.confirmations - a.confirmations)[0] ??\n (record.activeAttemptId ? observations.get(record.activeAttemptId) : undefined);\n return chosen ? statusOf(chosen) : UNKNOWN;\n }\n\n private async rawStatus(target: ReadTarget, id: string): Promise<TxStatus> {\n const { reader } = target.pooled.driver;\n const [observation, head, finalized] = await Promise.all([\n reader.observe({ id, idKind: 'tx-hash', canonical: true }, undefined, undefined),\n reader.getBlockHeight(),\n reader.getFinalizedHeight(),\n ]);\n return statusFromObservation(observation, head, finalized);\n }\n\n private defaultError(record: OperationRecord): SerializedError {\n const code = record.state === 'expired' ? 'TX_EXPIRED' : 'TX_REJECTED';\n return new ChainError(code, `operation ended in state '${record.state}'`).toJSON();\n }\n\n #reorged(op: OperationRecord, attempt: AttemptRecord, previousBlockHash: string): void {\n this.deps.events.emit('tx.reorged', {\n namespace: this.deps.namespace,\n operationId: op.id,\n attemptId: attempt.id,\n previousBlockHash,\n });\n }\n\n /**\n * Resends the stored raw bytes of a dropped active Attempt, at most once per\n * `rebroadcastIntervalMs`. The answer decides nothing: `dropped` is never terminal,\n * and a refusal or rejection of bytes a node once held says nothing about them. An\n * acceptance is remembered (`firstSeenAt`) like the engine's broadcast path does.\n */\n async #rebroadcastDropped(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n observation: AttemptObservation,\n now: number,\n signal?: AbortSignal,\n ): Promise<void> {\n if (\n now - (observation.lastBroadcastAt ?? 0) <\n this.deps.lifecycle().rebroadcastIntervalMs\n )\n return;\n let accepted = false;\n try {\n const result = await target.pooled.driver.broadcaster.broadcast(\n { raw: attempt.raw, ref: attempt.ref },\n signal ? { signal } : {},\n );\n accepted = result.kind === 'accepted' || result.kind === 'already-known';\n } catch (error) {\n // The code only: an error message may carry detail that logs must not.\n this.deps.log.debug('rebroadcast of a dropped attempt failed', {\n operationId: op.id,\n code: errorCode(error),\n });\n }\n await writeObservation(this.observationDeps, attempt, op.id, (stored) => ({\n lastBroadcastAt: now,\n ...(accepted ? { firstSeenAt: stored?.firstSeenAt ?? now } : {}),\n }));\n }\n}\n\n/** Refuses a stored Operation of another chain or network than `selection` (INVALID_INTENT). */\nexport function assertSameNetwork(\n selection: Pick<ResolvedSelection, 'chain' | 'network'>,\n record: OperationRecord,\n): void {\n const { chain, network } = selection;\n if (record.context.chain !== chain.id || record.context.network !== network.id) {\n throw new ValidationError(\n 'INVALID_INTENT',\n `operation '${record.id}' belongs to ${record.context.chain}:${record.context.network}, not ${chain.id}:${network.id}`,\n );\n }\n}\n\n/**\n * An unmanaged transaction has no proofs to wait for: its observed finality is the answer,\n * whether it succeeded or reverted (`waitFor` rejects a reverted one with TX_REVERTED).\n */\nfunction unmanagedFinal({ status, record }: Snapshot): boolean {\n return !record && status.finality === 'final';\n}\n\nfunction depth(head: bigint, height: bigint): number {\n const d = head - height + 1n;\n return d > 0n ? Number(d) : 0;\n}\n\n/**\n * A proven failure's fixed reason; a success clears any earlier reason. Drivers give a\n * fixed text because a node's own text can carry addresses or amounts; the stored reason\n * is sensitive data, and no event carries it.\n */\nfunction failureReason(proof: {\n readonly success: boolean;\n readonly reason?: string;\n}): string | undefined {\n return proof.success ? undefined : proof.reason;\n}\n"]}
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../src/core/lifecycle/monitor.ts"],"names":[],"mappings":"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","sourcesContent":["import { statusFromObservation } from '../blockchain/mapping';\nimport type { ResolvedSelection } from '../config/types';\nimport type { ProofSource } from '../driver/types';\nimport {\n ChainError,\n StateError,\n TimeoutError,\n ValidationError,\n isCryptoAioError,\n type SerializedError,\n} from '../errors/error';\nimport type { EventBus } from '../events/bus';\nimport type { Logger } from '../events/logger';\nimport type { TxFailure, TxStatus } from '../model/transaction';\nimport {\n isTerminal,\n type AttemptObservation,\n type AttemptRecord,\n type ClearableField,\n type Fence,\n type OperationPatch,\n type OperationRecord,\n type Stores,\n} from '../store/types';\nimport { isStaleView } from '../transport/stale-view';\nimport type { Clock } from '../util/clock';\nimport {\n PRE_SIGNING_STATES,\n errorCode,\n rehydrateError,\n type OperationEngine,\n type OperationTarget,\n type ReadTarget,\n type ResolvedLifecycle,\n} from './engine';\nimport { evaluateOperation } from './evaluate';\nimport {\n loadObservations,\n writeObservation,\n type ObservationDeps,\n type ObservationPatch,\n} from './observations';\nimport { statusOf, type OperationView } from './views';\nimport { Workers, type RecoveryReport, type WorkerOptions } from './workers';\n\nexport interface WaitOptions {\n /** Default: the handle's `confirmations`. Ignored when `finality: 'final'`. */\n readonly confirmations?: number;\n readonly finality?: 'included' | 'final';\n readonly timeoutMs?: number;\n readonly pollIntervalMs?: number;\n readonly signal?: AbortSignal;\n}\n\nexport interface ConfirmationResult {\n readonly status: TxStatus;\n readonly operation?: OperationView;\n}\n\nexport interface TxStatusEvent {\n readonly status: TxStatus;\n readonly operation?: OperationView;\n}\n\nexport type { RecoveryReport, WorkerOptions } from './workers';\n\n/**\n * Rebuilds the wallet-bound target of a stored Operation (from its `context`); `undefined`\n * (or a rejection) when it cannot be resolved any more, e.g. its wallet config is gone.\n */\nexport type TargetResolver = (\n op: OperationRecord,\n) => Promise<OperationTarget | undefined>;\n\n/** Rebuilds the signer-free read target of a stored Operation; see `TargetResolver`. */\nexport type ReadResolver = (op: OperationRecord) => Promise<ReadTarget | undefined>;\n\nexport interface MonitorDeps {\n readonly engine: OperationEngine;\n readonly stores: Stores;\n readonly events: EventBus;\n readonly clock: Clock;\n readonly log: Logger;\n readonly namespace: string;\n readonly lifecycle: () => ResolvedLifecycle;\n /**\n * Every check, worker pass and recovery read runs on this target (no wallet), so a\n * signer rotated out of config or a hung `getPublicKey` never stalls monitoring.\n */\n readonly resolveRead: ReadResolver;\n /**\n * Resolved lazily, only for the writes that need a wallet-bound target: the\n * all-rejected verdict, nonce reconciliation and recovery's resend (none of them signs).\n * Known gap: for the all-rejected verdict this resolution is bounded neither by the\n * pass `signal` nor by a per-pass cache, so each such Operation of a pass can wait up\n * to `lifecycle.signTimeoutMs` for a wallet whose resolution keeps failing.\n */\n readonly resolveTarget: TargetResolver;\n}\n\ninterface Snapshot {\n readonly status: TxStatus;\n readonly record?: OperationRecord;\n}\n\nconst SETTLED = new Set(['final', 'failed', 'rejected', 'replaced', 'expired']);\nconst UNKNOWN: TxStatus = {\n state: 'unknown',\n evidence: 'observed',\n confirmations: 0,\n finality: 'none',\n};\n\n/** Proven and settled: nothing observed later may overwrite it. */\nfunction isSettled(observation: AttemptObservation | null | undefined): boolean {\n return observation?.evidence === 'proven' && SETTLED.has(observation.state);\n}\n\n/**\n * Watches Attempts on chain and moves their Operation on evidence.\n * Observed data (a single endpoint's view, absence, `dropped`, `refused`, an unfinalized\n * block) only ever produces non-terminal states; a terminal state needs `proven` evidence\n * (finalized data confirmed by quorum proof reads). A stale view decides nothing.\n */\nexport class Monitor {\n /** The worker loop and recovery, over this monitor's checks. */\n readonly #workers: Workers;\n\n constructor(private readonly deps: MonitorDeps) {\n this.#workers = new Workers(deps, {\n checkPass: (target, op, fence, signal) =>\n this.#checkPass(target, op, fence, signal),\n check: (target, op, fence, signal) => this.check(target, op, fence, signal),\n find: (ref) => this.find(ref),\n });\n }\n\n private get observationDeps(): ObservationDeps {\n return {\n operations: this.deps.stores.operations,\n events: this.deps.events,\n namespace: this.deps.namespace,\n };\n }\n\n /** Finds a managed Operation by id, Attempt ref or observed canonical tx hash. */\n async find(ref: string): Promise<OperationRecord | null> {\n const store = this.deps.stores.operations;\n return (\n (await store.get(this.deps.namespace, ref)) ??\n (await store.findByRef(this.deps.namespace, ref))\n );\n }\n\n /**\n * One evaluation pass: observe live Attempts, persist observations, apply the transition.\n * `signal` is checked before every read, so an aborted pass stops after at most the\n * read in flight; it then throws the signal's reason and decides nothing further.\n */\n async check(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<OperationRecord> {\n return (await this.#checkPass(target, op, fence, signal)).record;\n }\n\n /** `check`, also telling whether the view was stale (it then decided nothing). */\n async #checkPass(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<{ readonly record: OperationRecord; readonly stale: boolean }> {\n if (isTerminal(op.state) || PRE_SIGNING_STATES.has(op.state))\n return { record: op, stale: false };\n const { pooled } = target;\n signal?.throwIfAborted();\n await pooled.transport.ensureFreshHealth(signal);\n signal?.throwIfAborted();\n const [head, finalized] = await Promise.all([\n pooled.driver.reader.getBlockHeight(),\n pooled.driver.reader.getFinalizedHeight(),\n ]);\n if (isStaleView(pooled.transport, head)) return { record: op, stale: true };\n const observations = new Map<string, AttemptObservation>();\n for (const attempt of op.attempts) {\n try {\n observations.set(\n attempt.id,\n await this.observeAttempt(target, op, attempt, head, finalized, signal),\n );\n } catch (error) {\n if (signal?.aborted || !isCryptoAioError(error) || !error.retryable) throw error;\n const current = await this.deps.stores.operations.getObservation(attempt.id);\n if (current) observations.set(attempt.id, current);\n }\n }\n return {\n record: await this.applyEvaluation(op, observations, fence, signal),\n stale: false,\n };\n }\n\n /** Current status of a managed Operation (after a check) or of an arbitrary transaction id. */\n async status(target: ReadTarget, ref: string, signal?: AbortSignal): Promise<Snapshot> {\n let record = await this.find(ref);\n if (!record) return { status: await this.rawStatus(target, ref) };\n assertSameNetwork(target.selection, record);\n if (!isTerminal(record.state) && !PRE_SIGNING_STATES.has(record.state)) {\n try {\n record = await this.check(target, record, undefined, signal);\n } catch (error) {\n if (signal?.aborted || !isCryptoAioError(error) || !error.retryable) throw error;\n }\n }\n const observations = await loadObservations(this.deps.stores.operations, record);\n return { status: this.bestStatus(record, observations), record };\n }\n\n /**\n * Polls until the wanted status: `confirmations` (default: the handle's) or, with\n * `finality: 'final'`, proven finality for a managed Operation and observed finality for\n * a transaction it does not manage. The caller's `signal` and the deadline bound\n * every pass and sleep; a pass stops after at most the read in flight.\n */\n async waitFor(\n target: ReadTarget,\n ref: string,\n options: WaitOptions = {},\n ): Promise<Snapshot> {\n const { signal } = options;\n if (signal?.aborted) throw signal.reason;\n const lifecycle = this.deps.lifecycle();\n const deadline =\n this.deps.clock.now() + (options.timeoutMs ?? lifecycle.waitTimeoutMs);\n const poll = options.pollIntervalMs ?? lifecycle.pollIntervalMs;\n const wanted = options.confirmations ?? target.selection.confirmations;\n const wantFinal = options.finality === 'final';\n let last: Snapshot | undefined;\n const stopped = (): unknown =>\n signal?.aborted\n ? signal.reason\n : new TimeoutError(\n 'TIMEOUT',\n 'the transaction was not confirmed before the timeout',\n {\n context: last?.record ? { operationId: last.record.id } : {},\n },\n );\n // One signal for every pass and sleep: the caller's abort or the deadline.\n const bound = new AbortController();\n const finished = new AbortController();\n const onAbort = () => bound.abort();\n signal?.addEventListener('abort', onAbort, { once: true });\n this.deps.clock\n .sleep(Math.max(0, deadline - this.deps.clock.now()), finished.signal)\n .then(onAbort, () => undefined);\n try {\n for (;;) {\n if (bound.signal.aborted || this.deps.clock.now() >= deadline) throw stopped();\n let snapshot: Snapshot | undefined;\n try {\n snapshot = await this.status(target, ref, bound.signal);\n } catch (error) {\n if (bound.signal.aborted) throw stopped();\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n }\n if (snapshot) {\n last = snapshot;\n const { status, record } = snapshot;\n if (record?.state === 'final') return snapshot;\n if (record && (record.state === 'failed' || record.state === 'expired')) {\n throw rehydrateError(record.error ?? this.defaultError(record), record.id);\n }\n if (record?.state === 'abandoned') {\n throw new StateError(\n 'INVALID_TRANSITION',\n `operation '${record.id}' was abandoned`,\n );\n }\n if (!record && status.state === 'failed' && status.finality === 'final') {\n throw new ChainError(\n 'TX_REVERTED',\n 'the transaction was included but failed on chain',\n );\n }\n const reached = wantFinal\n ? status.state === 'final' || unmanagedFinal(snapshot)\n : status.state === 'final' ||\n (status.state === 'included' && status.confirmations >= wanted);\n if (reached) return snapshot;\n }\n try {\n await this.deps.clock.sleep(poll, bound.signal);\n } catch {\n throw stopped();\n }\n }\n } finally {\n finished.abort();\n signal?.removeEventListener('abort', onAbort);\n }\n }\n\n /**\n * Yields each status change until the Operation is terminal, or until a transaction\n * it does not manage reaches observed finality, whether it succeeded or reverted. Ends\n * quietly when `signal` aborts.\n */\n async *watch(\n target: ReadTarget,\n ref: string,\n options: { readonly pollIntervalMs?: number; readonly signal?: AbortSignal } = {},\n ): AsyncGenerator<Snapshot> {\n const { signal } = options;\n const poll = options.pollIntervalMs ?? this.deps.lifecycle().pollIntervalMs;\n let last = '';\n while (!signal?.aborted) {\n let snapshot: Snapshot | undefined;\n try {\n snapshot = await this.status(target, ref, signal);\n } catch (error) {\n if (signal?.aborted) return;\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n }\n if (snapshot) {\n const { status, record } = snapshot;\n const key = [\n status.state,\n status.evidence,\n status.confirmations,\n status.blockHash ?? '',\n record?.state ?? '',\n ].join('|');\n if (key !== last) {\n last = key;\n yield snapshot;\n }\n if (record ? isTerminal(record.state) : unmanagedFinal(snapshot)) return;\n }\n try {\n await this.deps.clock.sleep(poll, signal);\n } catch {\n return;\n }\n }\n }\n\n // ---- workers and recovery ------------------------------------------------------------\n\n /** One worker pass (see `Workers.runOnce`); resolves to how many Operations it claimed. */\n runOnce(options: {\n readonly workerId: string;\n readonly batch?: number;\n readonly signal?: AbortSignal;\n }): Promise<number> {\n return this.#workers.runOnce(options);\n }\n\n /** Runs worker passes until `signal` aborts (see `Workers.start`). */\n start(options: WorkerOptions = {}): Promise<void> {\n return this.#workers.start(options);\n }\n\n /** Startup recovery for this namespace; it never signs (see `Workers.recover`). */\n recover(options: { readonly signal?: AbortSignal } = {}): Promise<RecoveryReport> {\n return this.#workers.recover(options);\n }\n\n // ---- observation ---------------------------------------------------------------------\n\n private async observeAttempt(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n head: bigint,\n finalized: bigint,\n signal?: AbortSignal,\n ): Promise<AttemptObservation> {\n const current = await this.deps.stores.operations.getObservation(attempt.id);\n if (current && isSettled(current)) return current;\n const { driver } = target.pooled;\n const from = op.intent.from;\n const now = this.deps.clock.now();\n signal?.throwIfAborted();\n const seen = await driver.reader.observe(attempt.ref, attempt.ordering, from);\n signal?.throwIfAborted();\n let reorgedFrom: string | undefined;\n let patch: ObservationPatch;\n if (seen.seen === 'block' && seen.blockHeight !== undefined) {\n // The transaction is in another block than recorded: its old block was orphaned, once\n // the quorum confirms it; one endpoint's other block alone decides nothing.\n if (\n current?.blockHash !== undefined &&\n seen.blockHash !== undefined &&\n current.blockHash !== seen.blockHash\n ) {\n if (!(await this.orphaned(target, current))) return current;\n signal?.throwIfAborted();\n reorgedFrom = current.blockHash;\n }\n patch = {\n state: seen.success === false ? 'failed' : 'included',\n evidence: 'observed',\n confirmations: depth(head, seen.blockHeight),\n blockHeight: seen.blockHeight,\n blockHash: seen.blockHash,\n ...(seen.txHash !== undefined ? { txHash: seen.txHash } : {}),\n // Why an included transaction failed, as the driver's fixed text; any earlier\n // reason (a refusal, an old failure) is cleared otherwise.\n reason: seen.success === false ? seen.reason : undefined,\n failure: seen.success === false ? (seen.failure ?? 'reverted') : undefined,\n firstSeenAt: current?.firstSeenAt ?? now,\n lastSeenAt: now,\n };\n if (seen.blockHeight <= finalized)\n patch = await this.proveFinal(target, op, attempt, patch, head, signal);\n } else {\n if (current?.blockHash !== undefined) {\n // Absence (or a mempool sighting) of an included transaction is not evidence of a\n // reorg by itself: a lagging or inconsistent endpoint shows the same. Only a\n // quorum-served different block at the recorded height proves it; otherwise decide\n // nothing.\n if (!(await this.orphaned(target, current))) return current;\n signal?.throwIfAborted();\n reorgedFrom = current.blockHash;\n }\n // Out of a block, an earlier failure's reason no longer applies (a refusal keeps\n // its own, below). Clearing relies on `putObservation` replacing the whole record,\n // a key set to `undefined` being absent.\n const cleared: ObservationPatch = {\n blockHash: undefined,\n blockHeight: undefined,\n confirmations: 0,\n reason: undefined,\n failure: undefined,\n };\n patch =\n seen.seen === 'mempool'\n ? {\n ...cleared,\n state: 'mempool',\n evidence: 'observed',\n firstSeenAt: current?.firstSeenAt ?? now,\n lastSeenAt: now,\n }\n : {\n ...cleared,\n ...(await this.whenAbsent(target, op, attempt, current, now, signal)),\n };\n }\n // This patch was derived from `current`; when another writer changed the\n // observation meanwhile (possibly with stronger evidence), keep theirs and decide nothing.\n let applied = false;\n const saved = await writeObservation(\n this.observationDeps,\n attempt,\n op.id,\n (stored) => {\n applied = (stored?.version ?? null) === (current?.version ?? null);\n return applied ? patch : undefined;\n },\n );\n if (!applied) return saved;\n if (reorgedFrom !== undefined) this.#reorged(op, attempt, reorgedFrom);\n if (\n saved.state === 'dropped' &&\n attempt.id === op.activeAttemptId &&\n op.state !== 'stalled'\n ) {\n signal?.throwIfAborted();\n await this.#rebroadcastDropped(target, op, attempt, saved, now, signal);\n }\n return saved;\n }\n\n /**\n * A block at or below the finalized height becomes `final`/`failed` + `proven` only when\n * the quorum proof confirms it. A retryable proof failure (e.g. PROVIDER_INCONSISTENT)\n * decides nothing: the observed patch is kept.\n */\n private async proveFinal(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n patch: ObservationPatch,\n head: bigint,\n signal?: AbortSignal,\n ): Promise<ObservationPatch> {\n let proof: Awaited<ReturnType<ProofSource['includedFinal']>>;\n signal?.throwIfAborted();\n try {\n proof = await target.pooled.driver.proofs.includedFinal(\n attempt.ref,\n attempt.ordering,\n op.intent.from,\n );\n } catch (error) {\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n return patch;\n }\n if (!proof.included) return patch;\n return {\n ...patch,\n state: proof.success ? 'final' : 'failed',\n evidence: 'proven',\n blockHeight: proof.blockHeight,\n blockHash: proof.blockHash,\n txHash: proof.txHash,\n confirmations: depth(head, proof.blockHeight),\n ...failureOf(proof),\n };\n }\n\n /**\n * Whether the block recorded for `observation` is no longer the one at its height.\n * Only the quorum-served hash decides; a disagreement or other retryable failure, or no\n * block at that height yet, decides nothing (`false`).\n */\n private async orphaned(\n target: ReadTarget,\n observation: AttemptObservation,\n ): Promise<boolean> {\n const { blockHeight, blockHash } = observation;\n if (blockHeight === undefined || blockHash === undefined) return false;\n let canonical: string | null;\n try {\n canonical = await target.pooled.driver.proofs.blockHash(blockHeight, 'latest');\n } catch (error) {\n if (!isCryptoAioError(error) || !error.retryable) throw error;\n return false;\n }\n return canonical !== null && canonical !== blockHash;\n }\n\n /** The transaction is not visible anywhere we can see: only finalized proofs may declare it dead. */\n private async whenAbsent(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n current: AttemptObservation | null,\n now: number,\n signal?: AbortSignal,\n ): Promise<ObservationPatch> {\n const { proofs } = target.pooled.driver;\n const read = <T>(work: () => Promise<T>): Promise<T> => {\n signal?.throwIfAborted();\n return work();\n };\n // The built ordering (never the reservation, whose seqno `validUntil`\n // the driver may have replaced while building).\n const ordering = attempt.ordering;\n const from = op.intent.from;\n const slotted =\n ordering.kind === 'nonce' ||\n ordering.kind === 'seqno' ||\n ordering.kind === 'inputs';\n const expiring = ordering.kind === 'expiry' || ordering.kind === 'seqno';\n const deadSlot =\n slotted && (await read(() => proofs.slotConsumed(ordering, from, 'finalized')));\n const deadExpiry =\n !deadSlot && expiring && (await read(() => proofs.expired(ordering)));\n if (deadSlot || deadExpiry) {\n const proof = await read(() => proofs.includedFinal(attempt.ref, ordering, from));\n if (proof.included) {\n return {\n state: proof.success ? 'final' : 'failed',\n evidence: 'proven',\n blockHeight: proof.blockHeight,\n blockHash: proof.blockHash,\n txHash: proof.txHash,\n ...failureOf(proof),\n };\n }\n return { state: deadSlot ? 'replaced' : 'expired', evidence: 'proven' };\n }\n if (slotted && (await read(() => proofs.slotConsumed(ordering, from, 'latest')))) {\n return { state: 'replaced', evidence: 'observed' };\n }\n if (current?.state === 'refused') {\n return {\n state: 'refused',\n evidence: 'observed',\n reason: current.reason,\n failure: undefined,\n };\n }\n const since = current?.lastSeenAt ?? current?.lastBroadcastAt ?? attempt.createdAt;\n const dropped = now - since >= this.deps.lifecycle().droppedGracePeriodMs;\n return { state: dropped ? 'dropped' : 'pending', evidence: 'observed' };\n }\n\n private async applyEvaluation(\n op: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<OperationRecord> {\n const evaluation = evaluateOperation(op, observations);\n const { winner } = evaluation;\n if (winner) {\n // The winner consumed the ordering slot: every other Attempt is proven replaced by it.\n // As in `whenAbsent`, a proven `replaced` carries no reason: a refusal's no longer\n // applies.\n const linked = (o: AttemptObservation | null | undefined) =>\n isSettled(o) && !(o?.state === 'replaced' && o.replacedBy === undefined);\n for (const attempt of op.attempts) {\n if (attempt.id === winner.id || linked(observations.get(attempt.id))) continue;\n await writeObservation(this.observationDeps, attempt, op.id, (stored) =>\n linked(stored)\n ? undefined\n : {\n state: 'replaced',\n evidence: 'proven',\n replacedBy: winner.ref.id,\n reason: undefined,\n failure: undefined,\n },\n );\n }\n }\n // Failing an all-rejected Operation releases its nonce, so the engine applies it\n // under the address lease; the monitor never makes a reservation-holding transition.\n if (evaluation.error?.code === 'TX_REJECTED')\n return this.failRejected(op, signal, fence);\n const terminal = isTerminal(evaluation.state);\n // A read-only pass (no fence) writes the Operation only when its state, outcome\n // or error changes, never just to schedule it: a version bump would make a concurrent\n // engine write (e.g. right after a broadcast) lose its compare-and-set. Scheduling\n // (`nextCheckAt`) belongs to fenced workers and to engine transitions.\n const changed =\n evaluation.state !== op.state ||\n (evaluation.outcome !== undefined && evaluation.outcome !== op.outcome) ||\n (evaluation.error !== undefined && evaluation.error.code !== op.error?.code);\n if (!changed && !fence) return op;\n const clear: ClearableField[] = [];\n if (terminal) clear.push('nextCheckAt');\n if (op.state === 'stalled' && evaluation.state !== 'stalled' && !evaluation.error)\n clear.push('error');\n const patch: OperationPatch = {\n ...(evaluation.state !== op.state ? { state: evaluation.state } : {}),\n ...(evaluation.outcome ? { outcome: evaluation.outcome } : {}),\n ...(evaluation.error\n ? {\n error: new ChainError(evaluation.error.code, evaluation.error.message, {\n context: { operationId: op.id },\n }).toJSON(),\n }\n : {}),\n ...(fence && !terminal\n ? { nextCheckAt: this.deps.clock.now() + this.deps.lifecycle().pollIntervalMs }\n : {}),\n ...(clear.length > 0 ? { clear } : {}),\n };\n return this.deps.engine.update(op, patch, fence);\n }\n\n /**\n * Hands the all-rejected verdict to the engine: an unfenced pass (`tryOnce`) tries the\n * lease once, a fenced one waits `acquireTimeoutMs`, and either wait is bounded by the\n * pass `signal` (the caller's abort and, in `waitFor`, its deadline). A fenced pass's\n * terminal write carries its claim `fence`, so a worker whose claim was taken over writes\n * nothing. An unresolvable target leaves the Operation non-terminal.\n */\n private async failRejected(\n op: OperationRecord,\n signal: AbortSignal | undefined,\n fence: Fence | undefined,\n ): Promise<OperationRecord> {\n let target: OperationTarget | undefined;\n let failure: unknown;\n try {\n target = await this.deps.resolveTarget(op);\n } catch (error) {\n failure = error;\n }\n if (!target) {\n this.deps.log.warn('cannot resolve the target to fail a rejected operation', {\n operationId: op.id,\n code: errorCode(failure),\n });\n return op;\n }\n // Every unfenced pass (`getTransactionStatus`, `watch`, `waitFor`), signalled or not,\n // tries the lease once: a busy lease leaves the Operation for a later pass. Only a\n // fenced worker pass waits `acquireTimeoutMs`.\n return this.deps.engine.failRejected(target, op, {\n signal,\n ...(fence ? { fence } : { acquireTimeoutMs: 0 }),\n });\n }\n\n private bestStatus(\n record: OperationRecord,\n observations: ReadonlyMap<string, AttemptObservation>,\n ): TxStatus {\n const all = record.attempts\n .map((a) => observations.get(a.id))\n .filter((o): o is AttemptObservation => o !== undefined);\n const chosen =\n all.find(\n (o) => o.state === 'final' || (o.state === 'failed' && o.evidence === 'proven'),\n ) ??\n all\n .filter((o) => o.state === 'included' || o.state === 'failed')\n .sort((a, b) => b.confirmations - a.confirmations)[0] ??\n (record.activeAttemptId ? observations.get(record.activeAttemptId) : undefined);\n return chosen ? statusOf(chosen) : UNKNOWN;\n }\n\n private async rawStatus(target: ReadTarget, id: string): Promise<TxStatus> {\n const { reader } = target.pooled.driver;\n const [observation, head, finalized] = await Promise.all([\n reader.observe({ id, idKind: 'tx-hash', canonical: true }, undefined, undefined),\n reader.getBlockHeight(),\n reader.getFinalizedHeight(),\n ]);\n return statusFromObservation(observation, head, finalized);\n }\n\n private defaultError(record: OperationRecord): SerializedError {\n const code = record.state === 'expired' ? 'TX_EXPIRED' : 'TX_REJECTED';\n return new ChainError(code, `operation ended in state '${record.state}'`).toJSON();\n }\n\n #reorged(op: OperationRecord, attempt: AttemptRecord, previousBlockHash: string): void {\n this.deps.events.emit('tx.reorged', {\n namespace: this.deps.namespace,\n operationId: op.id,\n attemptId: attempt.id,\n previousBlockHash,\n });\n }\n\n /**\n * Resends the stored raw bytes of a dropped active Attempt, at most once per\n * `rebroadcastIntervalMs`. The answer decides nothing: `dropped` is never terminal,\n * and a refusal or rejection of bytes a node once held says nothing about them. An\n * acceptance is remembered (`firstSeenAt`) like the engine's broadcast path does.\n */\n async #rebroadcastDropped(\n target: ReadTarget,\n op: OperationRecord,\n attempt: AttemptRecord,\n observation: AttemptObservation,\n now: number,\n signal?: AbortSignal,\n ): Promise<void> {\n if (\n now - (observation.lastBroadcastAt ?? 0) <\n this.deps.lifecycle().rebroadcastIntervalMs\n )\n return;\n let accepted = false;\n try {\n const result = await target.pooled.driver.broadcaster.broadcast(\n { raw: attempt.raw, ref: attempt.ref },\n signal ? { signal } : {},\n );\n accepted = result.kind === 'accepted' || result.kind === 'already-known';\n } catch (error) {\n // The code only: an error message may carry detail that logs must not.\n this.deps.log.debug('rebroadcast of a dropped attempt failed', {\n operationId: op.id,\n code: errorCode(error),\n });\n }\n await writeObservation(this.observationDeps, attempt, op.id, (stored) => ({\n lastBroadcastAt: now,\n ...(accepted ? { firstSeenAt: stored?.firstSeenAt ?? now } : {}),\n }));\n }\n}\n\n/** Refuses a stored Operation of another chain or network than `selection` (INVALID_INTENT). */\nexport function assertSameNetwork(\n selection: Pick<ResolvedSelection, 'chain' | 'network'>,\n record: OperationRecord,\n): void {\n const { chain, network } = selection;\n if (record.context.chain !== chain.id || record.context.network !== network.id) {\n throw new ValidationError(\n 'INVALID_INTENT',\n `operation '${record.id}' belongs to ${record.context.chain}:${record.context.network}, not ${chain.id}:${network.id}`,\n );\n }\n}\n\n/**\n * An unmanaged transaction has no proofs to wait for: its observed finality is the answer,\n * whether it succeeded or reverted (`waitFor` rejects a reverted one with TX_REVERTED).\n */\nfunction unmanagedFinal({ status, record }: Snapshot): boolean {\n return !record && status.finality === 'final';\n}\n\nfunction depth(head: bigint, height: bigint): number {\n const d = head - height + 1n;\n return d > 0n ? Number(d) : 0;\n}\n\n/**\n * A proven failure's fixed reason and what failed; a success clears both. Drivers give a\n * fixed text because a node's own text can carry addresses or amounts; the stored reason\n * is sensitive data, and no event carries it.\n */\nfunction failureOf(proof: {\n readonly success: boolean;\n readonly reason?: string;\n readonly failure?: TxFailure;\n}): { readonly reason: string | undefined; readonly failure: TxFailure | undefined } {\n return proof.success\n ? { reason: undefined, failure: undefined }\n : { reason: proof.reason, failure: proof.failure ?? 'reverted' };\n}\n"]}
@@ -41,7 +41,7 @@ export declare function reclaimLeaked(engine: Reconciler, op: OperationRecord, l
41
41
  /**
42
42
  * The lowest value reconciliation may reclaim: `chainPending` (a lagging endpoint can
43
43
  * under-report it), raised above every nonce the chain consumed at finality, i.e. those
44
- * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_REPLACED`).
44
+ * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_UNEVIDENCED`, `TX_REPLACED`).
45
45
  * A rejection, a failure before signing or an abandoned Operation consumed nothing.
46
46
  */
47
47
  export declare function consumedFloor(engine: Reconciler, wallet: Omit<OperationFilter, 'states' | 'limit'>, chainPending: bigint): Promise<bigint>;
@@ -69,7 +69,7 @@ async function reclaimLeaked(engine, op, lease, chainPending, preparing) {
69
69
  /**
70
70
  * The lowest value reconciliation may reclaim: `chainPending` (a lagging endpoint can
71
71
  * under-report it), raised above every nonce the chain consumed at finality, i.e. those
72
- * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_REPLACED`).
72
+ * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_UNEVIDENCED`, `TX_REPLACED`).
73
73
  * A rejection, a failure before signing or an abandoned Operation consumed nothing.
74
74
  */
75
75
  async function consumedFloor(engine, wallet, chainPending) {
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../../src/core/lifecycle/reconcile.ts"],"names":[],"mappings":"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","sourcesContent":["import { isCryptoAioError } from '../errors/error';\nimport type { LeaseHandle } from '../ordering/sequence';\nimport {\n NON_TERMINAL_STATES,\n type OperationFilter,\n type OperationPatch,\n type OperationRecord,\n} from '../store/types';\nimport type { EngineDeps, OperationTarget, ReadTarget } from './engine';\nimport { CONSUMED_FAILURES, hasReclaimable, heldNonces } from './engine-rules';\n\n/*\n * Nonce reconciliation, as functions over the engine's deps. The\n * engine hands in its deps and the few steps of its own these need (`Reconciler`).\n */\n\n/** What reconciliation needs from `OperationEngine`: its deps and a few of its steps. */\nexport interface Reconciler {\n readonly deps: EngineDeps;\n update(op: OperationRecord, patch: OperationPatch): Promise<OperationRecord>;\n require(operationId: string): Promise<OperationRecord>;\n sequenceKeyOf(op: OperationRecord): string;\n assertOwnedBy(target: OperationTarget, op: OperationRecord): void;\n withAddressLease<T>(\n target: ReadTarget,\n op: OperationRecord,\n fn: (lease: LeaseHandle | undefined) => Promise<T>,\n signal?: AbortSignal,\n options?: { readonly acquireTimeoutMs?: number },\n ): Promise<T>;\n}\n\n/**\n * Nonce reconciliation, never a filler transaction. Under the address lease,\n * returns to `released` every value in [floor, next) that no live Operation of\n * `op`'s wallet reserves, so the next allocation reuses it and the transfers waiting\n * behind the gap can land; `floor` is `consumedFloor` (never below a nonce the chain\n * consumed at finality), and the wallet's history is read only when some value is\n * reclaimable at all. It closes the leaks a release cannot: a crash between\n * allocation and the `prepared` write, a store failure inside a release after a terminal\n * write, and a failure recorded without a release. Every live `created` Operation\n * without a reservation is fenced first (`fenceStalePrepare`), so a `prepared` write\n * still in flight from a lapsed lease can never land on a released value (a legitimate\n * transfer re-reads its Operation under the lease). Returns the reclaimed values. The\n * lease wait is bounded by `signal` and `acquireTimeoutMs` (`0` tries once); a busy lease\n * rejects with SEQUENCE_BUSY. A target whose wallet does not own `op` is refused\n * (INVALID_INTENT): its lease guards another sequence.\n */\nexport async function reconcileNonces(\n engine: Reconciler,\n target: OperationTarget,\n op: OperationRecord,\n options: { readonly signal?: AbortSignal; readonly acquireTimeoutMs?: number } = {},\n): Promise<readonly bigint[]> {\n const { driver } = target.pooled;\n const sequence = driver.sequence;\n if (driver.ordering !== 'nonce' || !sequence) return [];\n engine.assertOwnedBy(target, op);\n const { signal, acquireTimeoutMs } = options;\n return engine.withAddressLease(\n target,\n op,\n async (lease) =>\n reclaimLeaked(\n engine,\n op,\n lease as LeaseHandle,\n await sequence.pending(op.intent.from),\n ),\n signal,\n acquireTimeoutMs === undefined ? undefined : { acquireTimeoutMs },\n );\n}\n\n/**\n * The body of `reconcileNonces`, under the held address lease of `op`'s wallet, with the\n * chain's pending nonce already read. `preparing` is an Operation this lease is preparing\n * right now (`prepareStage`): it is never fenced, since its own write follows.\n */\nexport async function reclaimLeaked(\n engine: Reconciler,\n op: OperationRecord,\n lease: LeaseHandle,\n chainPending: bigint,\n preparing?: string,\n): Promise<readonly bigint[]> {\n const wallet = {\n namespace: engine.deps.namespace,\n chain: op.context.chain,\n network: op.context.network,\n from: op.intent.from,\n };\n const key = engine.sequenceKeyOf(op);\n // Cheap first: with nothing reclaimable, neither the fencing writes nor the wallet's\n // history are needed (fencing only ever adds held values), and with no value at or\n // above `chainPending` ever allocated, not even the live Operations.\n const state = await engine.deps.stores.sequences.get(key);\n if (!state || state.next <= chainPending) return [];\n const live = await engine.deps.stores.operations.list({\n ...wallet,\n states: NON_TERMINAL_STATES,\n });\n if (!hasReclaimable(state, chainPending, live.flatMap(heldNonces))) return [];\n const held: bigint[] = [];\n for (const record of live) {\n const current =\n record.id === preparing ? record : await fenceStalePrepare(engine, record);\n held.push(...heldNonces(current));\n }\n const floor = await consumedFloor(engine, wallet, chainPending);\n await lease.renew();\n return engine.deps.sequences.reclaim(lease, key, floor, held);\n}\n\n/**\n * The lowest value reconciliation may reclaim: `chainPending` (a lagging endpoint can\n * under-report it), raised above every nonce the chain consumed at finality, i.e. those\n * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_REPLACED`).\n * A rejection, a failure before signing or an abandoned Operation consumed nothing.\n */\nexport async function consumedFloor(\n engine: Reconciler,\n wallet: Omit<OperationFilter, 'states' | 'limit'>,\n chainPending: bigint,\n): Promise<bigint> {\n let floor = chainPending;\n const history = await engine.deps.stores.operations.list({\n ...wallet,\n states: ['final', 'failed'],\n });\n for (const record of history) {\n if (record.state === 'failed' && !CONSUMED_FAILURES.has(record.error?.code ?? ''))\n continue;\n for (const nonce of heldNonces(record)) if (nonce >= floor) floor = nonce + 1n;\n }\n return floor;\n}\n\n/**\n * A `created` Operation without a reservation may still have a `prepared` write in\n * flight from a process whose lease lapsed (it allocated a nonce, renewed, then stalled).\n * A no-effect compare-and-set at the listed version makes that stale write lose its own\n * compare-and-set, so it can never land a reservation on a value this reconciliation\n * releases. This relies on the store bumping `version` on every `update`, a no-op one\n * included (the store contract pins it). After a lost compare-and-set the re-read\n * Operation is returned, and any reservation it now shows counts as held. Other\n * Operations are returned as listed.\n */\nexport async function fenceStalePrepare(\n engine: Reconciler,\n record: OperationRecord,\n): Promise<OperationRecord> {\n if (record.state !== 'created' || record.reservation !== undefined) return record;\n try {\n return await engine.update(record, { clear: ['error'] });\n } catch (error) {\n if (!isCryptoAioError(error, 'VERSION_CONFLICT')) throw error;\n return engine.require(record.id);\n }\n}\n"]}
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../../src/core/lifecycle/reconcile.ts"],"names":[],"mappings":"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","sourcesContent":["import { isCryptoAioError } from '../errors/error';\nimport type { LeaseHandle } from '../ordering/sequence';\nimport {\n NON_TERMINAL_STATES,\n type OperationFilter,\n type OperationPatch,\n type OperationRecord,\n} from '../store/types';\nimport type { EngineDeps, OperationTarget, ReadTarget } from './engine';\nimport { CONSUMED_FAILURES, hasReclaimable, heldNonces } from './engine-rules';\n\n/*\n * Nonce reconciliation, as functions over the engine's deps. The\n * engine hands in its deps and the few steps of its own these need (`Reconciler`).\n */\n\n/** What reconciliation needs from `OperationEngine`: its deps and a few of its steps. */\nexport interface Reconciler {\n readonly deps: EngineDeps;\n update(op: OperationRecord, patch: OperationPatch): Promise<OperationRecord>;\n require(operationId: string): Promise<OperationRecord>;\n sequenceKeyOf(op: OperationRecord): string;\n assertOwnedBy(target: OperationTarget, op: OperationRecord): void;\n withAddressLease<T>(\n target: ReadTarget,\n op: OperationRecord,\n fn: (lease: LeaseHandle | undefined) => Promise<T>,\n signal?: AbortSignal,\n options?: { readonly acquireTimeoutMs?: number },\n ): Promise<T>;\n}\n\n/**\n * Nonce reconciliation, never a filler transaction. Under the address lease,\n * returns to `released` every value in [floor, next) that no live Operation of\n * `op`'s wallet reserves, so the next allocation reuses it and the transfers waiting\n * behind the gap can land; `floor` is `consumedFloor` (never below a nonce the chain\n * consumed at finality), and the wallet's history is read only when some value is\n * reclaimable at all. It closes the leaks a release cannot: a crash between\n * allocation and the `prepared` write, a store failure inside a release after a terminal\n * write, and a failure recorded without a release. Every live `created` Operation\n * without a reservation is fenced first (`fenceStalePrepare`), so a `prepared` write\n * still in flight from a lapsed lease can never land on a released value (a legitimate\n * transfer re-reads its Operation under the lease). Returns the reclaimed values. The\n * lease wait is bounded by `signal` and `acquireTimeoutMs` (`0` tries once); a busy lease\n * rejects with SEQUENCE_BUSY. A target whose wallet does not own `op` is refused\n * (INVALID_INTENT): its lease guards another sequence.\n */\nexport async function reconcileNonces(\n engine: Reconciler,\n target: OperationTarget,\n op: OperationRecord,\n options: { readonly signal?: AbortSignal; readonly acquireTimeoutMs?: number } = {},\n): Promise<readonly bigint[]> {\n const { driver } = target.pooled;\n const sequence = driver.sequence;\n if (driver.ordering !== 'nonce' || !sequence) return [];\n engine.assertOwnedBy(target, op);\n const { signal, acquireTimeoutMs } = options;\n return engine.withAddressLease(\n target,\n op,\n async (lease) =>\n reclaimLeaked(\n engine,\n op,\n lease as LeaseHandle,\n await sequence.pending(op.intent.from),\n ),\n signal,\n acquireTimeoutMs === undefined ? undefined : { acquireTimeoutMs },\n );\n}\n\n/**\n * The body of `reconcileNonces`, under the held address lease of `op`'s wallet, with the\n * chain's pending nonce already read. `preparing` is an Operation this lease is preparing\n * right now (`prepareStage`): it is never fenced, since its own write follows.\n */\nexport async function reclaimLeaked(\n engine: Reconciler,\n op: OperationRecord,\n lease: LeaseHandle,\n chainPending: bigint,\n preparing?: string,\n): Promise<readonly bigint[]> {\n const wallet = {\n namespace: engine.deps.namespace,\n chain: op.context.chain,\n network: op.context.network,\n from: op.intent.from,\n };\n const key = engine.sequenceKeyOf(op);\n // Cheap first: with nothing reclaimable, neither the fencing writes nor the wallet's\n // history are needed (fencing only ever adds held values), and with no value at or\n // above `chainPending` ever allocated, not even the live Operations.\n const state = await engine.deps.stores.sequences.get(key);\n if (!state || state.next <= chainPending) return [];\n const live = await engine.deps.stores.operations.list({\n ...wallet,\n states: NON_TERMINAL_STATES,\n });\n if (!hasReclaimable(state, chainPending, live.flatMap(heldNonces))) return [];\n const held: bigint[] = [];\n for (const record of live) {\n const current =\n record.id === preparing ? record : await fenceStalePrepare(engine, record);\n held.push(...heldNonces(current));\n }\n const floor = await consumedFloor(engine, wallet, chainPending);\n await lease.renew();\n return engine.deps.sequences.reclaim(lease, key, floor, held);\n}\n\n/**\n * The lowest value reconciliation may reclaim: `chainPending` (a lagging endpoint can\n * under-report it), raised above every nonce the chain consumed at finality, i.e. those\n * of `final` Operations and of failures proven on chain (`TX_REVERTED`, `TX_UNEVIDENCED`, `TX_REPLACED`).\n * A rejection, a failure before signing or an abandoned Operation consumed nothing.\n */\nexport async function consumedFloor(\n engine: Reconciler,\n wallet: Omit<OperationFilter, 'states' | 'limit'>,\n chainPending: bigint,\n): Promise<bigint> {\n let floor = chainPending;\n const history = await engine.deps.stores.operations.list({\n ...wallet,\n states: ['final', 'failed'],\n });\n for (const record of history) {\n if (record.state === 'failed' && !CONSUMED_FAILURES.has(record.error?.code ?? ''))\n continue;\n for (const nonce of heldNonces(record)) if (nonce >= floor) floor = nonce + 1n;\n }\n return floor;\n}\n\n/**\n * A `created` Operation without a reservation may still have a `prepared` write in\n * flight from a process whose lease lapsed (it allocated a nonce, renewed, then stalled).\n * A no-effect compare-and-set at the listed version makes that stale write lose its own\n * compare-and-set, so it can never land a reservation on a value this reconciliation\n * releases. This relies on the store bumping `version` on every `update`, a no-op one\n * included (the store contract pins it). After a lost compare-and-set the re-read\n * Operation is returned, and any reservation it now shows counts as held. Other\n * Operations are returned as listed.\n */\nexport async function fenceStalePrepare(\n engine: Reconciler,\n record: OperationRecord,\n): Promise<OperationRecord> {\n if (record.state !== 'created' || record.reservation !== undefined) return record;\n try {\n return await engine.update(record, { clear: ['error'] });\n } catch (error) {\n if (!isCryptoAioError(error, 'VERSION_CONFLICT')) throw error;\n return engine.require(record.id);\n }\n}\n"]}
@@ -16,6 +16,12 @@ export interface RecoveryReport {
16
16
  readonly checked: number;
17
17
  /** Operations that need a caller (see `recovery.skipped`); never resent or checked. */
18
18
  readonly skipped: number;
19
+ /**
20
+ * `signed` or ambiguously `submitted` Operations whose wallet no longer resolves (its
21
+ * configuration or signer was removed): checked on chain, but their stored bytes were not
22
+ * sent again. Restore the wallet and recover again to resend them.
23
+ */
24
+ readonly unresent: number;
19
25
  /** Operations whose target could not be rebuilt, or whose resend or check threw. */
20
26
  readonly failed: number;
21
27
  /** Leaked nonce values that reconciliation returned for reuse (across all wallets). */
@@ -72,9 +78,9 @@ export declare class Workers {
72
78
  * a caller and are reported through `recovery.skipped` (codes and states only). Then each
73
79
  * wallet with a live Operation has its nonces reconciled under its address lease. A
74
80
  * failure is logged by code and counted, and the rest go on. `signal` stops recovery
75
- * between Operations and bounds each check and lease wait. Known gap: a `signed` or
76
- * ambiguous Operation whose wallet-bound target cannot be resolved is counted `failed`
77
- * without its check, although the check needs no wallet.
81
+ * between Operations and bounds each check and lease wait. A `signed` or ambiguous
82
+ * Operation whose wallet no longer resolves is still checked, since the check needs no
83
+ * wallet, and counted `unresent`: only its resend needs the wallet.
78
84
  */
79
85
  recover(options?: {
80
86
  readonly signal?: AbortSignal;
@@ -114,9 +114,9 @@ class Workers {
114
114
  * a caller and are reported through `recovery.skipped` (codes and states only). Then each
115
115
  * wallet with a live Operation has its nonces reconciled under its address lease. A
116
116
  * failure is logged by code and counted, and the rest go on. `signal` stops recovery
117
- * between Operations and bounds each check and lease wait. Known gap: a `signed` or
118
- * ambiguous Operation whose wallet-bound target cannot be resolved is counted `failed`
119
- * without its check, although the check needs no wallet.
117
+ * between Operations and bounds each check and lease wait. A `signed` or ambiguous
118
+ * Operation whose wallet no longer resolves is still checked, since the check needs no
119
+ * wallet, and counted `unresent`: only its resend needs the wallet.
120
120
  */
121
121
  async recover(options = {}) {
122
122
  const { signal } = options;
@@ -130,6 +130,7 @@ class Workers {
130
130
  let rebroadcast = 0;
131
131
  let checked = 0;
132
132
  let skipped = 0;
133
+ let unresent = 0;
133
134
  let failed = 0;
134
135
  let reconciled = 0;
135
136
  const skip = (op, reason) => {
@@ -157,18 +158,30 @@ class Workers {
157
158
  let current = op;
158
159
  if (op.state === 'signed' ||
159
160
  (op.state === 'submitted' && op.ambiguous === true)) {
160
- const writer = await this.#resolved(writes, op);
161
- try {
162
- current = await this.deps.engine.rebroadcast(writer, op.id, signal);
163
- }
164
- catch (error) {
165
- // A refusal or an unknown outcome is recorded on the Operation: check it next.
166
- if (!(0, error_1.isCryptoAioError)(error) ||
167
- (error.category !== 'chain' && error.ambiguous !== true))
161
+ const writer = await this.#resolved(writes, op).catch((error) => {
162
+ // A wallet whose configuration or signer is gone rules out the resend only.
163
+ if (!walletUnresolved(error))
168
164
  throw error;
169
- current = (await this.monitor.find(op.id)) ?? op;
165
+ unresent += 1;
166
+ this.deps.log.warn('recovery checks an operation it cannot resend', {
167
+ operationId: op.id,
168
+ code: (0, engine_rules_1.errorCode)(error),
169
+ });
170
+ return undefined;
171
+ });
172
+ if (writer) {
173
+ try {
174
+ current = await this.deps.engine.rebroadcast(writer, op.id, signal);
175
+ }
176
+ catch (error) {
177
+ // A refusal or an unknown outcome is recorded on the Operation: check it next.
178
+ if (!(0, error_1.isCryptoAioError)(error) ||
179
+ (error.category !== 'chain' && error.ambiguous !== true))
180
+ throw error;
181
+ current = (await this.monitor.find(op.id)) ?? op;
182
+ }
183
+ rebroadcast += 1;
170
184
  }
171
- rebroadcast += 1;
172
185
  }
173
186
  await this.monitor.check(target, current, undefined, signal);
174
187
  checked += 1;
@@ -202,7 +215,7 @@ class Workers {
202
215
  });
203
216
  }
204
217
  }
205
- return { rebroadcast, checked, skipped, failed, reconciled };
218
+ return { rebroadcast, checked, skipped, unresent, failed, reconciled };
206
219
  }
207
220
  /**
208
221
  * `resolve` for one pass: each execution context's target is rebuilt at most once, and
@@ -326,4 +339,9 @@ class Workers {
326
339
  }
327
340
  }
328
341
  exports.Workers = Workers;
342
+ /** A wallet that cannot be resolved for writes: its configuration or its signer is gone. */
343
+ function walletUnresolved(error) {
344
+ return ((0, error_1.isCryptoAioError)(error) &&
345
+ (error.category === 'config' || error.category === 'signing'));
346
+ }
329
347
  //# sourceMappingURL=workers.js.map