@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,897 @@
1
+ /* Additional update tests for setting edge cases and exercising contraints (unique/foreign) */
2
+ /* Requires a new DB for each test */
3
+ import { _tu, TestSetup1 } from '../utils/TestUtilsWalletStorage'
4
+ import { sdk, StorageProvider, StorageKnex, verifyOne } from '../../src/index.all'
5
+ import {
6
+ normalizeDate,
7
+ setLogging,
8
+ triggerForeignKeyConstraintError,
9
+ triggerUniqueConstraintError,
10
+ updateTable,
11
+ validateUpdateTime,
12
+ verifyValues
13
+ } from '../utils/TestUtilsWalletStorage'
14
+ import {
15
+ TableProvenTx,
16
+ TableProvenTxReq,
17
+ TableUser,
18
+ TableCertificate,
19
+ TableCertificateField,
20
+ TableOutputBasket,
21
+ TableTransaction,
22
+ TableCommission,
23
+ TableOutput,
24
+ TableOutputTag,
25
+ TableOutputTagMap,
26
+ TableTxLabel,
27
+ TableTxLabelMap,
28
+ TableMonitorEvent,
29
+ TableSyncState
30
+ } from '../../src/storage/schema/tables'
31
+
32
+ setLogging(false)
33
+
34
+ import knex, { Knex } from 'knex'
35
+
36
+ describe('update2 tests', () => {
37
+ const storages: StorageKnex[] = []
38
+ const setups: { setup: TestSetup1; storage: StorageKnex }[] = []
39
+ const chain: sdk.Chain = 'test'
40
+
41
+ const createDB = async (databaseName: string): Promise<void> => {
42
+ const localSQLiteFile = await _tu.newTmpFile(`${databaseName}.sqlite`, false, false, true)
43
+
44
+ // Need to pool connections
45
+ const knexSQLite: Knex = knex({
46
+ client: 'sqlite3',
47
+ connection: {
48
+ filename: localSQLiteFile
49
+ },
50
+ useNullAsDefault: true,
51
+ pool: {
52
+ min: 1,
53
+ max: 5
54
+ }
55
+ })
56
+
57
+ const storage = new StorageKnex({
58
+ ...StorageKnex.defaultOptions(),
59
+ knex: knexSQLite,
60
+ chain
61
+ })
62
+
63
+ storages.push(storage)
64
+
65
+ await storage.dropAllData()
66
+ await storage.migrate('test setup', '1'.repeat(64))
67
+ await storage.makeAvailable()
68
+ const setup = await _tu.createTestSetup1(storage)
69
+
70
+ setups.push({ setup, storage })
71
+ }
72
+
73
+ afterEach(async () => {
74
+ for (const storage of storages) {
75
+ if (storage instanceof StorageKnex) {
76
+ await storage.knex.destroy()
77
+ }
78
+ }
79
+ storages.length = 0
80
+ setups.length = 0
81
+ })
82
+
83
+ test('1_update ProvenTx', async () => {
84
+ await createDB('ProvenTx1')
85
+ for (const { storage } of setups) {
86
+ const records = await storage.findProvenTxs({ partial: {} })
87
+ const time = new Date('2001-01-02T12:00:00.000Z')
88
+ for (const record of records) {
89
+ await storage.updateProvenTx(record.provenTxId, {
90
+ blockHash: 'fred',
91
+ updated_at: time
92
+ })
93
+ const t = verifyOne(
94
+ await storage.findProvenTxs({
95
+ partial: { provenTxId: record.provenTxId }
96
+ })
97
+ )
98
+ expect(t.provenTxId).toBe(record.provenTxId)
99
+ expect(t.blockHash).toBe('fred')
100
+ expect(t.updated_at.getTime()).toBe(time.getTime())
101
+ }
102
+ }
103
+ })
104
+
105
+ test('2_update ProvenTx', async () => {
106
+ await createDB('ProvenTx2')
107
+ const primaryKey = 'provenTxId'
108
+ for (const { storage } of setups) {
109
+ const referenceTime = new Date()
110
+ const records = await storage.findProvenTxs({ partial: {} })
111
+ for (const record of records) {
112
+ try {
113
+ const testValues: TableProvenTx = {
114
+ provenTxId: record.provenTxId,
115
+ txid: 'mockTxid',
116
+ created_at: new Date('2024-12-30T23:00:00Z'),
117
+ updated_at: new Date('2024-12-30T23:05:00Z'),
118
+ blockHash: 'mockBlockHash',
119
+ height: 12345,
120
+ index: 1,
121
+ merklePath: [1, 2, 3, 4],
122
+ merkleRoot: '1234',
123
+ rawTx: [4, 3, 2, 1]
124
+ }
125
+ await updateTable(storage.updateProvenTx.bind(storage), record[primaryKey], testValues)
126
+ const updatedTx = verifyOne(
127
+ await storage.findProvenTxs({
128
+ partial: { [primaryKey]: record[primaryKey] }
129
+ })
130
+ )
131
+ verifyValues(updatedTx, testValues, referenceTime)
132
+ for (const [key, value] of Object.entries(testValues)) {
133
+ if (key === primaryKey) {
134
+ continue
135
+ }
136
+ if (typeof value === 'string') {
137
+ const validString = `valid${key}`
138
+ const r1 = await storage.updateProvenTx(record[primaryKey], {
139
+ [key]: validString
140
+ })
141
+ expect(r1).toBe(1)
142
+ const updatedRow = verifyOne(
143
+ await storage.findProvenTxs({
144
+ partial: { [primaryKey]: record[primaryKey] }
145
+ })
146
+ )
147
+ expect(updatedRow[key]).toBe(validString)
148
+ }
149
+ if (typeof value === 'number') {
150
+ const validNumber = value + 1
151
+ const r1 = await storage.updateProvenTx(record[primaryKey], {
152
+ [key]: validNumber
153
+ })
154
+ expect(r1).toBe(1)
155
+ const updatedRow = verifyOne(
156
+ await storage.findProvenTxs({
157
+ partial: { [primaryKey]: record[primaryKey] }
158
+ })
159
+ )
160
+ expect(updatedRow[key]).toBe(validNumber)
161
+ }
162
+ if (value instanceof Date) {
163
+ const validDate = new Date('2024-12-31T00:00:00Z')
164
+ const r1 = await storage.updateProvenTx(record[primaryKey], {
165
+ [key]: validDate
166
+ })
167
+ expect(r1).toBe(1)
168
+ const updatedRow = verifyOne(
169
+ await storage.findProvenTxs({
170
+ partial: { [primaryKey]: record[primaryKey] }
171
+ })
172
+ )
173
+ expect(new Date(updatedRow[key]).toISOString()).toBe(validDate.toISOString())
174
+ }
175
+ if (Array.isArray(value)) {
176
+ const validArray = value.map(v => v + 1)
177
+ const r1 = await storage.updateProvenTx(record[primaryKey], {
178
+ [key]: validArray
179
+ })
180
+ expect(r1).toBe(1)
181
+ const updatedRow = verifyOne(
182
+ await storage.findProvenTxs({
183
+ partial: { [primaryKey]: record[primaryKey] }
184
+ })
185
+ )
186
+ expect(updatedRow[key]).toEqual(validArray)
187
+ }
188
+ }
189
+ } catch (error: any) {
190
+ console.error(
191
+ `Error updating or verifying ProvenTx record with ${primaryKey}=${record[primaryKey]}:`,
192
+ error.message
193
+ )
194
+ throw error
195
+ }
196
+ }
197
+ }
198
+ })
199
+
200
+ test('3_update ProvenTx set created_at and updated_at time', async () => {
201
+ await createDB('ProvenTx3')
202
+ for (const { storage } of setups) {
203
+ const scenarios = [
204
+ {
205
+ description: 'Invalid created_at time',
206
+ updates: {
207
+ created_at: new Date('3000-01-01T00:00:00Z'),
208
+ updated_at: new Date('2024-12-30T23:05:00Z')
209
+ }
210
+ },
211
+ {
212
+ description: 'Invalid updated_at time',
213
+ updates: {
214
+ created_at: new Date('2024-12-30T23:00:00Z'),
215
+ updated_at: new Date('3000-01-01T00:00:00Z')
216
+ }
217
+ },
218
+ {
219
+ description: 'created_at time overwrites updated_at time',
220
+ updates: {
221
+ created_at: new Date('2024-12-30T23:00:00Z'),
222
+ updated_at: new Date('2024-12-30T23:05:00Z')
223
+ }
224
+ }
225
+ ]
226
+ for (const { updates } of scenarios) {
227
+ const referenceTime = new Date()
228
+ const records = await storage.findProvenTxs({ partial: {} })
229
+ for (const record of records) {
230
+ await storage.updateProvenTx(record.provenTxId, {
231
+ created_at: updates.created_at
232
+ })
233
+ await storage.updateProvenTx(record.provenTxId, {
234
+ updated_at: updates.updated_at
235
+ })
236
+ const t = verifyOne(
237
+ await storage.findProvenTxs({
238
+ partial: { provenTxId: record.provenTxId }
239
+ })
240
+ )
241
+ expect(validateUpdateTime(t.created_at, updates.created_at, referenceTime, 10, false)).toBe(true)
242
+ expect(validateUpdateTime(t.updated_at, updates.updated_at, referenceTime, 10, false)).toBe(true)
243
+ }
244
+ }
245
+ }
246
+ })
247
+
248
+ test('4_update ProvenTx setting individual values', async () => {
249
+ await createDB('ProvenTx4')
250
+ for (const { storage } of setups) {
251
+ const initialRecord: TableProvenTx = {
252
+ provenTxId: 3,
253
+ txid: 'mockTxid',
254
+ created_at: new Date(),
255
+ updated_at: new Date(),
256
+ blockHash: '',
257
+ height: 1,
258
+ index: 1,
259
+ merklePath: [],
260
+ merkleRoot: '',
261
+ rawTx: []
262
+ }
263
+ try {
264
+ const r = await storage.insertProvenTx(initialRecord)
265
+ expect(r).toBeGreaterThan(0)
266
+ const insertedRecords = await storage.findProvenTxs({ partial: {} })
267
+ expect(insertedRecords.length).toBeGreaterThan(0)
268
+ const foundRecord = insertedRecords.find(record => record.provenTxId === 3)
269
+ expect(foundRecord).toBeDefined()
270
+ expect(foundRecord?.txid).toBe('mockTxid')
271
+ } catch (error: any) {
272
+ console.error('Error inserting initial record:', (error as Error).message)
273
+ return
274
+ }
275
+ await expect(storage.updateProvenTx(1, { provenTxId: 0 })).rejects.toThrow(/FOREIGN KEY constraint failed/)
276
+ const r1 = await storage.updateProvenTx(3, { provenTxId: 0 })
277
+ await expect(Promise.resolve(r1)).resolves.toBe(1)
278
+ const r2 = await storage.findProvenTxs({ partial: {} })
279
+ expect(r2[0].provenTxId).toBe(0)
280
+ expect(r2[1].provenTxId).toBe(1)
281
+ const r3 = await storage.updateProvenTx(0, { provenTxId: 3 })
282
+ await expect(Promise.resolve(r3)).resolves.toBe(1)
283
+ const r4 = await storage.findProvenTxs({ partial: {} })
284
+ expect(r4[0].provenTxId).toBe(1)
285
+ expect(r4[1].provenTxId).toBe(3)
286
+ const r8 = await storage.updateProvenTx(3, { txid: 'mockValidTxid' })
287
+ await expect(Promise.resolve(r8)).resolves.toBe(1)
288
+ const r9 = await storage.findProvenTxs({ partial: {} })
289
+ expect(r9.find(r => r.provenTxId === 3)?.txid).toBe('mockValidTxid')
290
+ }
291
+ })
292
+
293
+ test('5_update ProvenTxReq', async () => {
294
+ await createDB('ProvenTx5')
295
+ const primaryKey = 'provenTxReqId'
296
+ for (const { storage } of setups) {
297
+ const records = await storage.findProvenTxReqs({ partial: {} })
298
+ let i = -1
299
+ for (const record of records) {
300
+ i++
301
+ try {
302
+ const testValues: TableProvenTxReq = {
303
+ provenTxReqId: record.provenTxReqId,
304
+ provenTxId: 1,
305
+ batch: `batch-001`,
306
+ status: 'completed',
307
+ txid: `mockTxid-${i}`,
308
+ created_at: new Date('2024-12-30T23:00:00Z'),
309
+ updated_at: new Date('2024-12-30T23:05:00Z'),
310
+ attempts: 3,
311
+ history: JSON.stringify({ validated: true, timestamp: Date.now() }),
312
+ inputBEEF: [5, 6, 7, 8],
313
+ notified: true,
314
+ notify: JSON.stringify({ email: 'test@example.com', sent: true }),
315
+ rawTx: [1, 2, 3, 4]
316
+ }
317
+ const r1 = await storage.updateProvenTxReq(record[primaryKey], testValues)
318
+ expect(r1).toBe(1)
319
+ const updatedRow = verifyOne(
320
+ await storage.findProvenTxReqs({
321
+ partial: { [primaryKey]: record[primaryKey] }
322
+ })
323
+ )
324
+ for (const [key, value] of Object.entries(testValues)) {
325
+ const actualValue = updatedRow[key]
326
+ const normalizedActual = normalizeDate(actualValue)
327
+ const normalizedExpected = normalizeDate(value)
328
+ if (normalizedActual && normalizedExpected) {
329
+ expect(normalizedActual).toBe(normalizedExpected)
330
+ continue
331
+ }
332
+ if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {
333
+ expect(JSON.parse(actualValue)).toStrictEqual(JSON.parse(value))
334
+ continue
335
+ }
336
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
337
+ expect(actualValue).toBe(value)
338
+ continue
339
+ }
340
+ if (typeof actualValue === 'object' && actualValue?.type === 'Buffer') {
341
+ const actualArray = actualValue.data || actualValue
342
+ const expectedArray =
343
+ Buffer.isBuffer(value) || Array.isArray(value) ? Array.from(value as ArrayLike<number>) : value
344
+ expect(actualArray).toStrictEqual(expectedArray)
345
+ continue
346
+ }
347
+ expect(JSON.stringify({ type: 'Buffer', data: actualValue })).toStrictEqual(JSON.stringify(value))
348
+ }
349
+ } catch (error: any) {
350
+ console.error(
351
+ `Error updating or verifying ProvenTxReq record with ${primaryKey}=${record[primaryKey]}:`,
352
+ error.message
353
+ )
354
+ throw error
355
+ }
356
+ }
357
+ }
358
+ })
359
+
360
+ test('6_update ProvenTxReq set created_at and updated_at time', async () => {
361
+ await createDB('ProvenTxReq6')
362
+ for (const { storage } of setups) {
363
+ const scenarios = [
364
+ {
365
+ description: 'Invalid created_at time',
366
+ updates: {
367
+ created_at: new Date('3000-01-01T00:00:00Z'),
368
+ updated_at: new Date('2024-12-30T23:05:00Z')
369
+ }
370
+ },
371
+ {
372
+ description: 'Invalid updated_at time',
373
+ updates: {
374
+ created_at: new Date('2024-12-30T23:00:00Z'),
375
+ updated_at: new Date('3000-01-01T00:00:00Z')
376
+ }
377
+ },
378
+ {
379
+ description: 'created_at time overwrites updated_at time',
380
+ updates: {
381
+ created_at: new Date('2024-12-30T23:00:00Z'),
382
+ updated_at: new Date('2024-12-30T23:05:00Z')
383
+ }
384
+ }
385
+ ]
386
+ for (const { updates } of scenarios) {
387
+ const referenceTime = new Date()
388
+ const records = await storage.findProvenTxReqs({ partial: {} })
389
+ for (const record of records) {
390
+ await storage.updateProvenTxReq(record.provenTxReqId, {
391
+ created_at: updates.created_at
392
+ })
393
+ await storage.updateProvenTxReq(record.provenTxReqId, {
394
+ updated_at: updates.updated_at
395
+ })
396
+ const t = verifyOne(
397
+ await storage.findProvenTxReqs({
398
+ partial: { provenTxReqId: record.provenTxReqId }
399
+ })
400
+ )
401
+ expect(validateUpdateTime(t.created_at, updates.created_at, referenceTime)).toBe(true)
402
+ expect(validateUpdateTime(t.updated_at, updates.updated_at, referenceTime)).toBe(true)
403
+ }
404
+ }
405
+ }
406
+ })
407
+
408
+ test('7_update ProvenTxReq setting individual values', async () => {
409
+ await createDB('ProvenTxReq7')
410
+ for (const { storage } of setups) {
411
+ const referenceTime = new Date()
412
+ const initialRecord: TableProvenTxReq = {
413
+ provenTxReqId: 3,
414
+ provenTxId: 1,
415
+ batch: 'batch',
416
+ status: 'nosend',
417
+ txid: 'mockTxid1',
418
+ created_at: referenceTime,
419
+ updated_at: referenceTime,
420
+ attempts: 0,
421
+ history: '{}',
422
+ inputBEEF: [],
423
+ notified: false,
424
+ notify: '{}',
425
+ rawTx: []
426
+ }
427
+ await storage.insertProvenTxReq(initialRecord)
428
+ const secondRecord: TableProvenTxReq = {
429
+ ...initialRecord,
430
+ provenTxReqId: 4,
431
+ txid: 'mockTxid2'
432
+ }
433
+ await storage.insertProvenTxReq(secondRecord)
434
+ const recordToUpdate3 = await storage.findProvenTxReqs({
435
+ partial: { provenTxReqId: 3 }
436
+ })
437
+ expect(recordToUpdate3.length).toBeGreaterThan(0)
438
+ const recordToUpdate4 = await storage.findProvenTxReqs({
439
+ partial: { provenTxReqId: 4 }
440
+ })
441
+ expect(recordToUpdate4.length).toBeGreaterThan(0)
442
+ const r3 = await storage.updateProvenTxReq(3, { batch: 'updatedBatch' })
443
+ await expect(Promise.resolve(r3)).resolves.toBe(1)
444
+ const updatedRecords = await storage.findProvenTxReqs({ partial: {} })
445
+ const updatedBatch = updatedRecords.find(r => r.provenTxReqId === 3)?.batch
446
+ expect(updatedBatch).toBe('updatedBatch')
447
+ try {
448
+ const r4 = await storage.updateProvenTxReq(4, { batch: 'updatedBatch' })
449
+ if (r4 === 0) {
450
+ console.warn('No rows updated. Ensure UNIQUE constraint exists on the batch column if rejection is expected.')
451
+ } else {
452
+ await expect(Promise.resolve(r4)).resolves.toBe(1)
453
+ }
454
+ } catch (error: any) {
455
+ expect(error.message).toMatch(/UNIQUE constraint failed/)
456
+ }
457
+ const r5 = await storage.updateProvenTxReq(3, { txid: 'newValidTxid' })
458
+ await expect(Promise.resolve(r5)).resolves.toBe(1)
459
+ await expect(storage.updateProvenTxReq(4, { txid: 'newValidTxid' })).rejects.toThrow(/UNIQUE constraint failed/)
460
+ const finalRecords = await storage.findProvenTxReqs({ partial: {} })
461
+ expect(finalRecords.find(r => r.provenTxReqId === 4)?.txid).toBe('mockTxid2')
462
+ await storage.updateProvenTxReq(3, { batch: 'batch', txid: 'mockTxid1' })
463
+ }
464
+ })
465
+
466
+ test('8_update User', async () => {
467
+ await createDB('User8')
468
+ const primaryKey = 'userId'
469
+ for (const { storage } of setups) {
470
+ const records = await storage.findUsers({ partial: {} })
471
+ for (const record of records) {
472
+ try {
473
+ const testValues: TableUser = {
474
+ userId: record.userId,
475
+ identityKey: `mockUpdatedIdentityKey-${record[primaryKey]}`,
476
+ created_at: new Date('2024-12-30T23:00:00Z'),
477
+ updated_at: new Date('2024-12-30T23:05:00Z'),
478
+ activeStorage: storage.getSettings().storageIdentityKey
479
+ }
480
+ const updateResult = await storage.updateUser(record[primaryKey], testValues)
481
+ expect(updateResult).toBe(1)
482
+ const updatedRow = verifyOne(
483
+ await storage.findUsers({
484
+ partial: { [primaryKey]: record[primaryKey] }
485
+ })
486
+ )
487
+ for (const [key, value] of Object.entries(testValues)) {
488
+ const actualValue = updatedRow[key]
489
+ const normalizedActual = normalizeDate(actualValue)
490
+ const normalizedExpected = normalizeDate(value)
491
+ if (normalizedActual && normalizedExpected) {
492
+ expect(normalizedActual).toBe(normalizedExpected)
493
+ continue
494
+ }
495
+ expect(actualValue).toBe(value)
496
+ }
497
+ } catch (error: any) {
498
+ console.error(
499
+ `Error updating or verifying User record with ${primaryKey}=${record[primaryKey]}:`,
500
+ error.message
501
+ )
502
+ throw error
503
+ }
504
+ }
505
+ }
506
+ })
507
+
508
+ test('9_update User set created_at and updated_at time', async () => {
509
+ await createDB('User9')
510
+ for (const { storage } of setups) {
511
+ const scenarios = [
512
+ {
513
+ description: 'Invalid created_at time',
514
+ updates: {
515
+ created_at: new Date('3000-01-01T00:00:00Z'),
516
+ updated_at: new Date('2024-12-30T23:05:00Z')
517
+ }
518
+ },
519
+ {
520
+ description: 'Invalid updated_at time',
521
+ updates: {
522
+ created_at: new Date('2024-12-30T23:00:00Z'),
523
+ updated_at: new Date('3000-01-01T00:00:00Z')
524
+ }
525
+ },
526
+ {
527
+ description: 'created_at time overwrites updated_at time',
528
+ updates: {
529
+ created_at: new Date('2024-12-30T23:00:00Z'),
530
+ updated_at: new Date('2024-12-30T23:05:00Z')
531
+ }
532
+ }
533
+ ]
534
+ for (const { description, updates } of scenarios) {
535
+ const referenceTime = new Date()
536
+ const records = await storage.findUsers({ partial: {} })
537
+ for (const record of records) {
538
+ await storage.updateUser(record.userId, {
539
+ created_at: updates.created_at
540
+ })
541
+ await storage.updateUser(record.userId, {
542
+ updated_at: updates.updated_at
543
+ })
544
+ const t = verifyOne(await storage.findUsers({ partial: { userId: record.userId } }))
545
+ expect(validateUpdateTime(t.created_at, updates.created_at, referenceTime)).toBe(true)
546
+ expect(validateUpdateTime(t.updated_at, updates.updated_at, referenceTime)).toBe(true)
547
+ }
548
+ }
549
+ }
550
+ })
551
+
552
+ test('10_update User trigger DB unique constraint errors', async () => {
553
+ await createDB('User10')
554
+ for (const { storage } of setups) {
555
+ try {
556
+ const r = await storage.updateUser(2, {
557
+ identityKey: 'mockDupIdentityKey'
558
+ })
559
+ await expect(Promise.resolve(r)).resolves.toBe(1)
560
+ } catch (error: any) {
561
+ console.error('Error updating second record:', error.message)
562
+ return
563
+ }
564
+ const r1 = await triggerUniqueConstraintError(storage, 'findUsers', 'updateUser', 'users', 'userId', {
565
+ userId: 2
566
+ })
567
+ await expect(Promise.resolve(r1)).resolves.toBe(true)
568
+ const r2 = await triggerUniqueConstraintError(storage, 'findUsers', 'updateUser', 'users', 'userId', {
569
+ identityKey: 'mockDupIdentityKey'
570
+ })
571
+ await expect(Promise.resolve(r2)).resolves.toBe(true)
572
+ const r3 = await triggerUniqueConstraintError(storage, 'findUsers', 'updateUser', 'users', 'userId', {
573
+ identityKey: 'mockUniqueIdentityKey'
574
+ })
575
+ await expect(Promise.resolve(r3)).resolves.toBe(false)
576
+ }
577
+ })
578
+
579
+ test('11_update User trigger DB foreign key constraint errors', async () => {
580
+ await createDB('User11')
581
+ for (const { storage } of setups) {
582
+ const r1 = await triggerForeignKeyConstraintError(storage, 'findUsers', 'updateUser', 'users', 'userId', {
583
+ userId: 0
584
+ })
585
+ await expect(Promise.resolve(r1)).resolves.toBe(true)
586
+ const r2 = await triggerForeignKeyConstraintError(
587
+ storage,
588
+ 'findUsers',
589
+ 'updateUser',
590
+ 'users',
591
+ 'userId',
592
+ { userId: 3 },
593
+ 0
594
+ )
595
+ await expect(Promise.resolve(r2)).resolves.toBe(false)
596
+ }
597
+ })
598
+
599
+ test('12_update User table setting individual values', async () => {
600
+ await createDB('User12')
601
+ for (const { storage } of setups) {
602
+ const initialRecord: TableUser = {
603
+ userId: 3,
604
+ identityKey: '',
605
+ created_at: new Date(),
606
+ updated_at: new Date(),
607
+ activeStorage: storage.getSettings().storageIdentityKey
608
+ }
609
+ try {
610
+ const r = await storage.insertUser(initialRecord)
611
+ expect(r).toBeGreaterThan(1)
612
+ } catch (error: any) {
613
+ console.error('Error inserting initial record:', error.message)
614
+ return
615
+ }
616
+ await expect(storage.updateUser(1, { userId: 0 })).rejects.toThrow(/FOREIGN KEY constraint failed/)
617
+ await expect(storage.updateUser(2, { userId: 0 })).rejects.toThrow(/FOREIGN KEY constraint failed/)
618
+ const r1 = await storage.updateUser(3, { userId: 0 })
619
+ await expect(Promise.resolve(r1)).resolves.toBe(1)
620
+ const r2 = await storage.findUsers({ partial: {} })
621
+ expect(r2[0].userId).toBe(0)
622
+ expect(r2[1].userId).toBe(1)
623
+ expect(r2[2].userId).toBe(2)
624
+ const r3 = await storage.updateUser(0, { userId: 3 })
625
+ await expect(Promise.resolve(r3)).resolves.toBe(1)
626
+ const r4 = await storage.findUsers({ partial: {} })
627
+ expect(r4[0].userId).toBe(1)
628
+ expect(r4[1].userId).toBe(2)
629
+ expect(r4[2].userId).toBe(3)
630
+ const r5 = await storage.updateUser(3, { userId: 9999 })
631
+ await expect(Promise.resolve(r5)).resolves.toBe(1)
632
+ const r6 = await storage.findUsers({ partial: {} })
633
+ expect(r6[0].userId).toBe(1)
634
+ expect(r6[1].userId).toBe(2)
635
+ expect(r6[2].userId).toBe(9999)
636
+ await expect(storage.updateUser(1, { userId: 9999 })).rejects.toThrow(/UNIQUE constraint failed/)
637
+ const r7 = await storage.findUsers({ partial: {} })
638
+ expect(r7[0].userId).toBe(1)
639
+ expect(r7[1].userId).toBe(2)
640
+ expect(r7[2].userId).toBe(9999)
641
+ const r8 = await storage.updateUser(9999, {
642
+ identityKey: 'mockValidIdentityKey'
643
+ })
644
+ await expect(Promise.resolve(r8)).resolves.toBe(1)
645
+ const r9 = await storage.findUsers({ partial: {} })
646
+ expect(r9[0].identityKey).not.toBe('mockValidIdentityKey')
647
+ expect(r9[1].identityKey).not.toBe('mockValidIdentityKey')
648
+ expect(r9[2].identityKey).toBe('mockValidIdentityKey')
649
+ await expect(storage.updateUser(2, { identityKey: 'mockValidIdentityKey' })).rejects.toThrow(
650
+ /UNIQUE constraint failed/
651
+ )
652
+ const r10 = await storage.findUsers({ partial: {} })
653
+ expect(r10[0].identityKey).not.toBe('mockValidIdentityKey')
654
+ expect(r10[1].identityKey).not.toBe('mockValidIdentityKey')
655
+ expect(r10[2].identityKey).toBe('mockValidIdentityKey')
656
+ const r11 = await storage.updateUser(9999, { userId: 3 })
657
+ await expect(Promise.resolve(r11)).resolves.toBe(1)
658
+ const r12 = await storage.findUsers({ partial: {} })
659
+ expect(r12[0].userId).toBe(1)
660
+ expect(r12[1].userId).toBe(2)
661
+ expect(r12[2].userId).toBe(3)
662
+ const createdAt = new Date('2024-12-30T23:00:00Z')
663
+ const updatedAt = new Date('2024-12-30T23:05:00Z')
664
+ const r13 = await storage.updateUser(3, {
665
+ created_at: createdAt,
666
+ updated_at: updatedAt
667
+ })
668
+ await expect(Promise.resolve(r13)).resolves.toBe(1)
669
+ const r14 = await storage.findUsers({ partial: {} })
670
+ const updatedRecord = r14.find(record => record.userId === 3)
671
+ expect(updatedRecord?.created_at).toEqual(createdAt)
672
+ expect(updatedRecord?.updated_at).toEqual(updatedAt)
673
+ }
674
+ })
675
+
676
+ test('13_update Certificate', async () => {
677
+ await createDB('Certificate13')
678
+ for (const { storage } of setups) {
679
+ const primaryKey = 'certificateId'
680
+ const records = await storage.findCertificates({ partial: {} })
681
+ for (const record of records) {
682
+ try {
683
+ const testValues: TableCertificate = {
684
+ certificateId: record.certificateId,
685
+ userId: 1,
686
+ certifier: `mockCertifier${record.certificateId}`,
687
+ serialNumber: `mockSerialNumber${record.certificateId}`,
688
+ type: `mockType${record.certificateId}`,
689
+ created_at: new Date('2024-12-30T23:00:00Z'),
690
+ updated_at: new Date('2024-12-30T23:05:00Z'),
691
+ isDeleted: false,
692
+ revocationOutpoint: 'mockRevocationOutpoint',
693
+ signature: 'mockSignature',
694
+ subject: 'mockSubject'
695
+ }
696
+ const r1 = await storage.updateCertificate(record[primaryKey], testValues)
697
+ expect(r1).toBe(1)
698
+ const updatedRow = verifyOne(
699
+ await storage.findCertificates({
700
+ partial: { [primaryKey]: record[primaryKey] }
701
+ })
702
+ )
703
+ for (const [key, value] of Object.entries(testValues)) {
704
+ const actualValue = updatedRow[key]
705
+ const normalizedActual = normalizeDate(actualValue)
706
+ const normalizedExpected = normalizeDate(value)
707
+ if (normalizedActual && normalizedExpected) {
708
+ expect(normalizedActual).toBe(normalizedExpected)
709
+ continue
710
+ }
711
+ if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {
712
+ expect(JSON.parse(actualValue)).toStrictEqual(JSON.parse(value))
713
+ continue
714
+ }
715
+ if (typeof actualValue === 'boolean') {
716
+ if (value === 1) {
717
+ expect(actualValue).toBe(true)
718
+ } else if (value === 0) {
719
+ expect(actualValue).toBe(false)
720
+ } else {
721
+ throw new Error(`Unexpected value for expectedValue: ${value}. Must be 0 or 1.`)
722
+ }
723
+ continue
724
+ }
725
+ if (typeof value === 'string' || typeof value === 'number') {
726
+ expect(actualValue).toBe(value)
727
+ continue
728
+ }
729
+ if (typeof actualValue === 'object' && actualValue?.type === 'Buffer') {
730
+ const actualArray = actualValue.data || actualValue
731
+ const expectedArray =
732
+ Buffer.isBuffer(value) || Array.isArray(value) ? Array.from(value as ArrayLike<number>) : value
733
+ expect(actualArray).toStrictEqual(expectedArray)
734
+ continue
735
+ }
736
+ expect(JSON.stringify({ type: 'Buffer', data: actualValue })).toStrictEqual(JSON.stringify(value))
737
+ }
738
+ } catch (error: any) {
739
+ console.error(
740
+ `Error updating or verifying Certificate record with ${primaryKey}=${record[primaryKey]}:`,
741
+ error.message
742
+ )
743
+ throw error
744
+ }
745
+ }
746
+ }
747
+ })
748
+
749
+ test('14_update Certificate set created_at and updated_at time', async () => {
750
+ await createDB('Certificate14')
751
+ for (const { storage } of setups) {
752
+ const scenarios = [
753
+ {
754
+ description: 'Invalid created_at time',
755
+ updates: {
756
+ created_at: new Date('3000-01-01T00:00:00Z'),
757
+ updated_at: new Date('2024-12-30T23:05:00Z')
758
+ }
759
+ },
760
+ {
761
+ description: 'Invalid updated_at time',
762
+ updates: {
763
+ created_at: new Date('2024-12-30T23:00:00Z'),
764
+ updated_at: new Date('3000-01-01T00:00:00Z')
765
+ }
766
+ },
767
+ {
768
+ description: 'created_at time overwrites updated_at time',
769
+ updates: {
770
+ created_at: new Date('2024-12-30T23:00:00Z'),
771
+ updated_at: new Date('2024-12-30T23:05:00Z')
772
+ }
773
+ }
774
+ ]
775
+ for (const { updates } of scenarios) {
776
+ const referenceTime = new Date()
777
+ const records = await storage.findCertificates({ partial: {} })
778
+ for (const record of records) {
779
+ await storage.updateUser(record.certificateId, {
780
+ created_at: updates.created_at
781
+ })
782
+ await storage.updateUser(record.certificateId, {
783
+ updated_at: updates.updated_at
784
+ })
785
+ const t = verifyOne(
786
+ await storage.findCertificates({
787
+ partial: { certificateId: record.certificateId }
788
+ })
789
+ )
790
+ expect(validateUpdateTime(t.created_at, updates.created_at, referenceTime)).toBe(true)
791
+ expect(validateUpdateTime(t.updated_at, updates.updated_at, referenceTime)).toBe(true)
792
+ }
793
+ }
794
+ }
795
+ })
796
+
797
+ test('15_update Certificate trigger DB unique constraint errors', async () => {
798
+ await createDB('Certificate15')
799
+ for (const { storage } of setups) {
800
+ const initMockDupValues = {
801
+ userId: 2,
802
+ type: `mockType2`,
803
+ certifier: `mockCertifier2`,
804
+ serialNumber: `mockSerialNumber2`
805
+ }
806
+ try {
807
+ const r = await storage.updateCertificate(2, initMockDupValues)
808
+ await expect(Promise.resolve(r)).resolves.toBe(1)
809
+ } catch (error: any) {
810
+ console.error('Error updating second record:', error.message)
811
+ }
812
+ const mockDupValues = {
813
+ userId: 2,
814
+ type: `mockType2`,
815
+ certifier: `mockCertifier2`,
816
+ serialNumber: `mockSerialNumber2`
817
+ }
818
+ const mockUniqueValues = {
819
+ userId: 2,
820
+ type: `mockTypeUnique`,
821
+ certifier: `mockCertifier2`,
822
+ serialNumber: `mockSerialNumber2`
823
+ }
824
+ const r1 = await triggerUniqueConstraintError(
825
+ storage,
826
+ 'findCertificates',
827
+ 'updateCertificate',
828
+ 'certificates',
829
+ 'certificateId',
830
+ { certificateId: 2 }
831
+ )
832
+ await expect(Promise.resolve(r1)).resolves.toBe(true)
833
+ const r2 = await triggerUniqueConstraintError(
834
+ storage,
835
+ 'findCertificates',
836
+ 'updateCertificate',
837
+ 'certificates',
838
+ 'certificateId',
839
+ mockDupValues
840
+ )
841
+ await expect(Promise.resolve(r2)).resolves.toBe(true)
842
+ const r3 = await triggerUniqueConstraintError(
843
+ storage,
844
+ 'findCertificates',
845
+ 'updateCertificate',
846
+ 'certificates',
847
+ 'certificateId',
848
+ mockUniqueValues
849
+ )
850
+ await expect(Promise.resolve(r3)).resolves.toBe(false)
851
+ }
852
+ })
853
+
854
+ test('16_update Certificate trigger DB foreign key constraint errors', async () => {
855
+ await createDB('Certificate16')
856
+ for (const { storage } of setups) {
857
+ const r1 = await triggerForeignKeyConstraintError(
858
+ storage,
859
+ 'findCertificates',
860
+ 'updateCertificate',
861
+ 'certificates',
862
+ 'certificateId',
863
+ { certificateId: 0 }
864
+ )
865
+ await expect(Promise.resolve(r1)).resolves.toBe(true)
866
+ const r2 = await triggerForeignKeyConstraintError(
867
+ storage,
868
+ 'findCertificates',
869
+ 'updateCertificate',
870
+ 'certificates',
871
+ 'certificateId',
872
+ { certificateId: 1 },
873
+ 0
874
+ )
875
+ await expect(Promise.resolve(r2)).resolves.toBe(false)
876
+ const r3 = await triggerForeignKeyConstraintError(
877
+ storage,
878
+ 'findCertificates',
879
+ 'updateCertificate',
880
+ 'certificates',
881
+ 'certificateId',
882
+ { userId: 0 }
883
+ )
884
+ await expect(Promise.resolve(r3)).resolves.toBe(true)
885
+ const r4 = await triggerForeignKeyConstraintError(
886
+ storage,
887
+ 'findCertificates',
888
+ 'updateCertificate',
889
+ 'certificates',
890
+ 'certificateId',
891
+ { userId: 1 },
892
+ 2
893
+ )
894
+ await expect(Promise.resolve(r4)).resolves.toBe(false)
895
+ }
896
+ })
897
+ })