@bsv/wallet-toolbox 2.13.0 → 2.13.2
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/CHANGELOG.md +283 -1
- package/README.md +403 -5
- package/docs/README.md +8 -1
- package/docs/client.md +13057 -4632
- package/docs/identity-verification.md +196 -0
- package/docs/monitor.md +505 -190
- package/docs/services.md +4013 -1153
- package/docs/setup.md +98 -58
- package/docs/storage.md +5780 -1609
- package/docs/wallet.md +10155 -10871
- package/out/src/CWIStyleWalletManager.d.ts +6 -8
- package/out/src/CWIStyleWalletManager.d.ts.map +1 -1
- package/out/src/CWIStyleWalletManager.js +170 -125
- package/out/src/CWIStyleWalletManager.js.map +1 -1
- package/out/src/Setup.d.ts +2 -0
- package/out/src/Setup.d.ts.map +1 -1
- package/out/src/Setup.js +3 -2
- package/out/src/Setup.js.map +1 -1
- package/out/src/ShamirWalletManager.d.ts.map +1 -1
- package/out/src/ShamirWalletManager.js +34 -19
- package/out/src/ShamirWalletManager.js.map +1 -1
- package/out/src/SimpleWalletManager.d.ts.map +1 -1
- package/out/src/SimpleWalletManager.js +7 -6
- package/out/src/SimpleWalletManager.js.map +1 -1
- package/out/src/Wallet.d.ts +50 -11
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js +183 -107
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletAuthenticationManager.d.ts.map +1 -1
- package/out/src/WalletAuthenticationManager.js +282 -26
- package/out/src/WalletAuthenticationManager.js.map +1 -1
- package/out/src/WalletLogger.js +1 -1
- package/out/src/WalletLogger.js.map +1 -1
- package/out/src/WalletPermissionsManager.d.ts +30 -17
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js +540 -312
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/WalletSettingsManager.d.ts +3 -2
- package/out/src/WalletSettingsManager.d.ts.map +1 -1
- package/out/src/WalletSettingsManager.js +141 -6
- package/out/src/WalletSettingsManager.js.map +1 -1
- package/out/src/entropy/EntropyCollector.d.ts.map +1 -1
- package/out/src/entropy/EntropyCollector.js +3 -2
- package/out/src/entropy/EntropyCollector.js.map +1 -1
- package/out/src/fundWalletP2PKH.d.ts.map +1 -1
- package/out/src/fundWalletP2PKH.js +143 -44
- package/out/src/fundWalletP2PKH.js.map +1 -1
- package/out/src/mockchain/MockChainTracker.d.ts.map +1 -1
- package/out/src/mockchain/MockChainTracker.js +5 -5
- package/out/src/mockchain/MockChainTracker.js.map +1 -1
- package/out/src/mockchain/MockServices.d.ts.map +1 -1
- package/out/src/mockchain/MockServices.js +32 -8
- package/out/src/mockchain/MockServices.js.map +1 -1
- package/out/src/monitor/Monitor.d.ts +17 -0
- package/out/src/monitor/Monitor.d.ts.map +1 -1
- package/out/src/monitor/Monitor.js +206 -42
- 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 +64 -16
- package/out/src/monitor/MonitorDaemon.js.map +1 -1
- package/out/src/monitor/monitorValidation.d.ts +12 -0
- package/out/src/monitor/monitorValidation.d.ts.map +1 -0
- package/out/src/monitor/monitorValidation.js +133 -0
- package/out/src/monitor/monitorValidation.js.map +1 -0
- package/out/src/monitor/tasks/TaskArcSSE.d.ts +2 -0
- package/out/src/monitor/tasks/TaskArcSSE.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskArcSSE.js +28 -12
- package/out/src/monitor/tasks/TaskArcSSE.js.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.d.ts +5 -0
- package/out/src/monitor/tasks/TaskCheckForProofs.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.js +29 -24
- package/out/src/monitor/tasks/TaskCheckForProofs.js.map +1 -1
- package/out/src/monitor/tasks/TaskCheckNoSends.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskCheckNoSends.js +11 -3
- package/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
- package/out/src/monitor/tasks/TaskFailAbandoned.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskFailAbandoned.js +9 -4
- package/out/src/monitor/tasks/TaskFailAbandoned.js.map +1 -1
- package/out/src/monitor/tasks/TaskNewHeader.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskNewHeader.js +3 -1
- package/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
- package/out/src/monitor/tasks/TaskReconcilePendingTransactions.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReconcilePendingTransactions.js +9 -3
- package/out/src/monitor/tasks/TaskReconcilePendingTransactions.js.map +1 -1
- package/out/src/monitor/tasks/TaskReorg.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReorg.js +4 -4
- package/out/src/monitor/tasks/TaskReorg.js.map +1 -1
- package/out/src/monitor/tasks/TaskReviewDoubleSpends.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReviewDoubleSpends.js +17 -7
- package/out/src/monitor/tasks/TaskReviewDoubleSpends.js.map +1 -1
- package/out/src/monitor/tasks/TaskReviewProvenTxs.d.ts +18 -1
- package/out/src/monitor/tasks/TaskReviewProvenTxs.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReviewProvenTxs.js +99 -21
- package/out/src/monitor/tasks/TaskReviewProvenTxs.js.map +1 -1
- package/out/src/monitor/tasks/TaskReviewUtxos.d.ts +4 -4
- package/out/src/monitor/tasks/TaskReviewUtxos.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReviewUtxos.js +41 -13
- package/out/src/monitor/tasks/TaskReviewUtxos.js.map +1 -1
- package/out/src/monitor/tasks/TaskSendWaiting.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskSendWaiting.js +52 -11
- package/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
- package/out/src/monitor/tasks/TaskUnFail.d.ts +1 -0
- package/out/src/monitor/tasks/TaskUnFail.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskUnFail.js +26 -8
- package/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
- package/out/src/sdk/PrivilegedKeyManager.d.ts.map +1 -1
- package/out/src/sdk/PrivilegedKeyManager.js +3 -2
- package/out/src/sdk/PrivilegedKeyManager.js.map +1 -1
- package/out/src/sdk/WalletErrorFromJson.d.ts.map +1 -1
- package/out/src/sdk/WalletErrorFromJson.js +112 -2
- package/out/src/sdk/WalletErrorFromJson.js.map +1 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts +17 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/services/Services.d.ts +4 -0
- package/out/src/services/Services.d.ts.map +1 -1
- package/out/src/services/Services.js +260 -117
- package/out/src/services/Services.js.map +1 -1
- package/out/src/services/chaintracker/BHServiceClient.d.ts +21 -4
- package/out/src/services/chaintracker/BHServiceClient.d.ts.map +1 -1
- package/out/src/services/chaintracker/BHServiceClient.js +267 -66
- package/out/src/services/chaintracker/BHServiceClient.js.map +1 -1
- package/out/src/services/chaintracker/ChaintracksChainTracker.d.ts +25 -3
- package/out/src/services/chaintracker/ChaintracksChainTracker.d.ts.map +1 -1
- package/out/src/services/chaintracker/ChaintracksChainTracker.js +188 -53
- package/out/src/services/chaintracker/ChaintracksChainTracker.js.map +1 -1
- package/out/src/services/chaintracker/LocalChainTracker.d.ts +26 -0
- package/out/src/services/chaintracker/LocalChainTracker.d.ts.map +1 -1
- package/out/src/services/chaintracker/LocalChainTracker.js +180 -10
- package/out/src/services/chaintracker/LocalChainTracker.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.js +59 -7
- package/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksApi.d.ts +6 -0
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts +7 -0
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksFetchApi.d.ts +2 -0
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksFetchApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts +9 -0
- package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts +19 -0
- package/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js +237 -61
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.d.ts +16 -0
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.js +150 -26
- package/out/src/services/chaintracker/chaintracks/ChaintracksService.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts +30 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.js +346 -30
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.d.ts +32 -1
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js +375 -43
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.js +28 -3
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDN.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDN.js +33 -9
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDN.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorChaintracks.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorChaintracks.js +4 -2
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.d.ts +2 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.js +17 -4
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.d.ts +2 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.js +40 -20
- package/out/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.js +14 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.d.ts +6 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.js +56 -9
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorChaintracksSSE.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorTeranodeP2P.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorTeranodeP2P.js +6 -3
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorTeranodeP2P.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.d.ts +4 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.js +27 -9
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.d.ts +8 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.js +49 -5
- package/out/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.d.ts +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js +90 -21
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.d.ts +3 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.js +185 -38
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.js +59 -6
- package/out/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.d.ts +2 -0
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.js +89 -39
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts +10 -0
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js +225 -24
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts +2 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +265 -96
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts +3 -0
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +225 -86
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts +3 -0
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +121 -35
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/configureChaintracksIngestors.js +2 -2
- package/out/src/services/chaintracker/chaintracks/configureChaintracksIngestors.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 +1 -7
- 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 +1 -7
- 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 +1 -7
- package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataCacheFs.d.ts +18 -0
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataCacheFs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataCacheFs.js +204 -14
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataCacheFs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.d.ts +6 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.js +486 -82
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataManager.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataReader.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataReader.js +17 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataReader.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataValidator.worker.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataValidator.worker.js +12 -2
- package/out/src/services/chaintracker/chaintracks/util/BulkFileDataValidator.worker.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 +99 -30
- package/out/src/services/chaintracker/chaintracks/util/BulkFilesReader.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkHeaderFile.d.ts +1 -0
- package/out/src/services/chaintracker/chaintracks/util/BulkHeaderFile.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/BulkHeaderFile.js +23 -15
- package/out/src/services/chaintracker/chaintracks/util/BulkHeaderFile.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFetch.d.ts +7 -0
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFetch.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFetch.js +90 -24
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFetch.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.d.ts +2 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.js +57 -11
- package/out/src/services/chaintracker/chaintracks/util/ChaintracksFs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/DurableFileBulkFileDownloadBudget.d.ts +9 -0
- package/out/src/services/chaintracker/chaintracks/util/DurableFileBulkFileDownloadBudget.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/DurableFileBulkFileDownloadBudget.js +100 -14
- package/out/src/services/chaintracker/chaintracks/util/DurableFileBulkFileDownloadBudget.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/HeightRange.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/HeightRange.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.d.ts +2 -0
- package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.js +104 -8
- package/out/src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/NodeBulkFileDataValidator.d.ts +1 -0
- package/out/src/services/chaintracker/chaintracks/util/NodeBulkFileDataValidator.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/NodeBulkFileDataValidator.js +79 -15
- package/out/src/services/chaintracker/chaintracks/util/NodeBulkFileDataValidator.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.d.ts +3 -0
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.js +15 -0
- package/out/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts +6 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js +311 -93
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/safeDiagnostic.d.ts +4 -0
- package/out/src/services/chaintracker/chaintracks/util/safeDiagnostic.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/safeDiagnostic.js +33 -0
- package/out/src/services/chaintracker/chaintracks/util/safeDiagnostic.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
- package/out/src/services/classifyOutputUtxo.d.ts.map +1 -1
- package/out/src/services/classifyOutputUtxo.js +19 -10
- package/out/src/services/classifyOutputUtxo.js.map +1 -1
- package/out/src/services/fiatRateValidation.d.ts +12 -0
- package/out/src/services/fiatRateValidation.d.ts.map +1 -0
- package/out/src/services/fiatRateValidation.js +138 -0
- package/out/src/services/fiatRateValidation.js.map +1 -0
- package/out/src/services/getCanonicalMerklePath.d.ts +15 -0
- package/out/src/services/getCanonicalMerklePath.d.ts.map +1 -0
- package/out/src/services/getCanonicalMerklePath.js +90 -0
- package/out/src/services/getCanonicalMerklePath.js.map +1 -0
- package/out/src/services/providers/ARC.d.ts +3 -16
- package/out/src/services/providers/ARC.d.ts.map +1 -1
- package/out/src/services/providers/ARC.js +36 -37
- package/out/src/services/providers/ARC.js.map +1 -1
- package/out/src/services/providers/ArcSSEClient.d.ts +25 -19
- package/out/src/services/providers/ArcSSEClient.d.ts.map +1 -1
- package/out/src/services/providers/ArcSSEClient.js +352 -85
- package/out/src/services/providers/ArcSSEClient.js.map +1 -1
- package/out/src/services/providers/Arcade.d.ts +1 -0
- package/out/src/services/providers/Arcade.d.ts.map +1 -1
- package/out/src/services/providers/Arcade.js +56 -41
- package/out/src/services/providers/Arcade.js.map +1 -1
- package/out/src/services/providers/Bitails.d.ts +3 -0
- package/out/src/services/providers/Bitails.d.ts.map +1 -1
- package/out/src/services/providers/Bitails.js +79 -12
- package/out/src/services/providers/Bitails.js.map +1 -1
- package/out/src/services/providers/SdkWhatsOnChain.d.ts +8 -2
- package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -1
- package/out/src/services/providers/SdkWhatsOnChain.js +83 -10
- package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -1
- package/out/src/services/providers/WhatsOnChain.d.ts +3 -0
- package/out/src/services/providers/WhatsOnChain.d.ts.map +1 -1
- package/out/src/services/providers/WhatsOnChain.js +221 -69
- package/out/src/services/providers/WhatsOnChain.js.map +1 -1
- package/out/src/services/providers/arcProviderConfig.d.ts +27 -0
- package/out/src/services/providers/arcProviderConfig.d.ts.map +1 -0
- package/out/src/services/providers/arcProviderConfig.js +83 -0
- package/out/src/services/providers/arcProviderConfig.js.map +1 -0
- package/out/src/services/providers/arcTxDataValidation.d.ts +4 -0
- package/out/src/services/providers/arcTxDataValidation.d.ts.map +1 -0
- package/out/src/services/providers/arcTxDataValidation.js +92 -0
- package/out/src/services/providers/arcTxDataValidation.js.map +1 -0
- package/out/src/services/providers/exchangeRates.d.ts +3 -3
- package/out/src/services/providers/exchangeRates.d.ts.map +1 -1
- package/out/src/services/providers/exchangeRates.js +153 -226
- package/out/src/services/providers/exchangeRates.js.map +1 -1
- package/out/src/services/providers/getBeefForTxid.d.ts.map +1 -1
- package/out/src/services/providers/getBeefForTxid.js.map +1 -1
- package/out/src/services/providers/whatsOnChainHelpers.d.ts +2 -2
- package/out/src/services/providers/whatsOnChainHelpers.d.ts.map +1 -1
- package/out/src/services/providers/whatsOnChainHelpers.js +11 -8
- package/out/src/services/providers/whatsOnChainHelpers.js.map +1 -1
- package/out/src/services/validateMerklePathResult.d.ts +30 -0
- package/out/src/services/validateMerklePathResult.d.ts.map +1 -0
- package/out/src/services/validateMerklePathResult.js +272 -0
- package/out/src/services/validateMerklePathResult.js.map +1 -0
- package/out/src/services/validatePostBeefResult.d.ts +17 -0
- package/out/src/services/validatePostBeefResult.d.ts.map +1 -0
- package/out/src/services/validatePostBeefResult.js +334 -0
- package/out/src/services/validatePostBeefResult.js.map +1 -0
- package/out/src/services/validateRawTxResult.d.ts +6 -0
- package/out/src/services/validateRawTxResult.d.ts.map +1 -0
- package/out/src/services/validateRawTxResult.js +77 -0
- package/out/src/services/validateRawTxResult.js.map +1 -0
- package/out/src/services/validateScriptHashHistoryResult.d.ts +5 -0
- package/out/src/services/validateScriptHashHistoryResult.d.ts.map +1 -0
- package/out/src/services/validateScriptHashHistoryResult.js +99 -0
- package/out/src/services/validateScriptHashHistoryResult.js.map +1 -0
- package/out/src/services/validateStatusForTxidsResult.d.ts +8 -0
- package/out/src/services/validateStatusForTxidsResult.d.ts.map +1 -0
- package/out/src/services/validateStatusForTxidsResult.js +181 -0
- package/out/src/services/validateStatusForTxidsResult.js.map +1 -0
- package/out/src/services/validateUtxoStatusResult.d.ts +6 -0
- package/out/src/services/validateUtxoStatusResult.d.ts.map +1 -0
- package/out/src/services/validateUtxoStatusResult.js +126 -0
- package/out/src/services/validateUtxoStatusResult.js.map +1 -0
- package/out/src/signer/actionBatch/ActionBatchPlanner.d.ts +3 -2
- package/out/src/signer/actionBatch/ActionBatchPlanner.d.ts.map +1 -1
- package/out/src/signer/actionBatch/ActionBatchPlanner.js +4 -3
- package/out/src/signer/actionBatch/ActionBatchPlanner.js.map +1 -1
- package/out/src/signer/actionBatch/ActionBatchWorkspace.d.ts +6 -5
- package/out/src/signer/actionBatch/ActionBatchWorkspace.d.ts.map +1 -1
- package/out/src/signer/actionBatch/ActionBatchWorkspace.js +70 -76
- package/out/src/signer/actionBatch/ActionBatchWorkspace.js.map +1 -1
- package/out/src/signer/actionBatch/actionBatchBootstrap.d.ts +2 -2
- package/out/src/signer/actionBatch/actionBatchBootstrap.d.ts.map +1 -1
- package/out/src/signer/actionBatch/actionBatchBootstrap.js +3 -3
- package/out/src/signer/actionBatch/actionBatchBootstrap.js.map +1 -1
- package/out/src/signer/methods/acquireDirectCertificate.d.ts +3 -2
- package/out/src/signer/methods/acquireDirectCertificate.d.ts.map +1 -1
- package/out/src/signer/methods/acquireDirectCertificate.js.map +1 -1
- package/out/src/signer/methods/buildSignableTransaction.d.ts +6 -5
- package/out/src/signer/methods/buildSignableTransaction.d.ts.map +1 -1
- package/out/src/signer/methods/buildSignableTransaction.js +6 -11
- package/out/src/signer/methods/buildSignableTransaction.js.map +1 -1
- package/out/src/signer/methods/createAction.d.ts +4 -3
- package/out/src/signer/methods/createAction.d.ts.map +1 -1
- package/out/src/signer/methods/createAction.js +4 -2
- package/out/src/signer/methods/createAction.js.map +1 -1
- package/out/src/signer/methods/createNoSendExpiryAction.d.ts +3 -3
- package/out/src/signer/methods/createNoSendExpiryAction.d.ts.map +1 -1
- package/out/src/signer/methods/createNoSendExpiryAction.js +9 -4
- package/out/src/signer/methods/createNoSendExpiryAction.js.map +1 -1
- package/out/src/signer/methods/internalizeAction.d.ts.map +1 -1
- package/out/src/signer/methods/internalizeAction.js +2 -2
- package/out/src/signer/methods/internalizeAction.js.map +1 -1
- package/out/src/signer/methods/proveCertificate.d.ts +3 -2
- package/out/src/signer/methods/proveCertificate.d.ts.map +1 -1
- package/out/src/signer/methods/proveCertificate.js.map +1 -1
- package/out/src/signer/methods/signAction.d.ts.map +1 -1
- package/out/src/signer/methods/signAction.js +3 -2
- package/out/src/signer/methods/signAction.js.map +1 -1
- package/out/src/signer/methods/verifyUnlockScripts.d.ts.map +1 -1
- package/out/src/signer/methods/verifyUnlockScripts.js +12 -17
- package/out/src/signer/methods/verifyUnlockScripts.js.map +1 -1
- package/out/src/storage/StorageIdb.d.ts +5 -3
- package/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +15 -20
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +5 -3
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +143 -93
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +19 -9
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +229 -145
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/StorageReader.d.ts +1 -1
- package/out/src/storage/StorageReader.d.ts.map +1 -1
- package/out/src/storage/StorageReader.js +9 -42
- package/out/src/storage/StorageReader.js.map +1 -1
- package/out/src/storage/StorageReaderWriter.d.ts +1 -0
- package/out/src/storage/StorageReaderWriter.d.ts.map +1 -1
- package/out/src/storage/StorageReaderWriter.js +37 -36
- package/out/src/storage/StorageReaderWriter.js.map +1 -1
- package/out/src/storage/StorageSyncReader.d.ts +1 -1
- package/out/src/storage/StorageSyncReader.d.ts.map +1 -1
- package/out/src/storage/StorageSyncReader.js +3 -36
- package/out/src/storage/StorageSyncReader.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts +8 -7
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js +38 -65
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/src/storage/adminServer/adminServer.d.ts +1 -1
- package/out/src/storage/adminServer/adminServer.d.ts.map +1 -1
- package/out/src/storage/adminServer/adminServer.js +16 -44
- package/out/src/storage/adminServer/adminServer.js.map +1 -1
- package/out/src/storage/methods/ListActionsSpecOp.d.ts +2 -2
- package/out/src/storage/methods/ListActionsSpecOp.d.ts.map +1 -1
- package/out/src/storage/methods/ListActionsSpecOp.js.map +1 -1
- package/out/src/storage/methods/ListOutputsSpecOp.d.ts +7 -4
- package/out/src/storage/methods/ListOutputsSpecOp.d.ts.map +1 -1
- package/out/src/storage/methods/ListOutputsSpecOp.js +1 -0
- package/out/src/storage/methods/ListOutputsSpecOp.js.map +1 -1
- package/out/src/storage/methods/actionBatch.d.ts.map +1 -1
- package/out/src/storage/methods/actionBatch.js +3 -2
- package/out/src/storage/methods/actionBatch.js.map +1 -1
- package/out/src/storage/methods/actionBatchBlobs.d.ts +2 -0
- package/out/src/storage/methods/actionBatchBlobs.d.ts.map +1 -1
- package/out/src/storage/methods/actionBatchBlobs.js +40 -22
- package/out/src/storage/methods/actionBatchBlobs.js.map +1 -1
- package/out/src/storage/methods/actionBatchValidation.d.ts.map +1 -1
- package/out/src/storage/methods/actionBatchValidation.js +22 -30
- package/out/src/storage/methods/actionBatchValidation.js.map +1 -1
- package/out/src/storage/methods/attemptToPostReqsToNetwork.d.ts +7 -2
- package/out/src/storage/methods/attemptToPostReqsToNetwork.d.ts.map +1 -1
- package/out/src/storage/methods/attemptToPostReqsToNetwork.js +57 -44
- package/out/src/storage/methods/attemptToPostReqsToNetwork.js.map +1 -1
- package/out/src/storage/methods/createAction.d.ts +7 -6
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +7 -5
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/generateChange.d.ts.map +1 -1
- package/out/src/storage/methods/generateChange.js +12 -11
- package/out/src/storage/methods/generateChange.js.map +1 -1
- package/out/src/storage/methods/getBeefForTransaction.js +5 -7
- package/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/out/src/storage/methods/internalizeAction.d.ts +3 -3
- package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
- package/out/src/storage/methods/internalizeAction.js +134 -129
- package/out/src/storage/methods/internalizeAction.js.map +1 -1
- package/out/src/storage/methods/listActionsIdb.d.ts +3 -2
- package/out/src/storage/methods/listActionsIdb.d.ts.map +1 -1
- package/out/src/storage/methods/listActionsIdb.js +2 -2
- package/out/src/storage/methods/listActionsIdb.js.map +1 -1
- package/out/src/storage/methods/listActionsKnex.d.ts +3 -2
- package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listActionsKnex.js +10 -9
- package/out/src/storage/methods/listActionsKnex.js.map +1 -1
- package/out/src/storage/methods/listCertificates.d.ts +3 -2
- package/out/src/storage/methods/listCertificates.d.ts.map +1 -1
- package/out/src/storage/methods/listCertificates.js.map +1 -1
- package/out/src/storage/methods/listOutputsIdb.d.ts +3 -2
- package/out/src/storage/methods/listOutputsIdb.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputsIdb.js +11 -11
- package/out/src/storage/methods/listOutputsIdb.js.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.d.ts +3 -2
- package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputsKnex.js +15 -23
- package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
- package/out/src/storage/methods/noSendExpiry.d.ts +3 -3
- package/out/src/storage/methods/noSendExpiry.d.ts.map +1 -1
- package/out/src/storage/methods/noSendExpiry.js +10 -8
- package/out/src/storage/methods/noSendExpiry.js.map +1 -1
- package/out/src/storage/methods/preparedBeef.d.ts.map +1 -1
- package/out/src/storage/methods/preparedBeef.js +13 -14
- package/out/src/storage/methods/preparedBeef.js.map +1 -1
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +37 -6
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/methods/reconcileFailedTransactionInputs.d.ts +1 -1
- package/out/src/storage/methods/reconcileFailedTransactionInputs.d.ts.map +1 -1
- package/out/src/storage/methods/reconcileFailedTransactionInputs.js.map +1 -1
- package/out/src/storage/methods/reviewStatusIdb.d.ts +1 -1
- package/out/src/storage/methods/reviewStatusIdb.d.ts.map +1 -1
- package/out/src/storage/methods/reviewStatusIdb.js.map +1 -1
- package/out/src/storage/methods/reviewUtxoOutputs.d.ts +1 -0
- package/out/src/storage/methods/reviewUtxoOutputs.d.ts.map +1 -1
- package/out/src/storage/methods/reviewUtxoOutputs.js +51 -4
- package/out/src/storage/methods/reviewUtxoOutputs.js.map +1 -1
- package/out/src/storage/methods/validateSyncProof.d.ts.map +1 -1
- package/out/src/storage/methods/validateSyncProof.js +3 -3
- package/out/src/storage/methods/validateSyncProof.js.map +1 -1
- package/out/src/storage/portable/index.d.ts.map +1 -1
- package/out/src/storage/portable/index.js +21 -13
- package/out/src/storage/portable/index.js.map +1 -1
- package/out/src/storage/remoting/BinaryJson.d.ts +11 -0
- package/out/src/storage/remoting/BinaryJson.d.ts.map +1 -1
- package/out/src/storage/remoting/BinaryJson.js +37 -0
- package/out/src/storage/remoting/BinaryJson.js.map +1 -1
- package/out/src/storage/remoting/KnexSessionManager.d.ts +26 -2
- package/out/src/storage/remoting/KnexSessionManager.d.ts.map +1 -1
- package/out/src/storage/remoting/KnexSessionManager.js +222 -30
- package/out/src/storage/remoting/KnexSessionManager.js.map +1 -1
- package/out/src/storage/remoting/KnexSyncTransferStore.d.ts.map +1 -1
- package/out/src/storage/remoting/KnexSyncTransferStore.js +3 -4
- package/out/src/storage/remoting/KnexSyncTransferStore.js.map +1 -1
- package/out/src/storage/remoting/StorageClient.d.ts +6 -1
- package/out/src/storage/remoting/StorageClient.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClient.js +63 -6
- package/out/src/storage/remoting/StorageClient.js.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.d.ts +23 -6
- package/out/src/storage/remoting/StorageClientBase.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.js +148 -19
- package/out/src/storage/remoting/StorageClientBase.js.map +1 -1
- package/out/src/storage/remoting/StorageMobile.d.ts +5 -0
- package/out/src/storage/remoting/StorageMobile.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageMobile.js +11 -9
- package/out/src/storage/remoting/StorageMobile.js.map +1 -1
- package/out/src/storage/remoting/StorageServer.d.ts +5 -1
- package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageServer.js +95 -19
- package/out/src/storage/remoting/StorageServer.js.map +1 -1
- package/out/src/storage/remoting/SyncTransfer.d.ts.map +1 -1
- package/out/src/storage/remoting/SyncTransfer.js +3 -2
- package/out/src/storage/remoting/SyncTransfer.js.map +1 -1
- package/out/src/storage/schema/KnexMigrations.d.ts +1 -0
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +28 -6
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/out/src/storage/schema/entities/EntityOutput.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityOutput.js +11 -4
- package/out/src/storage/schema/entities/EntityOutput.js.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTx.d.ts +2 -1
- package/out/src/storage/schema/entities/EntityProvenTx.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTx.js +93 -39
- package/out/src/storage/schema/entities/EntityProvenTx.js.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTxReq.js +1 -1
- package/out/src/storage/schema/entities/EntityProvenTxReq.js.map +1 -1
- package/out/src/storage/schema/entities/EntitySyncState.js +1 -1
- package/out/src/storage/schema/entities/EntitySyncState.js.map +1 -1
- package/out/src/storage/schema/tables/TableCertificate.d.ts +1 -1
- package/out/src/storage/schema/tables/TableCertificate.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableCertificateField.d.ts +1 -1
- package/out/src/storage/schema/tables/TableCertificateField.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableCommission.d.ts +1 -1
- package/out/src/storage/schema/tables/TableCommission.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableMonitorEvent.d.ts +1 -1
- package/out/src/storage/schema/tables/TableMonitorEvent.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableOutput.d.ts +1 -1
- package/out/src/storage/schema/tables/TableOutput.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableOutputBasket.d.ts +1 -1
- package/out/src/storage/schema/tables/TableOutputBasket.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableOutputTag.d.ts +1 -1
- package/out/src/storage/schema/tables/TableOutputTag.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableOutputTagMap.d.ts +1 -1
- package/out/src/storage/schema/tables/TableOutputTagMap.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableProvenTx.d.ts +1 -1
- package/out/src/storage/schema/tables/TableProvenTx.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableProvenTxReq.d.ts +1 -1
- package/out/src/storage/schema/tables/TableProvenTxReq.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableSettings.d.ts +1 -1
- package/out/src/storage/schema/tables/TableSettings.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableSyncState.d.ts +1 -1
- package/out/src/storage/schema/tables/TableSyncState.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableTransaction.d.ts +1 -1
- package/out/src/storage/schema/tables/TableTransaction.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableTransaction.js.map +1 -1
- package/out/src/storage/schema/tables/TableTxLabel.d.ts +1 -1
- package/out/src/storage/schema/tables/TableTxLabel.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableTxLabelMap.d.ts +1 -1
- package/out/src/storage/schema/tables/TableTxLabelMap.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableUser.d.ts +1 -1
- package/out/src/storage/schema/tables/TableUser.d.ts.map +1 -1
- package/out/src/storage/sync/StorageMySQLDojoReader.d.ts.map +1 -1
- package/out/src/storage/sync/StorageMySQLDojoReader.js +8 -7
- package/out/src/storage/sync/StorageMySQLDojoReader.js.map +1 -1
- package/out/src/utility/actionBatchDigest.d.ts.map +1 -1
- package/out/src/utility/actionBatchDigest.js +9 -7
- package/out/src/utility/actionBatchDigest.js.map +1 -1
- package/out/src/utility/actionBatchPack.d.ts.map +1 -1
- package/out/src/utility/actionBatchPack.js +7 -12
- package/out/src/utility/actionBatchPack.js.map +1 -1
- package/out/src/utility/brc153ReferenceLabels.d.ts.map +1 -1
- package/out/src/utility/brc153ReferenceLabels.js +4 -4
- package/out/src/utility/brc153ReferenceLabels.js.map +1 -1
- package/out/src/utility/brc177NoSendExpiry.d.ts +2 -2
- package/out/src/utility/brc177NoSendExpiry.d.ts.map +1 -1
- package/out/src/utility/canonicalizeAtomicBeef.js +2 -2
- package/out/src/utility/canonicalizeAtomicBeef.js.map +1 -1
- package/out/src/utility/exactActionSpend.d.ts +11 -0
- package/out/src/utility/exactActionSpend.d.ts.map +1 -0
- package/out/src/utility/exactActionSpend.js +11 -0
- package/out/src/utility/exactActionSpend.js.map +1 -0
- package/out/src/utility/identityUtils.d.ts +44 -4
- package/out/src/utility/identityUtils.d.ts.map +1 -1
- package/out/src/utility/identityUtils.js +376 -61
- package/out/src/utility/identityUtils.js.map +1 -1
- package/out/src/utility/parseTxScriptOffsets.d.ts.map +1 -1
- package/out/src/utility/parseTxScriptOffsets.js +1 -19
- package/out/src/utility/parseTxScriptOffsets.js.map +1 -1
- package/out/src/utility/tscProofToMerklePath.d.ts.map +1 -1
- package/out/src/utility/tscProofToMerklePath.js +35 -4
- package/out/src/utility/tscProofToMerklePath.js.map +1 -1
- package/out/src/utility/utilityHelpers.d.ts.map +1 -1
- package/out/src/utility/utilityHelpers.js +8 -6
- package/out/src/utility/utilityHelpers.js.map +1 -1
- package/out/src/utility/utilityHelpers.noBuffer.d.ts.map +1 -1
- package/out/src/utility/utilityHelpers.noBuffer.js +6 -6
- package/out/src/utility/utilityHelpers.noBuffer.js.map +1 -1
- package/out/src/utility/verifyOverlayOutput.d.ts +12 -0
- package/out/src/utility/verifyOverlayOutput.d.ts.map +1 -0
- package/out/src/utility/verifyOverlayOutput.js +22 -0
- package/out/src/utility/verifyOverlayOutput.js.map +1 -0
- package/out/src/utility/walletResultGuards.d.ts +14 -0
- package/out/src/utility/walletResultGuards.d.ts.map +1 -0
- package/out/src/utility/walletResultGuards.js +28 -0
- package/out/src/utility/walletResultGuards.js.map +1 -0
- package/out/src/wab-client/WABClient.d.ts +3 -17
- package/out/src/wab-client/WABClient.d.ts.map +1 -1
- package/out/src/wab-client/WABClient.js +30 -14
- package/out/src/wab-client/WABClient.js.map +1 -1
- package/out/src/wab-client/WABResponseValidation.d.ts +48 -0
- package/out/src/wab-client/WABResponseValidation.d.ts.map +1 -0
- package/out/src/wab-client/WABResponseValidation.js +321 -0
- package/out/src/wab-client/WABResponseValidation.js.map +1 -0
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.d.ts.map +1 -1
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.js +3 -2
- package/out/src/wab-client/auth-method-interactors/AuthMethodInteractor.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,9 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WalletPermissionsManager = void 0;
|
|
4
|
+
const validationHelpers_1 = require("@bsv/sdk/wallet/validationHelpers");
|
|
4
5
|
const sdk_1 = require("@bsv/sdk");
|
|
6
|
+
const utils_1 = require("@bsv/sdk/primitives/utils");
|
|
5
7
|
const brc114ActionTimeLabels_1 = require("./utility/brc114ActionTimeLabels");
|
|
6
8
|
const brc177NoSendExpiry_1 = require("./utility/brc177NoSendExpiry");
|
|
9
|
+
const exactActionSpend_1 = require("./utility/exactActionSpend");
|
|
10
|
+
const WERR_errors_1 = require("./sdk/WERR_errors");
|
|
11
|
+
const MAX_PERMISSION_TOKEN_FIELD_BYTES = 1024 * 1024;
|
|
12
|
+
const MAX_PERMISSION_TOKEN_PAYLOAD_BYTES = 4 * 1024 * 1024;
|
|
13
|
+
const MAX_PERMISSION_TOKEN_LIST_FIELDS = 256;
|
|
14
|
+
const MAX_MONEY_SATOSHIS = 21e14;
|
|
15
|
+
function parseCanonicalPermissionInteger(value, label, maximum = Number.MAX_SAFE_INTEGER) {
|
|
16
|
+
if (!/^(?:0|[1-9]\d*)$/.test(value))
|
|
17
|
+
throw new Error(`${label} is not a canonical non-negative integer.`);
|
|
18
|
+
const parsed = Number(value);
|
|
19
|
+
if (!Number.isSafeInteger(parsed) || parsed > maximum) {
|
|
20
|
+
throw new Error(`${label} is outside the supported range.`);
|
|
21
|
+
}
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
function parsePermissionBoolean(value, label) {
|
|
25
|
+
if (value !== 'true' && value !== 'false')
|
|
26
|
+
throw new Error(`${label} must be true or false.`);
|
|
27
|
+
return value === 'true';
|
|
28
|
+
}
|
|
29
|
+
function parsePermissionCertificateFields(value) {
|
|
30
|
+
const parsed = JSON.parse(value);
|
|
31
|
+
if (!Array.isArray(parsed) || parsed.length > MAX_PERMISSION_TOKEN_LIST_FIELDS) {
|
|
32
|
+
throw new Error('Permission certificate fields must be a bounded array.');
|
|
33
|
+
}
|
|
34
|
+
const fields = [];
|
|
35
|
+
const seen = new Set();
|
|
36
|
+
for (const field of parsed) {
|
|
37
|
+
if (typeof field !== 'string' ||
|
|
38
|
+
field.length === 0 ||
|
|
39
|
+
new TextEncoder().encode(field).length >= 50 ||
|
|
40
|
+
seen.has(field)) {
|
|
41
|
+
throw new Error('Permission certificate fields are invalid.');
|
|
42
|
+
}
|
|
43
|
+
seen.add(field);
|
|
44
|
+
fields.push(field);
|
|
45
|
+
}
|
|
46
|
+
return fields;
|
|
47
|
+
}
|
|
7
48
|
function brc177PreflightSatoshis(args) {
|
|
8
49
|
const outputs = args.outputs ?? [];
|
|
9
50
|
let total = 0;
|
|
@@ -125,6 +166,13 @@ class WalletPermissionsManager {
|
|
|
125
166
|
/** Cache recently confirmed permissions to avoid repeated lookups. */
|
|
126
167
|
permissionCache = new Map();
|
|
127
168
|
recentGrants = new Map();
|
|
169
|
+
/** Originator binding for partial actions issued through this manager. */
|
|
170
|
+
pendingActionOriginators = new Map();
|
|
171
|
+
/** Exact authorized transaction template for each pending action. */
|
|
172
|
+
pendingActionTemplates = new Map();
|
|
173
|
+
/** References that failed authorization and could not be conclusively aborted. */
|
|
174
|
+
blockedActionReferences = new Set();
|
|
175
|
+
permissionTokenLockingKeyPromise;
|
|
128
176
|
/**
|
|
129
177
|
* Token mints currently being written on-chain, keyed by permission cache
|
|
130
178
|
* key. A granted permission is only cached once its token finishes minting
|
|
@@ -143,6 +191,8 @@ class WalletPermissionsManager {
|
|
|
143
191
|
manifestCache = new Map();
|
|
144
192
|
manifestFetchInProgress = new Map();
|
|
145
193
|
static MANIFEST_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
194
|
+
static MANIFEST_MAX_BYTES = 256 * 1024;
|
|
195
|
+
static MANIFEST_TIMEOUT_MS = 10_000;
|
|
146
196
|
groupedPermissionFlowTail = new Map();
|
|
147
197
|
pactEstablishedCache = new Map();
|
|
148
198
|
/**
|
|
@@ -158,11 +208,6 @@ class WalletPermissionsManager {
|
|
|
158
208
|
static CACHE_TTL_MS = 5 * 60 * 1000;
|
|
159
209
|
/** Window during which freshly granted permissions are auto-allowed (except spending). */
|
|
160
210
|
static RECENT_GRANT_COVER_MS = 15 * 1000;
|
|
161
|
-
/** Default ports used when normalizing originator values. */
|
|
162
|
-
static DEFAULT_PORTS = {
|
|
163
|
-
'http:': '80',
|
|
164
|
-
'https:': '443'
|
|
165
|
-
};
|
|
166
211
|
/**
|
|
167
212
|
* Configuration that determines whether to skip or apply various checks and encryption.
|
|
168
213
|
*/
|
|
@@ -1120,11 +1165,22 @@ class WalletPermissionsManager {
|
|
|
1120
1165
|
return await inProgress;
|
|
1121
1166
|
}
|
|
1122
1167
|
const fetchPromise = (async () => {
|
|
1168
|
+
const controller = new AbortController();
|
|
1169
|
+
const timeout = setTimeout(() => controller.abort(), WalletPermissionsManager.MANIFEST_TIMEOUT_MS);
|
|
1123
1170
|
try {
|
|
1124
|
-
const
|
|
1125
|
-
const
|
|
1171
|
+
const localDevelopment = originator === 'localhost' || originator.startsWith('localhost:');
|
|
1172
|
+
const proto = localDevelopment ? 'http' : 'https';
|
|
1173
|
+
const expectedOrigin = `${proto}://${originator}`;
|
|
1174
|
+
// Localhost HTTP is an explicit development compatibility path. Every
|
|
1175
|
+
// public origin uses resolved-address validation and a DNS-pinned
|
|
1176
|
+
// connection so a manifest hostname cannot rebind to a private host.
|
|
1177
|
+
const manifestFetch = localDevelopment ? globalThis.fetch : (0, sdk_1.createPublicHTTPSFetch)(expectedOrigin);
|
|
1178
|
+
const response = await manifestFetch(`${expectedOrigin}/manifest.json`, {
|
|
1179
|
+
redirect: 'error',
|
|
1180
|
+
signal: controller.signal
|
|
1181
|
+
});
|
|
1126
1182
|
if (response.ok) {
|
|
1127
|
-
const manifest = await
|
|
1183
|
+
const manifest = await this.readBoundedManifest(response);
|
|
1128
1184
|
const namespace = manifest?.metanet || manifest?.babbage;
|
|
1129
1185
|
const groupPermissions = namespace?.groupPermissions || null;
|
|
1130
1186
|
const counterpartyPermissionsDeclared = this.validateCounterpartyPermissions(namespace?.counterpartyPermissions);
|
|
@@ -1139,6 +1195,9 @@ class WalletPermissionsManager {
|
|
|
1139
1195
|
catch {
|
|
1140
1196
|
// Manifest fetch or parse failed — fall through to return null/null defaults below
|
|
1141
1197
|
}
|
|
1198
|
+
finally {
|
|
1199
|
+
clearTimeout(timeout);
|
|
1200
|
+
}
|
|
1142
1201
|
const result = { groupPermissions: null, counterpartyPermissions: null };
|
|
1143
1202
|
this.manifestCache.set(originator, { ...result, fetchedAt: Date.now() });
|
|
1144
1203
|
return result;
|
|
@@ -1151,6 +1210,49 @@ class WalletPermissionsManager {
|
|
|
1151
1210
|
this.manifestFetchInProgress.delete(originator);
|
|
1152
1211
|
}
|
|
1153
1212
|
}
|
|
1213
|
+
async readBoundedManifest(response) {
|
|
1214
|
+
const declaredLength = response.headers?.get('content-length');
|
|
1215
|
+
if (declaredLength != null) {
|
|
1216
|
+
const parsedLength = Number(declaredLength);
|
|
1217
|
+
if (!Number.isSafeInteger(parsedLength) ||
|
|
1218
|
+
parsedLength < 0 ||
|
|
1219
|
+
parsedLength > WalletPermissionsManager.MANIFEST_MAX_BYTES) {
|
|
1220
|
+
throw new Error('Manifest response exceeds the configured size limit.');
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
if (response.body == null) {
|
|
1224
|
+
// Test and embedded fetch implementations may expose only json(). Bound
|
|
1225
|
+
// their parsed representation before accepting it.
|
|
1226
|
+
const parsed = await response.json();
|
|
1227
|
+
if (new TextEncoder().encode(JSON.stringify(parsed)).length > WalletPermissionsManager.MANIFEST_MAX_BYTES) {
|
|
1228
|
+
throw new Error('Manifest response exceeds the configured size limit.');
|
|
1229
|
+
}
|
|
1230
|
+
return parsed;
|
|
1231
|
+
}
|
|
1232
|
+
const reader = response.body.getReader();
|
|
1233
|
+
const chunks = [];
|
|
1234
|
+
let total = 0;
|
|
1235
|
+
for (;;) {
|
|
1236
|
+
const { done, value } = await reader.read();
|
|
1237
|
+
if (done)
|
|
1238
|
+
break;
|
|
1239
|
+
if (value == null)
|
|
1240
|
+
continue;
|
|
1241
|
+
total += value.byteLength;
|
|
1242
|
+
if (total > WalletPermissionsManager.MANIFEST_MAX_BYTES) {
|
|
1243
|
+
await reader.cancel();
|
|
1244
|
+
throw new Error('Manifest response exceeds the configured size limit.');
|
|
1245
|
+
}
|
|
1246
|
+
chunks.push(value);
|
|
1247
|
+
}
|
|
1248
|
+
const bytes = new Uint8Array(total);
|
|
1249
|
+
let offset = 0;
|
|
1250
|
+
for (const chunk of chunks) {
|
|
1251
|
+
bytes.set(chunk, offset);
|
|
1252
|
+
offset += chunk.byteLength;
|
|
1253
|
+
}
|
|
1254
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
|
|
1255
|
+
}
|
|
1154
1256
|
async fetchManifestGroupPermissions(originator) {
|
|
1155
1257
|
const { groupPermissions } = await this.fetchManifestPermissions(originator);
|
|
1156
1258
|
return groupPermissions;
|
|
@@ -1743,7 +1845,7 @@ class WalletPermissionsManager {
|
|
|
1743
1845
|
];
|
|
1744
1846
|
/** We always use `keyID="1"` and `counterparty="self"` for these encryption ops. */
|
|
1745
1847
|
async encryptPermissionTokenField(plaintext) {
|
|
1746
|
-
const data = typeof plaintext === 'string' ?
|
|
1848
|
+
const data = typeof plaintext === 'string' ? (0, utils_1.toArray)(plaintext, 'utf8') : plaintext;
|
|
1747
1849
|
const { ciphertext } = await this.underlying.encrypt({
|
|
1748
1850
|
plaintext: data,
|
|
1749
1851
|
protocolID: WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL,
|
|
@@ -1765,7 +1867,7 @@ class WalletPermissionsManager {
|
|
|
1765
1867
|
let parsed = this.parsedBeefCache.get(beef);
|
|
1766
1868
|
if (parsed === undefined) {
|
|
1767
1869
|
try {
|
|
1768
|
-
parsed = sdk_1.Beef.
|
|
1870
|
+
parsed = sdk_1.Beef.fromBinaryStrict(beef);
|
|
1769
1871
|
}
|
|
1770
1872
|
catch {
|
|
1771
1873
|
parsed = null;
|
|
@@ -1783,6 +1885,60 @@ class WalletPermissionsManager {
|
|
|
1783
1885
|
// fast path can't serve.
|
|
1784
1886
|
return sdk_1.Transaction.fromBEEF(beef ?? [], txid);
|
|
1785
1887
|
}
|
|
1888
|
+
async permissionTokenLockingKey() {
|
|
1889
|
+
const pending = this.permissionTokenLockingKeyPromise ??
|
|
1890
|
+
this.underlying
|
|
1891
|
+
.getPublicKey({
|
|
1892
|
+
protocolID: WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL,
|
|
1893
|
+
keyID: '1',
|
|
1894
|
+
counterparty: 'self',
|
|
1895
|
+
forSelf: true
|
|
1896
|
+
}, this.adminOriginator)
|
|
1897
|
+
.then(({ publicKey }) => {
|
|
1898
|
+
if (typeof publicKey !== 'string' || !/^(?:02|03)[0-9a-f]{64}$/i.test(publicKey)) {
|
|
1899
|
+
throw new Error('Wallet returned an invalid permission-token locking key.');
|
|
1900
|
+
}
|
|
1901
|
+
return publicKey.toLowerCase();
|
|
1902
|
+
});
|
|
1903
|
+
this.permissionTokenLockingKeyPromise = pending;
|
|
1904
|
+
try {
|
|
1905
|
+
return await pending;
|
|
1906
|
+
}
|
|
1907
|
+
catch (error) {
|
|
1908
|
+
if (this.permissionTokenLockingKeyPromise === pending)
|
|
1909
|
+
this.permissionTokenLockingKeyPromise = undefined;
|
|
1910
|
+
throw error;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
async authenticatedPermissionTokenSource(result, output, dataFieldCount) {
|
|
1914
|
+
try {
|
|
1915
|
+
const [txid, outputIndex] = this.parseOutpoint(output.outpoint);
|
|
1916
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1917
|
+
if (tx.id('hex').toLowerCase() !== txid)
|
|
1918
|
+
throw new Error('Permission token transaction ID mismatch.');
|
|
1919
|
+
const txOutput = tx.outputs[outputIndex];
|
|
1920
|
+
if (txOutput == null || txOutput.satoshis !== 1 || output.satoshis !== 1) {
|
|
1921
|
+
throw new Error('Permission token source output is invalid.');
|
|
1922
|
+
}
|
|
1923
|
+
const decoded = (0, sdk_1.decodeCanonicalPushDrop)(txOutput.lockingScript, {
|
|
1924
|
+
fieldCount: dataFieldCount + 1,
|
|
1925
|
+
maximumFieldBytes: MAX_PERMISSION_TOKEN_FIELD_BYTES,
|
|
1926
|
+
maximumPayloadBytes: MAX_PERMISSION_TOKEN_PAYLOAD_BYTES
|
|
1927
|
+
});
|
|
1928
|
+
if (decoded.lockingPublicKey.toString().toLowerCase() !== (await this.permissionTokenLockingKey())) {
|
|
1929
|
+
throw new Error('Permission token is not controlled by this wallet.');
|
|
1930
|
+
}
|
|
1931
|
+
const fields = decoded.fields.slice(0, -1);
|
|
1932
|
+
const signature = sdk_1.Signature.fromDER(decoded.fields.at(-1));
|
|
1933
|
+
if (!signature.verify(fields.flat(), decoded.lockingPublicKey)) {
|
|
1934
|
+
throw new Error('Permission token field signature is invalid.');
|
|
1935
|
+
}
|
|
1936
|
+
return { tx, txid, outputIndex, fields };
|
|
1937
|
+
}
|
|
1938
|
+
catch {
|
|
1939
|
+
return undefined;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1786
1942
|
async decryptPermissionTokenField(ciphertext) {
|
|
1787
1943
|
// Field decrypts run in tight loops over every token in a basket; yield a
|
|
1788
1944
|
// macrotask periodically so large scans don't starve the caller's event
|
|
@@ -1803,6 +1959,9 @@ class WalletPermissionsManager {
|
|
|
1803
1959
|
return ciphertext;
|
|
1804
1960
|
}
|
|
1805
1961
|
}
|
|
1962
|
+
async decryptPermissionTokenText(ciphertext) {
|
|
1963
|
+
return (0, utils_1.toUTF8Strict)(await this.decryptPermissionTokenField(ciphertext));
|
|
1964
|
+
}
|
|
1806
1965
|
/**
|
|
1807
1966
|
* Encrypts wallet metadata if configured to do so, otherwise returns the original plaintext for storage.
|
|
1808
1967
|
* @param plaintext The metadata to encrypt if configured to do so
|
|
@@ -1813,11 +1972,11 @@ class WalletPermissionsManager {
|
|
|
1813
1972
|
return plaintext;
|
|
1814
1973
|
}
|
|
1815
1974
|
const { ciphertext } = await this.underlying.encrypt({
|
|
1816
|
-
plaintext:
|
|
1975
|
+
plaintext: (0, utils_1.toArray)(plaintext, 'utf8'),
|
|
1817
1976
|
protocolID: WalletPermissionsManager.METADATA_ENCRYPTION_PROTOCOL,
|
|
1818
1977
|
keyID: '1'
|
|
1819
1978
|
}, this.adminOriginator);
|
|
1820
|
-
return
|
|
1979
|
+
return (0, utils_1.toBase64)(ciphertext);
|
|
1821
1980
|
}
|
|
1822
1981
|
/**
|
|
1823
1982
|
* Attempts to decrypt metadata. if decryption fails, assumes the value is already plaintext and returns it.
|
|
@@ -1827,11 +1986,11 @@ class WalletPermissionsManager {
|
|
|
1827
1986
|
async maybeDecryptMetadata(ciphertext) {
|
|
1828
1987
|
try {
|
|
1829
1988
|
const { plaintext } = await this.underlying.decrypt({
|
|
1830
|
-
ciphertext:
|
|
1989
|
+
ciphertext: (0, utils_1.toArray)(ciphertext, 'base64'),
|
|
1831
1990
|
protocolID: WalletPermissionsManager.METADATA_ENCRYPTION_PROTOCOL,
|
|
1832
1991
|
keyID: '1'
|
|
1833
1992
|
}, this.adminOriginator);
|
|
1834
|
-
return
|
|
1993
|
+
return (0, utils_1.toUTF8)(plaintext);
|
|
1835
1994
|
}
|
|
1836
1995
|
catch {
|
|
1837
1996
|
// Decryption failed (e.g. wrong key, unencrypted legacy value) — return original string unchanged
|
|
@@ -1845,32 +2004,33 @@ class WalletPermissionsManager {
|
|
|
1845
2004
|
}
|
|
1846
2005
|
/** Decrypts the standard 6 fields from a protocol (DPACP) PushDrop script. */
|
|
1847
2006
|
async decryptProtocolTokenFields(fields) {
|
|
1848
|
-
const domainDecoded =
|
|
1849
|
-
const expiryDecoded =
|
|
1850
|
-
const privDecoded =
|
|
1851
|
-
const
|
|
1852
|
-
const
|
|
1853
|
-
const
|
|
2007
|
+
const domainDecoded = await this.decryptPermissionTokenText(fields[0]);
|
|
2008
|
+
const expiryDecoded = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(fields[1]), 'Permission expiry');
|
|
2009
|
+
const privDecoded = parsePermissionBoolean(await this.decryptPermissionTokenText(fields[2]), 'Permission privileged flag');
|
|
2010
|
+
const securityLevel = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(fields[3]), 'Permission security level', 2);
|
|
2011
|
+
const secLevelDecoded = securityLevel;
|
|
2012
|
+
const protoNameDecoded = await this.decryptPermissionTokenText(fields[4]);
|
|
2013
|
+
const cptyDecoded = await this.decryptPermissionTokenText(fields[5]);
|
|
1854
2014
|
return { domainDecoded, expiryDecoded, privDecoded, secLevelDecoded, protoNameDecoded, cptyDecoded };
|
|
1855
2015
|
}
|
|
1856
2016
|
protocolTokenTags(originator, privileged, securityLevel, protocolName, counterparty) {
|
|
1857
2017
|
const tags = [
|
|
1858
|
-
`originator ${originator}`,
|
|
1859
2018
|
`privileged ${!!privileged}`,
|
|
1860
2019
|
`protocolName ${protocolName}`,
|
|
1861
2020
|
`protocolSecurityLevel ${securityLevel}`
|
|
1862
2021
|
];
|
|
2022
|
+
if (originator !== undefined)
|
|
2023
|
+
tags.unshift(`originator ${originator}`);
|
|
1863
2024
|
if (securityLevel === 2)
|
|
1864
2025
|
tags.push(`counterparty ${counterparty}`);
|
|
1865
2026
|
return tags;
|
|
1866
2027
|
}
|
|
1867
2028
|
async parseProtocolTokenOutput(result, output, expected) {
|
|
1868
|
-
const
|
|
1869
|
-
|
|
1870
|
-
const decoded = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1871
|
-
if (decoded?.fields == null || decoded.fields.length < 6)
|
|
2029
|
+
const source = await this.authenticatedPermissionTokenSource(result, output, 6);
|
|
2030
|
+
if (source == null)
|
|
1872
2031
|
return undefined;
|
|
1873
|
-
const
|
|
2032
|
+
const { tx, txid, outputIndex } = source;
|
|
2033
|
+
const fields = await this.decryptProtocolTokenFields(source.fields);
|
|
1874
2034
|
if (this.normalizeOriginator(fields.domainDecoded) !== expected.originator)
|
|
1875
2035
|
return undefined;
|
|
1876
2036
|
const matches = fields.privDecoded === !!expected.privileged &&
|
|
@@ -1895,16 +2055,15 @@ class WalletPermissionsManager {
|
|
|
1895
2055
|
};
|
|
1896
2056
|
}
|
|
1897
2057
|
async parseBasketTokenOutput(result, output, originator, basket) {
|
|
1898
|
-
const
|
|
1899
|
-
|
|
1900
|
-
const decoded = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1901
|
-
if (decoded?.fields == null || decoded.fields.length < 3)
|
|
2058
|
+
const source = await this.authenticatedPermissionTokenSource(result, output, 3);
|
|
2059
|
+
if (source == null)
|
|
1902
2060
|
return undefined;
|
|
1903
|
-
const
|
|
2061
|
+
const { tx, txid, outputIndex, fields } = source;
|
|
2062
|
+
const domainDecoded = await this.decryptPermissionTokenText(fields[0]);
|
|
1904
2063
|
if (this.normalizeOriginator(domainDecoded) !== originator)
|
|
1905
2064
|
return undefined;
|
|
1906
|
-
const expiryDecoded =
|
|
1907
|
-
const basketDecoded =
|
|
2065
|
+
const expiryDecoded = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(fields[1]), 'Permission expiry');
|
|
2066
|
+
const basketDecoded = await this.decryptPermissionTokenText(fields[2]);
|
|
1908
2067
|
if (basketDecoded !== basket)
|
|
1909
2068
|
return undefined;
|
|
1910
2069
|
return {
|
|
@@ -1920,20 +2079,19 @@ class WalletPermissionsManager {
|
|
|
1920
2079
|
};
|
|
1921
2080
|
}
|
|
1922
2081
|
async parseCertificateTokenOutput(result, output, expected) {
|
|
1923
|
-
const
|
|
1924
|
-
|
|
1925
|
-
const decoded = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1926
|
-
if (decoded?.fields == null || decoded.fields.length < 6)
|
|
2082
|
+
const source = await this.authenticatedPermissionTokenSource(result, output, 6);
|
|
2083
|
+
if (source == null)
|
|
1927
2084
|
return undefined;
|
|
1928
|
-
const
|
|
1929
|
-
const
|
|
2085
|
+
const { tx, txid, outputIndex } = source;
|
|
2086
|
+
const [domainRaw, expiryRaw, privRaw, typeRaw, fieldsRaw, verifierRaw] = source.fields;
|
|
2087
|
+
const domainDecoded = await this.decryptPermissionTokenText(domainRaw);
|
|
1930
2088
|
if (this.normalizeOriginator(domainDecoded) !== expected.originator)
|
|
1931
2089
|
return undefined;
|
|
1932
|
-
const expiryDecoded =
|
|
1933
|
-
const privileged =
|
|
1934
|
-
const certType =
|
|
1935
|
-
const verifier =
|
|
1936
|
-
const allFields =
|
|
2090
|
+
const expiryDecoded = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(expiryRaw), 'Permission expiry');
|
|
2091
|
+
const privileged = parsePermissionBoolean(await this.decryptPermissionTokenText(privRaw), 'Permission privileged flag');
|
|
2092
|
+
const certType = await this.decryptPermissionTokenText(typeRaw);
|
|
2093
|
+
const verifier = await this.decryptPermissionTokenText(verifierRaw);
|
|
2094
|
+
const allFields = parsePermissionCertificateFields(await this.decryptPermissionTokenText(fieldsRaw));
|
|
1937
2095
|
const metadataMatches = privileged === !!expected.privileged && certType === expected.certType && verifier === expected.verifier;
|
|
1938
2096
|
if (!metadataMatches)
|
|
1939
2097
|
return undefined;
|
|
@@ -1957,61 +2115,14 @@ class WalletPermissionsManager {
|
|
|
1957
2115
|
}
|
|
1958
2116
|
/** Parses outpoint string "txid.vout" into [txid, outputIndex]. */
|
|
1959
2117
|
parseOutpoint(outpoint) {
|
|
1960
|
-
const
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
reverseHexTxid(txid) {
|
|
1969
|
-
const hex = this.normalizeTxid(txid);
|
|
1970
|
-
if (!/^[0-9a-f]{64}$/.test(hex))
|
|
1971
|
-
return hex;
|
|
1972
|
-
const bytes = hex.match(/../g);
|
|
1973
|
-
return bytes != null ? bytes.reverse().join('') : hex;
|
|
1974
|
-
}
|
|
1975
|
-
/**
|
|
1976
|
-
* Returns true when an outpoint string (e.g. "txid.vout" or "txid:vout") refers to `token`.
|
|
1977
|
-
*/
|
|
1978
|
-
tokenMatchesOutpointString(outpoint, token) {
|
|
1979
|
-
const dot = outpoint.lastIndexOf('.');
|
|
1980
|
-
const colon = outpoint.lastIndexOf(':');
|
|
1981
|
-
const sep = Math.max(dot, colon);
|
|
1982
|
-
if (sep === -1)
|
|
1983
|
-
return false;
|
|
1984
|
-
const txidPart = outpoint.slice(0, sep);
|
|
1985
|
-
const vout = Number(outpoint.slice(sep + 1));
|
|
1986
|
-
if (!Number.isFinite(vout))
|
|
1987
|
-
return false;
|
|
1988
|
-
return this.normalizeTxid(txidPart) === this.normalizeTxid(token.txid) && vout === token.outputIndex;
|
|
1989
|
-
}
|
|
1990
|
-
/**
|
|
1991
|
-
* Finds the index of the tx input that spends the given permission token.
|
|
1992
|
-
* Handles multiple potential field names for TXID and vout.
|
|
1993
|
-
*/
|
|
1994
|
-
findInputIndexForToken(tx, token) {
|
|
1995
|
-
return tx.inputs.findIndex((input) => {
|
|
1996
|
-
const txidCandidate = input?.sourceTXID ??
|
|
1997
|
-
input?.sourceTxid ??
|
|
1998
|
-
input?.sourceTxId ??
|
|
1999
|
-
input?.prevTxId ??
|
|
2000
|
-
input?.prevTxid ??
|
|
2001
|
-
input?.prevTXID ??
|
|
2002
|
-
input?.txid ??
|
|
2003
|
-
input?.txID;
|
|
2004
|
-
const voutCandidate = input?.sourceOutputIndex ?? input?.sourceOutput ?? input?.outputIndex ?? input?.vout ?? input?.prevOutIndex;
|
|
2005
|
-
if (typeof txidCandidate === 'string' && typeof voutCandidate === 'number') {
|
|
2006
|
-
const cand = this.normalizeTxid(txidCandidate);
|
|
2007
|
-
if (cand === this.normalizeTxid(token.txid) && voutCandidate === token.outputIndex)
|
|
2008
|
-
return true;
|
|
2009
|
-
if (cand === this.reverseHexTxid(token.txid) && voutCandidate === token.outputIndex)
|
|
2010
|
-
return true;
|
|
2011
|
-
}
|
|
2012
|
-
const outpointCandidate = input?.outpoint ?? input?.sourceOutpoint ?? input?.prevOutpoint;
|
|
2013
|
-
return typeof outpointCandidate === 'string' && this.tokenMatchesOutpointString(outpointCandidate, token);
|
|
2014
|
-
});
|
|
2118
|
+
const match = /^([0-9a-f]{64})\.(0|[1-9]\d*)$/i.exec(outpoint);
|
|
2119
|
+
if (match == null)
|
|
2120
|
+
throw new Error('Permission token outpoint is invalid.');
|
|
2121
|
+
const outputIndex = Number(match[2]);
|
|
2122
|
+
if (!Number.isSafeInteger(outputIndex) || outputIndex > 0xffffffff) {
|
|
2123
|
+
throw new Error('Permission token outpoint is invalid.');
|
|
2124
|
+
}
|
|
2125
|
+
return [match[1].toLowerCase(), outputIndex];
|
|
2015
2126
|
}
|
|
2016
2127
|
/** Looks for a DPACP permission token matching origin/domain, privileged, protocol, cpty. */
|
|
2017
2128
|
async findProtocolToken(originator, privileged, protocolID, counterparty, includeExpired, originatorLookupValues) {
|
|
@@ -2022,7 +2133,8 @@ class WalletPermissionsManager {
|
|
|
2022
2133
|
basket: BASKET_MAP.protocol,
|
|
2023
2134
|
tags: this.protocolTokenTags(originTag, privileged, secLevel, protoName, counterparty),
|
|
2024
2135
|
tagQueryMode: 'all',
|
|
2025
|
-
include: 'entire transactions'
|
|
2136
|
+
include: 'entire transactions',
|
|
2137
|
+
limit: 10000
|
|
2026
2138
|
}, this.adminOriginator);
|
|
2027
2139
|
for (const out of result.outputs) {
|
|
2028
2140
|
const token = await this.parseProtocolTokenOutput(result, out, {
|
|
@@ -2052,7 +2164,8 @@ class WalletPermissionsManager {
|
|
|
2052
2164
|
basket: BASKET_MAP.protocol,
|
|
2053
2165
|
tags: this.protocolTokenTags(originTag, privileged, secLevel, protoName, counterparty),
|
|
2054
2166
|
tagQueryMode: 'all',
|
|
2055
|
-
include: 'entire transactions'
|
|
2167
|
+
include: 'entire transactions',
|
|
2168
|
+
limit: 10000
|
|
2056
2169
|
}, this.adminOriginator);
|
|
2057
2170
|
for (const out of result.outputs) {
|
|
2058
2171
|
if (seen.has(out.outpoint))
|
|
@@ -2078,9 +2191,10 @@ class WalletPermissionsManager {
|
|
|
2078
2191
|
for (const originTag of originsToTry) {
|
|
2079
2192
|
const result = await this.underlying.listOutputs({
|
|
2080
2193
|
basket: BASKET_MAP.basket,
|
|
2081
|
-
tags: [`originator ${originTag}`, `basket ${basket}`],
|
|
2194
|
+
tags: [originTag === undefined ? undefined : `originator ${originTag}`, `basket ${basket}`].filter((tag) => tag !== undefined),
|
|
2082
2195
|
tagQueryMode: 'all',
|
|
2083
|
-
include: 'entire transactions'
|
|
2196
|
+
include: 'entire transactions',
|
|
2197
|
+
limit: 10000
|
|
2084
2198
|
}, this.adminOriginator);
|
|
2085
2199
|
for (const out of result.outputs) {
|
|
2086
2200
|
const token = await this.parseBasketTokenOutput(result, out, originator, basket);
|
|
@@ -2099,9 +2213,15 @@ class WalletPermissionsManager {
|
|
|
2099
2213
|
for (const originTag of originsToTry) {
|
|
2100
2214
|
const result = await this.underlying.listOutputs({
|
|
2101
2215
|
basket: BASKET_MAP.certificate,
|
|
2102
|
-
tags: [
|
|
2216
|
+
tags: [
|
|
2217
|
+
originTag === undefined ? undefined : `originator ${originTag}`,
|
|
2218
|
+
`privileged ${!!privileged}`,
|
|
2219
|
+
`type ${certType}`,
|
|
2220
|
+
`verifier ${verifier}`
|
|
2221
|
+
].filter((tag) => tag !== undefined),
|
|
2103
2222
|
tagQueryMode: 'all',
|
|
2104
|
-
include: 'entire transactions'
|
|
2223
|
+
include: 'entire transactions',
|
|
2224
|
+
limit: 10000
|
|
2105
2225
|
}, this.adminOriginator);
|
|
2106
2226
|
for (const out of result.outputs) {
|
|
2107
2227
|
const token = await this.parseCertificateTokenOutput(result, out, {
|
|
@@ -2126,29 +2246,28 @@ class WalletPermissionsManager {
|
|
|
2126
2246
|
for (const originTag of originsToTry) {
|
|
2127
2247
|
const result = await this.underlying.listOutputs({
|
|
2128
2248
|
basket: BASKET_MAP.spending,
|
|
2129
|
-
tags: [`originator ${originTag}`],
|
|
2249
|
+
tags: originTag === undefined ? [] : [`originator ${originTag}`],
|
|
2130
2250
|
tagQueryMode: 'all',
|
|
2131
|
-
include: 'entire transactions'
|
|
2251
|
+
include: 'entire transactions',
|
|
2252
|
+
limit: 10000
|
|
2132
2253
|
}, this.adminOriginator);
|
|
2133
2254
|
for (const out of result.outputs) {
|
|
2134
|
-
const
|
|
2135
|
-
|
|
2136
|
-
const dec = sdk_1.PushDrop.decode(tx.outputs[Number(outputIndexStr)].lockingScript);
|
|
2137
|
-
if (!dec?.fields || dec.fields.length < 2)
|
|
2255
|
+
const source = await this.authenticatedPermissionTokenSource(result, out, 2);
|
|
2256
|
+
if (source == null)
|
|
2138
2257
|
continue;
|
|
2139
|
-
const
|
|
2140
|
-
const
|
|
2141
|
-
const
|
|
2258
|
+
const { tx, txid, outputIndex, fields } = source;
|
|
2259
|
+
const domainRaw = fields[0];
|
|
2260
|
+
const amtRaw = fields[1];
|
|
2261
|
+
const domainDecoded = await this.decryptPermissionTokenText(domainRaw);
|
|
2142
2262
|
const normalizedDomain = this.normalizeOriginator(domainDecoded);
|
|
2143
2263
|
if (normalizedDomain !== originator)
|
|
2144
2264
|
continue;
|
|
2145
|
-
const
|
|
2146
|
-
const authorizedAmount = Number.parseInt(amtDecodedStr, 10);
|
|
2265
|
+
const authorizedAmount = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(amtRaw), 'Permission spending amount', MAX_MONEY_SATOSHIS);
|
|
2147
2266
|
return {
|
|
2148
2267
|
tx: tx.toBEEF(),
|
|
2149
|
-
txid
|
|
2150
|
-
outputIndex
|
|
2151
|
-
outputScript: tx.outputs[
|
|
2268
|
+
txid,
|
|
2269
|
+
outputIndex,
|
|
2270
|
+
outputScript: tx.outputs[outputIndex].lockingScript.toHex(),
|
|
2152
2271
|
satoshis: out.satoshis,
|
|
2153
2272
|
originator,
|
|
2154
2273
|
rawOriginator: domainDecoded,
|
|
@@ -2224,7 +2343,7 @@ class WalletPermissionsManager {
|
|
|
2224
2343
|
const tags = this.buildTagsForRequest(r);
|
|
2225
2344
|
// Build a transaction with exactly one output, no explicit inputs since the wallet
|
|
2226
2345
|
// can internally fund it from its balance.
|
|
2227
|
-
await this.
|
|
2346
|
+
await this.completePermissionTokenAction({
|
|
2228
2347
|
description: `Grant ${r.type} permission`,
|
|
2229
2348
|
outputs: [
|
|
2230
2349
|
{
|
|
@@ -2241,7 +2360,7 @@ class WalletPermissionsManager {
|
|
|
2241
2360
|
// last-resort funding source for the resumed request.
|
|
2242
2361
|
acceptDelayedBroadcast: true
|
|
2243
2362
|
}
|
|
2244
|
-
}
|
|
2363
|
+
});
|
|
2245
2364
|
}
|
|
2246
2365
|
async mapWithConcurrency(items, concurrency, fn) {
|
|
2247
2366
|
if (items.length === 0)
|
|
@@ -2273,9 +2392,8 @@ class WalletPermissionsManager {
|
|
|
2273
2392
|
try {
|
|
2274
2393
|
return await runChunk(chunk);
|
|
2275
2394
|
}
|
|
2276
|
-
catch
|
|
2395
|
+
catch {
|
|
2277
2396
|
if (chunk.length <= 1) {
|
|
2278
|
-
console.error('Permission batch failed:', e);
|
|
2279
2397
|
return [];
|
|
2280
2398
|
}
|
|
2281
2399
|
const mid = Math.ceil(chunk.length / 2);
|
|
@@ -2309,11 +2427,11 @@ class WalletPermissionsManager {
|
|
|
2309
2427
|
const CHUNK = 25;
|
|
2310
2428
|
return await this.runBestEffortBatches(items, CHUNK, async (chunk) => {
|
|
2311
2429
|
const built = await this.mapWithConcurrency(chunk, 8, async (c) => await this.buildPermissionOutput(c.request, c.expiry, c.amount));
|
|
2312
|
-
await this.
|
|
2430
|
+
await this.completePermissionTokenAction({
|
|
2313
2431
|
description: `Grant ${built.length} permissions`,
|
|
2314
2432
|
outputs: built.map(b => b.output),
|
|
2315
2433
|
options: { acceptDelayedBroadcast: true }
|
|
2316
|
-
}
|
|
2434
|
+
});
|
|
2317
2435
|
return built.map(b => b.request);
|
|
2318
2436
|
}, strict);
|
|
2319
2437
|
}
|
|
@@ -2323,9 +2441,9 @@ class WalletPermissionsManager {
|
|
|
2323
2441
|
const built = await this.mapWithConcurrency(chunk, 8, async (c) => await this.buildPermissionOutput(c.request, c.expiry, c.amount));
|
|
2324
2442
|
const inputBeef = new sdk_1.Beef();
|
|
2325
2443
|
for (const c of chunk) {
|
|
2326
|
-
inputBeef.mergeBeef(sdk_1.Beef.
|
|
2444
|
+
inputBeef.mergeBeef(sdk_1.Beef.fromBinaryStrict(c.oldToken.tx));
|
|
2327
2445
|
}
|
|
2328
|
-
|
|
2446
|
+
await this.completePermissionTokenAction({
|
|
2329
2447
|
description: `Renew ${chunk.length} permissions`,
|
|
2330
2448
|
inputBEEF: inputBeef.toBinary(),
|
|
2331
2449
|
inputs: chunk.map((c, i) => ({
|
|
@@ -2339,28 +2457,23 @@ class WalletPermissionsManager {
|
|
|
2339
2457
|
randomizeOutputs: false,
|
|
2340
2458
|
signAndProcess: false
|
|
2341
2459
|
}
|
|
2342
|
-
},
|
|
2343
|
-
if (!signableTransaction?.reference || !signableTransaction.tx) {
|
|
2344
|
-
throw new Error('Failed to create signable transaction');
|
|
2345
|
-
}
|
|
2346
|
-
const partialTx = sdk_1.Transaction.fromAtomicBEEF(signableTransaction.tx);
|
|
2347
|
-
const pushdrop = new sdk_1.PushDrop(this.underlying);
|
|
2348
|
-
const spends = {};
|
|
2349
|
-
for (let i = 0; i < chunk.length; i++) {
|
|
2350
|
-
const token = chunk[i].oldToken;
|
|
2351
|
-
const unlocker = pushdrop.unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(token.outputScript));
|
|
2352
|
-
const unlockingScript = await unlocker.sign(partialTx, i);
|
|
2353
|
-
spends[i] = { unlockingScript: unlockingScript.toHex() };
|
|
2354
|
-
}
|
|
2355
|
-
const { txid } = await this.underlying.signAction({
|
|
2356
|
-
reference: signableTransaction.reference,
|
|
2357
|
-
spends
|
|
2358
|
-
});
|
|
2359
|
-
if (!txid)
|
|
2360
|
-
throw new Error('Failed to finalize renewal transaction');
|
|
2460
|
+
}, chunk.map(item => item.oldToken));
|
|
2361
2461
|
return built.map(b => b.request);
|
|
2362
2462
|
}, strict);
|
|
2363
2463
|
}
|
|
2464
|
+
permissionTokenInputSigners(tokens) {
|
|
2465
|
+
const inputSigners = Object.create(null);
|
|
2466
|
+
const pushdrop = new sdk_1.PushDrop(this.underlying);
|
|
2467
|
+
for (const token of tokens) {
|
|
2468
|
+
const outpoint = `${token.txid}.${token.outputIndex}`;
|
|
2469
|
+
const unlocker = pushdrop.unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(token.outputScript));
|
|
2470
|
+
inputSigners[outpoint] = async (transaction, inputIndex) => await unlocker.sign(transaction, inputIndex);
|
|
2471
|
+
}
|
|
2472
|
+
return inputSigners;
|
|
2473
|
+
}
|
|
2474
|
+
async completePermissionTokenAction(args, tokens = []) {
|
|
2475
|
+
return await (0, sdk_1.completeBoundAction)(this, args, { inputSigners: this.permissionTokenInputSigners(tokens) }, this.adminOriginator);
|
|
2476
|
+
}
|
|
2364
2477
|
async coalescePermissionTokens(oldTokens, newScript, opts) {
|
|
2365
2478
|
if (!oldTokens?.length)
|
|
2366
2479
|
throw new Error('No permission tokens to coalesce');
|
|
@@ -2370,9 +2483,9 @@ class WalletPermissionsManager {
|
|
|
2370
2483
|
// Merge all input token BEEFs into a single BEEF structure
|
|
2371
2484
|
const inputBeef = new sdk_1.Beef();
|
|
2372
2485
|
for (const token of oldTokens) {
|
|
2373
|
-
inputBeef.mergeBeef(sdk_1.Beef.
|
|
2486
|
+
inputBeef.mergeBeef(sdk_1.Beef.fromBinaryStrict(token.tx));
|
|
2374
2487
|
}
|
|
2375
|
-
const
|
|
2488
|
+
const transaction = await this.completePermissionTokenAction({
|
|
2376
2489
|
description: opts?.description ?? `Coalesce ${oldTokens.length} permission tokens`,
|
|
2377
2490
|
inputBEEF: inputBeef.toBinary(),
|
|
2378
2491
|
inputs: oldTokens.map((t, i) => ({
|
|
@@ -2394,29 +2507,8 @@ class WalletPermissionsManager {
|
|
|
2394
2507
|
randomizeOutputs: false,
|
|
2395
2508
|
signAndProcess: false
|
|
2396
2509
|
}
|
|
2397
|
-
},
|
|
2398
|
-
|
|
2399
|
-
throw new Error('Failed to create signable transaction');
|
|
2400
|
-
}
|
|
2401
|
-
// 2) Sign each input - each token needs its own unlocker with the correct locking script
|
|
2402
|
-
const partialTx = sdk_1.Transaction.fromAtomicBEEF(signableTransaction.tx);
|
|
2403
|
-
const pushdrop = new sdk_1.PushDrop(this.underlying);
|
|
2404
|
-
const spends = {};
|
|
2405
|
-
for (let i = 0; i < oldTokens.length; i++) {
|
|
2406
|
-
const token = oldTokens[i];
|
|
2407
|
-
// Each token requires its own unlocker with the specific locking script
|
|
2408
|
-
const unlocker = pushdrop.unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(token.outputScript));
|
|
2409
|
-
const unlockingScript = await unlocker.sign(partialTx, i);
|
|
2410
|
-
spends[i] = { unlockingScript: unlockingScript.toHex() };
|
|
2411
|
-
}
|
|
2412
|
-
// 3) Finalize the action
|
|
2413
|
-
const { txid } = await this.underlying.signAction({
|
|
2414
|
-
reference: signableTransaction.reference,
|
|
2415
|
-
spends
|
|
2416
|
-
});
|
|
2417
|
-
if (!txid)
|
|
2418
|
-
throw new Error('Failed to finalize coalescing transaction');
|
|
2419
|
-
return txid;
|
|
2510
|
+
}, oldTokens);
|
|
2511
|
+
return transaction.id('hex');
|
|
2420
2512
|
}
|
|
2421
2513
|
/**
|
|
2422
2514
|
* Renews a permission token by spending the old token as input and creating a new token output.
|
|
@@ -2449,7 +2541,7 @@ class WalletPermissionsManager {
|
|
|
2449
2541
|
// 3) For BRC-100, we do a "createAction" with a partial input referencing oldToken
|
|
2450
2542
|
// plus a single new output. We'll hydrate the template, then signAction for the wallet to finalize.
|
|
2451
2543
|
const oldOutpoint = `${oldToken.txid}.${oldToken.outputIndex}`;
|
|
2452
|
-
|
|
2544
|
+
await this.completePermissionTokenAction({
|
|
2453
2545
|
description: `Renew ${r.type} permission`,
|
|
2454
2546
|
inputBEEF: oldToken.tx,
|
|
2455
2547
|
inputs: [
|
|
@@ -2471,18 +2563,7 @@ class WalletPermissionsManager {
|
|
|
2471
2563
|
options: {
|
|
2472
2564
|
acceptDelayedBroadcast: true
|
|
2473
2565
|
}
|
|
2474
|
-
},
|
|
2475
|
-
const tx = sdk_1.Transaction.fromBEEF(signableTransaction.tx);
|
|
2476
|
-
const unlocker = new sdk_1.PushDrop(this.underlying).unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(oldToken.outputScript));
|
|
2477
|
-
const unlockingScript = await unlocker.sign(tx, 0);
|
|
2478
|
-
await this.underlying.signAction({
|
|
2479
|
-
reference: signableTransaction.reference,
|
|
2480
|
-
spends: {
|
|
2481
|
-
0: {
|
|
2482
|
-
unlockingScript: unlockingScript.toHex()
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
});
|
|
2566
|
+
}, [oldToken]);
|
|
2486
2567
|
}
|
|
2487
2568
|
}
|
|
2488
2569
|
/**
|
|
@@ -2583,7 +2664,10 @@ class WalletPermissionsManager {
|
|
|
2583
2664
|
const result = await this.underlying.listOutputs({ basket: BASKET_MAP.protocol, tags, tagQueryMode: 'all', include: 'entire transactions', limit: 10000 }, this.adminOriginator);
|
|
2584
2665
|
await this.collectProtocolTokens(result, originFilter, seen, tokens);
|
|
2585
2666
|
}
|
|
2586
|
-
return tokens
|
|
2667
|
+
return tokens.filter(token => (privileged === undefined || token.privileged === privileged) &&
|
|
2668
|
+
(protocolName === undefined || token.protocol === protocolName) &&
|
|
2669
|
+
(protocolSecurityLevel === undefined || token.securityLevel === protocolSecurityLevel) &&
|
|
2670
|
+
(counterparty === undefined || token.counterparty === counterparty));
|
|
2587
2671
|
}
|
|
2588
2672
|
/** Builds the base tag array for protocol permission listing. */
|
|
2589
2673
|
buildProtocolFilterTags({ privileged, protocolName, protocolSecurityLevel, counterparty }) {
|
|
@@ -2603,12 +2687,11 @@ class WalletPermissionsManager {
|
|
|
2603
2687
|
for (const out of result.outputs) {
|
|
2604
2688
|
if (seen.has(out.outpoint))
|
|
2605
2689
|
continue;
|
|
2606
|
-
const
|
|
2607
|
-
|
|
2608
|
-
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2609
|
-
if (!dec?.fields || dec.fields.length < 6)
|
|
2690
|
+
const source = await this.authenticatedPermissionTokenSource(result, out, 6);
|
|
2691
|
+
if (source == null)
|
|
2610
2692
|
continue;
|
|
2611
|
-
const
|
|
2693
|
+
const { tx, txid, outputIndex } = source;
|
|
2694
|
+
const f = await this.decryptProtocolTokenFields(source.fields);
|
|
2612
2695
|
const normalizedDomain = this.normalizeOriginator(f.domainDecoded);
|
|
2613
2696
|
if (originFilter != null && normalizedDomain !== originFilter.normalized)
|
|
2614
2697
|
continue;
|
|
@@ -2677,25 +2760,24 @@ class WalletPermissionsManager {
|
|
|
2677
2760
|
}, this.adminOriginator);
|
|
2678
2761
|
await this.collectBasketTokens(result, originFilter, seen, tokens);
|
|
2679
2762
|
}
|
|
2680
|
-
return tokens;
|
|
2763
|
+
return params.basket == null ? tokens : tokens.filter(token => token.basketName === params.basket);
|
|
2681
2764
|
}
|
|
2682
2765
|
/** Decodes and appends basket permission tokens from a listOutputs result. */
|
|
2683
2766
|
async collectBasketTokens(result, originFilter, seen, tokens) {
|
|
2684
2767
|
for (const out of result.outputs) {
|
|
2685
2768
|
if (seen.has(out.outpoint))
|
|
2686
2769
|
continue;
|
|
2687
|
-
const
|
|
2688
|
-
|
|
2689
|
-
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2690
|
-
if (!dec?.fields || dec.fields.length < 3)
|
|
2770
|
+
const source = await this.authenticatedPermissionTokenSource(result, out, 3);
|
|
2771
|
+
if (source == null)
|
|
2691
2772
|
continue;
|
|
2692
|
-
const
|
|
2693
|
-
const
|
|
2773
|
+
const { tx, txid, outputIndex } = source;
|
|
2774
|
+
const [domainRaw, expiryRaw, basketRaw] = source.fields;
|
|
2775
|
+
const domainDecoded = await this.decryptPermissionTokenText(domainRaw);
|
|
2694
2776
|
const normalizedDomain = this.normalizeOriginator(domainDecoded);
|
|
2695
2777
|
if (originFilter != null && normalizedDomain !== originFilter.normalized)
|
|
2696
2778
|
continue;
|
|
2697
|
-
const expiryDecoded =
|
|
2698
|
-
const basketDecoded =
|
|
2779
|
+
const expiryDecoded = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(expiryRaw), 'Permission expiry');
|
|
2780
|
+
const basketDecoded = await this.decryptPermissionTokenText(basketRaw);
|
|
2699
2781
|
seen.add(out.outpoint);
|
|
2700
2782
|
tokens.push({
|
|
2701
2783
|
tx: tx.toBEEF(),
|
|
@@ -2745,27 +2827,28 @@ class WalletPermissionsManager {
|
|
|
2745
2827
|
}, this.adminOriginator);
|
|
2746
2828
|
const tokens = [];
|
|
2747
2829
|
for (const out of result.outputs) {
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
const dec = sdk_1.PushDrop.decode(tx.outputs[Number(outputIndexStr)].lockingScript);
|
|
2751
|
-
if (!dec?.fields || dec.fields.length < 2)
|
|
2830
|
+
const source = await this.authenticatedPermissionTokenSource(result, out, 2);
|
|
2831
|
+
if (source == null)
|
|
2752
2832
|
continue;
|
|
2753
|
-
const
|
|
2754
|
-
const
|
|
2755
|
-
const
|
|
2756
|
-
const authorizedAmount =
|
|
2833
|
+
const { tx, txid, outputIndex, fields } = source;
|
|
2834
|
+
const [domainRaw, amtRaw] = fields;
|
|
2835
|
+
const domainDecoded = await this.decryptPermissionTokenText(domainRaw);
|
|
2836
|
+
const authorizedAmount = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(amtRaw), 'Permission spending amount', MAX_MONEY_SATOSHIS);
|
|
2757
2837
|
tokens.push({
|
|
2758
2838
|
tx: tx.toBEEF(),
|
|
2759
|
-
txid
|
|
2760
|
-
outputIndex
|
|
2839
|
+
txid,
|
|
2840
|
+
outputIndex,
|
|
2761
2841
|
satoshis: out.satoshis,
|
|
2762
|
-
outputScript: tx.outputs[
|
|
2842
|
+
outputScript: tx.outputs[outputIndex].lockingScript.toHex(),
|
|
2763
2843
|
originator: domainDecoded,
|
|
2764
2844
|
authorizedAmount,
|
|
2765
2845
|
expiry: 0
|
|
2766
2846
|
});
|
|
2767
2847
|
}
|
|
2768
|
-
|
|
2848
|
+
if (params.originator == null)
|
|
2849
|
+
return tokens;
|
|
2850
|
+
const normalizedOriginator = this.prepareOriginator(params.originator).normalized;
|
|
2851
|
+
return tokens.filter(token => this.normalizeOriginator(token.originator) === normalizedOriginator);
|
|
2769
2852
|
}
|
|
2770
2853
|
/**
|
|
2771
2854
|
* Returns `true` if the originator already holds a valid spending authorization token
|
|
@@ -2809,28 +2892,29 @@ class WalletPermissionsManager {
|
|
|
2809
2892
|
const result = await this.underlying.listOutputs({ basket: BASKET_MAP.certificate, tags, tagQueryMode: 'all', include: 'entire transactions', limit: 10000 }, this.adminOriginator);
|
|
2810
2893
|
await this.collectCertificateTokens(result, originFilter, seen, tokens);
|
|
2811
2894
|
}
|
|
2812
|
-
return tokens
|
|
2895
|
+
return tokens.filter(token => (params.privileged === undefined || token.privileged === params.privileged) &&
|
|
2896
|
+
(params.certType === undefined || token.certType === params.certType) &&
|
|
2897
|
+
(params.verifier === undefined || token.verifier === params.verifier));
|
|
2813
2898
|
}
|
|
2814
2899
|
/** Decodes and appends certificate permission tokens from a listOutputs result. */
|
|
2815
2900
|
async collectCertificateTokens(result, originFilter, seen, tokens) {
|
|
2816
2901
|
for (const out of result.outputs) {
|
|
2817
2902
|
if (seen.has(out.outpoint))
|
|
2818
2903
|
continue;
|
|
2819
|
-
const
|
|
2820
|
-
|
|
2821
|
-
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2822
|
-
if (!dec?.fields || dec.fields.length < 6)
|
|
2904
|
+
const source = await this.authenticatedPermissionTokenSource(result, out, 6);
|
|
2905
|
+
if (source == null)
|
|
2823
2906
|
continue;
|
|
2824
|
-
const
|
|
2825
|
-
const
|
|
2907
|
+
const { tx, txid, outputIndex } = source;
|
|
2908
|
+
const [domainRaw, expiryRaw, privRaw, typeRaw, fieldsRaw, verifierRaw] = source.fields;
|
|
2909
|
+
const domainDecoded = await this.decryptPermissionTokenText(domainRaw);
|
|
2826
2910
|
const normalizedDomain = this.normalizeOriginator(domainDecoded);
|
|
2827
2911
|
if (originFilter != null && normalizedDomain !== originFilter.normalized)
|
|
2828
2912
|
continue;
|
|
2829
|
-
const expiryDecoded =
|
|
2830
|
-
const privDecoded =
|
|
2831
|
-
const typeDecoded =
|
|
2832
|
-
const verifierDec =
|
|
2833
|
-
const allFields =
|
|
2913
|
+
const expiryDecoded = parseCanonicalPermissionInteger(await this.decryptPermissionTokenText(expiryRaw), 'Permission expiry');
|
|
2914
|
+
const privDecoded = parsePermissionBoolean(await this.decryptPermissionTokenText(privRaw), 'Permission privileged flag');
|
|
2915
|
+
const typeDecoded = await this.decryptPermissionTokenText(typeRaw);
|
|
2916
|
+
const verifierDec = await this.decryptPermissionTokenText(verifierRaw);
|
|
2917
|
+
const allFields = parsePermissionCertificateFields(await this.decryptPermissionTokenText(fieldsRaw));
|
|
2834
2918
|
seen.add(out.outpoint);
|
|
2835
2919
|
tokens.push({
|
|
2836
2920
|
tx: tx.toBEEF(),
|
|
@@ -2913,9 +2997,9 @@ class WalletPermissionsManager {
|
|
|
2913
2997
|
return;
|
|
2914
2998
|
const inputBeef = new sdk_1.Beef();
|
|
2915
2999
|
for (const token of oldTokens) {
|
|
2916
|
-
inputBeef.mergeBeef(sdk_1.Beef.
|
|
3000
|
+
inputBeef.mergeBeef(sdk_1.Beef.fromBinaryStrict(token.tx));
|
|
2917
3001
|
}
|
|
2918
|
-
|
|
3002
|
+
await this.completePermissionTokenAction({
|
|
2919
3003
|
description: `Revoke ${oldTokens.length} permissions`,
|
|
2920
3004
|
inputBEEF: inputBeef.toBinary(),
|
|
2921
3005
|
inputs: oldTokens.map((t, i) => ({
|
|
@@ -2928,37 +3012,7 @@ class WalletPermissionsManager {
|
|
|
2928
3012
|
randomizeOutputs: false,
|
|
2929
3013
|
signAndProcess: false
|
|
2930
3014
|
}
|
|
2931
|
-
},
|
|
2932
|
-
if (!signableTransaction?.reference || !signableTransaction.tx) {
|
|
2933
|
-
throw new Error('Failed to create signable transaction');
|
|
2934
|
-
}
|
|
2935
|
-
const tx = sdk_1.Transaction.fromAtomicBEEF(signableTransaction.tx);
|
|
2936
|
-
const inputsToSign = oldTokens.map(token => {
|
|
2937
|
-
let permInputIndex = this.findInputIndexForToken(tx, token);
|
|
2938
|
-
if (permInputIndex === -1 && tx.inputs.length === 1) {
|
|
2939
|
-
permInputIndex = 0;
|
|
2940
|
-
}
|
|
2941
|
-
if (permInputIndex === -1) {
|
|
2942
|
-
throw new Error('Unable to locate permission token input for revocation.');
|
|
2943
|
-
}
|
|
2944
|
-
return { token, permInputIndex };
|
|
2945
|
-
});
|
|
2946
|
-
const pushdrop = new sdk_1.PushDrop(this.underlying);
|
|
2947
|
-
const spends = {};
|
|
2948
|
-
const signed = await this.mapWithConcurrency(inputsToSign, 8, async ({ token, permInputIndex }) => {
|
|
2949
|
-
const unlocker = pushdrop.unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(token.outputScript));
|
|
2950
|
-
const unlockingScript = await unlocker.sign(tx, permInputIndex);
|
|
2951
|
-
return { permInputIndex, unlockingScriptHex: unlockingScript.toHex() };
|
|
2952
|
-
});
|
|
2953
|
-
for (const s of signed) {
|
|
2954
|
-
spends[s.permInputIndex] = { unlockingScript: s.unlockingScriptHex };
|
|
2955
|
-
}
|
|
2956
|
-
const { txid } = await this.underlying.signAction({
|
|
2957
|
-
reference: signableTransaction.reference,
|
|
2958
|
-
spends
|
|
2959
|
-
});
|
|
2960
|
-
if (!txid)
|
|
2961
|
-
throw new Error('Failed to finalize revoke transaction');
|
|
3015
|
+
}, oldTokens);
|
|
2962
3016
|
}
|
|
2963
3017
|
/**
|
|
2964
3018
|
* Revokes a permission token by spending it with no replacement output.
|
|
@@ -2966,7 +3020,7 @@ class WalletPermissionsManager {
|
|
|
2966
3020
|
*/
|
|
2967
3021
|
async revokePermission(oldToken) {
|
|
2968
3022
|
const oldOutpoint = `${oldToken.txid}.${oldToken.outputIndex}`;
|
|
2969
|
-
|
|
3023
|
+
await this.completePermissionTokenAction({
|
|
2970
3024
|
description: 'Revoke permission',
|
|
2971
3025
|
inputBEEF: oldToken.tx,
|
|
2972
3026
|
inputs: [
|
|
@@ -2979,30 +3033,13 @@ class WalletPermissionsManager {
|
|
|
2979
3033
|
options: {
|
|
2980
3034
|
acceptDelayedBroadcast: true
|
|
2981
3035
|
}
|
|
2982
|
-
},
|
|
2983
|
-
const tx = sdk_1.Transaction.fromBEEF(signableTransaction.tx);
|
|
2984
|
-
let permInputIndex = this.findInputIndexForToken(tx, oldToken);
|
|
2985
|
-
if (permInputIndex === -1 && tx.inputs.length === 1) {
|
|
2986
|
-
permInputIndex = 0;
|
|
2987
|
-
}
|
|
2988
|
-
if (permInputIndex === -1) {
|
|
2989
|
-
throw new Error('Unable to locate permission token input for revocation.');
|
|
2990
|
-
}
|
|
2991
|
-
const unlocker = new sdk_1.PushDrop(this.underlying).unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self', 'all', false, 1, sdk_1.LockingScript.fromHex(oldToken.outputScript));
|
|
2992
|
-
const unlockingScript = await unlocker.sign(tx, permInputIndex);
|
|
2993
|
-
await this.underlying.signAction({
|
|
2994
|
-
reference: signableTransaction.reference,
|
|
2995
|
-
spends: {
|
|
2996
|
-
[permInputIndex]: {
|
|
2997
|
-
unlockingScript: unlockingScript.toHex()
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
});
|
|
3036
|
+
}, [oldToken]);
|
|
3001
3037
|
}
|
|
3002
3038
|
/* ---------------------------------------------------------------------
|
|
3003
3039
|
* 7) BRC-100 WALLET INTERFACE FORWARDING WITH PERMISSION CHECKS
|
|
3004
3040
|
* --------------------------------------------------------------------- */
|
|
3005
3041
|
async createAction(args, originator) {
|
|
3042
|
+
const vargs = (0, validationHelpers_1.validateCreateActionArgs)(args);
|
|
3006
3043
|
// 1) Identify unique P-modules involved (one per schemeID) from both baskets and labels
|
|
3007
3044
|
const pModulesByScheme = new Map();
|
|
3008
3045
|
const nonPBaskets = this.collectNonPBaskets(args.outputs, pModulesByScheme);
|
|
@@ -3039,10 +3076,16 @@ class WalletPermissionsManager {
|
|
|
3039
3076
|
let createResult = await this.callCreateActionWithPModules(finalArgs, pModulesByScheme, originator);
|
|
3040
3077
|
if (createResult.signableTransaction == null)
|
|
3041
3078
|
return createResult;
|
|
3042
|
-
// 7)
|
|
3043
|
-
|
|
3079
|
+
// 7) Bind the action reference before parsing any storage-provided transaction
|
|
3080
|
+
// data. This ensures malformed BEEF is still aborted and cannot leave an
|
|
3081
|
+
// untracked action that may later be signed under another originator.
|
|
3044
3082
|
const reference = createResult.signableTransaction.reference;
|
|
3045
|
-
|
|
3083
|
+
if (this.pendingActionOriginators.has(reference)) {
|
|
3084
|
+
throw new WERR_errors_1.WERR_UNAUTHORIZED('The action reference is already pending.');
|
|
3085
|
+
}
|
|
3086
|
+
this.pendingActionOriginators.set(reference, originator ?? '');
|
|
3087
|
+
// 7a) Parse the signable tx to determine net spend, then gate on spending
|
|
3088
|
+
// authorization. SECURITY (GHSA-36f9-7rg5-cpf8) defense-in-depth: confirm every
|
|
3046
3089
|
// caller-requested output actually appears in the transaction we are about to
|
|
3047
3090
|
// authorize and sign. The locking scripts in the signable transaction
|
|
3048
3091
|
// originate from storage; a malicious or compromised remote storage provider
|
|
@@ -3051,16 +3094,25 @@ class WalletPermissionsManager {
|
|
|
3051
3094
|
// recipient. The signer (buildSignableTransaction) rejects this at the
|
|
3052
3095
|
// source; this is an independent check at the permissions layer.
|
|
3053
3096
|
try {
|
|
3097
|
+
const tx = sdk_1.Transaction.fromAtomicBEEF(createResult.signableTransaction.tx);
|
|
3054
3098
|
this.verifyRequestedOutputsPresent(tx, args);
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3099
|
+
let { netSpent, lineItems } = this.computeNetSpend(tx, args, originalInputDescriptions, originalOutputDescriptions);
|
|
3100
|
+
const exactWalletSpend = createResult[exactActionSpend_1.exactActionSpendSymbol];
|
|
3101
|
+
if (exactWalletSpend !== undefined) {
|
|
3102
|
+
if (!Number.isSafeInteger(exactWalletSpend) ||
|
|
3103
|
+
exactWalletSpend < -MAX_MONEY_SATOSHIS ||
|
|
3104
|
+
exactWalletSpend > MAX_MONEY_SATOSHIS ||
|
|
3105
|
+
exactWalletSpend < netSpent) {
|
|
3106
|
+
throw new Error('Wallet signer returned an invalid exact action-spend amount.');
|
|
3107
|
+
}
|
|
3108
|
+
const serviceCharge = exactWalletSpend - netSpent;
|
|
3109
|
+
if (serviceCharge > 0) {
|
|
3110
|
+
lineItems = [...lineItems, { type: 'output', satoshis: serviceCharge, description: 'Storage service charge' }];
|
|
3111
|
+
}
|
|
3112
|
+
netSpent = exactWalletSpend;
|
|
3113
|
+
}
|
|
3114
|
+
// 8) If netSpent > 0, require spending authorization. Abort if denied.
|
|
3115
|
+
if (netSpent > 0) {
|
|
3064
3116
|
await this.ensureSpendingAuthorization({
|
|
3065
3117
|
originator: originator,
|
|
3066
3118
|
satoshis: netSpent,
|
|
@@ -3069,17 +3121,29 @@ class WalletPermissionsManager {
|
|
|
3069
3121
|
allowRecentGrant: (0, brc177NoSendExpiry_1.parseBrc177NoSendExpiryLabels)(args.labels) == null
|
|
3070
3122
|
});
|
|
3071
3123
|
}
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3124
|
+
this.pendingActionTemplates.set(reference, tx);
|
|
3125
|
+
}
|
|
3126
|
+
catch (err) {
|
|
3127
|
+
await this.blockAndAbortAction(reference);
|
|
3128
|
+
throw err;
|
|
3076
3129
|
}
|
|
3077
3130
|
// 9) Finalize or return the signable transaction based on whether more signatures are needed.
|
|
3078
|
-
const vargs = sdk_1.Validation.validateCreateActionArgs(args);
|
|
3079
3131
|
if (vargs.isSignAction)
|
|
3080
3132
|
return createResult;
|
|
3081
|
-
|
|
3082
|
-
|
|
3133
|
+
try {
|
|
3134
|
+
const signResult = await this.underlying.signAction({
|
|
3135
|
+
reference,
|
|
3136
|
+
spends: {},
|
|
3137
|
+
options: { ...args.options, returnTXIDOnly: false }
|
|
3138
|
+
}, originator);
|
|
3139
|
+
this.assertAuthorizedSignResult(reference, {}, signResult);
|
|
3140
|
+
this.clearPendingAction(reference);
|
|
3141
|
+
return { ...createResult, ...signResult, signableTransaction: undefined };
|
|
3142
|
+
}
|
|
3143
|
+
catch (error) {
|
|
3144
|
+
await this.blockAndAbortAction(reference);
|
|
3145
|
+
throw error;
|
|
3146
|
+
}
|
|
3083
3147
|
}
|
|
3084
3148
|
/** Scans outputs to split P-scheme baskets from regular baskets; registers P-modules as a side effect. */
|
|
3085
3149
|
collectNonPBaskets(outputs, pModulesByScheme) {
|
|
@@ -3152,9 +3216,14 @@ class WalletPermissionsManager {
|
|
|
3152
3216
|
transformedArgs = transformed.args;
|
|
3153
3217
|
}
|
|
3154
3218
|
let createResult = await this.underlying.createAction(transformedArgs, originator);
|
|
3219
|
+
const exactWalletSpend = createResult[exactActionSpend_1.exactActionSpendSymbol];
|
|
3155
3220
|
for (let i = pModules.length - 1; i >= 0; i--) {
|
|
3156
3221
|
createResult = await pModules[i].onResponse(createResult, { method: 'createAction', originator: originator });
|
|
3157
3222
|
}
|
|
3223
|
+
if (exactWalletSpend !== undefined) {
|
|
3224
|
+
;
|
|
3225
|
+
createResult[exactActionSpend_1.exactActionSpendSymbol] = exactWalletSpend;
|
|
3226
|
+
}
|
|
3158
3227
|
return createResult;
|
|
3159
3228
|
}
|
|
3160
3229
|
/**
|
|
@@ -3207,11 +3276,17 @@ class WalletPermissionsManager {
|
|
|
3207
3276
|
// Sum originator-provided inputs:
|
|
3208
3277
|
let totalInputSatoshis = 0;
|
|
3209
3278
|
for (const input of tx.inputs) {
|
|
3210
|
-
const outpoint =
|
|
3279
|
+
const outpoint = this.inputOutpointForBinding(input);
|
|
3211
3280
|
const matchingIndex = (args.inputs || []).findIndex(i => i.outpoint === outpoint);
|
|
3212
3281
|
if (matchingIndex !== -1) {
|
|
3213
|
-
|
|
3214
|
-
|
|
3282
|
+
if (input.sourceTransaction == null) {
|
|
3283
|
+
throw new Error('Caller-provided action input is missing its authenticated source transaction.');
|
|
3284
|
+
}
|
|
3285
|
+
const sourceOutput = input.sourceTransaction.outputs[input.sourceOutputIndex];
|
|
3286
|
+
if (sourceOutput == null)
|
|
3287
|
+
throw new Error('Caller-provided action input source output is missing.');
|
|
3288
|
+
const satoshis = (0, validationHelpers_1.validateSatoshis)(sourceOutput.satoshis, 'caller input satoshis');
|
|
3289
|
+
totalInputSatoshis = this.checkedSatoshiTotal(totalInputSatoshis, satoshis, 'caller input total');
|
|
3215
3290
|
lineItems.push({
|
|
3216
3291
|
type: 'input',
|
|
3217
3292
|
description: originalInputDescriptions[matchingIndex] || 'No input description provided',
|
|
@@ -3220,30 +3295,151 @@ class WalletPermissionsManager {
|
|
|
3220
3295
|
}
|
|
3221
3296
|
}
|
|
3222
3297
|
// Sum originator-requested outputs:
|
|
3223
|
-
|
|
3298
|
+
let totalOutputSatoshis = 0;
|
|
3224
3299
|
for (const outIndex in args.outputs || []) {
|
|
3225
3300
|
const out = args.outputs[outIndex];
|
|
3301
|
+
const satoshis = (0, validationHelpers_1.validateSatoshis)(out.satoshis, 'requested output satoshis');
|
|
3302
|
+
totalOutputSatoshis = this.checkedSatoshiTotal(totalOutputSatoshis, satoshis, 'requested output total');
|
|
3226
3303
|
lineItems.push({
|
|
3227
3304
|
type: 'output',
|
|
3228
|
-
satoshis
|
|
3305
|
+
satoshis,
|
|
3229
3306
|
description: originalOutputDescriptions[outIndex] || 'No output description provided'
|
|
3230
3307
|
});
|
|
3231
3308
|
}
|
|
3232
3309
|
// Add an entry for the transaction fee:
|
|
3233
|
-
const fee = tx.getFee();
|
|
3310
|
+
const fee = (0, validationHelpers_1.validateSatoshis)(tx.getFee(), 'network fee');
|
|
3234
3311
|
lineItems.push({ type: 'fee', satoshis: fee, description: 'Network fee' });
|
|
3235
3312
|
/**
|
|
3236
3313
|
* Net spend = total foreign outflows minus total foreign inflows plus fee.
|
|
3237
3314
|
* Domestic wallet inputs/change outputs are not counted — they are internal.
|
|
3238
3315
|
*/
|
|
3239
|
-
const
|
|
3316
|
+
const grossSpent = this.checkedSatoshiTotal(totalOutputSatoshis, fee, 'gross action spend');
|
|
3317
|
+
const netSpent = grossSpent - totalInputSatoshis;
|
|
3318
|
+
if (!Number.isSafeInteger(netSpent) || netSpent < -MAX_MONEY_SATOSHIS || netSpent > MAX_MONEY_SATOSHIS) {
|
|
3319
|
+
throw new Error('Net action spend is outside the supported monetary range.');
|
|
3320
|
+
}
|
|
3240
3321
|
return { netSpent, lineItems };
|
|
3241
3322
|
}
|
|
3323
|
+
checkedSatoshiTotal(left, right, label) {
|
|
3324
|
+
const total = left + right;
|
|
3325
|
+
if (!Number.isSafeInteger(total) || total < 0 || total > MAX_MONEY_SATOSHIS) {
|
|
3326
|
+
throw new Error(`${label} is outside the supported monetary range.`);
|
|
3327
|
+
}
|
|
3328
|
+
return total;
|
|
3329
|
+
}
|
|
3330
|
+
inputOutpointForBinding(input) {
|
|
3331
|
+
const embeddedTxid = input.sourceTransaction?.id('hex');
|
|
3332
|
+
const explicitTxid = input.sourceTXID?.toLowerCase();
|
|
3333
|
+
if (explicitTxid != null && embeddedTxid != null && explicitTxid !== embeddedTxid) {
|
|
3334
|
+
throw new Error('Wallet action input source transaction is inconsistent.');
|
|
3335
|
+
}
|
|
3336
|
+
const txid = explicitTxid ?? embeddedTxid;
|
|
3337
|
+
if (txid == null || !/^[0-9a-f]{64}$/.test(txid)) {
|
|
3338
|
+
throw new Error('Wallet action input transaction ID is invalid.');
|
|
3339
|
+
}
|
|
3340
|
+
if (!Number.isSafeInteger(input.sourceOutputIndex) ||
|
|
3341
|
+
input.sourceOutputIndex < 0 ||
|
|
3342
|
+
input.sourceOutputIndex > 0xffffffff) {
|
|
3343
|
+
throw new Error('Wallet action input output index is invalid.');
|
|
3344
|
+
}
|
|
3345
|
+
return `${txid}.${input.sourceOutputIndex}`;
|
|
3346
|
+
}
|
|
3347
|
+
/** Binds a wallet's final result to the exact template that passed authorization. */
|
|
3348
|
+
assertAuthorizedSignResult(reference, spends, result) {
|
|
3349
|
+
const authorized = this.pendingActionTemplates.get(reference);
|
|
3350
|
+
if (authorized == null)
|
|
3351
|
+
throw new Error('The authorized action template is unavailable.');
|
|
3352
|
+
if (result.tx == null)
|
|
3353
|
+
throw new Error('Wallet finalization omitted transaction data required for binding.');
|
|
3354
|
+
const finalized = sdk_1.Transaction.fromAtomicBEEF(result.tx);
|
|
3355
|
+
if (finalized.version !== authorized.version ||
|
|
3356
|
+
finalized.lockTime !== authorized.lockTime ||
|
|
3357
|
+
finalized.inputs.length !== authorized.inputs.length ||
|
|
3358
|
+
finalized.outputs.length !== authorized.outputs.length) {
|
|
3359
|
+
throw new Error('Wallet finalization substituted the authorized transaction template.');
|
|
3360
|
+
}
|
|
3361
|
+
for (let index = 0; index < authorized.inputs.length; index++) {
|
|
3362
|
+
if (this.inputOutpointForBinding(finalized.inputs[index]) !==
|
|
3363
|
+
this.inputOutpointForBinding(authorized.inputs[index]) ||
|
|
3364
|
+
(finalized.inputs[index].sequence ?? 0xffffffff) !== (authorized.inputs[index].sequence ?? 0xffffffff)) {
|
|
3365
|
+
throw new Error('Wallet finalization substituted an authorized transaction input.');
|
|
3366
|
+
}
|
|
3367
|
+
const authorizedScript = authorized.inputs[index].unlockingScript?.toHex() ?? '';
|
|
3368
|
+
if (authorizedScript !== '' && finalized.inputs[index].unlockingScript?.toHex() !== authorizedScript) {
|
|
3369
|
+
throw new Error('Wallet finalization substituted an existing unlocking script.');
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
for (let index = 0; index < authorized.outputs.length; index++) {
|
|
3373
|
+
if (finalized.outputs[index].satoshis !== authorized.outputs[index].satoshis ||
|
|
3374
|
+
finalized.outputs[index].lockingScript.toHex() !== authorized.outputs[index].lockingScript.toHex()) {
|
|
3375
|
+
throw new Error('Wallet finalization substituted an authorized transaction output.');
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
for (const [indexText, spend] of Object.entries(spends ?? {})) {
|
|
3379
|
+
if (!/^(0|[1-9]\d*)$/.test(indexText))
|
|
3380
|
+
throw new Error('Signed input index is invalid.');
|
|
3381
|
+
const index = Number(indexText);
|
|
3382
|
+
if (!Number.isSafeInteger(index) || finalized.inputs[index] == null) {
|
|
3383
|
+
throw new Error('Signed input index is invalid.');
|
|
3384
|
+
}
|
|
3385
|
+
if (typeof spend?.unlockingScript !== 'string' ||
|
|
3386
|
+
!/^(?:[0-9a-f]{2})*$/i.test(spend.unlockingScript) ||
|
|
3387
|
+
finalized.inputs[index].unlockingScript?.toHex().toLowerCase() !== spend.unlockingScript.toLowerCase()) {
|
|
3388
|
+
throw new Error('Wallet finalization substituted an authorized unlocking script.');
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
const finalizedTxid = finalized.id('hex');
|
|
3392
|
+
if (result.txid != null && result.txid.toLowerCase() !== finalizedTxid) {
|
|
3393
|
+
throw new Error('Wallet finalization transaction ID does not match its transaction data.');
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
async blockAndAbortAction(reference) {
|
|
3397
|
+
this.blockedActionReferences.add(reference);
|
|
3398
|
+
const result = await this.underlying.abortAction({ reference });
|
|
3399
|
+
if (result.aborted === true)
|
|
3400
|
+
this.clearPendingAction(reference);
|
|
3401
|
+
}
|
|
3402
|
+
assertPendingActionOriginator(reference, originator, allowBlocked) {
|
|
3403
|
+
if (!allowBlocked && this.blockedActionReferences.has(reference)) {
|
|
3404
|
+
throw new WERR_errors_1.WERR_UNAUTHORIZED('This action was blocked after a failed authorization check.');
|
|
3405
|
+
}
|
|
3406
|
+
const expected = this.pendingActionOriginators.get(reference);
|
|
3407
|
+
if (expected == null) {
|
|
3408
|
+
throw new WERR_errors_1.WERR_UNAUTHORIZED('The action reference was not issued by this permissions manager.');
|
|
3409
|
+
}
|
|
3410
|
+
if (expected !== (originator ?? '')) {
|
|
3411
|
+
throw new WERR_errors_1.WERR_UNAUTHORIZED('The action reference belongs to a different originator.');
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
clearPendingAction(reference) {
|
|
3415
|
+
this.pendingActionOriginators.delete(reference);
|
|
3416
|
+
this.pendingActionTemplates.delete(reference);
|
|
3417
|
+
this.blockedActionReferences.delete(reference);
|
|
3418
|
+
}
|
|
3242
3419
|
async signAction(...args) {
|
|
3243
|
-
|
|
3420
|
+
const [requestArgs, originator] = args;
|
|
3421
|
+
this.assertPendingActionOriginator(requestArgs.reference, originator, false);
|
|
3422
|
+
try {
|
|
3423
|
+
const result = await this.underlying.signAction({
|
|
3424
|
+
...requestArgs,
|
|
3425
|
+
options: { ...requestArgs.options, returnTXIDOnly: false }
|
|
3426
|
+
}, originator);
|
|
3427
|
+
this.assertAuthorizedSignResult(requestArgs.reference, requestArgs.spends, result);
|
|
3428
|
+
this.clearPendingAction(requestArgs.reference);
|
|
3429
|
+
return result;
|
|
3430
|
+
}
|
|
3431
|
+
catch (error) {
|
|
3432
|
+
await this.blockAndAbortAction(requestArgs.reference);
|
|
3433
|
+
throw error;
|
|
3434
|
+
}
|
|
3244
3435
|
}
|
|
3245
3436
|
async abortAction(...args) {
|
|
3246
|
-
|
|
3437
|
+
const [requestArgs, originator] = args;
|
|
3438
|
+
this.assertPendingActionOriginator(requestArgs.reference, originator, true);
|
|
3439
|
+
const result = await this.underlying.abortAction(...args);
|
|
3440
|
+
if (result.aborted === true)
|
|
3441
|
+
this.clearPendingAction(requestArgs.reference);
|
|
3442
|
+
return result;
|
|
3247
3443
|
}
|
|
3248
3444
|
async listActions(...args) {
|
|
3249
3445
|
const [requestArgs, originator] = args;
|
|
@@ -3658,6 +3854,8 @@ class WalletPermissionsManager {
|
|
|
3658
3854
|
usageType: 'generic'
|
|
3659
3855
|
});
|
|
3660
3856
|
}
|
|
3857
|
+
// The underlying wallet may satisfy this with a caller-installed local trust anchor or the
|
|
3858
|
+
// certificate overlay. This permission gate authorizes resolution, not external certification.
|
|
3661
3859
|
return await this.underlying.discoverByIdentityKey(...args);
|
|
3662
3860
|
}
|
|
3663
3861
|
async discoverByAttributes(...args) {
|
|
@@ -3672,6 +3870,8 @@ class WalletPermissionsManager {
|
|
|
3672
3870
|
usageType: 'generic'
|
|
3673
3871
|
});
|
|
3674
3872
|
}
|
|
3873
|
+
// The underlying wallet may satisfy this with a caller-installed local trust anchor or the
|
|
3874
|
+
// certificate overlay. This permission gate authorizes resolution, not external certification.
|
|
3675
3875
|
return await this.underlying.discoverByAttributes(...args);
|
|
3676
3876
|
}
|
|
3677
3877
|
async isAuthenticated(...args) {
|
|
@@ -3858,7 +4058,11 @@ class WalletPermissionsManager {
|
|
|
3858
4058
|
}
|
|
3859
4059
|
return true;
|
|
3860
4060
|
}
|
|
3861
|
-
/**
|
|
4061
|
+
/**
|
|
4062
|
+
* Normalizes originator domains to their lowercase hostname. BRC-100
|
|
4063
|
+
* permission authority is hostname-scoped, so every port shares the same
|
|
4064
|
+
* grants and admin status.
|
|
4065
|
+
*/
|
|
3862
4066
|
normalizeOriginator(originator) {
|
|
3863
4067
|
if (!originator)
|
|
3864
4068
|
return '';
|
|
@@ -3876,12 +4080,7 @@ class WalletPermissionsManager {
|
|
|
3876
4080
|
const hostname = url.hostname.toLowerCase();
|
|
3877
4081
|
const needsBrackets = hostname.includes(':');
|
|
3878
4082
|
const baseHost = needsBrackets ? `[${hostname}]` : hostname;
|
|
3879
|
-
|
|
3880
|
-
const defaultPort = WalletPermissionsManager.DEFAULT_PORTS[url.protocol];
|
|
3881
|
-
if (port && defaultPort && port === defaultPort) {
|
|
3882
|
-
return baseHost;
|
|
3883
|
-
}
|
|
3884
|
-
return port ? `${baseHost}:${port}` : baseHost;
|
|
4083
|
+
return baseHost;
|
|
3885
4084
|
}
|
|
3886
4085
|
catch {
|
|
3887
4086
|
// Fall back to a conservative lowercase trim if URL parsing fails.
|
|
@@ -3912,8 +4111,37 @@ class WalletPermissionsManager {
|
|
|
3912
4111
|
if (!trimmed) {
|
|
3913
4112
|
throw new Error('Originator is required for permission checks.');
|
|
3914
4113
|
}
|
|
4114
|
+
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(trimmed)) {
|
|
4115
|
+
throw new Error('Originator must be a domain name with an optional port, without a URL scheme.');
|
|
4116
|
+
}
|
|
4117
|
+
let parsed;
|
|
4118
|
+
try {
|
|
4119
|
+
parsed = new URL(`https://${trimmed}`);
|
|
4120
|
+
}
|
|
4121
|
+
catch {
|
|
4122
|
+
throw new Error('Originator must be a valid domain name with an optional port.');
|
|
4123
|
+
}
|
|
4124
|
+
if (parsed.username !== '' ||
|
|
4125
|
+
parsed.password !== '' ||
|
|
4126
|
+
parsed.pathname !== '/' ||
|
|
4127
|
+
parsed.search !== '' ||
|
|
4128
|
+
parsed.hash !== '') {
|
|
4129
|
+
throw new Error('Originator must not contain credentials, a path, query parameters, or a fragment.');
|
|
4130
|
+
}
|
|
4131
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
4132
|
+
if (hostname.includes(':') || /^\d+(?:\.\d+){3}$/u.test(hostname)) {
|
|
4133
|
+
throw new Error('IP address originators are not permitted.');
|
|
4134
|
+
}
|
|
4135
|
+
if (hostname !== 'localhost' &&
|
|
4136
|
+
!hostname.split('.').every(label => /^[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?$/u.test(label))) {
|
|
4137
|
+
throw new Error('Originator must be a valid DNS hostname.');
|
|
4138
|
+
}
|
|
3915
4139
|
const normalized = this.normalizeOriginator(trimmed) || trimmed.toLowerCase();
|
|
3916
|
-
|
|
4140
|
+
// Search both current canonical tags and exact legacy tags first. The
|
|
4141
|
+
// untagged bounded fallback lets a grant minted for another port on this
|
|
4142
|
+
// hostname remain usable; decoded token fields are still authenticated and
|
|
4143
|
+
// compared to `normalized` before acceptance.
|
|
4144
|
+
const lookupValues = Array.from(new Set([trimmed, normalized, undefined]));
|
|
3917
4145
|
return { normalized, lookupValues };
|
|
3918
4146
|
}
|
|
3919
4147
|
/**
|