@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.
Files changed (390) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.env.template +22 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  4. package/.github/ISSUE_TEMPLATE/discussion.md +24 -0
  5. package/.github/pull_request_template.md +22 -0
  6. package/.github/workflows/push.yaml +145 -0
  7. package/.prettierrc +10 -0
  8. package/CHANGELOG.md +280 -0
  9. package/CONTRIBUTING.md +89 -0
  10. package/README.md +43 -0
  11. package/docs/README.md +85 -0
  12. package/docs/client.md +19627 -0
  13. package/docs/monitor.md +953 -0
  14. package/docs/open-rpc/index.html +46 -0
  15. package/docs/services.md +6377 -0
  16. package/docs/setup.md +1268 -0
  17. package/docs/storage.md +5367 -0
  18. package/docs/wallet.md +19626 -0
  19. package/jest.config.ts +25 -0
  20. package/license.md +28 -0
  21. package/out/tsconfig.all.tsbuildinfo +1 -0
  22. package/package.json +63 -0
  23. package/src/CWIStyleWalletManager.ts +1999 -0
  24. package/src/Setup.ts +579 -0
  25. package/src/SetupClient.ts +322 -0
  26. package/src/SetupWallet.ts +108 -0
  27. package/src/SimpleWalletManager.ts +526 -0
  28. package/src/Wallet.ts +1169 -0
  29. package/src/WalletAuthenticationManager.ts +153 -0
  30. package/src/WalletLogger.ts +213 -0
  31. package/src/WalletPermissionsManager.ts +3660 -0
  32. package/src/WalletSettingsManager.ts +114 -0
  33. package/src/__tests/CWIStyleWalletManager.test.d.ts.map +1 -0
  34. package/src/__tests/CWIStyleWalletManager.test.js.map +1 -0
  35. package/src/__tests/CWIStyleWalletManager.test.ts +675 -0
  36. package/src/__tests/WalletPermissionsManager.callbacks.test.ts +323 -0
  37. package/src/__tests/WalletPermissionsManager.checks.test.ts +844 -0
  38. package/src/__tests/WalletPermissionsManager.encryption.test.ts +412 -0
  39. package/src/__tests/WalletPermissionsManager.fixtures.ts +307 -0
  40. package/src/__tests/WalletPermissionsManager.flows.test.ts +462 -0
  41. package/src/__tests/WalletPermissionsManager.initialization.test.ts +300 -0
  42. package/src/__tests/WalletPermissionsManager.pmodules.test.ts +798 -0
  43. package/src/__tests/WalletPermissionsManager.proxying.test.ts +724 -0
  44. package/src/__tests/WalletPermissionsManager.tokens.test.ts +503 -0
  45. package/src/index.all.ts +27 -0
  46. package/src/index.client.ts +25 -0
  47. package/src/index.mobile.ts +21 -0
  48. package/src/index.ts +1 -0
  49. package/src/monitor/Monitor.ts +412 -0
  50. package/src/monitor/MonitorDaemon.ts +188 -0
  51. package/src/monitor/README.md +3 -0
  52. package/src/monitor/__test/MonitorDaemon.man.test.ts +45 -0
  53. package/src/monitor/tasks/TaskCheckForProofs.ts +243 -0
  54. package/src/monitor/tasks/TaskCheckNoSends.ts +73 -0
  55. package/src/monitor/tasks/TaskClock.ts +33 -0
  56. package/src/monitor/tasks/TaskFailAbandoned.ts +54 -0
  57. package/src/monitor/tasks/TaskMonitorCallHistory.ts +26 -0
  58. package/src/monitor/tasks/TaskNewHeader.ts +93 -0
  59. package/src/monitor/tasks/TaskPurge.ts +68 -0
  60. package/src/monitor/tasks/TaskReorg.ts +89 -0
  61. package/src/monitor/tasks/TaskReviewStatus.ts +48 -0
  62. package/src/monitor/tasks/TaskSendWaiting.ts +122 -0
  63. package/src/monitor/tasks/TaskSyncWhenIdle.ts +26 -0
  64. package/src/monitor/tasks/TaskUnFail.ts +151 -0
  65. package/src/monitor/tasks/WalletMonitorTask.ts +47 -0
  66. package/src/sdk/CertOpsWallet.ts +18 -0
  67. package/src/sdk/PrivilegedKeyManager.ts +372 -0
  68. package/src/sdk/README.md +13 -0
  69. package/src/sdk/WERR_errors.ts +234 -0
  70. package/src/sdk/WalletError.ts +170 -0
  71. package/src/sdk/WalletErrorFromJson.ts +80 -0
  72. package/src/sdk/WalletServices.interfaces.ts +700 -0
  73. package/src/sdk/WalletSigner.interfaces.ts +11 -0
  74. package/src/sdk/WalletStorage.interfaces.ts +606 -0
  75. package/src/sdk/__test/CertificateLifeCycle.test.ts +131 -0
  76. package/src/sdk/__test/PrivilegedKeyManager.test.ts +738 -0
  77. package/src/sdk/__test/WalletError.test.ts +318 -0
  78. package/src/sdk/__test/validationHelpers.test.ts +21 -0
  79. package/src/sdk/index.ts +10 -0
  80. package/src/sdk/types.ts +226 -0
  81. package/src/services/README.md +11 -0
  82. package/src/services/ServiceCollection.ts +248 -0
  83. package/src/services/Services.ts +603 -0
  84. package/src/services/__tests/ARC.man.test.ts +123 -0
  85. package/src/services/__tests/ARC.timeout.man.test.ts +79 -0
  86. package/src/services/__tests/ArcGorillaPool.man.test.ts +108 -0
  87. package/src/services/__tests/arcServices.test.ts +8 -0
  88. package/src/services/__tests/bitrails.test.ts +56 -0
  89. package/src/services/__tests/getMerklePath.test.ts +15 -0
  90. package/src/services/__tests/getRawTx.test.ts +13 -0
  91. package/src/services/__tests/postBeef.test.ts +104 -0
  92. package/src/services/__tests/verifyBeef.test.ts +50 -0
  93. package/src/services/chaintracker/BHServiceClient.ts +212 -0
  94. package/src/services/chaintracker/ChaintracksChainTracker.ts +71 -0
  95. package/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts +33 -0
  96. package/src/services/chaintracker/__tests/ChaintracksServiceClient.test.ts +29 -0
  97. package/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.ts +72 -0
  98. package/src/services/chaintracker/chaintracks/Api/BulkIngestorApi.ts +83 -0
  99. package/src/services/chaintracker/chaintracks/Api/BulkStorageApi.ts +92 -0
  100. package/src/services/chaintracker/chaintracks/Api/ChaintracksApi.ts +64 -0
  101. package/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.ts +189 -0
  102. package/src/services/chaintracker/chaintracks/Api/ChaintracksFetchApi.ts +18 -0
  103. package/src/services/chaintracker/chaintracks/Api/ChaintracksFsApi.ts +58 -0
  104. package/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.ts +386 -0
  105. package/src/services/chaintracker/chaintracks/Api/LiveIngestorApi.ts +25 -0
  106. package/src/services/chaintracker/chaintracks/Chaintracks.ts +609 -0
  107. package/src/services/chaintracker/chaintracks/ChaintracksService.ts +199 -0
  108. package/src/services/chaintracker/chaintracks/ChaintracksServiceClient.ts +154 -0
  109. package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorBase.ts +176 -0
  110. package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDN.ts +174 -0
  111. package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts +18 -0
  112. package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainCdn.ts +113 -0
  113. package/src/services/chaintracker/chaintracks/Ingest/BulkIngestorWhatsOnChainWs.ts +81 -0
  114. package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorBase.ts +86 -0
  115. package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorTeranodeP2P.ts +59 -0
  116. package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainPoll.ts +104 -0
  117. package/src/services/chaintracker/chaintracks/Ingest/LiveIngestorWhatsOnChainWs.ts +66 -0
  118. package/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.ts +566 -0
  119. package/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainServices.ts +219 -0
  120. package/src/services/chaintracker/chaintracks/Ingest/__tests/BulkIngestorCDNBabbage.test.ts +54 -0
  121. package/src/services/chaintracker/chaintracks/Ingest/__tests/LiveIngestorWhatsOnChainPoll.test.ts +33 -0
  122. package/src/services/chaintracker/chaintracks/Ingest/__tests/WhatsOnChainServices.test.ts +124 -0
  123. package/src/services/chaintracker/chaintracks/Storage/BulkStorageBase.ts +92 -0
  124. package/src/services/chaintracker/chaintracks/Storage/ChaintracksKnexMigrations.ts +104 -0
  125. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageBase.ts +382 -0
  126. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.ts +574 -0
  127. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.ts +438 -0
  128. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageMemory.ts +29 -0
  129. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.ts +304 -0
  130. package/src/services/chaintracker/chaintracks/Storage/__tests/ChaintracksStorageIdb.test.ts +102 -0
  131. package/src/services/chaintracker/chaintracks/Storage/__tests/ChaintracksStorageKnex.test.ts +45 -0
  132. package/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.ts +77 -0
  133. package/src/services/chaintracker/chaintracks/__tests/ChaintracksClientApi.test.ts +192 -0
  134. package/src/services/chaintracker/chaintracks/__tests/LocalCdnServer.ts +75 -0
  135. package/src/services/chaintracker/chaintracks/__tests/createIdbChaintracks.test.ts +62 -0
  136. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNetBlockHeaders.json +1 -0
  137. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_0.headers +0 -0
  138. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_1.headers +0 -0
  139. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_2.headers +0 -0
  140. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest349/mainNet_3.headers +0 -0
  141. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNetBlockHeaders.json +1 -0
  142. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_0.headers +0 -0
  143. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_1.headers +0 -0
  144. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_2.headers +0 -0
  145. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest379/mainNet_3.headers +0 -0
  146. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNetBlockHeaders.json +1 -0
  147. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_0.headers +0 -0
  148. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_1.headers +0 -0
  149. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_2.headers +0 -0
  150. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest399/mainNet_3.headers +0 -0
  151. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNetBlockHeaders.json +1 -0
  152. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_0.headers +0 -0
  153. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_1.headers +0 -0
  154. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_2.headers +0 -0
  155. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_3.headers +0 -0
  156. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest402/mainNet_4.headers +0 -0
  157. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNetBlockHeaders.json +1 -0
  158. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_0.headers +0 -0
  159. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_1.headers +0 -0
  160. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_2.headers +0 -0
  161. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_3.headers +0 -0
  162. package/src/services/chaintracker/chaintracks/__tests/data/cdnTest499/mainNet_4.headers +0 -0
  163. package/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts +92 -0
  164. package/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts +111 -0
  165. package/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts +91 -0
  166. package/src/services/chaintracker/chaintracks/createIdbChaintracks.ts +60 -0
  167. package/src/services/chaintracker/chaintracks/createKnexChaintracks.ts +65 -0
  168. package/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts +60 -0
  169. package/src/services/chaintracker/chaintracks/index.all.ts +12 -0
  170. package/src/services/chaintracker/chaintracks/index.client.ts +4 -0
  171. package/src/services/chaintracker/chaintracks/index.mobile.ts +37 -0
  172. package/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts +975 -0
  173. package/src/services/chaintracker/chaintracks/util/BulkFileDataReader.ts +60 -0
  174. package/src/services/chaintracker/chaintracks/util/BulkFilesReader.ts +336 -0
  175. package/src/services/chaintracker/chaintracks/util/BulkHeaderFile.ts +247 -0
  176. package/src/services/chaintracker/chaintracks/util/ChaintracksFetch.ts +69 -0
  177. package/src/services/chaintracker/chaintracks/util/ChaintracksFs.ts +141 -0
  178. package/src/services/chaintracker/chaintracks/util/HeightRange.ts +153 -0
  179. package/src/services/chaintracker/chaintracks/util/SingleWriterMultiReaderLock.ts +76 -0
  180. package/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts +304 -0
  181. package/src/services/chaintracker/chaintracks/util/__tests/ChaintracksFetch.test.ts +60 -0
  182. package/src/services/chaintracker/chaintracks/util/__tests/HeightRange.test.ts +67 -0
  183. package/src/services/chaintracker/chaintracks/util/__tests/SingleWriterMultiReaderLock.test.ts +49 -0
  184. package/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.ts +573 -0
  185. package/src/services/chaintracker/chaintracks/util/dirtyHashes.ts +29 -0
  186. package/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts +432 -0
  187. package/src/services/chaintracker/index.all.ts +4 -0
  188. package/src/services/chaintracker/index.client.ts +4 -0
  189. package/src/services/chaintracker/index.mobile.ts +4 -0
  190. package/src/services/createDefaultWalletServicesOptions.ts +77 -0
  191. package/src/services/index.ts +1 -0
  192. package/src/services/processingErrors/arcSuccessError.json +76 -0
  193. package/src/services/providers/ARC.ts +350 -0
  194. package/src/services/providers/Bitails.ts +256 -0
  195. package/src/services/providers/SdkWhatsOnChain.ts +83 -0
  196. package/src/services/providers/WhatsOnChain.ts +883 -0
  197. package/src/services/providers/__tests/WhatsOnChain.test.ts +242 -0
  198. package/src/services/providers/__tests/exchangeRates.test.ts +18 -0
  199. package/src/services/providers/exchangeRates.ts +265 -0
  200. package/src/services/providers/getBeefForTxid.ts +369 -0
  201. package/src/signer/README.md +5 -0
  202. package/src/signer/WalletSigner.ts +17 -0
  203. package/src/signer/methods/acquireDirectCertificate.ts +52 -0
  204. package/src/signer/methods/buildSignableTransaction.ts +183 -0
  205. package/src/signer/methods/completeSignedTransaction.ts +117 -0
  206. package/src/signer/methods/createAction.ts +172 -0
  207. package/src/signer/methods/internalizeAction.ts +106 -0
  208. package/src/signer/methods/proveCertificate.ts +43 -0
  209. package/src/signer/methods/signAction.ts +54 -0
  210. package/src/storage/README.md +14 -0
  211. package/src/storage/StorageIdb.ts +2304 -0
  212. package/src/storage/StorageKnex.ts +1425 -0
  213. package/src/storage/StorageProvider.ts +810 -0
  214. package/src/storage/StorageReader.ts +194 -0
  215. package/src/storage/StorageReaderWriter.ts +432 -0
  216. package/src/storage/StorageSyncReader.ts +34 -0
  217. package/src/storage/WalletStorageManager.ts +943 -0
  218. package/src/storage/__test/StorageIdb.test.ts +43 -0
  219. package/src/storage/__test/WalletStorageManager.test.ts +275 -0
  220. package/src/storage/__test/adminStats.man.test.ts +89 -0
  221. package/src/storage/__test/getBeefForTransaction.test.ts +385 -0
  222. package/src/storage/index.all.ts +11 -0
  223. package/src/storage/index.client.ts +7 -0
  224. package/src/storage/index.mobile.ts +6 -0
  225. package/src/storage/methods/ListActionsSpecOp.ts +70 -0
  226. package/src/storage/methods/ListOutputsSpecOp.ts +129 -0
  227. package/src/storage/methods/__test/GenerateChange/generateChangeSdk.test.ts +1057 -0
  228. package/src/storage/methods/__test/GenerateChange/randomValsUsed1.ts +20 -0
  229. package/src/storage/methods/__test/offsetKey.test.ts +274 -0
  230. package/src/storage/methods/attemptToPostReqsToNetwork.ts +389 -0
  231. package/src/storage/methods/createAction.ts +947 -0
  232. package/src/storage/methods/generateChange.ts +556 -0
  233. package/src/storage/methods/getBeefForTransaction.ts +139 -0
  234. package/src/storage/methods/getSyncChunk.ts +293 -0
  235. package/src/storage/methods/internalizeAction.ts +562 -0
  236. package/src/storage/methods/listActionsIdb.ts +183 -0
  237. package/src/storage/methods/listActionsKnex.ts +226 -0
  238. package/src/storage/methods/listCertificates.ts +73 -0
  239. package/src/storage/methods/listOutputsIdb.ts +203 -0
  240. package/src/storage/methods/listOutputsKnex.ts +263 -0
  241. package/src/storage/methods/offsetKey.ts +89 -0
  242. package/src/storage/methods/processAction.ts +420 -0
  243. package/src/storage/methods/purgeData.ts +251 -0
  244. package/src/storage/methods/purgeDataIdb.ts +10 -0
  245. package/src/storage/methods/reviewStatus.ts +101 -0
  246. package/src/storage/methods/reviewStatusIdb.ts +43 -0
  247. package/src/storage/methods/utils.Buffer.ts +33 -0
  248. package/src/storage/methods/utils.ts +56 -0
  249. package/src/storage/remoting/StorageClient.ts +567 -0
  250. package/src/storage/remoting/StorageMobile.ts +544 -0
  251. package/src/storage/remoting/StorageServer.ts +291 -0
  252. package/src/storage/remoting/__test/StorageClient.test.ts +113 -0
  253. package/src/storage/schema/KnexMigrations.ts +489 -0
  254. package/src/storage/schema/StorageIdbSchema.ts +150 -0
  255. package/src/storage/schema/entities/EntityBase.ts +210 -0
  256. package/src/storage/schema/entities/EntityCertificate.ts +188 -0
  257. package/src/storage/schema/entities/EntityCertificateField.ts +136 -0
  258. package/src/storage/schema/entities/EntityCommission.ts +148 -0
  259. package/src/storage/schema/entities/EntityOutput.ts +290 -0
  260. package/src/storage/schema/entities/EntityOutputBasket.ts +153 -0
  261. package/src/storage/schema/entities/EntityOutputTag.ts +121 -0
  262. package/src/storage/schema/entities/EntityOutputTagMap.ts +123 -0
  263. package/src/storage/schema/entities/EntityProvenTx.ts +319 -0
  264. package/src/storage/schema/entities/EntityProvenTxReq.ts +580 -0
  265. package/src/storage/schema/entities/EntitySyncState.ts +389 -0
  266. package/src/storage/schema/entities/EntityTransaction.ts +306 -0
  267. package/src/storage/schema/entities/EntityTxLabel.ts +121 -0
  268. package/src/storage/schema/entities/EntityTxLabelMap.ts +123 -0
  269. package/src/storage/schema/entities/EntityUser.ts +112 -0
  270. package/src/storage/schema/entities/MergeEntity.ts +73 -0
  271. package/src/storage/schema/entities/__tests/CertificateFieldTests.test.ts +353 -0
  272. package/src/storage/schema/entities/__tests/CertificateTests.test.ts +354 -0
  273. package/src/storage/schema/entities/__tests/CommissionTests.test.ts +371 -0
  274. package/src/storage/schema/entities/__tests/OutputBasketTests.test.ts +278 -0
  275. package/src/storage/schema/entities/__tests/OutputTagMapTests.test.ts +242 -0
  276. package/src/storage/schema/entities/__tests/OutputTagTests.test.ts +288 -0
  277. package/src/storage/schema/entities/__tests/OutputTests.test.ts +464 -0
  278. package/src/storage/schema/entities/__tests/ProvenTxReqTests.test.ts +340 -0
  279. package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +504 -0
  280. package/src/storage/schema/entities/__tests/SyncStateTests.test.ts +288 -0
  281. package/src/storage/schema/entities/__tests/TransactionTests.test.ts +604 -0
  282. package/src/storage/schema/entities/__tests/TxLabelMapTests.test.ts +361 -0
  283. package/src/storage/schema/entities/__tests/TxLabelTests.test.ts +198 -0
  284. package/src/storage/schema/entities/__tests/stampLogTests.test.ts +90 -0
  285. package/src/storage/schema/entities/__tests/usersTests.test.ts +340 -0
  286. package/src/storage/schema/entities/index.ts +16 -0
  287. package/src/storage/schema/tables/TableCertificate.ts +21 -0
  288. package/src/storage/schema/tables/TableCertificateField.ts +12 -0
  289. package/src/storage/schema/tables/TableCommission.ts +13 -0
  290. package/src/storage/schema/tables/TableMonitorEvent.ts +9 -0
  291. package/src/storage/schema/tables/TableOutput.ts +64 -0
  292. package/src/storage/schema/tables/TableOutputBasket.ts +12 -0
  293. package/src/storage/schema/tables/TableOutputTag.ts +10 -0
  294. package/src/storage/schema/tables/TableOutputTagMap.ts +9 -0
  295. package/src/storage/schema/tables/TableProvenTx.ts +14 -0
  296. package/src/storage/schema/tables/TableProvenTxReq.ts +65 -0
  297. package/src/storage/schema/tables/TableSettings.ts +17 -0
  298. package/src/storage/schema/tables/TableSyncState.ts +18 -0
  299. package/src/storage/schema/tables/TableTransaction.ts +54 -0
  300. package/src/storage/schema/tables/TableTxLabel.ts +10 -0
  301. package/src/storage/schema/tables/TableTxLabelMap.ts +9 -0
  302. package/src/storage/schema/tables/TableUser.ts +16 -0
  303. package/src/storage/schema/tables/index.ts +16 -0
  304. package/src/storage/sync/StorageMySQLDojoReader.ts +696 -0
  305. package/src/storage/sync/index.ts +1 -0
  306. package/src/utility/Format.ts +133 -0
  307. package/src/utility/README.md +3 -0
  308. package/src/utility/ReaderUint8Array.ts +187 -0
  309. package/src/utility/ScriptTemplateBRC29.ts +73 -0
  310. package/src/utility/__tests/utilityHelpers.noBuffer.test.ts +109 -0
  311. package/src/utility/aggregateResults.ts +68 -0
  312. package/src/utility/identityUtils.ts +159 -0
  313. package/src/utility/index.all.ts +7 -0
  314. package/src/utility/index.client.ts +7 -0
  315. package/src/utility/parseTxScriptOffsets.ts +29 -0
  316. package/src/utility/stampLog.ts +69 -0
  317. package/src/utility/tscProofToMerklePath.ts +48 -0
  318. package/src/utility/utilityHelpers.buffer.ts +34 -0
  319. package/src/utility/utilityHelpers.noBuffer.ts +60 -0
  320. package/src/utility/utilityHelpers.ts +275 -0
  321. package/src/wab-client/WABClient.ts +94 -0
  322. package/src/wab-client/__tests/WABClient.man.test.ts +59 -0
  323. package/src/wab-client/auth-method-interactors/AuthMethodInteractor.ts +47 -0
  324. package/src/wab-client/auth-method-interactors/DevConsoleInteractor.ts +73 -0
  325. package/src/wab-client/auth-method-interactors/PersonaIDInteractor.ts +35 -0
  326. package/src/wab-client/auth-method-interactors/TwilioPhoneInteractor.ts +72 -0
  327. package/syncVersions.js +71 -0
  328. package/test/Wallet/StorageClient/storageClient.man.test.ts +75 -0
  329. package/test/Wallet/action/abortAction.test.ts +47 -0
  330. package/test/Wallet/action/createAction.test.ts +299 -0
  331. package/test/Wallet/action/createAction2.test.ts +1273 -0
  332. package/test/Wallet/action/createActionToGenerateBeefs.man.test.ts +293 -0
  333. package/test/Wallet/action/internalizeAction.a.test.ts +286 -0
  334. package/test/Wallet/action/internalizeAction.test.ts +682 -0
  335. package/test/Wallet/action/relinquishOutput.test.ts +37 -0
  336. package/test/Wallet/certificate/acquireCertificate.test.ts +298 -0
  337. package/test/Wallet/certificate/listCertificates.test.ts +346 -0
  338. package/test/Wallet/construct/Wallet.constructor.test.ts +57 -0
  339. package/test/Wallet/get/getHeaderForHeight.test.ts +82 -0
  340. package/test/Wallet/get/getHeight.test.ts +52 -0
  341. package/test/Wallet/get/getKnownTxids.test.ts +86 -0
  342. package/test/Wallet/get/getNetwork.test.ts +27 -0
  343. package/test/Wallet/get/getVersion.test.ts +27 -0
  344. package/test/Wallet/list/listActions.test.ts +279 -0
  345. package/test/Wallet/list/listActions2.test.ts +1381 -0
  346. package/test/Wallet/list/listCertificates.test.ts +118 -0
  347. package/test/Wallet/list/listOutputs.test.ts +447 -0
  348. package/test/Wallet/live/walletLive.man.test.ts +521 -0
  349. package/test/Wallet/local/localWallet.man.test.ts +93 -0
  350. package/test/Wallet/local/localWallet2.man.test.ts +277 -0
  351. package/test/Wallet/signAction/mountaintop.man.test.ts +130 -0
  352. package/test/Wallet/specOps/specOps.man.test.ts +220 -0
  353. package/test/Wallet/support/janitor.man.test.ts +40 -0
  354. package/test/Wallet/support/operations.man.test.ts +407 -0
  355. package/test/Wallet/support/reqErrorReview.2025.05.06.man.test.ts +347 -0
  356. package/test/Wallet/sync/Wallet.sync.test.ts +215 -0
  357. package/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.ts +203 -0
  358. package/test/Wallet/sync/setActive.test.ts +170 -0
  359. package/test/WalletClient/LocalKVStore.man.test.ts +114 -0
  360. package/test/WalletClient/WERR.man.test.ts +35 -0
  361. package/test/bsv-ts-sdk/LocalKVStore.test.ts +102 -0
  362. package/test/checkDB.ts +57 -0
  363. package/test/checkdb +0 -0
  364. package/test/examples/backup.man.test.ts +59 -0
  365. package/test/examples/pushdrop.test.ts +282 -0
  366. package/test/monitor/Monitor.test.ts +620 -0
  367. package/test/services/Services.test.ts +263 -0
  368. package/test/storage/KnexMigrations.test.ts +86 -0
  369. package/test/storage/StorageMySQLDojoReader.man.test.ts +60 -0
  370. package/test/storage/count.test.ts +177 -0
  371. package/test/storage/find.test.ts +195 -0
  372. package/test/storage/findLegacy.test.ts +67 -0
  373. package/test/storage/idb/allocateChange.test.ts +251 -0
  374. package/test/storage/idb/count.test.ts +158 -0
  375. package/test/storage/idb/find.test.ts +177 -0
  376. package/test/storage/idb/idbSpeed.test.ts +36 -0
  377. package/test/storage/idb/insert.test.ts +268 -0
  378. package/test/storage/idb/transactionAbort.test.ts +108 -0
  379. package/test/storage/idb/update.test.ts +999 -0
  380. package/test/storage/insert.test.ts +278 -0
  381. package/test/storage/update.test.ts +1021 -0
  382. package/test/storage/update2.test.ts +897 -0
  383. package/test/utils/TestUtilsWalletStorage.ts +2526 -0
  384. package/test/utils/localWalletMethods.ts +363 -0
  385. package/test/utils/removeFailedFromDatabase.sql +17 -0
  386. package/ts2md.json +44 -0
  387. package/tsconfig.all.json +31 -0
  388. package/tsconfig.client.json +29 -0
  389. package/tsconfig.json +17 -0
  390. 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
+ }