@bsv/wallet-toolbox 2.1.25 → 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/CREATEACTION_BLOCKERS.md +391 -0
- package/docs/CUTOVER_RUNBOOK.md +95 -0
- package/docs/REQUIREMENTS_COMPLIANCE.md +157 -0
- package/docs/ROLLOUT_PLAN.md +273 -0
- package/docs/SESSION_HANDOFF.md +298 -0
- package/docs/STORAGE_METHOD_WIRING.md +176 -0
- package/docs/client.md +3765 -1325
- package/docs/monitor.md +255 -33
- package/docs/services.md +304 -280
- package/docs/setup.md +24 -24
- package/docs/storage.md +2783 -251
- package/docs/v3-upgrade/index.html +911 -0
- package/docs/wallet.md +4956 -9455
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletLogger.d.ts.map +1 -1
- package/out/src/WalletLogger.js.map +1 -1
- package/out/src/__tests/CWIStyleWalletManager.test.js.map +1 -1
- package/out/src/__tests/WalletPermissionsManager.fixtures.d.ts.map +1 -1
- package/out/src/__tests/WalletPermissionsManager.fixtures.js.map +1 -1
- package/out/src/entropy/EntropyCollector.d.ts.map +1 -1
- package/out/src/entropy/EntropyCollector.js.map +1 -1
- package/out/src/monitor/LeasedMonitorTask.d.ts +43 -0
- package/out/src/monitor/LeasedMonitorTask.d.ts.map +1 -0
- package/out/src/monitor/LeasedMonitorTask.js +89 -0
- package/out/src/monitor/LeasedMonitorTask.js.map +1 -0
- package/out/src/monitor/Monitor.d.ts +7 -0
- package/out/src/monitor/Monitor.d.ts.map +1 -1
- package/out/src/monitor/Monitor.js +7 -0
- package/out/src/monitor/Monitor.js.map +1 -1
- package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
- package/out/src/monitor/MonitorDaemon.js.map +1 -1
- package/out/src/monitor/V7LeasedTask.d.ts +43 -0
- package/out/src/monitor/V7LeasedTask.d.ts.map +1 -0
- package/out/src/monitor/V7LeasedTask.js +89 -0
- package/out/src/monitor/V7LeasedTask.js.map +1 -0
- package/out/src/monitor/index.all.d.ts +1 -0
- package/out/src/monitor/index.all.d.ts.map +1 -1
- package/out/src/monitor/index.all.js +1 -0
- package/out/src/monitor/index.all.js.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.d.ts +2 -0
- package/out/src/monitor/tasks/TaskCheckForProofs.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.js +55 -0
- package/out/src/monitor/tasks/TaskCheckForProofs.js.map +1 -1
- package/out/src/monitor/tasks/TaskSendWaiting.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +59 -59
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/sdk/types.d.ts +32 -0
- package/out/src/sdk/types.d.ts.map +1 -1
- package/out/src/sdk/types.js +50 -1
- package/out/src/sdk/types.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/__tests/SingleWriterMultiReaderLock.test.js.map +1 -1
- package/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +10 -5
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +133 -3
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +691 -94
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +114 -1
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +164 -4
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/src/storage/idbHelpers.d.ts +5 -0
- package/out/src/storage/idbHelpers.d.ts.map +1 -1
- package/out/src/storage/idbHelpers.js +42 -0
- package/out/src/storage/idbHelpers.js.map +1 -1
- package/out/src/storage/methods/attemptToPostReqsToNetwork.d.ts.map +1 -1
- package/out/src/storage/methods/attemptToPostReqsToNetwork.js +116 -4
- package/out/src/storage/methods/attemptToPostReqsToNetwork.js.map +1 -1
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +22 -5
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
- package/out/src/storage/methods/internalizeAction.js +172 -5
- package/out/src/storage/methods/internalizeAction.js.map +1 -1
- package/out/src/storage/methods/listActionsKnex.d.ts +49 -0
- package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listActionsKnex.js +179 -69
- package/out/src/storage/methods/listActionsKnex.js.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.js +51 -4
- package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +82 -14
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/methods/purgeData.d.ts.map +1 -1
- package/out/src/storage/methods/purgeData.js +22 -14
- package/out/src/storage/methods/purgeData.js.map +1 -1
- package/out/src/storage/methods/reviewStatus.d.ts.map +1 -1
- package/out/src/storage/methods/reviewStatus.js +18 -9
- package/out/src/storage/methods/reviewStatus.js.map +1 -1
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +134 -0
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/out/src/storage/schema/StorageIdbSchema.d.ts +43 -2
- package/out/src/storage/schema/StorageIdbSchema.d.ts.map +1 -1
- package/out/src/storage/schema/__tests/backfill.runner.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/backfill.runner.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/backfill.runner.test.js +148 -0
- package/out/src/storage/schema/__tests/backfill.runner.test.js.map +1 -0
- package/out/src/storage/schema/__tests/backfill.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/backfill.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/backfill.test.js +96 -0
- package/out/src/storage/schema/__tests/backfill.test.js.map +1 -0
- package/out/src/storage/schema/__tests/processingFsm.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/processingFsm.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/processingFsm.test.js +42 -0
- package/out/src/storage/schema/__tests/processingFsm.test.js.map +1 -0
- package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.js +82 -0
- package/out/src/storage/schema/__tests/processingFsmLegacyMapping.test.js.map +1 -0
- package/out/src/storage/schema/__tests/spendabilityRule.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/spendabilityRule.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/spendabilityRule.test.js +29 -0
- package/out/src/storage/schema/__tests/spendabilityRule.test.js.map +1 -0
- package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.d.ts +2 -0
- package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.d.ts.map +1 -0
- package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.js +77 -0
- package/out/src/storage/schema/__tests/v7FsmLegacyMapping.test.js.map +1 -0
- package/out/src/storage/schema/backfill.d.ts +35 -0
- package/out/src/storage/schema/backfill.d.ts.map +1 -0
- package/out/src/storage/schema/backfill.idb.d.ts +32 -0
- package/out/src/storage/schema/backfill.idb.d.ts.map +1 -0
- package/out/src/storage/schema/backfill.idb.js +95 -0
- package/out/src/storage/schema/backfill.idb.js.map +1 -0
- package/out/src/storage/schema/backfill.js +150 -0
- package/out/src/storage/schema/backfill.js.map +1 -0
- package/out/src/storage/schema/backfill.knex.d.ts +32 -0
- package/out/src/storage/schema/backfill.knex.d.ts.map +1 -0
- package/out/src/storage/schema/backfill.knex.js +240 -0
- package/out/src/storage/schema/backfill.knex.js.map +1 -0
- package/out/src/storage/schema/backfill.runner.d.ts +63 -0
- package/out/src/storage/schema/backfill.runner.d.ts.map +1 -0
- package/out/src/storage/schema/backfill.runner.js +64 -0
- package/out/src/storage/schema/backfill.runner.js.map +1 -0
- package/out/src/storage/schema/coinbaseMaturityBackfill.d.ts +25 -0
- package/out/src/storage/schema/coinbaseMaturityBackfill.d.ts.map +1 -0
- package/out/src/storage/schema/coinbaseMaturityBackfill.js +75 -0
- package/out/src/storage/schema/coinbaseMaturityBackfill.js.map +1 -0
- package/out/src/storage/schema/monitorLease.d.ts +57 -0
- package/out/src/storage/schema/monitorLease.d.ts.map +1 -0
- package/out/src/storage/schema/monitorLease.js +101 -0
- package/out/src/storage/schema/monitorLease.js.map +1 -0
- package/out/src/storage/schema/processingFsm.d.ts +27 -0
- package/out/src/storage/schema/processingFsm.d.ts.map +1 -0
- package/out/src/storage/schema/processingFsm.js +132 -0
- package/out/src/storage/schema/processingFsm.js.map +1 -0
- package/out/src/storage/schema/schemaCutover.d.ts +34 -0
- package/out/src/storage/schema/schemaCutover.d.ts.map +1 -0
- package/out/src/storage/schema/schemaCutover.js +230 -0
- package/out/src/storage/schema/schemaCutover.js.map +1 -0
- package/out/src/storage/schema/schemaCutoverIdb.d.ts +26 -0
- package/out/src/storage/schema/schemaCutoverIdb.d.ts.map +1 -0
- package/out/src/storage/schema/schemaCutoverIdb.js +90 -0
- package/out/src/storage/schema/schemaCutoverIdb.js.map +1 -0
- package/out/src/storage/schema/spendabilityRefresh.d.ts +49 -0
- package/out/src/storage/schema/spendabilityRefresh.d.ts.map +1 -0
- package/out/src/storage/schema/spendabilityRefresh.js +120 -0
- package/out/src/storage/schema/spendabilityRefresh.js.map +1 -0
- package/out/src/storage/schema/spendabilityRule.d.ts +45 -0
- package/out/src/storage/schema/spendabilityRule.d.ts.map +1 -0
- package/out/src/storage/schema/spendabilityRule.js +52 -0
- package/out/src/storage/schema/spendabilityRule.js.map +1 -0
- package/out/src/storage/schema/tables/TableAction.d.ts +3 -3
- package/out/src/storage/schema/tables/TableAction.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableChainTip.d.ts +1 -1
- package/out/src/storage/schema/tables/TableMonitorLease.d.ts +1 -1
- package/out/src/storage/schema/tables/TableOutput.d.ts +7 -0
- package/out/src/storage/schema/tables/TableOutput.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableOutput.js.map +1 -1
- package/out/src/storage/schema/tables/TableTransactionNew.d.ts +50 -0
- package/out/src/storage/schema/tables/TableTransactionNew.d.ts.map +1 -0
- package/out/src/storage/schema/tables/TableTransactionNew.js +3 -0
- package/out/src/storage/schema/tables/TableTransactionNew.js.map +1 -0
- package/out/src/storage/schema/tables/TableTxAudit.d.ts +1 -1
- package/out/src/storage/schema/tables/index.d.ts +5 -0
- package/out/src/storage/schema/tables/index.d.ts.map +1 -1
- package/out/src/storage/schema/tables/index.js +5 -0
- package/out/src/storage/schema/tables/index.js.map +1 -1
- package/out/src/storage/schema/transactionCrud.d.ts +41 -0
- package/out/src/storage/schema/transactionCrud.d.ts.map +1 -0
- package/out/src/storage/schema/transactionCrud.js +205 -0
- package/out/src/storage/schema/transactionCrud.js.map +1 -0
- package/out/src/storage/schema/transactionService.d.ts +315 -0
- package/out/src/storage/schema/transactionService.d.ts.map +1 -0
- package/out/src/storage/schema/transactionService.js +783 -0
- package/out/src/storage/schema/transactionService.js.map +1 -0
- package/out/src/storage/schema/txAudit.d.ts +33 -0
- package/out/src/storage/schema/txAudit.d.ts.map +1 -0
- package/out/src/storage/schema/txAudit.js +64 -0
- package/out/src/storage/schema/txAudit.js.map +1 -0
- package/out/src/storage/schema/v7Backfill.d.ts.map +1 -1
- package/out/src/storage/schema/v7Backfill.js +4 -1
- package/out/src/storage/schema/v7Backfill.js.map +1 -1
- package/out/src/storage/schema/v7Backfill.runner.d.ts.map +1 -1
- package/out/src/storage/schema/v7Backfill.runner.js +3 -1
- package/out/src/storage/schema/v7Backfill.runner.js.map +1 -1
- package/out/src/storage/schema/v7CoinbaseMaturityBackfill.d.ts +25 -0
- package/out/src/storage/schema/v7CoinbaseMaturityBackfill.d.ts.map +1 -0
- package/out/src/storage/schema/v7CoinbaseMaturityBackfill.js +75 -0
- package/out/src/storage/schema/v7CoinbaseMaturityBackfill.js.map +1 -0
- package/out/src/storage/schema/v7Crud.d.ts +5 -3
- package/out/src/storage/schema/v7Crud.d.ts.map +1 -1
- package/out/src/storage/schema/v7Crud.js +11 -9
- package/out/src/storage/schema/v7Crud.js.map +1 -1
- package/out/src/storage/schema/v7Cutover.d.ts +34 -0
- package/out/src/storage/schema/v7Cutover.d.ts.map +1 -0
- package/out/src/storage/schema/v7Cutover.js +223 -0
- package/out/src/storage/schema/v7Cutover.js.map +1 -0
- package/out/src/storage/schema/v7CutoverIdb.d.ts +26 -0
- package/out/src/storage/schema/v7CutoverIdb.d.ts.map +1 -0
- package/out/src/storage/schema/v7CutoverIdb.js +90 -0
- package/out/src/storage/schema/v7CutoverIdb.js.map +1 -0
- package/out/src/storage/schema/v7Fsm.d.ts.map +1 -1
- package/out/src/storage/schema/v7Fsm.js +22 -6
- package/out/src/storage/schema/v7Fsm.js.map +1 -1
- package/out/src/storage/schema/v7Service.d.ts +305 -0
- package/out/src/storage/schema/v7Service.d.ts.map +1 -0
- package/out/src/storage/schema/v7Service.js +757 -0
- package/out/src/storage/schema/v7Service.js.map +1 -0
- package/out/src/storage/schema/v7SpendabilityRefresh.d.ts +49 -0
- package/out/src/storage/schema/v7SpendabilityRefresh.d.ts.map +1 -0
- package/out/src/storage/schema/v7SpendabilityRefresh.js +111 -0
- package/out/src/storage/schema/v7SpendabilityRefresh.js.map +1 -0
- package/out/src/storage/storageProviderHelpers.js +1 -1
- package/out/src/storage/storageProviderHelpers.js.map +1 -1
- package/out/src/utility/Format.js.map +1 -1
- package/package.json +7 -4
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Storage Method Wiring Analysis
|
|
2
|
+
|
|
3
|
+
Scope: legacy storage methods in `src/storage/methods/{createAction,processAction,internalizeAction,listActionsKnex,listOutputsKnex,attemptToPostReqsToNetwork}.ts` against the TransactionService surface in `src/storage/schema/transactionService.ts` and the post-cutover layout established by `src/storage/schema/schemaCutover.ts`.
|
|
4
|
+
|
|
5
|
+
Approach: static read-through of each method's table touches; cross-reference with TransactionService public API; identify gaps.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Post-cutover layout (recap)
|
|
10
|
+
|
|
11
|
+
After `runSchemaCutover`:
|
|
12
|
+
- `transactions` is the new-schema table (was `transactions_new`) — columns: `transactionId, txid, processing, processingChangedAt, nextActionAt, attempts, rebroadcastCycles, wasBroadcast, idempotencyKey, batch, rawTx, inputBeef, height, merkleIndex, merklePath, merkleRoot, blockHash, isCoinbase, lastProvider, lastProviderStatus, frozenReason, rowVersion, created_at, updated_at`.
|
|
13
|
+
- `actions` holds per-user view: `actionId, userId, transactionId(→transactions), reference, description, isOutgoing, satoshisDelta, userNosend, hidden, userAborted, notifyJson, rowVersion`.
|
|
14
|
+
- `tx_labels_map.transactionId` now FKs `actions.actionId` (not transactions). Critical: legacy code paths joining `tx_labels_map.transactionId = transactions.transactionId` are broken post-cutover.
|
|
15
|
+
- `transactions_legacy`, `proven_txs_legacy`, `proven_tx_reqs_legacy` retain old data, off the hot path.
|
|
16
|
+
- `outputs.transactionId` / `outputs.spentBy` / `commissions.transactionId` are remapped to new-schema IDs but the columns still point at the new `transactions` table — same shape, different meaning.
|
|
17
|
+
|
|
18
|
+
Implication: any method still reading legacy fields (`status, satoshis, isOutgoing, description, version, lockTime, reference, userId, inputBEEF, provenTxId`) directly from `transactions` will break — those columns are gone. Everything user-scoped now lives in `actions`. Every status/FSM concern now lives in `transactions.processing` (ProcessingStatus, not TransactionStatus).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Per-method table/field access map
|
|
23
|
+
|
|
24
|
+
### `createAction.ts`
|
|
25
|
+
|
|
26
|
+
| Operation | Legacy SQL pattern | Post-cutover state | New-schema replacement |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| `storage.insertTransaction(newTx)` with legacy fields | `INSERT transactions(...)` | most columns gone except `txid, rawTx, inputBeef` | `TransactionService.create({txid, processing:'queued', rawTx, inputBeef})` + `createAction({userId, transactionId, reference, description, isOutgoing, satoshisDelta:0})`. **Gap: at this stage `txid` is unknown — new-schema requires it as natural key.** |
|
|
29
|
+
| `storage.updateTransaction(id, {satoshis})` | `UPDATE transactions SET satoshis=?` | column absent | Update `actions.satoshisDelta`. **Gap: `updateActionSatoshisDelta`.** |
|
|
30
|
+
| `storage.findOrInsertTxLabelMap(transactionId, labelId)` | `INSERT tx_labels_map(transactionId, txLabelId)` | `transactionId` column FKs `actions.actionId` | Pass `actionId`, not `transactionId`. Shim required. |
|
|
31
|
+
| outputs / commissions / output_baskets writes | unchanged | unchanged | No change. |
|
|
32
|
+
| `getBeefForTransaction`, `getRawTxOfKnownValidTransaction`, `getProvenOrRawTx` | reads `proven_txs`/`proven_tx_reqs` | both `_legacy` | New path reads `rawTx, merklePath, height, blockHash` from new-schema `transactions`. |
|
|
33
|
+
|
|
34
|
+
### `processAction.ts`
|
|
35
|
+
|
|
36
|
+
| Operation | Legacy | Post-cutover | New-schema replacement |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| `findTransactions({userId, reference})` | SELECT on legacy table | columns absent | **Gap: `findActionByReference(userId, reference)`** |
|
|
39
|
+
| read `transaction.{status, isOutgoing, inputBEEF, transactionId}` | legacy columns | gone | resolve via `findAction` + `findById`. `status` derived from `processing`. |
|
|
40
|
+
| `EntityProvenTxReq.insertOrMerge` | writes `proven_tx_reqs` | `_legacy` | **Gap.** Funnel into `TransactionService.create` or `transition` with rawTx/inputBeef. |
|
|
41
|
+
| `updateProvenTxReq(ids, {status, batch})` | `_legacy` | gone | **Gap: `transitionMany` + `setBatch`.** |
|
|
42
|
+
| `updateTransaction(ids, {status})` | column gone | gone | **Gap: `transitionMany`.** Bulk variant. |
|
|
43
|
+
| `getReqsAndBeefToShareWithWorld` | joins `proven_tx_reqs`+`proven_txs` | both `_legacy` | **Gap: `collectReqsAndBeef(txids)`** rebuilt on new-schema. |
|
|
44
|
+
| `attemptToPostReqsToNetwork` | uses `EntityProvenTxReq` | underlying table renamed | Whole path needs reframing. |
|
|
45
|
+
| `findCommissions` | unchanged | unchanged | No change. |
|
|
46
|
+
|
|
47
|
+
`ReqTxStatus` tuples from `determineReqTxStatus` are the central FSM gap (see §4).
|
|
48
|
+
|
|
49
|
+
### `internalizeAction.ts`
|
|
50
|
+
|
|
51
|
+
| Operation | Legacy | Post-cutover | New-schema replacement |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `findTransactions({userId, txid})` | SELECT | join required | **Gap: `findActionByUserTxid(userId, txid)`** |
|
|
54
|
+
| `findOrInsertTransaction(newTx)` | INSERT/UPSERT legacy | columns gone | **Gap: `findOrCreateActionForTxid(args)`** — upsert on transactions by txid + upsert on actions by (userId, transactionId). |
|
|
55
|
+
| `updateTransaction(id, {satoshis, provenTxId, status})` | columns gone | split needed | **Gap: `updateActionSatoshisDelta`** + use `recordProof` for confirmed case. |
|
|
56
|
+
| `findOrInsertProvenTx({height, index, merklePath, ...})` | INSERT `proven_txs` | `_legacy` | `recordProof({transactionId, height, ...})`. **Gap: row may not exist yet** — need `createWithProof(args)` shortcut. |
|
|
57
|
+
| `getProvenOrReq(txid, ...)` | reads `proven_txs` + `proven_tx_reqs` | `_legacy` | **Gap: `findOrCreateForBroadcast({txid, rawTx, inputBeef})`** returning `{isNew, transaction}`. |
|
|
58
|
+
| tx_labels / output writes | unchanged | unchanged | Label map: pass `actionId`. |
|
|
59
|
+
|
|
60
|
+
### `listActionsKnex.ts`
|
|
61
|
+
|
|
62
|
+
| Operation | Legacy | Post-cutover | New-schema replacement |
|
|
63
|
+
|---|---|---|---|
|
|
64
|
+
| `SELECT … FROM transactions WHERE userId=? AND status IN (…)` (CTE + main) | columns scattered | post-cutover: `transactions` has `txid, created_at, transactionId`; per-user fields on `actions`; status is `transactions.processing`; `satoshis → actions.satoshisDelta`; `version, lockTime` are NOT stored at all in new-schema | **Gap: `listActionsForUser({userId, statusFilter, labelIds, queryMode, createdAtRange, limit, offset})`** JOINing `actions ⨝ transactions` and optionally `tx_labels_map`. Status filter maps from `TransactionStatus → ProcessingStatus`. **`version`/`lockTime` lost in new-schema** — reconstruct from `rawTx` parsing or restore as columns. |
|
|
65
|
+
| `tx_labels_map.transactionId IN labelIds` | now `actionId` | join via `actions` first | Keep raw SQL using `actionId` or wrap in `findActionsByLabelIds`. |
|
|
66
|
+
| `getLabelsForTransactionId(tx.transactionId)` | reads `tx_labels_map` by transactionId | now means actionId | **Gap: `getLabelsForAction(actionId)`** or rename helper. |
|
|
67
|
+
| `getRawTxOfKnownValidTransaction(tx.txid)` | reads `proven_txs`/`proven_tx_reqs` | `_legacy` | Use `TransactionService.findById(id).rawTx` directly. |
|
|
68
|
+
|
|
69
|
+
### `listOutputsKnex.ts`
|
|
70
|
+
|
|
71
|
+
| Operation | Legacy | Post-cutover | New-schema replacement |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| Join `outputs o ⨝ transactions t` then `WHERE t.status IN ('completed','unproven','nosend','sending')` | column gone | filter on `transactions.processing` with mapped ProcessingStatus set | **Gap: change WHERE to `t.processing IN (...)`** or expose `listOutputsForUser`. |
|
|
74
|
+
| Label enrichment via `tx_labels_map.transactionId IN (output.transactionId)` | `tx_labels_map.transactionId` is `actionId`, `outputs.transactionId` is `transactions.transactionId` — different keyspaces | **Critical break.** | Add `outputs → actions → tx_labels_map` hop. **Gap: `getLabelsByOutputIds(outputIds, userId)`**. |
|
|
75
|
+
| `output_tags` / `output_tags_map` | unchanged | unchanged | No change. |
|
|
76
|
+
|
|
77
|
+
### `attemptToPostReqsToNetwork.ts`
|
|
78
|
+
|
|
79
|
+
| Operation | Legacy | Post-cutover | New-schema replacement |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| All `EntityProvenTxReq` fields | `proven_tx_reqs` | `_legacy` | Every field migrates to new-schema `transactions`: rawTx→`rawTx`, inputBEEF→`inputBeef`, attempts→`attempts`, status→`processing`, wasBroadcast→`wasBroadcast`, batch→`batch`. History notes need `tx_audit` entries. **Gap: `recordSendAttempt`, `recordBroadcastResult`, `recordHistoryNote`, `setBatch`, `incrementAttempts`, `loadForSend(txid[])`.** |
|
|
82
|
+
| `mergeReqToBeefToShareExternally` | reads `proven_txs`+`proven_tx_reqs` | `_legacy` | **Gap: `mergeBeefForTxids(beef, txids)`** that reads from new-schema `transactions`. |
|
|
83
|
+
| `updateTransactionsStatus(ids, newTxStatus)` | mass status update + outputs side-effect | column gone | **Gap: `transitionMany`**. Outputs-spendable side-effect splits out — keep the transaction service pure. |
|
|
84
|
+
| `findTransactions({transactionId})` in `markStaleInputsAsSpent` | resolves `userId` | only need `userId` | **`findUserIdForTransactionId(transactionId)`** shim. |
|
|
85
|
+
| `findOutputsByOutpoints`, `updateOutput`, `validateOutputScript`, `services.isUtxo` | unchanged | unchanged | No change. |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 3. Net-new TransactionService methods
|
|
90
|
+
|
|
91
|
+
Total: **15** net-new methods (+2 small shims).
|
|
92
|
+
|
|
93
|
+
| # | Signature | Replaces | Complexity |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| 1 | `findActionByReference(userId, reference): Promise<{action, transaction} \|Promise<TableTransactionNew | undefined>` | processAction validation | S |
|
|
96
|
+
| 2 | `findActionByUserTxid(userId, txid): Promise<{action, transaction} \|Promise<TableTransactionNew | undefined>` | internalizeAction.asyncSetup | S |
|
|
97
|
+
| 3 | `findOrCreateActionForTxid(args): Promise<{action, transaction, isNew}>` | internalizeAction.findOrInsertTargetTransaction | M |
|
|
98
|
+
| 4 | `updateActionSatoshisDelta(actionId, delta, now?): Promise<void>` | createAction + internalizeAction | S |
|
|
99
|
+
| 5 | `createWithProof(args): Promise<TableTransactionNew>` | internalizeAction.newInternalize (bump present) | M |
|
|
100
|
+
| 6 | `findOrCreateForBroadcast({txid, rawTx, inputBeef, notifyActionIds}): Promise<{transaction, isNew}>` | internalizeAction.getProvenOrReq | M |
|
|
101
|
+
| 7 | `transitionMany({transactionIds, expectedFrom?, to, provider?, providerStatus?, details?}): Promise<{updated, skipped}>` | processAction.shareReqsWithWorld + updateReqsFromAggregateResults | M |
|
|
102
|
+
| 8 | `setBatch(transactionIds, batch \| undefined): Promise<void>` | processAction | S |
|
|
103
|
+
| 9 | `incrementAttempts(transactionId, now?): Promise<TableTransactionNew | undefined>|Promise<TableTransactionNew | undefined>` | attemptToPostReqsToNetwork validate + serviceError | S |
|
|
104
|
+
| 10 | `recordBroadcastResult({transactionId, txid, status, provider, providerStatus, wasBroadcast?, details?}): Promise<TableTransactionNew | undefined>|Promise<TableTransactionNew | undefined>` | composite of req.status/req.wasBroadcast/history-note writes | M |
|
|
105
|
+
| 11 | `recordHistoryNote(transactionId, note): Promise<void>` | `req.addHistoryNote` everywhere — writes a `tx_audit` row | S |
|
|
106
|
+
| 12 | `mergeBeefForTxids(beef, txids): Promise<void>` | `mergeReqToBeefToShareExternally` + part of `getReqsAndBeefToShareWithWorld` | M |
|
|
107
|
+
| 13 | `collectReqsAndBeef(txids, extraTxids?): Promise<{beef, details}>` | processAction.shareReqsWithWorld | L (carries `readyToSend`/`alreadySent`/`error`/`unknown` classification) |
|
|
108
|
+
| 14 | `listActionsForUser({userId, statusFilter?, labelIds?, labelQueryMode?, createdAtFrom?, createdAtTo?, limit, offset, columns?}): Promise<{rows, total?}>` | listActionsKnex CTE-based query | L |
|
|
109
|
+
| 15 | `listOutputsForUser({userId, basketId?, tagIds?, tagQueryMode?, processingFilter, includeSpent, limit, offset, includeLockingScripts?})` | listOutputsKnex JOIN+CTE | L |
|
|
110
|
+
|
|
111
|
+
Shims (in StorageKnex compat layer or service surface):
|
|
112
|
+
- `actionIdFromTransactionId(userId, transactionId)` — for `tx_labels_map` writes.
|
|
113
|
+
- `getUserIdForTransactionId(transactionId)` — for `attemptToPostReqsToNetwork.markStaleInputsAsSpent`.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 4. FSM transition coverage gaps
|
|
118
|
+
|
|
119
|
+
`TransactionService.transition` already takes any `(from, to)` and defers to the FSM. Wiring needs a complete `legacyReqStatus + legacyTxStatus` → `ProcessingStatus` mapping. Triggers:
|
|
120
|
+
|
|
121
|
+
| Trigger site | Legacy `req → tx` | `ProcessingStatus` |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| processAction / `isNoSend && !isSendWith` | `nosend → nosend` | `queued → nosend` |
|
|
124
|
+
| processAction / `!isNoSend && isDelayed` | `unsent → unprocessed` | `queued → queued` (collapses; disambiguate via `nextActionAt`) |
|
|
125
|
+
| processAction / `!isNoSend && !isDelayed` (pre) | `unprocessed → unprocessed` | `queued → broadcasting` |
|
|
126
|
+
| processAction / `!isNoSend && !isDelayed` (post) | `unmined → unproven` | `broadcasting → broadcasted` |
|
|
127
|
+
| internalizeAction / bump present | `(none) → completed` | `(new) → confirmed` via `recordProof`/`createWithProof` |
|
|
128
|
+
| internalizeAction / bump absent | `unsent → unproven` | `queued → broadcasted` |
|
|
129
|
+
| attemptToPostReqsToNetwork / `invalid` | `* → invalid` | `* → invalid` |
|
|
130
|
+
| attemptToPostReqsToNetwork / `success` | `* → unmined`, tx `* → unproven`, `wasBroadcast=true` | `* → broadcasted` with `wasBroadcast=true` |
|
|
131
|
+
| attemptToPostReqsToNetwork / `doubleSpend` | `* → doubleSpend`, tx `* → failed` | `* → doubleSpend` (terminal) |
|
|
132
|
+
| attemptToPostReqsToNetwork / `invalidTx` | `* → invalid`, tx `* → failed` | `* → invalid` |
|
|
133
|
+
| attemptToPostReqsToNetwork / `serviceError` | `* → sending` + attempts++ | `* → sending` + `incrementAttempts` |
|
|
134
|
+
| Monitor proof | `* → completed`, proven | `* → confirmed` (covered by `recordProof`) |
|
|
135
|
+
|
|
136
|
+
Audit: FSM table in `processingFsm` must accept `queued → nosend`, `queued → broadcasting`, `broadcasting → broadcasted`, `broadcasting → doubleSpend`, `broadcasting → invalid`, `sending → broadcasting` (retry). Verify before wiring proceeds. ~1 day to extend FSM + add audit tests.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 5. Recommended sequencing
|
|
141
|
+
|
|
142
|
+
Argument: lowest blast radius first, validate the new-schema abstraction, graduate to high-traffic FSM-heavy methods.
|
|
143
|
+
|
|
144
|
+
| Order | Method | Why |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| 1 | **`listOutputsKnex.ts`** (status filter swap + label-join repair) | Read-only, highest call frequency. Validates `listOutputsForUser` API shape + ProcessingStatus mapping. Zero FSM concerns. Fast revert. |
|
|
147
|
+
| 2 | **`listActionsKnex.ts`** | Read-only. Establishes `actions ⨝ transactions ⨝ tx_labels_map` shape every other method reuses. Surfaces `version`/`lockTime` data loss early. |
|
|
148
|
+
| 3 | **`createAction.ts`** | Forces resolution of `(reference, txid)` ordering — the new schema demands txid up front, createAction allocates before txid is known. Unblocks all write-path migrations. |
|
|
149
|
+
| 4 | **`processAction.ts`** | Brings FSM in. Validates `transitionMany`, `setBatch`, `findActionByReference`, `collectReqsAndBeef`. Highest-risk but highest-coverage. |
|
|
150
|
+
| 5 | **`attemptToPostReqsToNetwork.ts`** | Heaviest legacy-entity coupling. Mechanical after processAction proves the new-schema handles batched FSM + history notes. |
|
|
151
|
+
| 6 | **`internalizeAction.ts`** | Lowest call frequency, highest branching. Validate everything else first; internalize reuses mature primitives. |
|
|
152
|
+
|
|
153
|
+
Pilot: wire `listOutputsKnex.ts` first (1 day) — pure read-side, exercises ProcessingStatus + actions/transactions join + label keyspace change in one low-risk change. Validates TransactionService API shape for larger methods.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 6. Effort estimate (senior engineering)
|
|
158
|
+
|
|
159
|
+
| Phase | Days |
|
|
160
|
+
|---|---|
|
|
161
|
+
| FSM audit + missing transitions + tests | 1 |
|
|
162
|
+
| TransactionService methods 1–6 (find/create/proof) | 2 |
|
|
163
|
+
| TransactionService methods 7–11 (transition/batch/attempts/history) | 2 |
|
|
164
|
+
| TransactionService methods 12–13 (beef merge + collectReqsAndBeef) | 2 |
|
|
165
|
+
| TransactionService methods 14–15 (listActionsForUser, listOutputsForUser) | 2 |
|
|
166
|
+
| Wire `listOutputsKnex.ts` + tests | 1 |
|
|
167
|
+
| Wire `listActionsKnex.ts` + tests (incl. version/lockTime decision) | 1.5 |
|
|
168
|
+
| Wire `createAction.ts` + reference/txid resolution + tests | 2 |
|
|
169
|
+
| Wire `processAction.ts` + FSM-rich path + tests | 3 |
|
|
170
|
+
| Wire `attemptToPostReqsToNetwork.ts` + EntityProvenTxReq decomposition + tests | 3 |
|
|
171
|
+
| Wire `internalizeAction.ts` (merge/new, confirmed/unproven) + tests | 2.5 |
|
|
172
|
+
| Integration & end-to-end test pass post-cutover, fix fall-out | 2 |
|
|
173
|
+
| Buffer for FSM edge cases / unforeseen schema gaps | 2 |
|
|
174
|
+
| **Total** | **~26 engineering-days (≈5–6 weeks calendar, single senior)** |
|
|
175
|
+
|
|
176
|
+
Parallelizable: TransactionService additions + per-method wiring fan out to 2 engineers → ~3–4 weeks calendar.
|