@bsv/wallet-toolbox 2.13.0 → 2.13.2

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