@bsv/wallet-toolbox 2.1.27 → 2.1.28

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 (42) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/docs/client.md +303 -153
  3. package/docs/monitor.md +69 -1
  4. package/docs/storage.md +107 -31
  5. package/docs/wallet.md +246 -118
  6. package/out/src/monitor/Monitor.d.ts.map +1 -1
  7. package/out/src/monitor/Monitor.js +12 -0
  8. package/out/src/monitor/Monitor.js.map +1 -1
  9. package/out/src/monitor/tasks/TaskCheckNoSends.d.ts +59 -1
  10. package/out/src/monitor/tasks/TaskCheckNoSends.d.ts.map +1 -1
  11. package/out/src/monitor/tasks/TaskCheckNoSends.js +93 -4
  12. package/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
  13. package/out/src/services/__tests/getFiatExchangeRate.test.js +25 -0
  14. package/out/src/services/__tests/getFiatExchangeRate.test.js.map +1 -1
  15. package/out/src/services/__tests/getMerklePath.test.js +8 -0
  16. package/out/src/services/__tests/getMerklePath.test.js.map +1 -1
  17. package/out/src/services/__tests/verifyBeef.test.js +37 -0
  18. package/out/src/services/__tests/verifyBeef.test.js.map +1 -1
  19. package/out/src/services/chaintracker/__tests/ChaintracksChainTracker.test.js +36 -0
  20. package/out/src/services/chaintracker/__tests/ChaintracksChainTracker.test.js.map +1 -1
  21. package/out/src/services/chaintracker/__tests/ChaintracksServiceClient.test.js +34 -0
  22. package/out/src/services/chaintracker/__tests/ChaintracksServiceClient.test.js.map +1 -1
  23. package/out/src/signer/methods/internalizeAction.d.ts +8 -1
  24. package/out/src/signer/methods/internalizeAction.d.ts.map +1 -1
  25. package/out/src/signer/methods/internalizeAction.js +8 -1
  26. package/out/src/signer/methods/internalizeAction.js.map +1 -1
  27. package/out/src/storage/StorageProvider.d.ts.map +1 -1
  28. package/out/src/storage/StorageProvider.js +80 -2
  29. package/out/src/storage/StorageProvider.js.map +1 -1
  30. package/out/src/storage/methods/ListActionsSpecOp.d.ts.map +1 -1
  31. package/out/src/storage/methods/ListActionsSpecOp.js +68 -5
  32. package/out/src/storage/methods/ListActionsSpecOp.js.map +1 -1
  33. package/out/src/storage/methods/createAction.js +27 -13
  34. package/out/src/storage/methods/createAction.js.map +1 -1
  35. package/out/src/storage/methods/internalizeAction.d.ts +69 -2
  36. package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
  37. package/out/src/storage/methods/internalizeAction.js +206 -26
  38. package/out/src/storage/methods/internalizeAction.js.map +1 -1
  39. package/out/src/storage/portable/index.d.ts.map +1 -1
  40. package/out/src/storage/portable/index.js +160 -114
  41. package/out/src/storage/portable/index.js.map +1 -1
  42. package/package.json +6 -6
package/docs/monitor.md CHANGED
@@ -542,7 +542,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
542
542
  ---
543
543
  ##### Class: TaskCheckNoSends
544
544
 
545
- `TaskCheckNoSends` is a WalletMonitor task that retreives merkle proofs for
545
+ `TaskCheckNoSends` is a WalletMonitor task that retrieves merkle proofs for
546
546
  'nosend' transactions that MAY have been shared externally.
547
547
 
548
548
  Unlike intentionally processed transactions, 'nosend' transactions are fully valid
@@ -554,10 +554,54 @@ managed to get mined by some external process.
554
554
  If a proof is obtained and validated, a new ProvenTx record is created and
555
555
  the original ProvenTxReq status is advanced to 'notifying'.
556
556
 
557
+ # Aging schedule on the checkNow path
558
+
559
+ When this task is triggered by a new block header (`checkNow = true`, wired in
560
+ `Monitor.processNewBlockHeader`), it does NOT scan every `nosend` row on every
561
+ block. The set of `nosend` rows can grow large over a wallet's lifetime
562
+ (txs sitting in escrow, un-aborted tests, abandoned batches), and a fast,
563
+ unfiltered scan on every block would do an unbounded number of external
564
+ `getMerklePath` lookups per block.
565
+
566
+ Instead, the row's age (now - `created_at`) determines how often it is
567
+ eligible for a checkNow-triggered chain check. The schedule starts at "skip
568
+ entirely" for very fresh rows (to protect in-flight batched-tx workflows
569
+ where chained `createAction({ noSend: true, sendWith: [...] })` builds
570
+ deliberately keep rows in `nosend` until a single terminator broadcasts the
571
+ whole BEEF), then progresses to "every block", "hourly", "daily", and
572
+ "weekly" as rows age:
573
+
574
+ age < 5 min → skip (in-flight batch protection)
575
+ 5 min ≤ age < 1 hr → check on every checkNow trigger
576
+ 1 hr ≤ age < 24 hr → check on ~hourly cadence (block-height % 6)
577
+ 24 hr ≤ age < 7 days → check on ~daily cadence (block-height % 144)
578
+ age ≥ 7 days → check on ~weekly cadence (block-height % 1008)
579
+
580
+ Block-height modulo gives a deterministic, stateless way to schedule
581
+ checks for older rows; no per-row "last checked" persistence is required.
582
+ Each row's modulo offset is keyed by its `provenTxReqId` so that rows in
583
+ the same age tier are staggered across the modulo cycle rather than all
584
+ firing on the same block — `(blockHeight + provenTxReqId) % tierInterval`.
585
+ For a wallet with N rows in tier T and tier interval K, this gives
586
+ roughly N/K rows fired per block instead of N rows fired every K blocks.
587
+
588
+ The scheduled daily cadence (no `checkNow`) is unaffected — it still scans
589
+ every row regardless of age. That path is the once-per-day fallback that
590
+ guarantees externally-broadcast `nosend` txs are eventually recognized
591
+ even if the aging schedule on the checkNow path defers them.
592
+
557
593
  ```ts
558
594
  export class TaskCheckNoSends extends WalletMonitorTask {
559
595
  static readonly taskName = "CheckNoSends";
560
596
  static checkNow = false;
597
+ static readonly tier0FreshSkipMsecs = 5 * 60 * 1000;
598
+ static readonly tier1EveryBlockMsecs = 60 * 60 * 1000;
599
+ static readonly tier2HourlyMsecs = 24 * 60 * 60 * 1000;
600
+ static readonly tier3DailyMsecs = 7 * 24 * 60 * 60 * 1000;
601
+ static readonly tier2BlockInterval = 6;
602
+ static readonly tier3BlockInterval = 144;
603
+ static readonly tier4BlockInterval = 1008;
604
+ static shouldCheckOnCheckNow(createdAt: Date, nowMs: number, currentBlockHeight: number, provenTxReqId: number): boolean
561
605
  constructor(monitor: Monitor, public triggerMsecs = Monitor.oneDay * 1)
562
606
  trigger(nowMsecsSinceEpoch: number): {
563
607
  run: boolean;
@@ -577,6 +621,30 @@ listener can set this true to cause
577
621
  static checkNow = false
578
622
  ```
579
623
 
624
+ ###### Property tier0FreshSkipMsecs
625
+
626
+ Aging-schedule constants for the `checkNow` path. Rows below `tier0FreshSkipMsecs`
627
+ are never checked via checkNow (batched-tx protection). Rows from tier 0 up
628
+ to `tier1EveryBlockMsecs` are checked on every checkNow trigger. Beyond that,
629
+ checks happen on `block-height % tierNBlockInterval === 0` cadences with
630
+ growing intervals. The scheduled daily cadence (no checkNow) is unaffected.
631
+
632
+ ```ts
633
+ static readonly tier0FreshSkipMsecs = 5 * 60 * 1000
634
+ ```
635
+
636
+ ###### Method shouldCheckOnCheckNow
637
+
638
+ Decide whether a single `nosend` row should be chain-checked on the
639
+ current `checkNow` trigger, based on its age, the current block
640
+ height, and its `provenTxReqId` (used to stagger same-tier rows
641
+ across the modulo cycle). See class docstring for the full schedule
642
+ and staggering rationale.
643
+
644
+ ```ts
645
+ static shouldCheckOnCheckNow(createdAt: Date, nowMs: number, currentBlockHeight: number, provenTxReqId: number): boolean
646
+ ```
647
+
580
648
  ###### Method trigger
581
649
 
582
650
  Normally triggered by checkNow getting set by new block header found event from chaintracks
package/docs/storage.md CHANGED
@@ -22,25 +22,25 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
22
22
 
23
23
  | | | |
24
24
  | --- | --- | --- |
25
- | [AdminStatsResult](#interface-adminstatsresult) | [PostReqsToNetworkResult](#interface-postreqstonetworkresult) | [TableOutput](#interface-tableoutput) |
26
- | [AggregatePostBeefTxResult](#interface-aggregatepostbeeftxresult) | [ProvenTxFromTxidResult](#interface-proventxfromtxidresult) | [TableOutputBasket](#interface-tableoutputbasket) |
27
- | [CommitNewTxResults](#interface-commitnewtxresults) | [ProvenTxReqHistory](#interface-proventxreqhistory) | [TableOutputTag](#interface-tableoutputtag) |
28
- | [EntitySyncMap](#interface-entitysyncmap) | [ProvenTxReqHistorySummaryApi](#interface-proventxreqhistorysummaryapi) | [TableOutputTagMap](#interface-tableoutputtagmap) |
29
- | [GenerateChangeSdkChangeInput](#interface-generatechangesdkchangeinput) | [ProvenTxReqNotify](#interface-proventxreqnotify) | [TableOutputX](#interface-tableoutputx) |
30
- | [GenerateChangeSdkChangeOutput](#interface-generatechangesdkchangeoutput) | [StorageAdminStats](#interface-storageadminstats) | [TableProvenTx](#interface-tableproventx) |
31
- | [GenerateChangeSdkInput](#interface-generatechangesdkinput) | [StorageIdbOptions](#interface-storageidboptions) | [TableProvenTxReq](#interface-tableproventxreq) |
32
- | [GenerateChangeSdkOutput](#interface-generatechangesdkoutput) | [StorageIdbSchema](#interface-storageidbschema) | [TableProvenTxReqDynamics](#interface-tableproventxreqdynamics) |
33
- | [GenerateChangeSdkParams](#interface-generatechangesdkparams) | [StorageKnexOptions](#interface-storageknexoptions) | [TableSettings](#interface-tablesettings) |
34
- | [GenerateChangeSdkResult](#interface-generatechangesdkresult) | [StorageProviderOptions](#interface-storageprovideroptions) | [TableSyncState](#interface-tablesyncstate) |
35
- | [GenerateChangeSdkStorageChange](#interface-generatechangesdkstoragechange) | [StorageReaderOptions](#interface-storagereaderoptions) | [TableTransaction](#interface-tabletransaction) |
36
- | [GetReqsAndBeefDetail](#interface-getreqsandbeefdetail) | [StorageReaderWriterOptions](#interface-storagereaderwriteroptions) | [TableTxLabel](#interface-tabletxlabel) |
37
- | [GetReqsAndBeefResult](#interface-getreqsandbeefresult) | [SyncError](#interface-syncerror) | [TableTxLabelMap](#interface-tabletxlabelmap) |
38
- | [ListActionsSpecOp](#interface-listactionsspecop) | [SyncMap](#interface-syncmap) | [TableUser](#interface-tableuser) |
39
- | [ListOutputsSpecOp](#interface-listoutputsspecop) | [TableCertificate](#interface-tablecertificate) | [ValidateGenerateChangeSdkParamsResult](#interface-validategeneratechangesdkparamsresult) |
40
- | [MonitorAdminContext](#interface-monitoradmincontext) | [TableCertificateField](#interface-tablecertificatefield) | [VerifyAndRepairBeefResult](#interface-verifyandrepairbeefresult) |
41
- | [MonitorAdminContextConfig](#interface-monitoradmincontextconfig) | [TableCertificateX](#interface-tablecertificatex) | [WalletStorageServerOptions](#interface-walletstorageserveroptions) |
42
- | [PostBeefResultForTxidApi](#interface-postbeefresultfortxidapi) | [TableCommission](#interface-tablecommission) | [XValidCreateActionOutput](#interface-xvalidcreateactionoutput) |
43
- | [PostReqsToNetworkDetails](#interface-postreqstonetworkdetails) | [TableMonitorEvent](#interface-tablemonitorevent) | |
25
+ | [AdminStatsResult](#interface-adminstatsresult) | [PostReqsToNetworkResult](#interface-postreqstonetworkresult) | [TableMonitorEvent](#interface-tablemonitorevent) |
26
+ | [AggregatePostBeefTxResult](#interface-aggregatepostbeeftxresult) | [ProvenTxFromTxidResult](#interface-proventxfromtxidresult) | [TableOutput](#interface-tableoutput) |
27
+ | [CommitNewTxResults](#interface-commitnewtxresults) | [ProvenTxReqHistory](#interface-proventxreqhistory) | [TableOutputBasket](#interface-tableoutputbasket) |
28
+ | [EntitySyncMap](#interface-entitysyncmap) | [ProvenTxReqHistorySummaryApi](#interface-proventxreqhistorysummaryapi) | [TableOutputTag](#interface-tableoutputtag) |
29
+ | [GenerateChangeSdkChangeInput](#interface-generatechangesdkchangeinput) | [ProvenTxReqNotify](#interface-proventxreqnotify) | [TableOutputTagMap](#interface-tableoutputtagmap) |
30
+ | [GenerateChangeSdkChangeOutput](#interface-generatechangesdkchangeoutput) | [SpentInputTransition](#interface-spentinputtransition) | [TableOutputX](#interface-tableoutputx) |
31
+ | [GenerateChangeSdkInput](#interface-generatechangesdkinput) | [StorageAdminStats](#interface-storageadminstats) | [TableProvenTx](#interface-tableproventx) |
32
+ | [GenerateChangeSdkOutput](#interface-generatechangesdkoutput) | [StorageIdbOptions](#interface-storageidboptions) | [TableProvenTxReq](#interface-tableproventxreq) |
33
+ | [GenerateChangeSdkParams](#interface-generatechangesdkparams) | [StorageIdbSchema](#interface-storageidbschema) | [TableProvenTxReqDynamics](#interface-tableproventxreqdynamics) |
34
+ | [GenerateChangeSdkResult](#interface-generatechangesdkresult) | [StorageKnexOptions](#interface-storageknexoptions) | [TableSettings](#interface-tablesettings) |
35
+ | [GenerateChangeSdkStorageChange](#interface-generatechangesdkstoragechange) | [StorageProviderOptions](#interface-storageprovideroptions) | [TableSyncState](#interface-tablesyncstate) |
36
+ | [GetReqsAndBeefDetail](#interface-getreqsandbeefdetail) | [StorageReaderOptions](#interface-storagereaderoptions) | [TableTransaction](#interface-tabletransaction) |
37
+ | [GetReqsAndBeefResult](#interface-getreqsandbeefresult) | [StorageReaderWriterOptions](#interface-storagereaderwriteroptions) | [TableTxLabel](#interface-tabletxlabel) |
38
+ | [ListActionsSpecOp](#interface-listactionsspecop) | [SyncError](#interface-syncerror) | [TableTxLabelMap](#interface-tabletxlabelmap) |
39
+ | [ListOutputsSpecOp](#interface-listoutputsspecop) | [SyncMap](#interface-syncmap) | [TableUser](#interface-tableuser) |
40
+ | [MonitorAdminContext](#interface-monitoradmincontext) | [TableCertificate](#interface-tablecertificate) | [ValidateGenerateChangeSdkParamsResult](#interface-validategeneratechangesdkparamsresult) |
41
+ | [MonitorAdminContextConfig](#interface-monitoradmincontextconfig) | [TableCertificateField](#interface-tablecertificatefield) | [VerifyAndRepairBeefResult](#interface-verifyandrepairbeefresult) |
42
+ | [PostBeefResultForTxidApi](#interface-postbeefresultfortxidapi) | [TableCertificateX](#interface-tablecertificatex) | [WalletStorageServerOptions](#interface-walletstorageserveroptions) |
43
+ | [PostReqsToNetworkDetails](#interface-postreqstonetworkdetails) | [TableCommission](#interface-tablecommission) | [XValidCreateActionOutput](#interface-xvalidcreateactionoutput) |
44
44
 
45
45
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
46
46
 
@@ -588,6 +588,26 @@ export interface ProvenTxReqNotify {
588
588
 
589
589
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
590
590
 
591
+ ---
592
+ ##### Interface: SpentInputTransition
593
+
594
+ ```ts
595
+ export interface SpentInputTransition {
596
+ outputId: number;
597
+ setSpentBy: boolean;
598
+ }
599
+ ```
600
+
601
+ ###### Property setSpentBy
602
+
603
+ true if the call set spentBy; false if only spendable was flipped.
604
+
605
+ ```ts
606
+ setSpentBy: boolean
607
+ ```
608
+
609
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
610
+
591
611
  ---
592
612
  ##### Interface: StorageAdminStats
593
613
 
@@ -4712,12 +4732,13 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
4712
4732
  | [listOutputs](#function-listoutputs) | [purgeDataIdb](#function-purgedataidb) | [upgradeUsers](#function-upgradeusers) |
4713
4733
  | [listOutputsIdb](#function-listoutputsidb) | [redeemServiceCharges](#function-redeemservicecharges) | [validateDate](#function-validatedate) |
4714
4734
  | [lockScriptWithKeyOffsetFromPubKey](#function-lockscriptwithkeyoffsetfrompubkey) | [renderAdminPage](#function-renderadminpage) | [validateEntities](#function-validateentities) |
4715
- | [markStaleInputsAsSpent](#function-markstaleinputsasspent) | [reviewStatus](#function-reviewstatus) | [validateEntity](#function-validateentity) |
4716
- | [matchesCertificateFieldPartial](#function-matchescertificatefieldpartial) | [reviewStatusIdb](#function-reviewstatusidb) | [validateGenerateChangeSdkParams](#function-validategeneratechangesdkparams) |
4717
- | [matchesCertificatePartial](#function-matchescertificatepartial) | [setDisableDoubleSpendCheckForTest](#function-setdisabledoublespendcheckfortest) | [validateGenerateChangeSdkResult](#function-validategeneratechangesdkresult) |
4718
- | [matchesCommissionPartial](#function-matchescommissionpartial) | [shareReqsWithWorld](#function-sharereqswithworld) | [validateStorageFeeModel](#function-validatestoragefeemodel) |
4719
- | [matchesMonitorEventPartial](#function-matchesmonitoreventpartial) | [transactionInputSize](#function-transactioninputsize) | [validateSyncChunkEntities](#function-validatesyncchunkentities) |
4720
- | [matchesOutputBasketPartial](#function-matchesoutputbasketpartial) | [transactionOutputSize](#function-transactionoutputsize) | [varUintSize](#function-varuintsize) |
4735
+ | [markStaleInputsAsSpent](#function-markstaleinputsasspent) | [restoreInputsToSpendable](#function-restoreinputstospendable) | [validateEntity](#function-validateentity) |
4736
+ | [markUserInputsSpent](#function-markuserinputsspent) | [reviewStatus](#function-reviewstatus) | [validateGenerateChangeSdkParams](#function-validategeneratechangesdkparams) |
4737
+ | [matchesCertificateFieldPartial](#function-matchescertificatefieldpartial) | [reviewStatusIdb](#function-reviewstatusidb) | [validateGenerateChangeSdkResult](#function-validategeneratechangesdkresult) |
4738
+ | [matchesCertificatePartial](#function-matchescertificatepartial) | [setDisableDoubleSpendCheckForTest](#function-setdisabledoublespendcheckfortest) | [validateStorageFeeModel](#function-validatestoragefeemodel) |
4739
+ | [matchesCommissionPartial](#function-matchescommissionpartial) | [shareReqsWithWorld](#function-sharereqswithworld) | [validateSyncChunkEntities](#function-validatesyncchunkentities) |
4740
+ | [matchesMonitorEventPartial](#function-matchesmonitoreventpartial) | [transactionInputSize](#function-transactioninputsize) | [varUintSize](#function-varuintsize) |
4741
+ | [matchesOutputBasketPartial](#function-matchesoutputbasketpartial) | [transactionOutputSize](#function-transactionoutputsize) | |
4721
4742
 
4722
4743
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
4723
4744
 
@@ -4916,7 +4937,17 @@ A "wallet payment" adds an outputs value to the wallet's change "balance". These
4916
4937
  Processing starts with simple validation and then checks for a pre-existing transaction.
4917
4938
  If the transaction is already known to the user, then the outputs are reviewed against the existing outputs treatment,
4918
4939
  and merge rules are added to the arguments passed to the storage layer.
4919
- The existing transaction must be in the 'unproven' or 'completed' status. Any other status is an error.
4940
+
4941
+ The existing transaction's `status` determines what the merge path does next:
4942
+ - `'unproven'` or `'completed'`: outputs are merged into the existing record. The transaction status is left as-is.
4943
+ - `'nosend'`: an ambiguous case. The transaction was created with `noSend: true` and may have been externally
4944
+ broadcast, may be sitting in a sendWith chain, or may be stuck mid-flight. The merge path treats the
4945
+ `internalizeAction` call as explicit authorization to advance the lifecycle. Specifically: `transactions.status`
4946
+ is promoted to `'completed'` (when a BUMP is included in the BEEF) or `'unproven'` (otherwise), and the
4947
+ `proven_tx_req` is moved out of `'nosend'` so Monitor's standard proof-fetching flow can finalize it.
4948
+ This makes the `internalizeAction` semantics consistent regardless of whether the originator shares the
4949
+ same storage as the internalizer or not.
4950
+ - Any other status: an error.
4920
4951
 
4921
4952
  When the transaction already exists, the description is updated. The isOutgoing sense is not changed.
4922
4953
 
@@ -5070,6 +5101,17 @@ See also: [AggregatePostBeefTxResult](./storage.md#interface-aggregatepostbeeftx
5070
5101
 
5071
5102
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5072
5103
 
5104
+ ---
5105
+ ##### Function: markUserInputsSpent
5106
+
5107
+ ```ts
5108
+ export async function markUserInputsSpent(storage: StorageProvider, userId: number, tx: BsvTransaction, transactionId: number): Promise<SpentInputTransition[]>
5109
+ ```
5110
+
5111
+ See also: [SpentInputTransition](./storage.md#interface-spentinputtransition), [StorageProvider](./storage.md#class-storageprovider)
5112
+
5113
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5114
+
5073
5115
  ---
5074
5116
  ##### Function: matchesCertificateFieldPartial
5075
5117
 
@@ -5366,6 +5408,17 @@ export function renderAdminPage(): string
5366
5408
 
5367
5409
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5368
5410
 
5411
+ ---
5412
+ ##### Function: restoreInputsToSpendable
5413
+
5414
+ ```ts
5415
+ export async function restoreInputsToSpendable(storage: StorageProvider, transitions: SpentInputTransition[]): Promise<void>
5416
+ ```
5417
+
5418
+ See also: [SpentInputTransition](./storage.md#interface-spentinputtransition), [StorageProvider](./storage.md#class-storageprovider)
5419
+
5420
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
5421
+
5369
5422
  ---
5370
5423
  ##### Function: reviewStatus
5371
5424
 
@@ -5900,13 +5953,36 @@ getLabelToSpecOp: () => Record<string, ListActionsSpecOp> = () => {
5900
5953
  labelsToIntercept: ["abort"],
5901
5954
  setStatusFilter: () => ["nosend"],
5902
5955
  postProcess: async (s: StorageProvider, auth: AuthId, vargs: Validation.ValidListActionsArgs, specOpLabels: string[], txs: Array<Partial<TableTransaction>>): Promise<void> => {
5903
- if (specOpLabels.includes("abort")) {
5904
- for (const tx of txs) {
5905
- if (tx.status === "nosend") {
5906
- await s.abortAction(auth, { reference: tx.reference! });
5907
- tx.status = "failed";
5956
+ if (!specOpLabels.includes("abort"))
5957
+ return;
5958
+ const candidates = txs.filter(tx => tx.status === "nosend" && !!tx.txid);
5959
+ const candidateTxids = candidates.map(tx => tx.txid as string);
5960
+ const protectedTxids = new Set<string>();
5961
+ if (candidateTxids.length > 0) {
5962
+ const services = s.getServices();
5963
+ try {
5964
+ const r = await services.getStatusForTxids(candidateTxids);
5965
+ if (r.status === "success") {
5966
+ for (const result of r.results) {
5967
+ if (result.status === "mined" || result.status === "known") {
5968
+ protectedTxids.add(result.txid);
5969
+ }
5970
+ }
5908
5971
  }
5909
5972
  }
5973
+ catch {
5974
+ }
5975
+ }
5976
+ for (const tx of txs) {
5977
+ if (tx.status !== "nosend")
5978
+ continue;
5979
+ if (tx.txid && protectedTxids.has(tx.txid)) {
5980
+ continue;
5981
+ }
5982
+ const result = await s.abortAction(auth, { reference: tx.reference! });
5983
+ if (result.aborted) {
5984
+ tx.status = "failed";
5985
+ }
5910
5986
  }
5911
5987
  }
5912
5988
  },