@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,407 @@
1
+ import { Beef, MerklePath, Transaction, WalletOutput, Validation, Utils } from '@bsv/sdk'
2
+ import { TableOutput, TableUser, verifyOne, verifyOneOrNone } from '../../../src'
3
+ import { _tu, logger } from '../../utils/TestUtilsWalletStorage'
4
+ import { specOpInvalidChange } from '../../../src/sdk'
5
+ import { Format } from '../../../src/utility/Format'
6
+ import { asString } from '../../../src/utility/utilityHelpers.noBuffer'
7
+
8
+ describe('operations.man tests', () => {
9
+ jest.setTimeout(99999999)
10
+
11
+ test('0 review and release all production invalid change utxos', async () => {
12
+ // const tags = [] // only return invalid change utxos, do not update them to unspendable.
13
+ // const tags = ['release'] // release invalid change utxos to unspendable
14
+ const tags = ['all'] // only return invalid utxos, do not update them to unspendable.
15
+ // const tags = ['release', 'all'] // release invalid utxos to unspendable
16
+ const action = tags.includes('release') ? 'updated to unspendable' : 'found'
17
+ const target = tags.includes('all') ? 'spendable utxos' : 'spendable change utxos'
18
+ const { env, storage } = await _tu.createMainReviewSetup()
19
+ const users = await storage.findUsers({ partial: { userId: 88 } })
20
+ // const users = await storage.findUsers({ partial: {} }) // all users...
21
+ const withInvalid: Record<number, { user: TableUser; outputs: WalletOutput[]; total: number }> = {}
22
+ const vargs: Validation.ValidListOutputsArgs = {
23
+ basket: specOpInvalidChange,
24
+ tags,
25
+ tagQueryMode: 'all',
26
+ includeLockingScripts: false,
27
+ includeTransactions: false,
28
+ includeCustomInstructions: false,
29
+ includeTags: false,
30
+ includeLabels: false,
31
+ limit: 0,
32
+ offset: 0,
33
+ seekPermission: false,
34
+ knownTxids: []
35
+ }
36
+ let log = ''
37
+ for (const user of users) {
38
+ const { userId } = user
39
+ const auth = { userId, identityKey: '' }
40
+ let r = await storage.listOutputs(auth, vargs)
41
+ if (r.totalOutputs > 0) {
42
+ const total: number = r.outputs.reduce((s, o) => (s += o.satoshis), 0)
43
+ let l = `userId ${userId}: ${r.totalOutputs} ${target} ${action}, total ${total}, ${user.identityKey}\n`
44
+ for (const o of r.outputs) {
45
+ l += ` ${o.outpoint} ${o.satoshis} now ${o.spendable ? 'spendable' : 'spent'}\n`
46
+ }
47
+ console.log(l)
48
+ log += l
49
+ withInvalid[userId] = { user, outputs: r.outputs, total }
50
+ }
51
+ }
52
+ console.log(log || `zero invalid ${target} ${action}.`)
53
+ await storage.destroy()
54
+ })
55
+
56
+ test('1 review and unfail false doubleSpends', async () => {
57
+ const { env, storage, services } = await _tu.createMainReviewSetup()
58
+ let offset = 400
59
+ const limit = 100
60
+ let allUnfails: number[] = []
61
+ let reviewed = 0
62
+ for (;;) {
63
+ let log = ''
64
+ const unfails: number[] = []
65
+ const reqs = await storage.findProvenTxReqs({
66
+ partial: { status: 'doubleSpend' },
67
+ paged: { limit, offset },
68
+ orderDescending: true
69
+ })
70
+ for (const req of reqs) {
71
+ const gsr = await services.getStatusForTxids([req.txid])
72
+ if (gsr.results[0].status !== 'unknown') {
73
+ log += `unfail ${req.provenTxReqId} ${req.txid}\n`
74
+ unfails.push(req.provenTxReqId)
75
+ }
76
+ reviewed++
77
+ }
78
+ console.log(`DoubleSpends OFFSET: ${offset} ${reviewed} ${unfails.length} unfails\n${log}`)
79
+ allUnfails = allUnfails.concat(unfails)
80
+ if (reqs.length < limit) break
81
+ offset += reqs.length
82
+ }
83
+ for (const id of allUnfails) {
84
+ await storage.updateProvenTxReq(id, { status: 'unfail' })
85
+ }
86
+ await storage.destroy()
87
+ })
88
+
89
+ test('2 review and unfail false invalids', async () => {
90
+ const { env, storage, services } = await _tu.createMainReviewSetup()
91
+ let offset = 500
92
+ const limit = 100
93
+ let allUnfails: number[] = []
94
+ let reviewed = 0
95
+ for (;;) {
96
+ let log = ''
97
+ const unfails: number[] = []
98
+ const reqs = await storage.findProvenTxReqs({
99
+ partial: { status: 'invalid' },
100
+ paged: { limit, offset },
101
+ orderDescending: true
102
+ })
103
+ for (const req of reqs) {
104
+ if (!req.txid || !req.rawTx) continue
105
+ const gsr = await services.getStatusForTxids([req.txid])
106
+ if (gsr.results[0].status !== 'unknown') {
107
+ log += `unfail ${req.provenTxReqId} ${req.txid}\n`
108
+ unfails.push(req.provenTxReqId)
109
+ }
110
+ reviewed++
111
+ }
112
+ console.log(`Failed OFFSET: ${offset} ${reviewed} ${unfails.length} unfails\n${log}`)
113
+ allUnfails = allUnfails.concat(unfails)
114
+ if (reqs.length < limit) break
115
+ offset += reqs.length
116
+ }
117
+ for (const id of allUnfails) {
118
+ await storage.updateProvenTxReq(id, { status: 'unfail' })
119
+ }
120
+ await storage.destroy()
121
+ })
122
+
123
+ test.skip('3 review proven_txs', async () => {
124
+ const { env, storage, services } = await _tu.createMainReviewSetup()
125
+ let offset = 0
126
+ const limit = 100
127
+ let allUnfails: number[] = []
128
+ //for (const provenTxId of [3064, 3065, 11268, 11269, 11270, 11271] ) {
129
+ for (let height = 895000; height < 895026; height++) {
130
+ let log = ''
131
+ const unfails: number[] = []
132
+ const txs = await storage.findProvenTxs({ partial: { height }, paged: { limit, offset } })
133
+ for (const tx of txs) {
134
+ const gmpr = await services.getMerklePath(tx.txid)
135
+ if (gmpr && gmpr.header && gmpr.merklePath) {
136
+ const mp = gmpr.merklePath
137
+ const h = gmpr.header
138
+ const mr = mp.computeRoot(tx.txid)
139
+ const index = mp.path[0].find(leaf => leaf.hash === tx.txid)?.offset!
140
+
141
+ const mp2 = MerklePath.fromBinary(tx.merklePath)
142
+ const mr2 = mp2.computeRoot()
143
+
144
+ if (h.height !== mp.blockHeight || h.merkleRoot !== mr) {
145
+ console.log(`Merkle root mismatch for ${tx.txid} ${h.merkleRoot} != ${mr}`)
146
+ } else {
147
+ if (
148
+ tx.merkleRoot !== mr ||
149
+ tx.height !== mp.blockHeight ||
150
+ tx.blockHash !== h.hash ||
151
+ tx.index !== index ||
152
+ mp2.blockHeight !== tx.height ||
153
+ mr2 !== tx.merkleRoot ||
154
+ asString(tx.merklePath) !== asString(mp.toBinary())
155
+ ) {
156
+ debugger
157
+ await storage.updateProvenTx(tx.provenTxId, {
158
+ merklePath: mp.toBinary(),
159
+ merkleRoot: mr,
160
+ height: mp.blockHeight,
161
+ blockHash: h.hash,
162
+ index
163
+ })
164
+ log += `updated ${tx.provenTxId}\n`
165
+ }
166
+ }
167
+ }
168
+ }
169
+ //console.log(`${offset} ${log}`)
170
+ //if (txs.length < limit) break
171
+ //offset += txs.length
172
+ }
173
+ await storage.destroy()
174
+ })
175
+
176
+ test.skip('10 re-internalize failed WUI exports', async () => {
177
+ const { env, storage, services } = await _tu.createMainReviewSetup()
178
+ // From this user
179
+ const user0 = verifyOne(await storage.findUsers({ partial: { userId: 2 } }))
180
+ // To these users
181
+ const users = await storage.findUsers({ partial: { userId: 141 } }) // 111, 141
182
+ for (const user of users) {
183
+ const { userId, identityKey } = user
184
+ const [outputs] = await storage.knex.raw<TableOutput[][]>(`
185
+ SELECT f.* FROM outputs as f where f.userId = 2 and not f.customInstructions is null
186
+ and JSON_EXTRACT(f.customInstructions, '$.payee') = '${identityKey}'
187
+ and not exists(select * from outputs as r where r.userId = ${userId} and r.txid = f.txid)
188
+ `)
189
+ if (outputs.length > 0) console.log(`userId ${userId} ${identityKey} ${outputs.length} outputs`)
190
+ for (const output of outputs) {
191
+ const req = verifyOneOrNone(
192
+ await storage.findProvenTxReqs({ partial: { txid: output.txid, status: 'completed' } })
193
+ )
194
+ const { type, derivationPrefix, derivationSuffix, payee } = JSON.parse(output.customInstructions!)
195
+ if (req && type === 'BRC29' && derivationPrefix && derivationSuffix) {
196
+ const beef = await storage.getBeefForTransaction(req.txid, {})
197
+ // {"type":"BRC29","derivationPrefix":"LDFooHSsXzw=","derivationSuffix":"4f4ixKv+6SY=","payee":"0352caa755d5b6279e15e47e096db908e7c4a73a31775e7e8720bdd4cf2d44873a"}
198
+ await storage.internalizeAction(
199
+ { userId, identityKey: user.identityKey },
200
+ {
201
+ tx: beef.toBinaryAtomic(req.txid),
202
+ outputs: [
203
+ {
204
+ outputIndex: 0,
205
+ protocol: 'wallet payment',
206
+ paymentRemittance: {
207
+ derivationPrefix: derivationPrefix,
208
+ derivationSuffix: derivationSuffix,
209
+ senderIdentityKey: user0.identityKey
210
+ }
211
+ }
212
+ ],
213
+ description: 'Internalizing export funds tx into foreign wallet'
214
+ }
215
+ )
216
+ console.log('internalize', userId, output.txid)
217
+ }
218
+ }
219
+ }
220
+ /*
221
+ */
222
+ await storage.destroy()
223
+ })
224
+
225
+ test.skip('11 review recent transaction change use for specific userId', async () => {
226
+ const userId = 311
227
+ const { env, storage, services } = await _tu.createMainReviewSetup()
228
+ const countTxs = await storage.countTransactions({
229
+ partial: { userId },
230
+ status: ['completed', 'unproven', 'failed']
231
+ })
232
+ const txs = await storage.findTransactions({
233
+ partial: { userId },
234
+ status: ['unproven', 'completed', 'failed'],
235
+ paged: { limit: 100, offset: Math.max(0, countTxs - 100) }
236
+ })
237
+ for (const tx of txs) {
238
+ const ls = await Format.toLogStringTableTransaction(tx, storage)
239
+ console.log(ls)
240
+ }
241
+ const countReqs = await storage.countProvenTxReqs({ partial: {}, status: ['completed', 'unmined'] })
242
+ const reqs = await storage.findProvenTxReqs({
243
+ partial: {},
244
+ status: ['unmined', 'completed'],
245
+ paged: { limit: 100, offset: countReqs - 100 }
246
+ })
247
+ await storage.destroy()
248
+ })
249
+
250
+ test.skip('12 check storage merged BEEF', async () => {
251
+ const userId = 127
252
+ const txid = 'efba8b92a22c3308f432b292b5ec7efb3869ecd50c62cb3ddfb83871bc7be194'
253
+ const vout = 1
254
+ const { env, storage, services } = await _tu.createMainReviewSetup()
255
+
256
+ const ptx = verifyOne(await storage.findProvenTxs({ partial: { txid } }))
257
+
258
+ const mp = MerklePath.fromBinary(ptx.merklePath)
259
+ expect(mp.blockHeight).toBe(ptx.height)
260
+
261
+ const txids = ['24b19a5179c1f146e825643df4c6dc2ba21674828c20fc2948e105cb1ca91eae']
262
+
263
+ const r = await storage.getReqsAndBeefToShareWithWorld(txids, [])
264
+
265
+ await storage.destroy()
266
+ })
267
+
268
+ test('13 review use of outputs in all following transactions', async () => {
269
+ const { env, storage, services } = await _tu.createMainReviewSetup()
270
+
271
+ const txids = ['2df7b5059112a42fc40adb54ee36244cee0dd216c35ad6c4b6ef4631c14a0e83'] //, '9fb38fc87c6ff39f5c7321a4c689db535c024498ed20031434485c981dd7a182', '3fb6b02e1d001dded1daee3f59dcd684489b96a35a9dfb5082b4119a31689966', '72ea8d84a4c54dbca292f4a79a5ff08cb9917fc3127c1dcff0628aeba8b40823', '0564a515566bc43c1396becf12bbf2d82d821ae7b6e0ef404eedfa090d4877c2', '3b93e4327a50a7f4a421af9fbdec0206b3b7ba5252bc5a0142d0d64aa34c2e73', 'd4b0c3d820696afad43b43e095f3b8c3df52385bb4aeddff0212e0a472dd8e4e']
272
+ const userId = 111
273
+ const txs = await storage.findTransactions({
274
+ partial: { userId },
275
+ status: ['completed', 'unproven', 'failed'],
276
+ orderDescending: true,
277
+ paged: { limit: 50 }
278
+ })
279
+ const allTxids = txs.map(tx => tx.txid!)
280
+ debugger
281
+ const reqs = await storage.findProvenTxReqs({ partial: {}, txids: allTxids })
282
+ const beef = new Beef()
283
+ for (const req of reqs) {
284
+ beef.mergeRawTx(req.rawTx!)
285
+ }
286
+
287
+ for (const txid of txids) {
288
+ const o = await storage.findOutputs({ partial: { txid, userId } })
289
+ const tx = await storage.findTransactions({ partial: { txid, userId } })
290
+ if (o && tx) {
291
+ const ltx = await Format.toLogStringTableTransaction(tx[0], storage)
292
+ logger(ltx)
293
+ for (const btx of beef.txs) {
294
+ const tx = btx.tx!
295
+ for (const i of tx.inputs) {
296
+ if (i.sourceTXID === txid && i.sourceOutputIndex === 0) {
297
+ const sltx = Format.toLogStringBeefTxid(beef, btx.txid)
298
+ logger(sltx)
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ await storage.destroy()
305
+ })
306
+
307
+ test('14 review utxo status of inputs of tx', async () => {
308
+ const { env, storage, services } = await _tu.createMainReviewSetup()
309
+
310
+ const tx = Transaction.fromHex(testTxInputUtxoStatus)
311
+
312
+ const inputTxs: Record<string, Transaction> = {}
313
+
314
+ for (const input of tx.inputs) {
315
+ if (input.sourceTXID && !inputTxs[input.sourceTXID]) {
316
+ const source = await services.getRawTx(input.sourceTXID!)
317
+ if (!source.rawTx) {
318
+ throw new Error(`Source transaction ${input.sourceTXID} not found`)
319
+ }
320
+ inputTxs[input.sourceTXID] = Transaction.fromBinary(source.rawTx!)
321
+ }
322
+ }
323
+ let log = ''
324
+ for (const input of tx.inputs) {
325
+ const stx = inputTxs[input.sourceTXID!]!
326
+ const output = stx.outputs[input.sourceOutputIndex]!
327
+ const hash = services.hashOutputScript(output.lockingScript.toHex())
328
+ const outpoint = `${input.sourceTXID}.${input.sourceOutputIndex}`
329
+ const or = await services.getUtxoStatus(hash, undefined, outpoint)
330
+ log += `${outpoint} ${or.isUtxo} ${or.status}\n`
331
+ }
332
+ logger(log)
333
+ await storage.destroy()
334
+ })
335
+
336
+ test('14a review utxo status of custom spentBy null spendable false outputs', async () => {
337
+ const { env, storage, services } = await _tu.createMainReviewSetup()
338
+
339
+ let offset = 0
340
+ const limit = 100
341
+
342
+ for (;;) {
343
+ let validOutputIds: number[] = []
344
+
345
+ let log = `offset ${offset}\n`
346
+ // select count(*)
347
+ // and o.lockingScript is null
348
+ // and o.txid = '533e50fba3fca9b08845fc46ae3df81713129876faddf84f9d26d4185dea8324'
349
+ const outputs: {
350
+ outputId: number
351
+ txid: string
352
+ vout: number
353
+ lockingScript: number[]
354
+ scriptOffset: number
355
+ scriptLength: number
356
+ }[] = (
357
+ await storage.knex.raw(`
358
+ select o.outputId, o.txid, o.vout, o.lockingScript, o.scriptOffset, o.scriptLength
359
+ from outputs o, transactions t
360
+ where o.transactionId = t.transactionId
361
+ and o.type = 'custom' and o.spentBy is null and o.spendable = 0
362
+ and t.status = 'completed'
363
+ limit ${limit}
364
+ offset ${offset}
365
+ `)
366
+ )[0]
367
+
368
+ for (const { outputId, txid, vout, lockingScript, scriptOffset, scriptLength } of outputs) {
369
+ let script: number[] | null | undefined = lockingScript
370
+ if (!lockingScript) {
371
+ script = await storage.getRawTxOfKnownValidTransaction(txid, scriptOffset, scriptLength)
372
+ }
373
+ expect(script).toBeTruthy()
374
+ const hex = Utils.toHex(script!)
375
+ const hash = services.hashOutputScript(hex)
376
+ const outpoint = `${txid}.${vout}`
377
+ const or = await services.getUtxoStatus(hash, undefined, outpoint)
378
+ if (or.isUtxo && or.status === 'success') {
379
+ log += `${outpoint} ${or.isUtxo} ${or.status}\n`
380
+ validOutputIds.push(outputId)
381
+ }
382
+ }
383
+ log += `offset ${offset}\n`
384
+ logger(log)
385
+
386
+ for (const outputId of validOutputIds) {
387
+ await storage.updateOutput(outputId, { spendable: true })
388
+ }
389
+
390
+ if (outputs.length < limit) break
391
+ offset += limit
392
+ }
393
+ await storage.destroy()
394
+ })
395
+
396
+ test('15 abort a transaction', async () => {
397
+ const { env, storage } = await _tu.createMainReviewSetup()
398
+ const refOrTxid = '42671b6c9b79cec03bf5be9105203589b8b092774a40b459fbd835e5fd582202'
399
+ const userId = 496
400
+ const auth = { userId, identityKey: '' }
401
+ const r = await storage.abortAction(auth, { reference: refOrTxid })
402
+ console.log(r)
403
+ await storage.destroy()
404
+ })
405
+ })
406
+
407
+ const testTxInputUtxoStatus = `010000003E63EAF142160AD52F3172D75305D0D495A99AD9F17A693017EF8630C86F37A200000000006A473044022004E94D9188B2CE1193969509F32B46F94A36DB2BB4FC0832936F937C59FDDA470220781E5A5AD34EE49C985E5177380D6D111546D7BCCBAAA219B292FB49400DB7C9C221021A67430A3C5F274D3563892965758D3DEAE67799DD47E28DA95FBD1013D3B302FFFFFFFF74B95869A62F82E50642B4B18C78321BC12858A640155C8DA34EC4043393CCA6000000006A4730440220680AEF159D6C158C703912A9FBA090A063A26D92DBDFB7F15D6026FB5EAC332E0220375559499733A35955CA5F562669C8A947624BF22A8475EC0CD2C488530BCBD1C22103F55B1909BFD6851773E7FA7E567B58BF586D1EF76D0DE00330EE7F05E19672C2FFFFFFFFCDA6E22336EA4F8898D56C85C022F35338A6CD9E8D14FC75EA39DEC3B78FB83E010000006B483045022100E2B532D81252E60465E694F40A67B8CC52CCEAA1992494AAE264E039ED4D471602204E5C65F74BB49D263C54E43CFE22C8AB39B8AEB89F64CFEF933E5EBE08C5EF6DC22103E4F28DF126FBE92CF4418EF16636D18D75F8FFEADF0D03A0339A53B4A37DDDF7FFFFFFFFE330B3BBCB5815DD6B2B03BA5105F71F09CB8C26344F67C7A5E082473DF75859030000006B483045022100EBF506D10F04EC171C6A598056F06946D0B6F244FD08AA3E5A2DABB2EAC01A2A02206E557D4D7048E19F1DE094C5BCB7FC507FEC7E13C419AE829AD9180BACE4D5D8C22102960CADC2656A19DAAF1FCC04F6CF235C0E83822336F3CD32D599A426DFF85114FFFFFFFF7A58F2A977D75EDC8D349AEC609DAEC3AB06C12CE83276FB986D0B36D37C3C3C090000006A47304402205B353BE3BBC19B3766D12D5268E34E34675EB8BB8DD7624A522C1A36C1A1F481022072DD8D7F11C5507781FE9C55931A95BB3FE0FF7748DB4D1765FB6DFCBDF27268C22103F051F897874F7365DBF96773EE4D54EEA289BF05EE1610FF8C7F52EBC15A8294FFFFFFFF2D1C1B9098484F91435CB9965F07886E30FB8D1EA7F221C9072DAD8AAD545B294C0000006A47304402205D42AC6A4CA02F7006781515E9DAB1101B2F8006193F7E3EEB61CDC3132EFDDE02203EB616AD39280D1A07E9B31D1E4BAF56F831AF95A21A16D304235DD7DC65CF20C22103F051F897874F7365DBF96773EE4D54EEA289BF05EE1610FF8C7F52EBC15A8294FFFFFFFF2D1C1B9098484F91435CB9965F07886E30FB8D1EA7F221C9072DAD8AAD545B29160000006B48304502210080AE055C991A3EFED069C3E0D22E984DAF0C2DDDE6C102280EAA6E7ABBA2E9A00220339DE057226FAD63D021A3167C3AEDA0447D49DFA782A59850F699012C44FA4DC221033F8A1AD07E37C12FCE914102509C9ABFC313F69D9329F5137FD2EA79F633C86CFFFFFFFFFBD56D01AAB9E6F7E73F0D6A232F4D73D552A933E3ECBFC2E4BD95F4ECF9A1C6020000006A473044022043AEAFBF8C63FC98CECFE79569BE2F0D94C02E44C2C50CAD37104C4EA0D0B8E4022072EA0F50DF429D15500F4F2795147256A40DEA751BECD6572E0C5AE51D6DF553C221033F8A1AD07E37C12FCE914102509C9ABFC313F69D9329F5137FD2EA79F633C86CFFFFFFFF1D6A18F2411362A374CE97D2480C54E21173A58C5E83D7679DB1BC5CA112A55D020000006A47304402204B5E9B9612F89CADC7BF2D7035BFFB1EE9127586F504D4C635B674D8A1BE000702207837EEC18E2BD808F58935C4C78685715B2C5A3D84AB39895F8DA1AA0F7E6A28C22102D7EAA52A92B311A96A0AEBB18CABFE3A9B17B82048ED1E3E58628A4959ED91B4FFFFFFFF4A2297374C26D0E5EE98C07FDA64DAD58577F89502835CD433EEC3191A66F380B30000006B483045022100CF83B0C64FD8ECA6761CC7BD3D72F2B38CC17B747C1E98F48DACD155B7CE9B3502202C696010E7673325CAEAE2E0D7F0BA8DC2EADC6FDB7A3779AA359820A16CD848C22102D7EAA52A92B311A96A0AEBB18CABFE3A9B17B82048ED1E3E58628A4959ED91B4FFFFFFFF589F60C44908602772131C5D457186E18F4D22D659353AC84F3A0795057F2378000000006B483045022100C4EC4D00EA39C2EBBA147752C67BB722B695777F00C462B7AE3E76467DB5EE9B02205402285B07031D4EA0FCCD298FED76F590243D1D9CE8B8C44F83F97B59691E9BC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFFB750A581EEA3A60079DE6D28FE07BAE3C7A63065D92DA936C67FE4C52F1C1DE6000000006A47304402201860470374A282FF58B6EE576A1EF46B60238131FD00D0C0C27777F8F76CAC4502204163110A54EB0B81C6F0791E363F3DF0F0A14C08F6A7AE2E8FC77B7713ED109BC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF833F3725A47C30A4AD5EBE5EA46D9AED81D5213BA2B51DE74A8BF23B65AC99A39F0000006B483045022100F1B40B6D4053E817FC674872DB1B8FE8C64D625CF4974893846A490117D034C60220343365C584D60269BF7845AFD2B69B4CF230530091102B1493B32D7B73E0CA0FC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF833F3725A47C30A4AD5EBE5EA46D9AED81D5213BA2B51DE74A8BF23B65AC99A39E0000006B483045022100A21CBDF75C58FAD76313F2CBE8D0E0DC1E3B5FCB9ECC61594A91D4F61218C85902202BB2250C3477EFC9D7C28F1D1E0ADB3296952671D340065ADA8B93A330C39244C22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFFA1DD547EAB22B19A49862C2ED7C3E059DBBB5307738F9D9581CED2B4AAB6B6D9010000006B483045022100A0918681C651851B91617C8E1C01074F2A0291EBB083AB2163D72FF565DD8590022008E27FC437A0DE19A3F39F3C2C3F1B3C1F508E52DC69ACC2CBF9D1774C7C4047C22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF0BB9D0E3A9CCEA73BC8682B66C559D6232265488647F0B7EEECE00BD0C2F5904000000006B483045022100C568678B624F6F04E8645AD8340638075E07AD4BCBB0FA9446B2153599B803C902204B9BD26BD58614360B86F95E9812E68A759450E64659AA5B8707FA629D12B438C22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF5367F929C9123A4853ED77A0087F72D135031A8E64C3D047976EFCD3807FC0D5010000006A47304402200B1F4939A427C65ED456B62158271F269C33740C5E4D9ED2F9E864E410F23511022059F10A7FEFE82CF89C274FE9486CFAEF7B148290386DDD3F6423280F0667EEF7C22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFF5367F929C9123A4853ED77A0087F72D135031A8E64C3D047976EFCD3807FC0D5000000006A473044022012D66417842DDF0079734B3885CE56D42B2309A49CFD1313895CE6401E67E47602200F8FCCBECEEC0546577872F4BA7B95EAF4621506238D88E89A0A0B12E46876DCC22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFF46CF567BCF79C0E845BC95A488DC8BEB8E3558783F21B30A2902F333D6080C3A000000006A47304402202DEBF679DE7F93DDABC84CC1953DC52570EF291F4BFE1C61840AAA2D3CDA0AF5022041C66B14238FE4CD4C5E7E3BF6BA2BDA031F7D4EACA3F15FC28DD6CDAF2B2E54C221036D9E146EDA0C9E01DF36F4735C39B29E8C8B58BFDB2BCF82E407A1CEEB8ED040FFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D40000006A4730440220154EB1B8E54A660311C1A400F94F370B382BE9EA5B37836328BF2C2FADCFDD7C022006BE9C8336F56AE98135CBF6D87ABB47B3F5C38028E1438246078648CA031BF5C221036D9E146EDA0C9E01DF36F4735C39B29E8C8B58BFDB2BCF82E407A1CEEB8ED040FFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D30000006B483045022100D7CD746B6352CDCF939870F2FC4B119B2F526171E00DA06ADB3359155E5BC03C022022E5126E535BE59FCF2AD6F6850B3F48DE7D5552D49468B00A01B728F4AB7239C221029C4787B4B8514206737095BB1C95E62BB901845E5AB8C4144B06E09C654F8F6CFFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D20000006B483045022100CBC2A4BC0070EF066FDFC99D7214025E410C368D7711D1F30DB4D0A676C1D7B20220675CB5B255B882408C2797FFA5A25FE652F8B1D6E2CCBD8029905FDBAE88F9FEC22103346CEED4C7E38ECFDEF9DA13316C9549E2E3AB1BE03CEF2E1D799371C315897EFFFFFFFFCA40E64BC0512AD8EB45E5611A5482F609FD69D99C9E0AE4980D50C11B6C67D8000000006B483045022100E48A110972F0783E15EA0E89BD348D1531622872B0E35AB61B79A9098E3CFA5202206893582684F5CF2BDC6158EA4624B63788044E8142EA4247AD6979F66AFA7D48C221029C4787B4B8514206737095BB1C95E62BB901845E5AB8C4144B06E09C654F8F6CFFFFFFFFF47FA4B80212220A78327B2FE5F93263EA6659FFA6BD6D380C1D58C6739BE8D5010000006A473044022056F79F2D88910609ED1D2A83E86702A7794122D45C6433009BEBA328F60969E20220488D7D11D2DEED21A8A2034A537DF86A9319093DF782A54D1C49048D8A8028CEC2210364E1D7C8AB3D509207760BACF81BB050E67322EBF2E905FF309E89ACE13BE894FFFFFFFF1F6FCB9D335E553262F3FB1CA6A826DBBE9428DD579EA51BA6090C83A7D4FCDA010000006A47304402205C9C3FFC78210A7B93912FAC417775EE6DCD8B6794BE36D01C7D0BF36BC408D702201A253C7F4BD2464DED11A837C9EA628A97399632ED04C2FEA22CBD75579E58E8C2210364E1D7C8AB3D509207760BACF81BB050E67322EBF2E905FF309E89ACE13BE894FFFFFFFF09B0858061E61218B0BB5956508F643E3818FA1FBB1400ADA6D994704418DCD9010000006A47304402203FE198B7AB8F61546D62B35A4DF160DB438C84EFFD7067B46C60AF5F27E0CBB502205FB58F426A03427CDA37CCF5B63F672F5BFE71C7E8B791AFDEEACBD1D3595CB1C22103FB41089708436C88CF77E0700CB67ACDE37F255DC4CCDBD7637AA79307269630FFFFFFFF9B1A1B386F7D66899033F7B2AEB6A934CBA1BC2953AD4FE5E16A47EEC5F3FE23000000006A47304402202DDBBB9E92D1446A4F3890657F1F56EC2DC8F41DE864077CFDB41E6C99F75FDE02204553AC6BD3B9AE35DB4664BD18BF57B3E8E9BE84D76E40B78B77E760C36A064EC22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF02FB55CA273FD7916E9C7B8F38D3F0287F9897980C840E0FA10F035DA33DAD47010000006B483045022100AC5FA70052293648A3BE5319C55B4E0A7E579F744CA04593F6EB88E0B88C1BA9022001B3419B5262022A8D5AADBEC1296167D436EE1808CD11CAC22C6B12B382CEB2C22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF770E137F47D0C046AA1F02ED198F0F5EACBA78AED8A12D5B6AC9B169C75CC8ABB50000006A47304402204EBD05E2826D5263973B0C33AA32A6E5213C8378A16CF620E41E0AE27F04A5ED02201C38314E0755513CB720BDAAAACB495945C8B64873F04CCB0AB4ECE98C023543C22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF770E137F47D0C046AA1F02ED198F0F5EACBA78AED8A12D5B6AC9B169C75CC8ABB40000006B483045022100CEE6BBBA8DFB309895A264091C9E9965EA71559F13DB22CE66DCD6A9E215E9DF0220355620462931985C870E5793C2F7222440CE468B1AD339BE4A85BADB81B25C08C22103D7558C265481BC9009884F2C6E629E7B6183D97538E9623503FC8CF5C7363D62FFFFFFFF249E0A85AC5C5F61771C6A7B1121C11FE2B68BCCA8734286AB936F10F0DF4C9E000000006B483045022100A1F45E58C823833DFA5BC5B7FE96618670911C9F1961B6E79CCBCC5D951859BB022034373BFF50DF19DD0E12736DAC6D9C4F5371C373CD6FB6CA0C07AF66AFD7F911C22103F9832BCBECE37C09BF91A46792F89C12C400F0E23F3B959CEA9EF1A9F5668888FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E64330100006A473044022065A5B6C567A05E90B6C236678AEDBC6FE93371AC2F64D1EC0BF3F294EEC3A53202202E28C99E9E285DA66BAC4EEF042BABCD94A41E43A284F31A97D0A45CBE828A66C22103F9832BCBECE37C09BF91A46792F89C12C400F0E23F3B959CEA9EF1A9F5668888FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E643501000069463043021F5601776FD074AB9A0FC636661D156CF07BF5B15B6648C5BC66D05DE4D3A663022048F33208CED52287867C6E56498553998ED9F5FF46FA5A5F2B14EC6F6C9F1FC6C221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E64340100006B483045022100ED170557BCF179486B0CD35E56717721AA948941E84234F7CACC5EE3C24C3110022063B0CFBDB9C6C8F2AEBA01EFE48ED5B273006B8B6D238C1C1282763F7BA0852FC22102F72539E17B2A9FB12999AD5AEA4FEECB2CE50574B56B5CEEE4D02D8CD07090B7FFFFFFFF51386BF256B3987E0C6404D27D06E3E53B0DE6904A419F6B8DF038F13988A8CA000000006B483045022100E34C6EA96AF4701F0CF16E898E979EBC3EB214DDA8B485AEE811E21F1C34782D022047EAD42030B2E67B15B2A3417A0420D77467C71CA31AC06E759415E2ED1E73B0C221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFF11F69487F837BD1D30C88D6F89800760FD914CBEA11EFEFB97CC2EF8467FD29C000000006A473044022079A8AE9B2F18D6C8A8C57F925C8EDE9E7DC4E9B029A08FF04FB0E7955B18E8DA0220050B99D687C43AF8CADC311DB062309B2232D0A978AC6E39328A562D3965243DC221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFFE10CEAE7D2BB2D7C60DD853E6DF8540D352C6FCA363553690425F267F4E36BB5380000006B4830450221009CF2B05A6B673E2AFF83CDA2B52D2FEF073DC8DC84C544CB5F978532A626CC7502206B6F69D943286ED45E7A5F430DEE8C6475F95EB8E557A2E2C5785F60B4E5E5E3C221022586C020EC9DF598D68F69967E61123B8F487CEFF465C8A1A0BCD377C0D4C608FFFFFFFFFBC6C11521941FBBB72A0F3B68D609F66419586D47ED2F313C64181918A04A92010000006B483045022100BEDFA3ADCBF41A099F4372746682F305A5245E08FA137801E7D4EBDE8E7EDEED02206D15AFECC651B8F6C65B59B8844C2088AA154625746A8A02C617D99277D95895C22103987C11B7D23C49817D6164B9C57CE5C845BE9E11342EBCF19095A7486B9BF147FFFFFFFF5D08873B553F347F83F8B30740C5DCBB7586E22A121ADF1888DA6F23F2C253646D0000006A47304402202E6E19291842A0390CA9098510F686D993D02F7A5C01305E5B7EF075BBBEC92E022031C1E35D8DE8F62FA015249FAD699DCA3BD7D48C60FA262C4A25872A99885E98C22103987C11B7D23C49817D6164B9C57CE5C845BE9E11342EBCF19095A7486B9BF147FFFFFFFF5D08873B553F347F83F8B30740C5DCBB7586E22A121ADF1888DA6F23F2C253646C0000006A473044022010920B2B3465ECF21A685884AD54E041C54B0CC73DE7A988921C742B06BEB51302203DB46BD95FEBD29A69008A214A0E7ED65B6B49FB5C96DD086ED10851B7C55B3DC2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF73D4D99BA348D4DA8E7F221709280F16A14B4C1E72C1A0E24AD5FC8F09CEED7D010000006A4730440220584F82CBCD237083BE0B5C80645AB8A31C0EAD5C140BD5C299EA3B7270ADADF40220429CAD186E80F0936528B2A3313EEF8A0BC67403969880BF0C1E762FCF82A062C2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF0843CB3AD2622892163DF29617F45A799E09B667AD707AD6FE7D0C2FF6FA0248010000006B483045022100DE499AD82B27200F140417C92D2BB7223F4A51AA4E3B3EC0942FFADCA8572F990220587EA05565349E79CA85DFEEE6617335BF50DD56CC0A73434478B867927253D7C2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF7E3EFF23768186357CD9E23A3C5E64D7CCDF778D4625C5FD7AF8AA0BA26D18B1010000006A47304402201667B3A2445F77BCD6A4A9DCB87B052E50189F8F261847F165EA6AA8C30204B8022034A449DCEED01B782EEB764B1453A7696B6F45BCDF58F5A16242A27B40254A26C2210205EB0CF0442AC7CF95F237F83631F3A71A769F14070BFBA130E7F6446D0FDA89FFFFFFFF7BD7CA433910CD9CD3A31E3C526C8A08F56218ABEBB8FA7B6D7F9013770903B7060000006B483045022100CBE66D90AF66E7B2098644D489E761D2E1A017DA1BCF514F6EB9CC0D143D3E29022028C3D949EBEB493C630EBA6B94E963DEE224F82E0CAFA688DCE82BF2E3E33029C2210205EB0CF0442AC7CF95F237F83631F3A71A769F14070BFBA130E7F6446D0FDA89FFFFFFFFC06A85664B630EC529F066F082CD4ECE9C6D627B4A25FA052A4321CE201F5249000000006B483045022100B8E3DBB1B95253947D66224F2B56D4AD32CEE62862AA6079BBFDB2A29097384C02207B06BAFDD798EBFC1042952A214EE0095AC456E4EC7ADCD2D7643AC940E37808C22102E6A2C34586C6A2F9F9D8247622E03E2427D8DA8BAD7069B5FBD4BAB7CFD495BEFFFFFFFF5455D0E0DAF167EA4DD6268EBF681F5B627E3CDB95A64E45B46504B47DE7559B010000006A47304402202FB18936EAA9E7574D68B64FD3A72163DC02F36E76105F6230B69B9A8CE8186E02200669E0FF51A609CF52F2D484CF90DECC7E0F288815D889DD54A208FDAFCB0480C22102E6A2C34586C6A2F9F9D8247622E03E2427D8DA8BAD7069B5FBD4BAB7CFD495BEFFFFFFFF0FC11392D3D66CE589DBEE6396A9C91906E94E5FFB0F10582DD84DC27C139549010000006B483045022100B1B780C18EE1B24A67756E15ED487626247718743B25781E8DCEF385817EBA0A0220422935FE91405FD3E2834EBE03EA27DEA2AD73F2E5A32798D3EFAA28A11B0E45C22102D54A842BF3053DA8139191C78DD95859326551C14D33317232240E825AC86721FFFFFFFF5C81D63ACF4A9539158B16F116C9FE16E61AD2EAE8627B0DAF6E5E27D7065BCE4B0000006A473044022070BEAC59696981AB7E13CB99C8AA5EBDA64AB3B2CEFC4197760480B24473C62A02201AC5EA4E1AA854C7CF641A70D5629CE17D3101D0F29F383EBFD300D11B8355F7C22103E0C3031D39F82DCED6FE23F7DAEF43C1C2AA37279E6CACFCC3D65C20896EFAFEFFFFFFFFA832AAD47D0F6C088C259B108C1234866D824B63081D056889560A63987A9F61000000006B483045022100F67205F32BE5981277C403ADD7DDCF355760545FA5F07B5221AC51AD39B5D6240220015D5AC3AE684183E92F128C96B8C4FBE37D581A2238B55548D0FAE5188C93D0C221030A82429D655A883ABB84A6F494ED0F584FAE70AF76F6FFE089FC858DFF6791CAFFFFFFFF9F7AB7BD8B01B35936A0806314FBA6E05978B00B588809CBC1BFE440BE48F437010000006B483045022100B0E893E5300216E39CBA60AA01BBCF233024A364F6688305CBB5A23FD99A9DDB02200BE2E288377E83222C066A4647EEE4A0F8DB1289034F19C75B029071A74B1BB3C221028AA47294780FCE86047AD43B106B887101311EF2EC15CF8CC781A5E94E941B87FFFFFFFF437A577E1B156B11BA5D3D4F77883778B8A16344DE7A493337A48A4277E3501F640000006B4830450221008BDFE07288CC912878F66E451DA2067E02FD2169B32C42ADC226CA0AC588ABFC02207F3F185DB742C755F554539C2DDAE99DB84BF31198623F3D36B28A6040F13187C221028DC193FA0BAE51229C0D913B37B4B85E7D8657C67E6B39DE55F0F829F3E56F97FFFFFFFFEB46CAC62C55714409DC0CB9DEB430A28BDF64DE9F67D2A462E6901B4D633376010000006A47304402203627468E6F210ABD49276436DC5A76DF6160D25650C62F5943140AC70FECF39302202294C59CF141219551382ECCE8D529F346A88413070DC90FB11B3AFA24C9DDE5C2210375727B6DF18C46DA978E03F1197AD63F3A7A2EB59ECC6C808F01CF01DF4CC462FFFFFFFFFE263AF23E8A0656DA85D0E776CD26B77EB606869C41119CF0211DC3EB7FACD1210100006B483045022100967F8B5E10858E507C64F9DA6FF840133FD5A76E515C3CFDF88833E9819733F2022052B33CD8CD3AB5CF745C75136F2CDF675620BB94D09616117567FD22D08AD052C2210375727B6DF18C46DA978E03F1197AD63F3A7A2EB59ECC6C808F01CF01DF4CC462FFFFFFFFFE263AF23E8A0656DA85D0E776CD26B77EB606869C41119CF0211DC3EB7FACD1200100006B483045022100ADC229F8037EB7B3D08D6DE7A0DEAAE2874D7B943406D9ADAEC34899A7CC0B62022059DE20822F8E1DF474C0C763EAB20EB1AADC9DAC2EBB3D685CB24EC6917AFC49C221027ED09AC05B9215F00B6F8BE59CEC79284542F5E8C1D17AC660B2C296FCEE931BFFFFFFFF232740426EDFE1EA3337FB4438252AA67FB144C6CB1DAC76FEBB16BB954C6ABA000000006B483045022100DB65D8077D5EA9C886629F328BFCAC9ACBA3FF83E50EA18C360CE22CD6DC3BDC022001759AF276AFE21C13A66539008DC5F0469129A3FB7A51703B2FE416047C8A1CC221027ED09AC05B9215F00B6F8BE59CEC79284542F5E8C1D17AC660B2C296FCEE931BFFFFFFFF09537489C63ED62DF8D069AEFD16BF4775E1D9878F0BE9EAC4AC2CB3A8169DAE260000006B483045022100D0CAA6FD70BF80C6E936F4738221F874E9C620FE1CA96BC0D87F23FF863B33DE0220124B342E241E41C2645DC4181A75239618D267E64BBDAB7A72109BFAB89FE784C22102C4559C96B87528C3B2385DC63216B0EEE1E25524E9E45CBB7577DEF21B1D62B9FFFFFFFF3739FA73213ED1440431274667DDCEA593DFBDFADFF26F37359BC06492BBB0E59B0000006B48304502210099AA3BD609A06C875D0F584B0A6644387179ACB6F63C690C6FF20B650653259802205898DD42BC06A8F8D1A74A2F74CCBA7B0D6DCBDA51A9B7ADD12E5F4F13121CCFC2210366C2029F74160CBA941383501C988D37BF932629F97B4E07DF1A339EC25ADB71FFFFFFFFC34D896F7B4EAE1344A02398292A2FDDD464E15A0C3321FF17D3B96D92D8FB64340000006B483045022100F32667A5734DDA65A6DDF9DFA789907B1ABBEBB0062CD694FA6E2A57A13178A202205BAF300DFADA245B470BA87794219E8173723FF3AC6FEA06296D23297375BF45C2210268C6B69A5BC61E1F3452D5828D7D2D8FBD4AAC371665ADB17973198377DD10D4FFFFFFFFCFD345CB9C6D4574D28EF1E0704B2657434FBAE1521F27D9AE1E005039DF4D92940000006B483045022100F228CC33D6EAAE7C0631741D1D0DD1EE02ECF725DDEFB1D02C877B3E449AA588022052C50C407B0217EE829BC1392971198ED7D08D18A5ABF90C13D9A81F20D7EA65C2210265BD8F8378E28817B5CBE47B08E326FC9972F27D1A354A85F43888507B10A497FFFFFFFF4DFCB8A82E6BFA8EB78BA4E66F0142B49D685D3036094A7F490DB544007E2292560000006B483045022100A82557798CCA2E6D8F00FBB49A9DE767BB2079E90B615DF29E7F44A870BBA43C02207B2B038237D55F962046B8046E53DF428999D716EEC2B980A927ADD5AE3A607AC22102463CABC398AAC0B7239F1AB82D0794B4E9FF87D4DBBE8747E5A94586485013DCFFFFFFFFEAEACA9F9CDE43599A95F529769BE324C910E0BE55BC84E1F1E92F0DE60F82842A0000006A473044022041765D681A868D6898F1931ECA896B624C7796DF89A7C80004AEFCD4A84D0A19022053ABCE69D529BE59BBC859D4314C2E093FB2C24823001A396DCE4CD7B2F21AA7C2210364BB8517C6A28CF7253DAEBBBA7064A4216125DE6476426E74480A3371B92D42FFFFFFFF25DB850D2664BA6B4DEADC76366DA35C1780C4B937E6DF473C602B49C2F47688380100006A47304402202145BEFCBD10A3D97AF74E264AEFBB6931227FF723BE6A680D277B185E25919902205C1769C6BF8F036F57B092F428C06E39081AF979DE35415AF6C74B294BDD4211C22103B04A47F53CF3BB0F7B00088D453E36618148B9261FAEF8CE8F6B3FA3DFEFBDCAFFFFFFFF01031864CD2E0000001976A91465BD7B5E75C7450F77976954A91DE75C73BEB4CE88AC00000000`