@bopen-io/wallet-toolbox 1.7.18
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/.claude/settings.local.json +10 -0
- package/.env.template +22 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/discussion.md +24 -0
- package/.github/pull_request_template.md +22 -0
- package/.github/workflows/push.yaml +145 -0
- package/.prettierrc +10 -0
- package/CHANGELOG.md +280 -0
- package/CONTRIBUTING.md +89 -0
- package/README.md +43 -0
- package/docs/README.md +85 -0
- package/docs/client.md +19627 -0
- package/docs/monitor.md +953 -0
- package/docs/open-rpc/index.html +46 -0
- package/docs/services.md +6377 -0
- package/docs/setup.md +1268 -0
- package/docs/storage.md +5367 -0
- package/docs/wallet.md +19626 -0
- package/jest.config.ts +25 -0
- package/license.md +28 -0
- package/out/tsconfig.all.tsbuildinfo +1 -0
- package/package.json +63 -0
- package/src/CWIStyleWalletManager.ts +1999 -0
- package/src/Setup.ts +579 -0
- package/src/SetupClient.ts +322 -0
- package/src/SetupWallet.ts +108 -0
- package/src/SimpleWalletManager.ts +526 -0
- package/src/Wallet.ts +1169 -0
- package/src/WalletAuthenticationManager.ts +153 -0
- package/src/WalletLogger.ts +213 -0
- package/src/WalletPermissionsManager.ts +3660 -0
- package/src/WalletSettingsManager.ts +114 -0
- package/src/__tests/CWIStyleWalletManager.test.d.ts.map +1 -0
- package/src/__tests/CWIStyleWalletManager.test.js.map +1 -0
- package/src/__tests/CWIStyleWalletManager.test.ts +675 -0
- package/src/__tests/WalletPermissionsManager.callbacks.test.ts +323 -0
- package/src/__tests/WalletPermissionsManager.checks.test.ts +844 -0
- package/src/__tests/WalletPermissionsManager.encryption.test.ts +412 -0
- package/src/__tests/WalletPermissionsManager.fixtures.ts +307 -0
- package/src/__tests/WalletPermissionsManager.flows.test.ts +462 -0
- package/src/__tests/WalletPermissionsManager.initialization.test.ts +300 -0
- package/src/__tests/WalletPermissionsManager.pmodules.test.ts +798 -0
- package/src/__tests/WalletPermissionsManager.proxying.test.ts +724 -0
- package/src/__tests/WalletPermissionsManager.tokens.test.ts +503 -0
- package/src/index.all.ts +27 -0
- package/src/index.client.ts +25 -0
- package/src/index.mobile.ts +21 -0
- package/src/index.ts +1 -0
- package/src/monitor/Monitor.ts +412 -0
- package/src/monitor/MonitorDaemon.ts +188 -0
- package/src/monitor/README.md +3 -0
- package/src/monitor/__test/MonitorDaemon.man.test.ts +45 -0
- package/src/monitor/tasks/TaskCheckForProofs.ts +243 -0
- package/src/monitor/tasks/TaskCheckNoSends.ts +73 -0
- package/src/monitor/tasks/TaskClock.ts +33 -0
- package/src/monitor/tasks/TaskFailAbandoned.ts +54 -0
- package/src/monitor/tasks/TaskMonitorCallHistory.ts +26 -0
- package/src/monitor/tasks/TaskNewHeader.ts +93 -0
- package/src/monitor/tasks/TaskPurge.ts +68 -0
- package/src/monitor/tasks/TaskReorg.ts +89 -0
- package/src/monitor/tasks/TaskReviewStatus.ts +48 -0
- package/src/monitor/tasks/TaskSendWaiting.ts +122 -0
- package/src/monitor/tasks/TaskSyncWhenIdle.ts +26 -0
- package/src/monitor/tasks/TaskUnFail.ts +151 -0
- package/src/monitor/tasks/WalletMonitorTask.ts +47 -0
- package/src/sdk/CertOpsWallet.ts +18 -0
- package/src/sdk/PrivilegedKeyManager.ts +372 -0
- package/src/sdk/README.md +13 -0
- package/src/sdk/WERR_errors.ts +234 -0
- package/src/sdk/WalletError.ts +170 -0
- package/src/sdk/WalletErrorFromJson.ts +80 -0
- package/src/sdk/WalletServices.interfaces.ts +700 -0
- package/src/sdk/WalletSigner.interfaces.ts +11 -0
- package/src/sdk/WalletStorage.interfaces.ts +606 -0
- package/src/sdk/__test/CertificateLifeCycle.test.ts +131 -0
- package/src/sdk/__test/PrivilegedKeyManager.test.ts +738 -0
- package/src/sdk/__test/WalletError.test.ts +318 -0
- package/src/sdk/__test/validationHelpers.test.ts +21 -0
- package/src/sdk/index.ts +10 -0
- package/src/sdk/types.ts +226 -0
- package/src/services/README.md +11 -0
- package/src/services/ServiceCollection.ts +248 -0
- package/src/services/Services.ts +603 -0
- package/src/services/__tests/ARC.man.test.ts +123 -0
- package/src/services/__tests/ARC.timeout.man.test.ts +79 -0
- package/src/services/__tests/ArcGorillaPool.man.test.ts +108 -0
- package/src/services/__tests/arcServices.test.ts +8 -0
- package/src/services/__tests/bitrails.test.ts +56 -0
- package/src/services/__tests/getMerklePath.test.ts +15 -0
- package/src/services/__tests/getRawTx.test.ts +13 -0
- package/src/services/__tests/postBeef.test.ts +104 -0
- package/src/services/__tests/verifyBeef.test.ts +50 -0
- package/src/services/chaintracker/BHServiceClient.ts +212 -0
- package/src/services/chaintracker/ChaintracksChainTracker.ts +71 -0
- package/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts +33 -0
- package/src/services/chaintracker/__tests/ChaintracksServiceClient.test.ts +29 -0
- package/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.ts +72 -0
- package/src/services/chaintracker/chaintracks/Api/BulkIngestorApi.ts +83 -0
- package/src/services/chaintracker/chaintracks/Api/BulkStorageApi.ts +92 -0
- package/src/services/chaintracker/chaintracks/Api/ChaintracksApi.ts +64 -0
- package/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.ts +189 -0
- package/src/services/chaintracker/chaintracks/Api/ChaintracksFetchApi.ts +18 -0
- package/src/services/chaintracker/chaintracks/Api/ChaintracksFsApi.ts +58 -0
- package/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.ts +386 -0
- package/src/services/chaintracker/chaintracks/Api/LiveIngestorApi.ts +25 -0
- package/src/services/chaintracker/chaintracks/Chaintracks.ts +609 -0
- package/src/services/chaintracker/chaintracks/ChaintracksService.ts +199 -0
- package/src/services/chaintracker/chaintracks/ChaintracksServiceClient.ts +154 -0
- package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.ts +176 -0
- package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDN.ts +174 -0
- package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts +18 -0
- package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.ts +113 -0
- package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.ts +81 -0
- package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.ts +86 -0
- package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorTeranodeP2P.ts +59 -0
- package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.ts +104 -0
- package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.ts +66 -0
- package/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.ts +566 -0
- package/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.ts +219 -0
- package/src/services/chaintracker/chaintracks/Ingest/__tests/BulkIngestorCDNBabbage.test.ts +54 -0
- package/src/services/chaintracker/chaintracks/Ingest/__tests/LiveIngestorWhatsOnChainPoll.test.ts +33 -0
- package/src/services/chaintracker/chaintracks/Ingest/__tests/WhatsOnChainServices.test.ts +124 -0
- package/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.ts +92 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.ts +104 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.ts +382 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.ts +574 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.ts +438 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageMemory.ts +29 -0
- package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.ts +304 -0
- package/src/services/chaintracker/chaintracks/Storage/__tests/ChaintracksStorageIdb.test.ts +102 -0
- package/src/services/chaintracker/chaintracks/Storage/__tests/ChaintracksStorageKnex.test.ts +45 -0
- package/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.ts +77 -0
- package/src/services/chaintracker/chaintracks/__tests/ChaintracksClientApi.test.ts +192 -0
- package/src/services/chaintracker/chaintracks/__tests/LocalCdnServer.ts +75 -0
- package/src/services/chaintracker/chaintracks/__tests/createIdbChaintracks.test.ts +62 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNetBlockHeaders.json +1 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_0.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_1.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_2.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_3.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNetBlockHeaders.json +1 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_0.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_1.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_2.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_3.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNetBlockHeaders.json +1 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_0.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_1.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_2.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_3.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNetBlockHeaders.json +1 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_0.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_1.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_2.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_3.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_4.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNetBlockHeaders.json +1 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_0.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_1.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_2.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_3.headers +0 -0
- package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_4.headers +0 -0
- package/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts +92 -0
- package/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts +111 -0
- package/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts +91 -0
- package/src/services/chaintracker/chaintracks/createIdbChaintracks.ts +60 -0
- package/src/services/chaintracker/chaintracks/createKnexChaintracks.ts +65 -0
- package/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts +60 -0
- package/src/services/chaintracker/chaintracks/index.all.ts +12 -0
- package/src/services/chaintracker/chaintracks/index.client.ts +4 -0
- package/src/services/chaintracker/chaintracks/index.mobile.ts +37 -0
- package/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts +975 -0
- package/src/services/chaintracker/chaintracks/util/BulkFileDataReader.ts +60 -0
- package/src/services/chaintracker/chaintracks/util/BulkFilesReader.ts +336 -0
- package/src/services/chaintracker/chaintracks/util/BulkHeaderFile.ts +247 -0
- package/src/services/chaintracker/chaintracks/util/ChaintracksFetch.ts +69 -0
- package/src/services/chaintracker/chaintracks/util/ChaintracksFs.ts +141 -0
- package/src/services/chaintracker/chaintracks/util/HeightRange.ts +153 -0
- package/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.ts +76 -0
- package/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts +304 -0
- package/src/services/chaintracker/chaintracks/util/__tests/ChaintracksFetch.test.ts +60 -0
- package/src/services/chaintracker/chaintracks/util/__tests/HeightRange.test.ts +67 -0
- package/src/services/chaintracker/chaintracks/util/__tests/SingleWriterMultiReaderLock.test.ts +49 -0
- package/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.ts +573 -0
- package/src/services/chaintracker/chaintracks/util/dirtyHashes.ts +29 -0
- package/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts +432 -0
- package/src/services/chaintracker/index.all.ts +4 -0
- package/src/services/chaintracker/index.client.ts +4 -0
- package/src/services/chaintracker/index.mobile.ts +4 -0
- package/src/services/createDefaultWalletServicesOptions.ts +77 -0
- package/src/services/index.ts +1 -0
- package/src/services/processingErrors/arcSuccessError.json +76 -0
- package/src/services/providers/ARC.ts +350 -0
- package/src/services/providers/Bitails.ts +256 -0
- package/src/services/providers/SdkWhatsOnChain.ts +83 -0
- package/src/services/providers/WhatsOnChain.ts +883 -0
- package/src/services/providers/__tests/WhatsOnChain.test.ts +242 -0
- package/src/services/providers/__tests/exchangeRates.test.ts +18 -0
- package/src/services/providers/exchangeRates.ts +265 -0
- package/src/services/providers/getBeefForTxid.ts +369 -0
- package/src/signer/README.md +5 -0
- package/src/signer/WalletSigner.ts +17 -0
- package/src/signer/methods/acquireDirectCertificate.ts +52 -0
- package/src/signer/methods/buildSignableTransaction.ts +183 -0
- package/src/signer/methods/completeSignedTransaction.ts +117 -0
- package/src/signer/methods/createAction.ts +172 -0
- package/src/signer/methods/internalizeAction.ts +106 -0
- package/src/signer/methods/proveCertificate.ts +43 -0
- package/src/signer/methods/signAction.ts +54 -0
- package/src/storage/README.md +14 -0
- package/src/storage/StorageIdb.ts +2304 -0
- package/src/storage/StorageKnex.ts +1425 -0
- package/src/storage/StorageProvider.ts +810 -0
- package/src/storage/StorageReader.ts +194 -0
- package/src/storage/StorageReaderWriter.ts +432 -0
- package/src/storage/StorageSyncReader.ts +34 -0
- package/src/storage/WalletStorageManager.ts +943 -0
- package/src/storage/__test/StorageIdb.test.ts +43 -0
- package/src/storage/__test/WalletStorageManager.test.ts +275 -0
- package/src/storage/__test/adminStats.man.test.ts +89 -0
- package/src/storage/__test/getBeefForTransaction.test.ts +385 -0
- package/src/storage/index.all.ts +11 -0
- package/src/storage/index.client.ts +7 -0
- package/src/storage/index.mobile.ts +6 -0
- package/src/storage/methods/ListActionsSpecOp.ts +70 -0
- package/src/storage/methods/ListOutputsSpecOp.ts +129 -0
- package/src/storage/methods/__test/GenerateChange/generateChangeSdk.test.ts +1057 -0
- package/src/storage/methods/__test/GenerateChange/randomValsUsed1.ts +20 -0
- package/src/storage/methods/__test/offsetKey.test.ts +274 -0
- package/src/storage/methods/attemptToPostReqsToNetwork.ts +389 -0
- package/src/storage/methods/createAction.ts +947 -0
- package/src/storage/methods/generateChange.ts +556 -0
- package/src/storage/methods/getBeefForTransaction.ts +139 -0
- package/src/storage/methods/getSyncChunk.ts +293 -0
- package/src/storage/methods/internalizeAction.ts +562 -0
- package/src/storage/methods/listActionsIdb.ts +183 -0
- package/src/storage/methods/listActionsKnex.ts +226 -0
- package/src/storage/methods/listCertificates.ts +73 -0
- package/src/storage/methods/listOutputsIdb.ts +203 -0
- package/src/storage/methods/listOutputsKnex.ts +263 -0
- package/src/storage/methods/offsetKey.ts +89 -0
- package/src/storage/methods/processAction.ts +420 -0
- package/src/storage/methods/purgeData.ts +251 -0
- package/src/storage/methods/purgeDataIdb.ts +10 -0
- package/src/storage/methods/reviewStatus.ts +101 -0
- package/src/storage/methods/reviewStatusIdb.ts +43 -0
- package/src/storage/methods/utils.Buffer.ts +33 -0
- package/src/storage/methods/utils.ts +56 -0
- package/src/storage/remoting/StorageClient.ts +567 -0
- package/src/storage/remoting/StorageMobile.ts +544 -0
- package/src/storage/remoting/StorageServer.ts +291 -0
- package/src/storage/remoting/__test/StorageClient.test.ts +113 -0
- package/src/storage/schema/KnexMigrations.ts +489 -0
- package/src/storage/schema/StorageIdbSchema.ts +150 -0
- package/src/storage/schema/entities/EntityBase.ts +210 -0
- package/src/storage/schema/entities/EntityCertificate.ts +188 -0
- package/src/storage/schema/entities/EntityCertificateField.ts +136 -0
- package/src/storage/schema/entities/EntityCommission.ts +148 -0
- package/src/storage/schema/entities/EntityOutput.ts +290 -0
- package/src/storage/schema/entities/EntityOutputBasket.ts +153 -0
- package/src/storage/schema/entities/EntityOutputTag.ts +121 -0
- package/src/storage/schema/entities/EntityOutputTagMap.ts +123 -0
- package/src/storage/schema/entities/EntityProvenTx.ts +319 -0
- package/src/storage/schema/entities/EntityProvenTxReq.ts +580 -0
- package/src/storage/schema/entities/EntitySyncState.ts +389 -0
- package/src/storage/schema/entities/EntityTransaction.ts +306 -0
- package/src/storage/schema/entities/EntityTxLabel.ts +121 -0
- package/src/storage/schema/entities/EntityTxLabelMap.ts +123 -0
- package/src/storage/schema/entities/EntityUser.ts +112 -0
- package/src/storage/schema/entities/MergeEntity.ts +73 -0
- package/src/storage/schema/entities/__tests/CertificateFieldTests.test.ts +353 -0
- package/src/storage/schema/entities/__tests/CertificateTests.test.ts +354 -0
- package/src/storage/schema/entities/__tests/CommissionTests.test.ts +371 -0
- package/src/storage/schema/entities/__tests/OutputBasketTests.test.ts +278 -0
- package/src/storage/schema/entities/__tests/OutputTagMapTests.test.ts +242 -0
- package/src/storage/schema/entities/__tests/OutputTagTests.test.ts +288 -0
- package/src/storage/schema/entities/__tests/OutputTests.test.ts +464 -0
- package/src/storage/schema/entities/__tests/ProvenTxReqTests.test.ts +340 -0
- package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +504 -0
- package/src/storage/schema/entities/__tests/SyncStateTests.test.ts +288 -0
- package/src/storage/schema/entities/__tests/TransactionTests.test.ts +604 -0
- package/src/storage/schema/entities/__tests/TxLabelMapTests.test.ts +361 -0
- package/src/storage/schema/entities/__tests/TxLabelTests.test.ts +198 -0
- package/src/storage/schema/entities/__tests/stampLogTests.test.ts +90 -0
- package/src/storage/schema/entities/__tests/usersTests.test.ts +340 -0
- package/src/storage/schema/entities/index.ts +16 -0
- package/src/storage/schema/tables/TableCertificate.ts +21 -0
- package/src/storage/schema/tables/TableCertificateField.ts +12 -0
- package/src/storage/schema/tables/TableCommission.ts +13 -0
- package/src/storage/schema/tables/TableMonitorEvent.ts +9 -0
- package/src/storage/schema/tables/TableOutput.ts +64 -0
- package/src/storage/schema/tables/TableOutputBasket.ts +12 -0
- package/src/storage/schema/tables/TableOutputTag.ts +10 -0
- package/src/storage/schema/tables/TableOutputTagMap.ts +9 -0
- package/src/storage/schema/tables/TableProvenTx.ts +14 -0
- package/src/storage/schema/tables/TableProvenTxReq.ts +65 -0
- package/src/storage/schema/tables/TableSettings.ts +17 -0
- package/src/storage/schema/tables/TableSyncState.ts +18 -0
- package/src/storage/schema/tables/TableTransaction.ts +54 -0
- package/src/storage/schema/tables/TableTxLabel.ts +10 -0
- package/src/storage/schema/tables/TableTxLabelMap.ts +9 -0
- package/src/storage/schema/tables/TableUser.ts +16 -0
- package/src/storage/schema/tables/index.ts +16 -0
- package/src/storage/sync/StorageMySQLDojoReader.ts +696 -0
- package/src/storage/sync/index.ts +1 -0
- package/src/utility/Format.ts +133 -0
- package/src/utility/README.md +3 -0
- package/src/utility/ReaderUint8Array.ts +187 -0
- package/src/utility/ScriptTemplateBRC29.ts +73 -0
- package/src/utility/__tests/utilityHelpers.noBuffer.test.ts +109 -0
- package/src/utility/aggregateResults.ts +68 -0
- package/src/utility/identityUtils.ts +159 -0
- package/src/utility/index.all.ts +7 -0
- package/src/utility/index.client.ts +7 -0
- package/src/utility/parseTxScriptOffsets.ts +29 -0
- package/src/utility/stampLog.ts +69 -0
- package/src/utility/tscProofToMerklePath.ts +48 -0
- package/src/utility/utilityHelpers.buffer.ts +34 -0
- package/src/utility/utilityHelpers.noBuffer.ts +60 -0
- package/src/utility/utilityHelpers.ts +275 -0
- package/src/wab-client/WABClient.ts +94 -0
- package/src/wab-client/__tests/WABClient.man.test.ts +59 -0
- package/src/wab-client/auth-method-interactors/AuthMethodInteractor.ts +47 -0
- package/src/wab-client/auth-method-interactors/DevConsoleInteractor.ts +73 -0
- package/src/wab-client/auth-method-interactors/PersonaIDInteractor.ts +35 -0
- package/src/wab-client/auth-method-interactors/TwilioPhoneInteractor.ts +72 -0
- package/syncVersions.js +71 -0
- package/test/Wallet/StorageClient/storageClient.man.test.ts +75 -0
- package/test/Wallet/action/abortAction.test.ts +47 -0
- package/test/Wallet/action/createAction.test.ts +299 -0
- package/test/Wallet/action/createAction2.test.ts +1273 -0
- package/test/Wallet/action/createActionToGenerateBeefs.man.test.ts +293 -0
- package/test/Wallet/action/internalizeAction.a.test.ts +286 -0
- package/test/Wallet/action/internalizeAction.test.ts +682 -0
- package/test/Wallet/action/relinquishOutput.test.ts +37 -0
- package/test/Wallet/certificate/acquireCertificate.test.ts +298 -0
- package/test/Wallet/certificate/listCertificates.test.ts +346 -0
- package/test/Wallet/construct/Wallet.constructor.test.ts +57 -0
- package/test/Wallet/get/getHeaderForHeight.test.ts +82 -0
- package/test/Wallet/get/getHeight.test.ts +52 -0
- package/test/Wallet/get/getKnownTxids.test.ts +86 -0
- package/test/Wallet/get/getNetwork.test.ts +27 -0
- package/test/Wallet/get/getVersion.test.ts +27 -0
- package/test/Wallet/list/listActions.test.ts +279 -0
- package/test/Wallet/list/listActions2.test.ts +1381 -0
- package/test/Wallet/list/listCertificates.test.ts +118 -0
- package/test/Wallet/list/listOutputs.test.ts +447 -0
- package/test/Wallet/live/walletLive.man.test.ts +521 -0
- package/test/Wallet/local/localWallet.man.test.ts +93 -0
- package/test/Wallet/local/localWallet2.man.test.ts +277 -0
- package/test/Wallet/signAction/mountaintop.man.test.ts +130 -0
- package/test/Wallet/specOps/specOps.man.test.ts +220 -0
- package/test/Wallet/support/janitor.man.test.ts +40 -0
- package/test/Wallet/support/operations.man.test.ts +407 -0
- package/test/Wallet/support/reqErrorReview.2025.05.06.man.test.ts +347 -0
- package/test/Wallet/sync/Wallet.sync.test.ts +215 -0
- package/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.ts +203 -0
- package/test/Wallet/sync/setActive.test.ts +170 -0
- package/test/WalletClient/LocalKVStore.man.test.ts +114 -0
- package/test/WalletClient/WERR.man.test.ts +35 -0
- package/test/bsv-ts-sdk/LocalKVStore.test.ts +102 -0
- package/test/checkDB.ts +57 -0
- package/test/checkdb +0 -0
- package/test/examples/backup.man.test.ts +59 -0
- package/test/examples/pushdrop.test.ts +282 -0
- package/test/monitor/Monitor.test.ts +620 -0
- package/test/services/Services.test.ts +263 -0
- package/test/storage/KnexMigrations.test.ts +86 -0
- package/test/storage/StorageMySQLDojoReader.man.test.ts +60 -0
- package/test/storage/count.test.ts +177 -0
- package/test/storage/find.test.ts +195 -0
- package/test/storage/findLegacy.test.ts +67 -0
- package/test/storage/idb/allocateChange.test.ts +251 -0
- package/test/storage/idb/count.test.ts +158 -0
- package/test/storage/idb/find.test.ts +177 -0
- package/test/storage/idb/idbSpeed.test.ts +36 -0
- package/test/storage/idb/insert.test.ts +268 -0
- package/test/storage/idb/transactionAbort.test.ts +108 -0
- package/test/storage/idb/update.test.ts +999 -0
- package/test/storage/insert.test.ts +278 -0
- package/test/storage/update.test.ts +1021 -0
- package/test/storage/update2.test.ts +897 -0
- package/test/utils/TestUtilsWalletStorage.ts +2526 -0
- package/test/utils/localWalletMethods.ts +363 -0
- package/test/utils/removeFailedFromDatabase.sql +17 -0
- package/ts2md.json +44 -0
- package/tsconfig.all.json +31 -0
- package/tsconfig.client.json +29 -0
- package/tsconfig.json +17 -0
- package/tsconfig.mobile.json +28 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { GetMerklePathResult } from '../../sdk'
|
|
2
|
+
import { EntityProvenTx, EntityProvenTxReq } from '../../storage/schema/entities'
|
|
3
|
+
import { TableProvenTxReq } from '../../storage/schema/tables'
|
|
4
|
+
import { doubleSha256BE } from '../../utility/utilityHelpers'
|
|
5
|
+
import { asString } from '../../utility/utilityHelpers.noBuffer'
|
|
6
|
+
import { Monitor } from '../Monitor'
|
|
7
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `TaskCheckForProofs` is a WalletMonitor task that retreives merkle proofs for
|
|
11
|
+
* transactions.
|
|
12
|
+
*
|
|
13
|
+
* It is normally triggered by the Chaintracks new block header event.
|
|
14
|
+
*
|
|
15
|
+
* When a new block is found, cwi-external-services are used to obtain proofs for
|
|
16
|
+
* any transactions that are currently in the 'unmined' or 'unknown' state.
|
|
17
|
+
*
|
|
18
|
+
* If a proof is obtained and validated, a new ProvenTx record is created and
|
|
19
|
+
* the original ProvenTxReq status is advanced to 'notifying'.
|
|
20
|
+
*/
|
|
21
|
+
export class TaskCheckForProofs extends WalletMonitorTask {
|
|
22
|
+
static taskName = 'CheckForProofs'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* An external service such as the chaintracks new block header
|
|
26
|
+
* listener can set this true to cause
|
|
27
|
+
*/
|
|
28
|
+
static checkNow = false
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
monitor: Monitor,
|
|
32
|
+
public triggerMsecs = 0
|
|
33
|
+
) {
|
|
34
|
+
super(monitor, TaskCheckForProofs.taskName)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Normally triggered by checkNow getting set by new block header found event from chaintracks
|
|
39
|
+
*/
|
|
40
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
41
|
+
return {
|
|
42
|
+
run: TaskCheckForProofs.checkNow
|
|
43
|
+
// Check only when checkNow flag is set.
|
|
44
|
+
// || (this.triggerMsecs > 0 && nowMsecsSinceEpoch - this.lastRunMsecsSinceEpoch > this.triggerMsecs)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async runTask(): Promise<string> {
|
|
49
|
+
let log = ''
|
|
50
|
+
const countsAsAttempt = TaskCheckForProofs.checkNow
|
|
51
|
+
TaskCheckForProofs.checkNow = false
|
|
52
|
+
|
|
53
|
+
const maxAcceptableHeight = this.monitor.lastNewHeader?.height
|
|
54
|
+
if (maxAcceptableHeight === undefined) {
|
|
55
|
+
return log
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const limit = 100
|
|
59
|
+
let offset = 0
|
|
60
|
+
for (;;) {
|
|
61
|
+
const reqs = await this.storage.findProvenTxReqs({
|
|
62
|
+
partial: {},
|
|
63
|
+
status: ['callback', 'unmined', 'sending', 'unknown', 'unconfirmed'],
|
|
64
|
+
paged: { limit, offset }
|
|
65
|
+
})
|
|
66
|
+
if (reqs.length === 0) break
|
|
67
|
+
log += `${reqs.length} reqs with status 'callback', 'unmined', 'sending', 'unknown', or 'unconfirmed'\n`
|
|
68
|
+
const r = await getProofs(this, reqs, 2, countsAsAttempt, false, maxAcceptableHeight)
|
|
69
|
+
log += `${r.log}\n`
|
|
70
|
+
//console.log(log);
|
|
71
|
+
if (reqs.length < limit) break
|
|
72
|
+
offset += limit
|
|
73
|
+
}
|
|
74
|
+
return log
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Process an array of table.ProvenTxReq (typically with status 'unmined' or 'unknown')
|
|
80
|
+
*
|
|
81
|
+
* If req is invalid, set status 'invalid'
|
|
82
|
+
*
|
|
83
|
+
* Verify the requests are valid, lookup proofs or updated transaction status using the array of getProofServices,
|
|
84
|
+
*
|
|
85
|
+
* When proofs are found, create new ProvenTxApi records and transition the requests' status to 'unconfirmed' or 'notifying',
|
|
86
|
+
* depending on chaintracks succeeding on proof verification.
|
|
87
|
+
*
|
|
88
|
+
* Increments attempts if proofs where requested.
|
|
89
|
+
*
|
|
90
|
+
* @param reqs
|
|
91
|
+
* @returns reqs partitioned by status
|
|
92
|
+
*/
|
|
93
|
+
export async function getProofs(
|
|
94
|
+
task: WalletMonitorTask,
|
|
95
|
+
reqs: TableProvenTxReq[],
|
|
96
|
+
indent = 0,
|
|
97
|
+
countsAsAttempt = false,
|
|
98
|
+
ignoreStatus = false,
|
|
99
|
+
maxAcceptableHeight: number
|
|
100
|
+
): Promise<{
|
|
101
|
+
proven: TableProvenTxReq[]
|
|
102
|
+
invalid: TableProvenTxReq[]
|
|
103
|
+
log: string
|
|
104
|
+
}> {
|
|
105
|
+
const proven: TableProvenTxReq[] = []
|
|
106
|
+
const invalid: TableProvenTxReq[] = []
|
|
107
|
+
|
|
108
|
+
let log = ''
|
|
109
|
+
for (const reqApi of reqs) {
|
|
110
|
+
log += ' '.repeat(indent)
|
|
111
|
+
log += `reqId ${reqApi.provenTxReqId} txid ${reqApi.txid}: `
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
!ignoreStatus &&
|
|
115
|
+
reqApi.status !== 'callback' &&
|
|
116
|
+
reqApi.status !== 'unmined' &&
|
|
117
|
+
reqApi.status !== 'unknown' &&
|
|
118
|
+
reqApi.status !== 'unconfirmed' &&
|
|
119
|
+
reqApi.status !== 'nosend' &&
|
|
120
|
+
reqApi.status !== 'sending'
|
|
121
|
+
) {
|
|
122
|
+
log += `status of '${reqApi.status}' is not ready to be proven.\n`
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const req = new EntityProvenTxReq(reqApi)
|
|
127
|
+
|
|
128
|
+
if (Number.isInteger(req.provenTxId)) {
|
|
129
|
+
log += `Already linked to provenTxId ${req.provenTxId}.\n`
|
|
130
|
+
req.notified = false
|
|
131
|
+
req.status = 'completed'
|
|
132
|
+
await req.updateStorageDynamicProperties(task.storage)
|
|
133
|
+
proven.push(reqApi)
|
|
134
|
+
continue
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
log += '\n'
|
|
138
|
+
|
|
139
|
+
let reqIsValid = false
|
|
140
|
+
if (req.rawTx) {
|
|
141
|
+
const txid = asString(doubleSha256BE(req.rawTx))
|
|
142
|
+
if (txid === req.txid) reqIsValid = true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!reqIsValid) {
|
|
146
|
+
log += ` rawTx doesn't hash to txid. status => invalid.\n`
|
|
147
|
+
req.notified = false
|
|
148
|
+
req.status = 'invalid'
|
|
149
|
+
await req.updateStorageDynamicProperties(task.storage)
|
|
150
|
+
invalid.push(reqApi)
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const limit =
|
|
155
|
+
task.monitor.chain === 'main'
|
|
156
|
+
? task.monitor.options.unprovenAttemptsLimitMain
|
|
157
|
+
: task.monitor.options.unprovenAttemptsLimitTest
|
|
158
|
+
if (!ignoreStatus && req.attempts > limit) {
|
|
159
|
+
log += ` too many failed attempts ${req.attempts}\n`
|
|
160
|
+
req.notified = false
|
|
161
|
+
req.status = 'invalid'
|
|
162
|
+
await req.updateStorageDynamicProperties(task.storage)
|
|
163
|
+
invalid.push(reqApi)
|
|
164
|
+
continue
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const since = new Date()
|
|
168
|
+
|
|
169
|
+
let r: GetMerklePathResult
|
|
170
|
+
let ptx: EntityProvenTx | undefined
|
|
171
|
+
|
|
172
|
+
// External services will try multiple providers until one returns a proof,
|
|
173
|
+
// or they all fail.
|
|
174
|
+
// There may also be an array of proofs to consider when a transaction
|
|
175
|
+
// is recently mined and appears in orphan blocks in addition to active chain blocks.
|
|
176
|
+
// Since orphan blocks can end up on chain again, multiple proofs has value.
|
|
177
|
+
//
|
|
178
|
+
// On failure, there may be a mapi response, or an error.
|
|
179
|
+
//
|
|
180
|
+
// The proofs returned are considered sequentially, validating and chaintracks confirming.
|
|
181
|
+
//
|
|
182
|
+
// If a good proof is found, proceed to using it.
|
|
183
|
+
//
|
|
184
|
+
// When all received proofs fail, force a bump to the next service provider and try
|
|
185
|
+
// one more time.
|
|
186
|
+
//
|
|
187
|
+
r = await task.monitor.services.getMerklePath(req.txid)
|
|
188
|
+
if (r.header && r.header.height > maxAcceptableHeight) {
|
|
189
|
+
// Ignore proofs from bleeding edge of new blocks as these are the most often re-orged.
|
|
190
|
+
log += ` ignoring possible proof from very new block at height ${r.header.height} ${r.header.hash}\n`
|
|
191
|
+
continue
|
|
192
|
+
}
|
|
193
|
+
ptx = await EntityProvenTx.fromReq(req, r, countsAsAttempt && req.status !== 'nosend')
|
|
194
|
+
|
|
195
|
+
if (ptx) {
|
|
196
|
+
// We have a merklePath proof for the request (and a block header)
|
|
197
|
+
await req.updateStorageDynamicProperties(task.storage)
|
|
198
|
+
await req.refreshFromStorage(task.storage)
|
|
199
|
+
const { provenTxReqId, status, txid, attempts, history } = req.toApi()
|
|
200
|
+
const { index, height, blockHash, merklePath, merkleRoot } = ptx.toApi()
|
|
201
|
+
const r = await task.storage.runAsStorageProvider(async sp => {
|
|
202
|
+
return await sp.updateProvenTxReqWithNewProvenTx({
|
|
203
|
+
provenTxReqId,
|
|
204
|
+
status,
|
|
205
|
+
txid,
|
|
206
|
+
attempts,
|
|
207
|
+
history,
|
|
208
|
+
index,
|
|
209
|
+
height,
|
|
210
|
+
blockHash,
|
|
211
|
+
merklePath,
|
|
212
|
+
merkleRoot
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
req.status = r.status
|
|
216
|
+
req.apiHistory = r.history
|
|
217
|
+
req.provenTxId = r.provenTxId
|
|
218
|
+
req.notified = true
|
|
219
|
+
|
|
220
|
+
task.monitor.callOnProvenTransaction({
|
|
221
|
+
txid,
|
|
222
|
+
txIndex: index,
|
|
223
|
+
blockHeight: height,
|
|
224
|
+
blockHash,
|
|
225
|
+
merklePath,
|
|
226
|
+
merkleRoot
|
|
227
|
+
})
|
|
228
|
+
} else {
|
|
229
|
+
if (countsAsAttempt && req.status !== 'nosend') {
|
|
230
|
+
req.attempts++
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
await req.updateStorageDynamicProperties(task.storage)
|
|
234
|
+
await req.refreshFromStorage(task.storage)
|
|
235
|
+
|
|
236
|
+
log += req.historyPretty(since, indent + 2) + '\n'
|
|
237
|
+
|
|
238
|
+
if (req.status === 'completed') proven.push(req.api)
|
|
239
|
+
if (req.status === 'invalid') invalid.push(req.api)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return { proven, invalid, log }
|
|
243
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Monitor } from '../Monitor'
|
|
2
|
+
import { getProofs } from './TaskCheckForProofs'
|
|
3
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `TaskCheckNoSends` is a WalletMonitor task that retreives merkle proofs for
|
|
7
|
+
* 'nosend' transactions that MAY have been shared externally.
|
|
8
|
+
*
|
|
9
|
+
* Unlike intentionally processed transactions, 'nosend' transactions are fully valid
|
|
10
|
+
* transactions which have not been processed by the wallet.
|
|
11
|
+
*
|
|
12
|
+
* By default, this task runs once a day to check if any 'nosend' transaction has
|
|
13
|
+
* managed to get mined by some external process.
|
|
14
|
+
*
|
|
15
|
+
* If a proof is obtained and validated, a new ProvenTx record is created and
|
|
16
|
+
* the original ProvenTxReq status is advanced to 'notifying'.
|
|
17
|
+
*/
|
|
18
|
+
export class TaskCheckNoSends extends WalletMonitorTask {
|
|
19
|
+
static taskName = 'CheckNoSends'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* An external service such as the chaintracks new block header
|
|
23
|
+
* listener can set this true to cause
|
|
24
|
+
*/
|
|
25
|
+
static checkNow = false
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
monitor: Monitor,
|
|
29
|
+
public triggerMsecs = Monitor.oneDay * 1
|
|
30
|
+
) {
|
|
31
|
+
super(monitor, TaskCheckNoSends.taskName)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Normally triggered by checkNow getting set by new block header found event from chaintracks
|
|
36
|
+
*/
|
|
37
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
38
|
+
return {
|
|
39
|
+
run:
|
|
40
|
+
TaskCheckNoSends.checkNow ||
|
|
41
|
+
(this.triggerMsecs > 0 && nowMsecsSinceEpoch - this.lastRunMsecsSinceEpoch > this.triggerMsecs)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async runTask(): Promise<string> {
|
|
46
|
+
let log = ''
|
|
47
|
+
const countsAsAttempt = TaskCheckNoSends.checkNow
|
|
48
|
+
TaskCheckNoSends.checkNow = false
|
|
49
|
+
|
|
50
|
+
const maxAcceptableHeight = this.monitor.lastNewHeader?.height
|
|
51
|
+
if (maxAcceptableHeight === undefined) {
|
|
52
|
+
return log
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const limit = 100
|
|
56
|
+
let offset = 0
|
|
57
|
+
for (;;) {
|
|
58
|
+
const reqs = await this.storage.findProvenTxReqs({
|
|
59
|
+
partial: {},
|
|
60
|
+
status: ['nosend'],
|
|
61
|
+
paged: { limit, offset }
|
|
62
|
+
})
|
|
63
|
+
if (reqs.length === 0) break
|
|
64
|
+
log += `${reqs.length} reqs with status 'nosend'\n`
|
|
65
|
+
const r = await getProofs(this, reqs, 2, countsAsAttempt, false, maxAcceptableHeight)
|
|
66
|
+
log += `${r.log}\n`
|
|
67
|
+
//console.log(log);
|
|
68
|
+
if (reqs.length < limit) break
|
|
69
|
+
offset += limit
|
|
70
|
+
}
|
|
71
|
+
return log
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Monitor } from '../Monitor'
|
|
2
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
3
|
+
|
|
4
|
+
export class TaskClock extends WalletMonitorTask {
|
|
5
|
+
static taskName = 'Clock'
|
|
6
|
+
nextMinute: number
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
monitor: Monitor,
|
|
10
|
+
public triggerMsecs = 1 * Monitor.oneSecond
|
|
11
|
+
) {
|
|
12
|
+
super(monitor, TaskClock.taskName)
|
|
13
|
+
this.nextMinute = this.getNextMinute()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
17
|
+
const s = this.storage
|
|
18
|
+
|
|
19
|
+
const run = Date.now() > this.nextMinute
|
|
20
|
+
|
|
21
|
+
return { run }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async runTask(): Promise<string> {
|
|
25
|
+
const log = `${new Date(this.nextMinute).toISOString()}`
|
|
26
|
+
this.nextMinute = this.getNextMinute()
|
|
27
|
+
return log
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getNextMinute(): number {
|
|
31
|
+
return Math.ceil(Date.now() / Monitor.oneMinute) * Monitor.oneMinute
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Monitor } from '../Monitor'
|
|
2
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handles transactions which do not have terminal status and have not been
|
|
6
|
+
* updated for an extended time period.
|
|
7
|
+
*
|
|
8
|
+
* Calls `updateTransactionStatus` to set `status` to `failed`.
|
|
9
|
+
* This returns inputs to spendable status and verifies that any
|
|
10
|
+
* outputs are not spendable.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export class TaskFailAbandoned extends WalletMonitorTask {
|
|
14
|
+
static taskName = 'FailAbandoned'
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
monitor: Monitor,
|
|
18
|
+
public triggerMsecs = 1000 * 60 * 5
|
|
19
|
+
) {
|
|
20
|
+
super(monitor, TaskFailAbandoned.taskName)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
24
|
+
return {
|
|
25
|
+
run: nowMsecsSinceEpoch > this.lastRunMsecsSinceEpoch + this.triggerMsecs
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async runTask(): Promise<string> {
|
|
30
|
+
let log = ''
|
|
31
|
+
const limit = 100
|
|
32
|
+
let offset = 0
|
|
33
|
+
for (;;) {
|
|
34
|
+
const now = new Date()
|
|
35
|
+
const abandoned = new Date(now.getTime() - this.monitor.options.abandonedMsecs)
|
|
36
|
+
const done = await this.storage.runAsStorageProvider(async sp => {
|
|
37
|
+
const txsAll = await sp.findTransactions({
|
|
38
|
+
partial: {},
|
|
39
|
+
status: ['unprocessed', 'unsigned'],
|
|
40
|
+
paged: { limit, offset }
|
|
41
|
+
})
|
|
42
|
+
const txs = txsAll.filter(t => t.updated_at && t.updated_at < abandoned)
|
|
43
|
+
for (const tx of txs) {
|
|
44
|
+
await sp.updateTransactionStatus('failed', tx.transactionId)
|
|
45
|
+
log += `updated tx ${tx.transactionId} status to 'failed'\n`
|
|
46
|
+
}
|
|
47
|
+
return txs.length < limit
|
|
48
|
+
})
|
|
49
|
+
if (done) break
|
|
50
|
+
offset += limit
|
|
51
|
+
}
|
|
52
|
+
return log
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TableMonitorEvent } from '../../storage/index.client'
|
|
2
|
+
import { Monitor } from '../Monitor'
|
|
3
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
4
|
+
|
|
5
|
+
export class TaskMonitorCallHistory extends WalletMonitorTask {
|
|
6
|
+
static taskName = 'MonitorCallHistory'
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
monitor: Monitor,
|
|
10
|
+
public triggerMsecs = Monitor.oneMinute * 12
|
|
11
|
+
) {
|
|
12
|
+
super(monitor, TaskMonitorCallHistory.taskName)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
16
|
+
return {
|
|
17
|
+
run: nowMsecsSinceEpoch > this.lastRunMsecsSinceEpoch + this.triggerMsecs
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async runTask(): Promise<string> {
|
|
22
|
+
const r = await this.monitor.services.getServicesCallHistory(true)
|
|
23
|
+
const log = JSON.stringify(r)
|
|
24
|
+
return log
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { BlockHeader } from '../../sdk/WalletServices.interfaces'
|
|
2
|
+
import { Monitor } from '../Monitor'
|
|
3
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This task polls for new block headers performing two essential functions:
|
|
7
|
+
* 1. The arrival of a new block is the right time to check for proofs for recently broadcast transactions.
|
|
8
|
+
* 2. The height of the block is used to limit which proofs are accepted with the aim of avoiding re-orged proofs.
|
|
9
|
+
*
|
|
10
|
+
* The most common new block orphan is one which is almost immediately orphaned.
|
|
11
|
+
* Waiting a minute before pursuing proof requests avoids almost all the re-org work that could be done.
|
|
12
|
+
* Thus this task queues new headers for one cycle.
|
|
13
|
+
* If a new header arrives during that cycle, it replaces the queued header and delays again.
|
|
14
|
+
* Only when there is an elapsed cycle without a new header does proof solicitation get triggered,
|
|
15
|
+
* with that header height as the limit for which proofs are accepted.
|
|
16
|
+
*/
|
|
17
|
+
export class TaskNewHeader extends WalletMonitorTask {
|
|
18
|
+
static taskName = 'NewHeader'
|
|
19
|
+
/**
|
|
20
|
+
* This is always the most recent chain tip header returned from the chaintracker.
|
|
21
|
+
*/
|
|
22
|
+
header?: BlockHeader
|
|
23
|
+
/**
|
|
24
|
+
* Tracks the value of `header` except that it is set to undefined
|
|
25
|
+
* when a cycle without a new header occurs and `processNewBlockHeader` is called.
|
|
26
|
+
*/
|
|
27
|
+
queuedHeader?: BlockHeader
|
|
28
|
+
queuedHeaderWhen?: Date
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
monitor: Monitor,
|
|
32
|
+
public triggerMsecs = 1 * Monitor.oneMinute
|
|
33
|
+
) {
|
|
34
|
+
super(monitor, TaskNewHeader.taskName)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async getHeader(): Promise<BlockHeader> {
|
|
38
|
+
return await this.monitor.chaintracks.findChainTipHeader()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* TODO: This is a temporary incomplete solution for which a full chaintracker
|
|
43
|
+
* with new header and reorg event notification is required.
|
|
44
|
+
*
|
|
45
|
+
* New header events drive retrieving merklePaths for newly mined transactions.
|
|
46
|
+
* This implementation performs this function.
|
|
47
|
+
*
|
|
48
|
+
* Reorg events are needed to know when previously retrieved mekrlePaths need to be
|
|
49
|
+
* updated in the proven_txs table (and ideally notifications delivered to users).
|
|
50
|
+
* Note that in-general, a reorg only shifts where in the block a transaction is mined,
|
|
51
|
+
* and sometimes which block. In the case of coinbase transactions, a transaction may
|
|
52
|
+
* also fail after a reorg.
|
|
53
|
+
*/
|
|
54
|
+
override async asyncSetup(): Promise<void> {}
|
|
55
|
+
|
|
56
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
57
|
+
const run = true
|
|
58
|
+
return { run }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async runTask(): Promise<string> {
|
|
62
|
+
let log = ''
|
|
63
|
+
const oldHeader = this.header
|
|
64
|
+
this.header = await this.getHeader()
|
|
65
|
+
let isNew = true
|
|
66
|
+
if (!oldHeader) {
|
|
67
|
+
log = `first header: ${this.header.height} ${this.header.hash}`
|
|
68
|
+
} else if (oldHeader.height > this.header.height) {
|
|
69
|
+
log = `old header: ${this.header.height} vs ${oldHeader.height}`
|
|
70
|
+
this.header = oldHeader // Revert to old header with the higher height
|
|
71
|
+
isNew = false
|
|
72
|
+
} else if (oldHeader.height < this.header.height) {
|
|
73
|
+
const skip = this.header.height - oldHeader.height - 1
|
|
74
|
+
const skipped = skip > 0 ? ` SKIPPED ${skip}` : ''
|
|
75
|
+
log = `new header: ${this.header.height} ${this.header.hash}${skipped}`
|
|
76
|
+
} else if (oldHeader.height === this.header.height && oldHeader.hash != this.header.hash) {
|
|
77
|
+
log = `reorg header: ${this.header.height} ${this.header.hash}`
|
|
78
|
+
} else {
|
|
79
|
+
isNew = false
|
|
80
|
+
}
|
|
81
|
+
if (isNew) {
|
|
82
|
+
this.queuedHeader = this.header
|
|
83
|
+
this.queuedHeaderWhen = new Date()
|
|
84
|
+
} else if (this.queuedHeader) {
|
|
85
|
+
// Only process new block header if it has remained the chain tip for a full cycle
|
|
86
|
+
const delay = (new Date().getTime() - this.queuedHeaderWhen!.getTime()) / 1000 // seconds
|
|
87
|
+
log = `process header: ${this.header.height} ${this.header.hash} delayed ${delay.toFixed(1)} secs`
|
|
88
|
+
this.monitor.processNewBlockHeader(this.queuedHeader)
|
|
89
|
+
this.queuedHeader = undefined
|
|
90
|
+
}
|
|
91
|
+
return log
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { PurgeParams } from '../../sdk/WalletStorage.interfaces'
|
|
2
|
+
import { Monitor } from '../Monitor'
|
|
3
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The database stores a variety of data that may be considered transient.
|
|
7
|
+
*
|
|
8
|
+
* At one extreme, the data that must be preserved:
|
|
9
|
+
* - unspent outputs (UTXOs)
|
|
10
|
+
* - in-use metadata (labels, baskets, tags...)
|
|
11
|
+
*
|
|
12
|
+
* At the other extreme, everything can be preserved to fully log all transaction creation and processing actions.
|
|
13
|
+
*
|
|
14
|
+
* The following purge actions are available to support sustained operation:
|
|
15
|
+
* - Failed transactions, delete all associated data including:
|
|
16
|
+
* + Delete tag and label mapping records
|
|
17
|
+
* + Delete output records
|
|
18
|
+
* + Delete transaction records
|
|
19
|
+
* + Delete mapi_responses records
|
|
20
|
+
* + Delete proven_tx_reqs records
|
|
21
|
+
* + Delete commissions records
|
|
22
|
+
* + Update output records marked spentBy failed transactions
|
|
23
|
+
* - Completed transactions, delete transient data including:
|
|
24
|
+
* + transactions table set truncatedExternalInputs = null
|
|
25
|
+
* + transactions table set beef = null
|
|
26
|
+
* + transactions table set rawTx = null
|
|
27
|
+
* + Delete mapi_responses records
|
|
28
|
+
* + proven_tx_reqs table delete records
|
|
29
|
+
*/
|
|
30
|
+
export interface TaskPurgeParams extends PurgeParams {}
|
|
31
|
+
|
|
32
|
+
export class TaskPurge extends WalletMonitorTask {
|
|
33
|
+
static taskName = 'Purge'
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Set to true to trigger running this task
|
|
37
|
+
*/
|
|
38
|
+
static checkNow = false
|
|
39
|
+
|
|
40
|
+
constructor(
|
|
41
|
+
monitor: Monitor,
|
|
42
|
+
public params: TaskPurgeParams,
|
|
43
|
+
public triggerMsecs = 0
|
|
44
|
+
) {
|
|
45
|
+
super(monitor, TaskPurge.taskName)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
49
|
+
return {
|
|
50
|
+
run:
|
|
51
|
+
TaskPurge.checkNow ||
|
|
52
|
+
(this.triggerMsecs > 0 && nowMsecsSinceEpoch - this.lastRunMsecsSinceEpoch > this.triggerMsecs)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async runTask(): Promise<string> {
|
|
57
|
+
let log = ''
|
|
58
|
+
TaskPurge.checkNow = false
|
|
59
|
+
|
|
60
|
+
const r = await this.storage.runAsStorageProvider(async sp => {
|
|
61
|
+
return await sp.purgeData(this.params)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
if (r.count > 0) log = `${r.count} records updated or deleted.\n${r.log}`
|
|
65
|
+
|
|
66
|
+
return log
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { TableProvenTx } from '../../index.client'
|
|
2
|
+
import { BlockHeader } from '../../services/chaintracker/chaintracks/Api/BlockHeaderApi'
|
|
3
|
+
import { DeactivedHeader, Monitor } from '../Monitor'
|
|
4
|
+
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check the `monitor.deactivatedHeaders` for any headers that have been deactivated.
|
|
8
|
+
*
|
|
9
|
+
* When headers are found, review matching ProvenTx records and update proof data as appropriate.
|
|
10
|
+
*
|
|
11
|
+
* New deactivated headers are pushed onto the `deactivatedHeaders` array.
|
|
12
|
+
* They must be shifted out as they are processed.
|
|
13
|
+
*
|
|
14
|
+
* The current implementation ages deactivation notifications by 10 minutes with each retry.
|
|
15
|
+
* If a successful proof update confirms original proof data after 3 retries, the original is retained.
|
|
16
|
+
*
|
|
17
|
+
* In normal operation there should rarely be any work for this task to perform.
|
|
18
|
+
* The most common result is that there are no matching proven_txs records because
|
|
19
|
+
* generating new proven_txs records intentionally lags new block generation to
|
|
20
|
+
* minimize this disruption.
|
|
21
|
+
*
|
|
22
|
+
* It is very disruptive to update a proven_txs record because:
|
|
23
|
+
* - Sync'ed storage is impacted.
|
|
24
|
+
* - Generated beefs are impacted.
|
|
25
|
+
* - Updated proof data may be unavailable at the time a reorg is first reported.
|
|
26
|
+
*
|
|
27
|
+
* Proper reorg handling also requires repairing invalid beefs for new transactions when
|
|
28
|
+
* createAction fails to verify a generated beef against the chaintracker.
|
|
29
|
+
*/
|
|
30
|
+
export class TaskReorg extends WalletMonitorTask {
|
|
31
|
+
static taskName = 'Reorg'
|
|
32
|
+
|
|
33
|
+
process: DeactivedHeader[] = []
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
monitor: Monitor,
|
|
37
|
+
public agedMsecs = Monitor.oneMinute * 10,
|
|
38
|
+
public maxRetries = 3
|
|
39
|
+
) {
|
|
40
|
+
super(monitor, TaskReorg.taskName)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Shift aged deactivated headers onto `process` array.
|
|
45
|
+
* @param nowMsecsSinceEpoch current time in milliseconds since epoch.
|
|
46
|
+
* @returns `run` true iff there are aged deactivated headers to process.
|
|
47
|
+
*/
|
|
48
|
+
trigger(nowMsecsSinceEpoch: number): { run: boolean } {
|
|
49
|
+
const cutoff = nowMsecsSinceEpoch - this.agedMsecs
|
|
50
|
+
const q = this.monitor.deactivatedHeaders
|
|
51
|
+
while (q.length > 0 && cutoff > q[0].whenMsecs) {
|
|
52
|
+
// Prepare to process deactivated headers that have aged sufficiently (agedMsecs)
|
|
53
|
+
const header = q.shift()!
|
|
54
|
+
this.process.push(header)
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
run: this.process.length > 0
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async runTask(): Promise<string> {
|
|
62
|
+
let log = ''
|
|
63
|
+
|
|
64
|
+
for (;;) {
|
|
65
|
+
// Loop over deactivated headers to process
|
|
66
|
+
const header = this.process.shift()
|
|
67
|
+
if (!header) break
|
|
68
|
+
|
|
69
|
+
const r = await this.storage.reproveHeader(header.header.hash)
|
|
70
|
+
|
|
71
|
+
log += r.log
|
|
72
|
+
|
|
73
|
+
if (r.unavailable.length > 0 || r.unchanged.length > 0) {
|
|
74
|
+
if (header.tries + 1 >= this.maxRetries) {
|
|
75
|
+
log += ` maximum retries ${this.maxRetries} exceeded\n`
|
|
76
|
+
} else {
|
|
77
|
+
log += ` retrying...\n`
|
|
78
|
+
this.monitor.deactivatedHeaders.push({
|
|
79
|
+
header: header.header,
|
|
80
|
+
whenMsecs: Date.now(),
|
|
81
|
+
tries: header.tries + 1
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return log
|
|
88
|
+
}
|
|
89
|
+
}
|