@attocash/cli 0.1.0

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 (400) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +707 -0
  3. package/dist/application/app.d.ts +138 -0
  4. package/dist/application/app.js +654 -0
  5. package/dist/application/operations.d.ts +9 -0
  6. package/dist/application/operations.js +96 -0
  7. package/dist/cli/cli.d.ts +1 -0
  8. package/dist/cli/cli.js +460 -0
  9. package/dist/cli/help.d.ts +4 -0
  10. package/dist/cli/help.js +49 -0
  11. package/dist/cli/main.d.ts +2 -0
  12. package/dist/cli/main.js +13 -0
  13. package/dist/cli/onboarding.d.ts +14 -0
  14. package/dist/cli/onboarding.js +144 -0
  15. package/dist/cli/output.d.ts +2 -0
  16. package/dist/cli/output.js +231 -0
  17. package/dist/cli/terminal.d.ts +6 -0
  18. package/dist/cli/terminal.js +92 -0
  19. package/dist/cli/update-check.d.ts +1 -0
  20. package/dist/cli/update-check.js +12 -0
  21. package/dist/cli/updates.d.ts +2 -0
  22. package/dist/cli/updates.js +98 -0
  23. package/dist/core.d.ts +14 -0
  24. package/dist/core.js +14 -0
  25. package/dist/doctor/credential-probe.d.ts +7 -0
  26. package/dist/doctor/credential-probe.js +49 -0
  27. package/dist/doctor/doctor.d.ts +4 -0
  28. package/dist/doctor/doctor.js +213 -0
  29. package/dist/doctor/keyring.d.ts +7 -0
  30. package/dist/doctor/keyring.js +150 -0
  31. package/dist/doctor/profile.d.ts +19 -0
  32. package/dist/doctor/profile.js +73 -0
  33. package/dist/doctor/types.d.ts +40 -0
  34. package/dist/doctor/types.js +1 -0
  35. package/dist/domain/amount.d.ts +6 -0
  36. package/dist/domain/amount.js +27 -0
  37. package/dist/domain/errors.d.ts +10 -0
  38. package/dist/domain/errors.js +16 -0
  39. package/dist/labels/directory.d.ts +87 -0
  40. package/dist/labels/directory.js +140 -0
  41. package/dist/labels/personal.d.ts +17 -0
  42. package/dist/labels/personal.js +56 -0
  43. package/dist/labels/presentation.d.ts +154 -0
  44. package/dist/labels/presentation.js +90 -0
  45. package/dist/network/reader.d.ts +31 -0
  46. package/dist/network/reader.js +370 -0
  47. package/dist/network/retry.d.ts +7 -0
  48. package/dist/network/retry.js +53 -0
  49. package/dist/network/work.d.ts +3 -0
  50. package/dist/network/work.js +66 -0
  51. package/dist/pricing/market.d.ts +29 -0
  52. package/dist/pricing/market.js +150 -0
  53. package/dist/pricing/terms.d.ts +6 -0
  54. package/dist/pricing/terms.js +12 -0
  55. package/dist/spending/destination.d.ts +16 -0
  56. package/dist/spending/destination.js +42 -0
  57. package/dist/spending/journal.d.ts +28 -0
  58. package/dist/spending/journal.js +69 -0
  59. package/dist/spending/ledger.d.ts +118 -0
  60. package/dist/spending/ledger.js +444 -0
  61. package/dist/spending/payments.d.ts +67 -0
  62. package/dist/spending/payments.js +424 -0
  63. package/dist/spending/pool.d.ts +13 -0
  64. package/dist/spending/pool.js +38 -0
  65. package/dist/spending/reconcile.d.ts +18 -0
  66. package/dist/spending/reconcile.js +64 -0
  67. package/dist/storage/profiles.d.ts +13 -0
  68. package/dist/storage/profiles.js +86 -0
  69. package/dist/storage/secrets.d.ts +16 -0
  70. package/dist/storage/secrets.js +104 -0
  71. package/dist/storage/state.d.ts +32 -0
  72. package/dist/storage/state.js +255 -0
  73. package/dist/wallet/auto-receive.d.ts +57 -0
  74. package/dist/wallet/auto-receive.js +140 -0
  75. package/dist/wallet/defaults.d.ts +3 -0
  76. package/dist/wallet/defaults.js +26 -0
  77. package/dist/wallet/signing.d.ts +17 -0
  78. package/dist/wallet/signing.js +128 -0
  79. package/dist/wallet/types.d.ts +65 -0
  80. package/dist/wallet/types.js +1 -0
  81. package/dist/wallet/work.d.ts +29 -0
  82. package/dist/wallet/work.js +154 -0
  83. package/dist/watches/manager.d.ts +75 -0
  84. package/dist/watches/manager.js +197 -0
  85. package/node_modules/@attocash/commons-core/Kotlin-DateTime-library-kotlinx-datetime.mjs +6678 -0
  86. package/node_modules/@attocash/commons-core/Kotlin-DateTime-library-kotlinx-datetime.mjs.map +1 -0
  87. package/node_modules/@attocash/commons-core/LICENSE +28 -0
  88. package/node_modules/@attocash/commons-core/README.md +118 -0
  89. package/node_modules/@attocash/commons-core/commons-commons-core.d.mts +1036 -0
  90. package/node_modules/@attocash/commons-core/commons-commons-core.mjs +7701 -0
  91. package/node_modules/@attocash/commons-core/commons-commons-core.mjs.map +1 -0
  92. package/node_modules/@attocash/commons-core/kotlin-kotlin-stdlib.mjs +17681 -0
  93. package/node_modules/@attocash/commons-core/kotlin-kotlin-stdlib.mjs.map +1 -0
  94. package/node_modules/@attocash/commons-core/kotlin_org_jetbrains_kotlin_kotlin_dom_api_compat.mjs +4 -0
  95. package/node_modules/@attocash/commons-core/kotlin_org_jetbrains_kotlin_kotlin_dom_api_compat.mjs.map +1 -0
  96. package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-bytestring.mjs +209 -0
  97. package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-bytestring.mjs.map +1 -0
  98. package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-core.mjs +2284 -0
  99. package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-core.mjs.map +1 -0
  100. package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-core.mjs +6042 -0
  101. package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-core.mjs.map +1 -0
  102. package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  103. package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  104. package/node_modules/@attocash/commons-core/package.json +27 -0
  105. package/node_modules/@attocash/commons-node/LICENSE +28 -0
  106. package/node_modules/@attocash/commons-node/README.md +92 -0
  107. package/node_modules/@attocash/commons-node/commons-commons-node.d.mts +255 -0
  108. package/node_modules/@attocash/commons-node/commons-commons-node.mjs +2977 -0
  109. package/node_modules/@attocash/commons-node/commons-commons-node.mjs.map +1 -0
  110. package/node_modules/@attocash/commons-node/kotlin-logging.mjs +432 -0
  111. package/node_modules/@attocash/commons-node/kotlin-logging.mjs.map +1 -0
  112. package/node_modules/@attocash/commons-node/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  113. package/node_modules/@attocash/commons-node/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  114. package/node_modules/@attocash/commons-node/package.json +29 -0
  115. package/node_modules/@attocash/commons-node-remote/LICENSE +28 -0
  116. package/node_modules/@attocash/commons-node-remote/README.md +61 -0
  117. package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.d.mts +122 -0
  118. package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.mjs +1810 -0
  119. package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.mjs.map +1 -0
  120. package/node_modules/@attocash/commons-node-remote/kotlin-logging.mjs +432 -0
  121. package/node_modules/@attocash/commons-node-remote/kotlin-logging.mjs.map +1 -0
  122. package/node_modules/@attocash/commons-node-remote/kotlinx-browser.mjs +8 -0
  123. package/node_modules/@attocash/commons-node-remote/kotlinx-browser.mjs.map +1 -0
  124. package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
  125. package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
  126. package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  127. package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  128. package/node_modules/@attocash/commons-node-remote/package.json +31 -0
  129. package/node_modules/@attocash/commons-transport/LICENSE +28 -0
  130. package/node_modules/@attocash/commons-transport/README.md +5 -0
  131. package/node_modules/@attocash/commons-transport/commons-commons-transport.d.mts +64 -0
  132. package/node_modules/@attocash/commons-transport/commons-commons-transport.mjs +249 -0
  133. package/node_modules/@attocash/commons-transport/commons-commons-transport.mjs.map +1 -0
  134. package/node_modules/@attocash/commons-transport/kotlinx-atomicfu.mjs +263 -0
  135. package/node_modules/@attocash/commons-transport/kotlinx-atomicfu.mjs.map +1 -0
  136. package/node_modules/@attocash/commons-transport/kotlinx-browser.mjs +8 -0
  137. package/node_modules/@attocash/commons-transport/kotlinx-browser.mjs.map +1 -0
  138. package/node_modules/@attocash/commons-transport/kotlinx-coroutines-core.mjs +11604 -0
  139. package/node_modules/@attocash/commons-transport/kotlinx-coroutines-core.mjs.map +1 -0
  140. package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
  141. package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
  142. package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  143. package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  144. package/node_modules/@attocash/commons-transport/ktor-ktor-client-content-negotiation.mjs +499 -0
  145. package/node_modules/@attocash/commons-transport/ktor-ktor-client-content-negotiation.mjs.map +1 -0
  146. package/node_modules/@attocash/commons-transport/ktor-ktor-client-core.mjs +6456 -0
  147. package/node_modules/@attocash/commons-transport/ktor-ktor-client-core.mjs.map +1 -0
  148. package/node_modules/@attocash/commons-transport/ktor-ktor-events.mjs +83 -0
  149. package/node_modules/@attocash/commons-transport/ktor-ktor-events.mjs.map +1 -0
  150. package/node_modules/@attocash/commons-transport/ktor-ktor-http-cio.mjs +1714 -0
  151. package/node_modules/@attocash/commons-transport/ktor-ktor-http-cio.mjs.map +1 -0
  152. package/node_modules/@attocash/commons-transport/ktor-ktor-http.mjs +3197 -0
  153. package/node_modules/@attocash/commons-transport/ktor-ktor-http.mjs.map +1 -0
  154. package/node_modules/@attocash/commons-transport/ktor-ktor-io.mjs +2290 -0
  155. package/node_modules/@attocash/commons-transport/ktor-ktor-io.mjs.map +1 -0
  156. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx-json.mjs +46 -0
  157. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx-json.mjs.map +1 -0
  158. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx.mjs +482 -0
  159. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx.mjs.map +1 -0
  160. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization.mjs +165 -0
  161. package/node_modules/@attocash/commons-transport/ktor-ktor-serialization.mjs.map +1 -0
  162. package/node_modules/@attocash/commons-transport/ktor-ktor-sse.mjs +4 -0
  163. package/node_modules/@attocash/commons-transport/ktor-ktor-sse.mjs.map +1 -0
  164. package/node_modules/@attocash/commons-transport/ktor-ktor-utils.mjs +3222 -0
  165. package/node_modules/@attocash/commons-transport/ktor-ktor-utils.mjs.map +1 -0
  166. package/node_modules/@attocash/commons-transport/ktor-ktor-websocket-serialization.mjs +4 -0
  167. package/node_modules/@attocash/commons-transport/ktor-ktor-websocket-serialization.mjs.map +1 -0
  168. package/node_modules/@attocash/commons-transport/ktor-ktor-websockets.mjs +1485 -0
  169. package/node_modules/@attocash/commons-transport/ktor-ktor-websockets.mjs.map +1 -0
  170. package/node_modules/@attocash/commons-transport/package.json +29 -0
  171. package/node_modules/@attocash/commons-worker/LICENSE +28 -0
  172. package/node_modules/@attocash/commons-worker/README.md +48 -0
  173. package/node_modules/@attocash/commons-worker/commons-commons-worker.d.mts +73 -0
  174. package/node_modules/@attocash/commons-worker/commons-commons-worker.mjs +702 -0
  175. package/node_modules/@attocash/commons-worker/commons-commons-worker.mjs.map +1 -0
  176. package/node_modules/@attocash/commons-worker/kotlin-logging.mjs +432 -0
  177. package/node_modules/@attocash/commons-worker/kotlin-logging.mjs.map +1 -0
  178. package/node_modules/@attocash/commons-worker/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  179. package/node_modules/@attocash/commons-worker/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  180. package/node_modules/@attocash/commons-worker/package.json +29 -0
  181. package/node_modules/@attocash/commons-worker-remote/LICENSE +28 -0
  182. package/node_modules/@attocash/commons-worker-remote/README.md +60 -0
  183. package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.d.mts +93 -0
  184. package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.mjs +289 -0
  185. package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.mjs.map +1 -0
  186. package/node_modules/@attocash/commons-worker-remote/kotlin-logging.mjs +432 -0
  187. package/node_modules/@attocash/commons-worker-remote/kotlin-logging.mjs.map +1 -0
  188. package/node_modules/@attocash/commons-worker-remote/kotlinx-browser.mjs +8 -0
  189. package/node_modules/@attocash/commons-worker-remote/kotlinx-browser.mjs.map +1 -0
  190. package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
  191. package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
  192. package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
  193. package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
  194. package/node_modules/@attocash/commons-worker-remote/package.json +31 -0
  195. package/node_modules/@js-joda/core/CHANGELOG.md +363 -0
  196. package/node_modules/@js-joda/core/CheatSheet.md +947 -0
  197. package/node_modules/@js-joda/core/LICENSE +34 -0
  198. package/node_modules/@js-joda/core/README.md +155 -0
  199. package/node_modules/@js-joda/core/bower.json +21 -0
  200. package/node_modules/@js-joda/core/dist/js-joda.d.ts +2452 -0
  201. package/node_modules/@js-joda/core/dist/js-joda.esm.js +13564 -0
  202. package/node_modules/@js-joda/core/dist/js-joda.flow.js +949 -0
  203. package/node_modules/@js-joda/core/dist/js-joda.js +13630 -0
  204. package/node_modules/@js-joda/core/dist/js-joda.js.map +1 -0
  205. package/node_modules/@js-joda/core/dist/js-joda.min.js +5 -0
  206. package/node_modules/@js-joda/core/package.json +76 -0
  207. package/node_modules/@js-joda/core/src/Clock.js +330 -0
  208. package/node_modules/@js-joda/core/src/DayOfWeek.js +451 -0
  209. package/node_modules/@js-joda/core/src/Duration.js +1205 -0
  210. package/node_modules/@js-joda/core/src/Enum.js +30 -0
  211. package/node_modules/@js-joda/core/src/Instant.js +1012 -0
  212. package/node_modules/@js-joda/core/src/LocalDate.js +1703 -0
  213. package/node_modules/@js-joda/core/src/LocalDateTime.js +1686 -0
  214. package/node_modules/@js-joda/core/src/LocalTime.js +1415 -0
  215. package/node_modules/@js-joda/core/src/MathUtil.js +236 -0
  216. package/node_modules/@js-joda/core/src/Month.js +600 -0
  217. package/node_modules/@js-joda/core/src/MonthDay.js +730 -0
  218. package/node_modules/@js-joda/core/src/OffsetDateTime.js +757 -0
  219. package/node_modules/@js-joda/core/src/OffsetTime.js +621 -0
  220. package/node_modules/@js-joda/core/src/Period.js +933 -0
  221. package/node_modules/@js-joda/core/src/StringUtil.js +43 -0
  222. package/node_modules/@js-joda/core/src/Year.js +1015 -0
  223. package/node_modules/@js-joda/core/src/YearConstants.js +21 -0
  224. package/node_modules/@js-joda/core/src/YearMonth.js +1096 -0
  225. package/node_modules/@js-joda/core/src/ZoneId.js +236 -0
  226. package/node_modules/@js-joda/core/src/ZoneIdFactory.js +201 -0
  227. package/node_modules/@js-joda/core/src/ZoneOffset.js +486 -0
  228. package/node_modules/@js-joda/core/src/ZoneRegion.js +72 -0
  229. package/node_modules/@js-joda/core/src/ZonedDateTime.js +2007 -0
  230. package/node_modules/@js-joda/core/src/_init.js +68 -0
  231. package/node_modules/@js-joda/core/src/assert.js +33 -0
  232. package/node_modules/@js-joda/core/src/chrono/ChronoLocalDate.js +230 -0
  233. package/node_modules/@js-joda/core/src/chrono/ChronoLocalDateTime.js +130 -0
  234. package/node_modules/@js-joda/core/src/chrono/ChronoZonedDateTime.js +194 -0
  235. package/node_modules/@js-joda/core/src/chrono/IsoChronology.js +235 -0
  236. package/node_modules/@js-joda/core/src/convert.js +83 -0
  237. package/node_modules/@js-joda/core/src/errors.js +54 -0
  238. package/node_modules/@js-joda/core/src/format/DateTimeBuilder.js +535 -0
  239. package/node_modules/@js-joda/core/src/format/DateTimeFormatter.js +728 -0
  240. package/node_modules/@js-joda/core/src/format/DateTimeFormatterBuilder.js +1545 -0
  241. package/node_modules/@js-joda/core/src/format/DateTimeParseContext.js +297 -0
  242. package/node_modules/@js-joda/core/src/format/DateTimePrintContext.js +138 -0
  243. package/node_modules/@js-joda/core/src/format/DecimalStyle.js +113 -0
  244. package/node_modules/@js-joda/core/src/format/EnumMap.js +70 -0
  245. package/node_modules/@js-joda/core/src/format/ParsePosition.js +31 -0
  246. package/node_modules/@js-joda/core/src/format/ResolverStyle.js +93 -0
  247. package/node_modules/@js-joda/core/src/format/SignStyle.js +38 -0
  248. package/node_modules/@js-joda/core/src/format/StringBuilder.js +47 -0
  249. package/node_modules/@js-joda/core/src/format/TextStyle.js +114 -0
  250. package/node_modules/@js-joda/core/src/format/parser/CharLiteralPrinterParser.js +46 -0
  251. package/node_modules/@js-joda/core/src/format/parser/CompositePrinterParser.js +89 -0
  252. package/node_modules/@js-joda/core/src/format/parser/FractionPrinterParser.js +162 -0
  253. package/node_modules/@js-joda/core/src/format/parser/NumberPrinterParser.js +367 -0
  254. package/node_modules/@js-joda/core/src/format/parser/OffsetIdPrinterParser.js +177 -0
  255. package/node_modules/@js-joda/core/src/format/parser/PadPrinterParserDecorator.js +81 -0
  256. package/node_modules/@js-joda/core/src/format/parser/SettingsParser.js +44 -0
  257. package/node_modules/@js-joda/core/src/format/parser/StringLiteralPrinterParser.js +39 -0
  258. package/node_modules/@js-joda/core/src/format/parser/ZoneIdPrinterParser.js +218 -0
  259. package/node_modules/@js-joda/core/src/js-joda.js +210 -0
  260. package/node_modules/@js-joda/core/src/license-preamble.js +3 -0
  261. package/node_modules/@js-joda/core/src/temporal/ChronoField.js +470 -0
  262. package/node_modules/@js-joda/core/src/temporal/ChronoUnit.js +310 -0
  263. package/node_modules/@js-joda/core/src/temporal/DefaultInterfaceTemporal.js +118 -0
  264. package/node_modules/@js-joda/core/src/temporal/IsoFields.js +859 -0
  265. package/node_modules/@js-joda/core/src/temporal/NativeJsTemporal.js +105 -0
  266. package/node_modules/@js-joda/core/src/temporal/Temporal.js +346 -0
  267. package/node_modules/@js-joda/core/src/temporal/TemporalAccessor.js +125 -0
  268. package/node_modules/@js-joda/core/src/temporal/TemporalAdjuster.js +92 -0
  269. package/node_modules/@js-joda/core/src/temporal/TemporalAdjusters.js +464 -0
  270. package/node_modules/@js-joda/core/src/temporal/TemporalAmount.js +166 -0
  271. package/node_modules/@js-joda/core/src/temporal/TemporalField.js +248 -0
  272. package/node_modules/@js-joda/core/src/temporal/TemporalQueries.js +223 -0
  273. package/node_modules/@js-joda/core/src/temporal/TemporalQueriesFactory.js +77 -0
  274. package/node_modules/@js-joda/core/src/temporal/TemporalQuery.js +107 -0
  275. package/node_modules/@js-joda/core/src/temporal/TemporalUnit.js +179 -0
  276. package/node_modules/@js-joda/core/src/temporal/ValueRange.js +257 -0
  277. package/node_modules/@js-joda/core/src/use.js +20 -0
  278. package/node_modules/@js-joda/core/src/zone/SystemDefaultZoneId.js +31 -0
  279. package/node_modules/@js-joda/core/src/zone/SystemDefaultZoneRules.js +162 -0
  280. package/node_modules/@js-joda/core/src/zone/ZoneOffsetTransition.js +289 -0
  281. package/node_modules/@js-joda/core/src/zone/ZoneRules.js +464 -0
  282. package/node_modules/@js-joda/core/src/zone/ZoneRulesProvider.js +36 -0
  283. package/node_modules/@noble/hashes/LICENSE +21 -0
  284. package/node_modules/@noble/hashes/README.md +563 -0
  285. package/node_modules/@noble/hashes/_blake.d.ts +21 -0
  286. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  287. package/node_modules/@noble/hashes/_blake.js +52 -0
  288. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  289. package/node_modules/@noble/hashes/_md.d.ts +99 -0
  290. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  291. package/node_modules/@noble/hashes/_md.js +202 -0
  292. package/node_modules/@noble/hashes/_md.js.map +1 -0
  293. package/node_modules/@noble/hashes/_u64.d.ts +63 -0
  294. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  295. package/node_modules/@noble/hashes/_u64.js +84 -0
  296. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  297. package/node_modules/@noble/hashes/argon2.d.ts +112 -0
  298. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  299. package/node_modules/@noble/hashes/argon2.js +517 -0
  300. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  301. package/node_modules/@noble/hashes/blake1.d.ts +156 -0
  302. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  303. package/node_modules/@noble/hashes/blake1.js +560 -0
  304. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  305. package/node_modules/@noble/hashes/blake2.d.ts +184 -0
  306. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  307. package/node_modules/@noble/hashes/blake2.js +501 -0
  308. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  309. package/node_modules/@noble/hashes/blake3.d.ts +68 -0
  310. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  311. package/node_modules/@noble/hashes/blake3.js +284 -0
  312. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  313. package/node_modules/@noble/hashes/eskdf.d.ts +92 -0
  314. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  315. package/node_modules/@noble/hashes/eskdf.js +218 -0
  316. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  317. package/node_modules/@noble/hashes/hkdf.d.ts +64 -0
  318. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  319. package/node_modules/@noble/hashes/hkdf.js +120 -0
  320. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  321. package/node_modules/@noble/hashes/hmac.d.ts +47 -0
  322. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  323. package/node_modules/@noble/hashes/hmac.js +93 -0
  324. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  325. package/node_modules/@noble/hashes/index.d.ts +2 -0
  326. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  327. package/node_modules/@noble/hashes/index.js +35 -0
  328. package/node_modules/@noble/hashes/index.js.map +1 -0
  329. package/node_modules/@noble/hashes/legacy.d.ts +102 -0
  330. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  331. package/node_modules/@noble/hashes/legacy.js +327 -0
  332. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  333. package/node_modules/@noble/hashes/package.json +97 -0
  334. package/node_modules/@noble/hashes/pbkdf2.d.ts +56 -0
  335. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  336. package/node_modules/@noble/hashes/pbkdf2.js +135 -0
  337. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  338. package/node_modules/@noble/hashes/scrypt.d.ts +65 -0
  339. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  340. package/node_modules/@noble/hashes/scrypt.js +257 -0
  341. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  342. package/node_modules/@noble/hashes/sha2.d.ts +249 -0
  343. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  344. package/node_modules/@noble/hashes/sha2.js +458 -0
  345. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  346. package/node_modules/@noble/hashes/sha3-addons.d.ts +461 -0
  347. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  348. package/node_modules/@noble/hashes/sha3-addons.js +783 -0
  349. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  350. package/node_modules/@noble/hashes/sha3.d.ts +199 -0
  351. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  352. package/node_modules/@noble/hashes/sha3.js +431 -0
  353. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  354. package/node_modules/@noble/hashes/src/_blake.ts +57 -0
  355. package/node_modules/@noble/hashes/src/_md.ts +222 -0
  356. package/node_modules/@noble/hashes/src/_u64.ts +117 -0
  357. package/node_modules/@noble/hashes/src/argon2.ts +667 -0
  358. package/node_modules/@noble/hashes/src/blake1.ts +614 -0
  359. package/node_modules/@noble/hashes/src/blake2.ts +582 -0
  360. package/node_modules/@noble/hashes/src/blake3.ts +317 -0
  361. package/node_modules/@noble/hashes/src/eskdf.ts +259 -0
  362. package/node_modules/@noble/hashes/src/hkdf.ts +133 -0
  363. package/node_modules/@noble/hashes/src/hmac.ts +126 -0
  364. package/node_modules/@noble/hashes/src/index.ts +33 -0
  365. package/node_modules/@noble/hashes/src/legacy.ts +339 -0
  366. package/node_modules/@noble/hashes/src/pbkdf2.ts +175 -0
  367. package/node_modules/@noble/hashes/src/scrypt.ts +315 -0
  368. package/node_modules/@noble/hashes/src/sha2.ts +530 -0
  369. package/node_modules/@noble/hashes/src/sha3-addons.ts +983 -0
  370. package/node_modules/@noble/hashes/src/sha3.ts +485 -0
  371. package/node_modules/@noble/hashes/src/utils.ts +848 -0
  372. package/node_modules/@noble/hashes/src/webcrypto.ts +239 -0
  373. package/node_modules/@noble/hashes/utils.d.ts +519 -0
  374. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  375. package/node_modules/@noble/hashes/utils.js +578 -0
  376. package/node_modules/@noble/hashes/utils.js.map +1 -0
  377. package/node_modules/@noble/hashes/webcrypto.d.ts +120 -0
  378. package/node_modules/@noble/hashes/webcrypto.d.ts.map +1 -0
  379. package/node_modules/@noble/hashes/webcrypto.js +165 -0
  380. package/node_modules/@noble/hashes/webcrypto.js.map +1 -0
  381. package/node_modules/ws/LICENSE +20 -0
  382. package/node_modules/ws/README.md +548 -0
  383. package/node_modules/ws/browser.js +8 -0
  384. package/node_modules/ws/index.js +22 -0
  385. package/node_modules/ws/lib/buffer-util.js +131 -0
  386. package/node_modules/ws/lib/constants.js +19 -0
  387. package/node_modules/ws/lib/event-target.js +292 -0
  388. package/node_modules/ws/lib/extension.js +203 -0
  389. package/node_modules/ws/lib/limiter.js +55 -0
  390. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  391. package/node_modules/ws/lib/receiver.js +743 -0
  392. package/node_modules/ws/lib/sender.js +607 -0
  393. package/node_modules/ws/lib/stream.js +161 -0
  394. package/node_modules/ws/lib/subprotocol.js +62 -0
  395. package/node_modules/ws/lib/validation.js +152 -0
  396. package/node_modules/ws/lib/websocket-server.js +562 -0
  397. package/node_modules/ws/lib/websocket.js +1407 -0
  398. package/node_modules/ws/package.json +74 -0
  399. package/node_modules/ws/wrapper.mjs +21 -0
  400. package/package.json +53 -0
@@ -0,0 +1,654 @@
1
+ import { PersonalLabels } from '../labels/personal.js';
2
+ import { GlobalDirectory } from '../labels/directory.js';
3
+ import { AddressLabels } from '../labels/presentation.js';
4
+ import { createHash } from 'node:crypto';
5
+ import { AttoMnemonic, toAttoIndex, } from '@attocash/commons-core';
6
+ import { amountOutput, amountRaw } from '../domain/amount.js';
7
+ import { AttoError } from '../domain/errors.js';
8
+ import { NodeReader, parseAddress, publicModel } from '../network/reader.js';
9
+ import { OsSecretStore } from '../storage/secrets.js';
10
+ import { StateStore } from '../storage/state.js';
11
+ import { resolveWalletProfile } from '../storage/profiles.js';
12
+ import { SpendLedger } from '../spending/ledger.js';
13
+ import { Payments } from '../spending/payments.js';
14
+ import { WalletWork } from '../wallet/work.js';
15
+ import { WatchManager } from '../watches/manager.js';
16
+ import { AutoReceiver } from '../wallet/auto-receive.js';
17
+ import { defaultSettings } from '../wallet/defaults.js';
18
+ import { derivedSigner, mnemonicSeed, signingWallet } from '../wallet/signing.js';
19
+ import { operations, parseOperation } from './operations.js';
20
+ import { MarketData } from '../pricing/market.js';
21
+ import { marketTerms } from '../pricing/terms.js';
22
+ import { runDoctor } from '../doctor/doctor.js';
23
+ const RESET_KEY = 'wallet.reset';
24
+ export class AttoApplication {
25
+ store;
26
+ ledger;
27
+ secrets;
28
+ market;
29
+ personal;
30
+ labels;
31
+ auto;
32
+ work;
33
+ payments;
34
+ watchManager;
35
+ watchConfiguration = '';
36
+ watchQueue = Promise.resolve();
37
+ closed = false;
38
+ started = false;
39
+ resetting = false;
40
+ recoveryReads = 0;
41
+ calls = new Set();
42
+ mcp;
43
+ doctorAbort = new AbortController();
44
+ constructor(options = {}) {
45
+ const profile = resolveWalletProfile(options.directory);
46
+ this.store = new StateStore(profile.directory);
47
+ try {
48
+ this.secrets = options.secrets ?? new OsSecretStore(profile.credentialAccount, profile.credentialService);
49
+ this.mcp = options.access === 'mcp';
50
+ this.ledger = new SpendLedger(this.store);
51
+ this.personal = new PersonalLabels(this.store);
52
+ this.labels = new AddressLabels(this.personal, options.globalDirectory ?? new GlobalDirectory(this.store.directory));
53
+ this.market = options.market ?? new MarketData();
54
+ this.store.transaction(() => {
55
+ if (!this.store.get('settings'))
56
+ this.store.set('settings', defaultSettings());
57
+ });
58
+ this.work = new WalletWork(this.store, () => this.settings());
59
+ this.payments = new Payments(this.store, this.ledger, {
60
+ settings: () => this.settings(), addresses: () => this.addresses(), seed: () => this.seed(),
61
+ requireWrite: () => this.requireMcpWrite(), mcp: this.mcp,
62
+ }, this.market, this.work, options.sendRetry, options.onDestination);
63
+ this.auto = new AutoReceiver(() => ({
64
+ settings: this.mcp && this.ledger.mcpAccess() !== 'spend' ? { ...this.settings(), autoReceive: false } : this.settings(),
65
+ addresses: this.addresses(),
66
+ }), (index, hash) => this.receive({ index, hash }, true), event => options.onReceiveProgress?.(this.labels.decorate(event, this.settings().network)));
67
+ }
68
+ catch (error) {
69
+ this.store.close();
70
+ throw error;
71
+ }
72
+ }
73
+ settings() { return this.store.get('settings'); }
74
+ addresses() { return this.store.get('addresses') ?? []; }
75
+ selectedAddresses(input) {
76
+ const selected = input.addresses ?? (input.index !== undefined ? [this.address(input.index).address]
77
+ : this.addresses().filter(address => input.all || address.active).map(address => address.address));
78
+ return [...new Set(selected.map(address => parseAddress(address).value))];
79
+ }
80
+ identity() { return this.store.get('identity'); }
81
+ reader() { return new NodeReader(this.settings()); }
82
+ requireSession() {
83
+ if (this.closed)
84
+ throw new AttoError('SESSION_CLOSED', 'This wallet session has closed.');
85
+ if (this.resetting)
86
+ throw new AttoError('WALLET_BUSY', 'Wallet reset is in progress.');
87
+ }
88
+ requireReady() {
89
+ this.requireSession();
90
+ this.requireResetFinished();
91
+ }
92
+ requireResetFinished() {
93
+ if (this.store.get(RESET_KEY))
94
+ throw new AttoError('WALLET_RESET_REQUIRED', 'Wallet reset was interrupted. Run atto wallet reset again to finish cleanup.');
95
+ }
96
+ requireMcpWrite() {
97
+ this.requireResetFinished();
98
+ if (this.mcp && this.ledger.mcpAccess() !== 'spend') {
99
+ throw new AttoError('MCP_READ_ONLY', 'MCP has read-only access to this wallet. Propose limits and obtain local terminal approval to enable transactions.');
100
+ }
101
+ }
102
+ proposalWallet() {
103
+ return { directory: this.store.directory, walletFingerprint: this.identity()?.fingerprint ?? null, network: this.settings().network };
104
+ }
105
+ requireLocalApproval() {
106
+ this.requireReady();
107
+ if (this.mcp)
108
+ throw new AttoError('LOCAL_APPROVAL_REQUIRED', 'Limit changes require approval in a local terminal.');
109
+ }
110
+ async reviewLimitsProposal(id) {
111
+ this.requireLocalApproval();
112
+ return this.store.withWalletLock(async () => ({
113
+ proposal: this.ledger.reviewProposal(id, this.proposalWallet()), directory: this.store.directory,
114
+ identity: this.identity() ?? null, network: this.settings().network,
115
+ policy: this.ledger.policy(), mcpAccess: this.ledger.mcpAccess(), pool: this.ledger.pool(),
116
+ }));
117
+ }
118
+ async approveLimitsProposal(id) {
119
+ this.requireLocalApproval();
120
+ return this.store.withWalletLock(async () => {
121
+ const proposal = this.ledger.reviewProposal(id, this.proposalWallet());
122
+ if (proposal.status === 'pending' && proposal.pool) {
123
+ for (const index of proposal.pool.indexes)
124
+ await this.deriveAddress(index);
125
+ }
126
+ this.ledger.approveProposal(id, this.proposalWallet());
127
+ return this.ledger.usage();
128
+ });
129
+ }
130
+ async rejectLimitsProposal(id) {
131
+ this.requireLocalApproval();
132
+ return this.store.withWalletLock(async () => {
133
+ this.ledger.rejectProposal(id, this.proposalWallet());
134
+ return this.ledger.usage();
135
+ });
136
+ }
137
+ async createWallet(mnemonic) {
138
+ this.requireReady();
139
+ return this.store.withWalletLock(async () => {
140
+ this.requireReady();
141
+ if (this.identity())
142
+ throw new AttoError('WALLET_EXISTS', 'This wallet is already initialized.');
143
+ const existing = await this.secrets.get();
144
+ if (existing && !mnemonic)
145
+ throw new AttoError('WALLET_EXISTS', 'A credential already exists. Import its phrase to recover the public wallet state.');
146
+ const phrase = (mnemonic ?? (await AttoMnemonic.generate()).phrase).normalize('NFKD').trim().replace(/\s+/g, ' ');
147
+ const seed = await mnemonicSeed(phrase);
148
+ try {
149
+ if (existing && existing !== phrase)
150
+ throw new AttoError('WALLET_EXISTS', 'The password-store entry belongs to a different mnemonic.');
151
+ const signer = await derivedSigner(seed, 0);
152
+ const address = { index: 0, address: signer.address.value, publicKey: signer.publicKey.toString(), active: true };
153
+ const identity = { address: address.address, fingerprint: createHash('sha256').update(address.publicKey).digest('hex') };
154
+ if (!existing)
155
+ await this.secrets.set(phrase);
156
+ this.store.transaction(() => { this.store.set('identity', identity); this.store.set('addresses', [address]); });
157
+ return { identity, addresses: [address] };
158
+ }
159
+ finally {
160
+ seed.value.fill(0);
161
+ }
162
+ });
163
+ }
164
+ async backupMnemonic() {
165
+ this.requireSession();
166
+ this.recoveryReads++;
167
+ try {
168
+ const phrase = await this.secrets.get();
169
+ if (!phrase)
170
+ throw new AttoError('WALLET_NOT_INITIALIZED', 'Create or import a wallet through the CLI first.');
171
+ return phrase;
172
+ }
173
+ finally {
174
+ this.recoveryReads--;
175
+ }
176
+ }
177
+ requireResetAvailable() {
178
+ this.requireSession();
179
+ if (this.mcp)
180
+ throw new AttoError('LOCAL_APPROVAL_REQUIRED', 'Wallet reset requires approval in a local terminal.');
181
+ if (this.started || this.calls.size || this.recoveryReads || this.store.busy
182
+ || this.watchManager?.list().some(watch => ['running', 'reconnecting'].includes(watch.status))) {
183
+ throw new AttoError('WALLET_BUSY', 'Stop active wallet operations and reset from a new terminal command.');
184
+ }
185
+ if (!this.secrets.remove)
186
+ throw new AttoError('SECRET_STORE_UNSUPPORTED', 'This password store does not support wallet reset.');
187
+ }
188
+ requireNoPendingPayments() {
189
+ if (this.ledger.pending().length)
190
+ throw new AttoError('PUBLICATION_UNCERTAIN', 'Resolve unfinished payments before resetting this wallet. Check the journal and resume their original request IDs.');
191
+ }
192
+ async reviewWalletReset() {
193
+ this.requireResetAvailable();
194
+ return this.store.withWalletLock(async () => {
195
+ this.requireNoPendingPayments();
196
+ return { directory: this.store.directory, identity: this.identity() ?? null, network: this.settings().network };
197
+ });
198
+ }
199
+ async resetWallet(expectedFingerprint) {
200
+ this.requireResetAvailable();
201
+ this.resetting = true;
202
+ try {
203
+ // A previous completed send may still have speculative public work queued.
204
+ // Stop it before clearing state; normal calls cannot start during reset.
205
+ await this.work.close();
206
+ await this.store.withExclusiveReset(() => this.store.withWalletLock(async () => {
207
+ if ((this.identity()?.fingerprint ?? null) !== expectedFingerprint) {
208
+ throw new AttoError('WALLET_CHANGED', 'The wallet changed after confirmation. Review it before resetting again.');
209
+ }
210
+ this.requireNoPendingPayments();
211
+ const releases = [];
212
+ try {
213
+ for (const address of this.addresses()) {
214
+ const release = this.store.tryAccountLocks([address.index]);
215
+ if (!release)
216
+ throw new AttoError('WALLET_BUSY', 'Wait for account operations before resetting this wallet.');
217
+ releases.push(release);
218
+ }
219
+ // Keyring and SQLite cannot share a transaction. Preserve the old
220
+ // public state behind a durable marker until credential deletion is
221
+ // verified, so interruption always resumes through this same path.
222
+ if (!this.store.get(RESET_KEY))
223
+ this.store.transaction(() => this.store.set(RESET_KEY, { startedAt: new Date().toISOString() }));
224
+ if (await this.secrets.get() !== null)
225
+ await this.secrets.remove();
226
+ if (await this.secrets.get() !== null)
227
+ throw new AttoError('SECRET_STORE_UNAVAILABLE', 'The password store did not remove the wallet credential. Unlock it and run wallet reset again.');
228
+ this.store.transaction(() => {
229
+ this.store.clearForReset();
230
+ this.store.set('settings', defaultSettings());
231
+ });
232
+ }
233
+ finally {
234
+ for (const release of releases)
235
+ release();
236
+ }
237
+ }));
238
+ return { reset: true };
239
+ }
240
+ finally {
241
+ this.resetting = false;
242
+ await this.close();
243
+ }
244
+ }
245
+ async seed() {
246
+ this.requireResetFinished();
247
+ const identity = this.identity();
248
+ if (!identity)
249
+ throw new AttoError('WALLET_NOT_INITIALIZED', 'Create or import a wallet through the CLI first.');
250
+ const seed = await mnemonicSeed(await this.backupMnemonic());
251
+ const signer = await derivedSigner(seed, 0);
252
+ if (signer.address.value !== identity.address) {
253
+ seed.value.fill(0);
254
+ throw new AttoError('WALLET_MISMATCH', 'The credential does not match this wallet’s public state.');
255
+ }
256
+ return seed;
257
+ }
258
+ address(index = 0, requireActive = false) {
259
+ const address = this.addresses().find(address => address.index === index);
260
+ if (!address)
261
+ throw new AttoError('ADDRESS_NOT_DERIVED', 'Derive or activate the key index first.');
262
+ if (requireActive && !address.active)
263
+ throw new AttoError('ADDRESS_INACTIVE', 'Activate this address before automatic receiving.');
264
+ return address;
265
+ }
266
+ async derive(index, active) {
267
+ return this.store.withWalletLock(async () => {
268
+ this.requireMcpWrite();
269
+ return this.deriveAddress(index, active);
270
+ });
271
+ }
272
+ /** The caller owns the wallet lock, including terminal pool approval. */
273
+ async deriveAddress(index, active) {
274
+ const addresses = this.addresses();
275
+ let address = addresses.find(address => address.index === index);
276
+ if (active === true && !address?.active && addresses.filter(address => address.active).length >= 100) {
277
+ throw new AttoError('ACTIVE_ADDRESS_LIMIT', 'At most 100 addresses can be active. Deactivate an address before activating another.');
278
+ }
279
+ if (!address) {
280
+ const seed = await this.seed();
281
+ try {
282
+ const signer = await derivedSigner(seed, index);
283
+ address = { index, address: signer.address.value, publicKey: signer.publicKey.toString(), active: active ?? false };
284
+ addresses.push(address);
285
+ }
286
+ finally {
287
+ seed.value.fill(0);
288
+ }
289
+ }
290
+ if (active !== undefined)
291
+ address.active = active;
292
+ this.store.set('addresses', addresses.sort((a, b) => a.index - b.index));
293
+ return address;
294
+ }
295
+ async configure(input) {
296
+ return this.store.withWalletLock(async () => {
297
+ this.requireMcpWrite();
298
+ const settings = { ...this.settings(), ...input };
299
+ settings.representative = parseAddress(settings.representative).value;
300
+ settings.minReceiveRaw = amountRaw(settings.minReceiveRaw, 'RAW');
301
+ const changesNetwork = settings.nodeUrl !== this.settings().nodeUrl || settings.network !== this.settings().network;
302
+ if (this.ledger.pending().length && changesNetwork) {
303
+ throw new AttoError('PUBLICATION_UNCERTAIN', 'Resolve pending sends before changing the node or network.');
304
+ }
305
+ const releases = [];
306
+ try {
307
+ if (changesNetwork)
308
+ for (const address of this.addresses()) {
309
+ const release = this.store.tryAccountLocks([address.index]);
310
+ if (!release)
311
+ throw new AttoError('WALLET_BUSY', 'Wait for account operations before changing the node or network.');
312
+ releases.push(release);
313
+ }
314
+ this.store.set('settings', settings);
315
+ }
316
+ finally {
317
+ for (const release of releases)
318
+ release();
319
+ }
320
+ await this.serializeWatches(async () => {
321
+ await this.watchManager?.close();
322
+ this.watchManager = undefined;
323
+ });
324
+ return settings;
325
+ });
326
+ }
327
+ result(transaction, status = 'published') {
328
+ return { status, hash: transaction.hash.toString(), transaction: publicModel(transaction) };
329
+ }
330
+ async pendingReceivable(address, hash) {
331
+ let found;
332
+ const controller = new AbortController();
333
+ const timer = setTimeout(() => controller.abort(), 2000);
334
+ try {
335
+ await this.reader().stream({ event: 'receivable', addresses: [address], minAmountRaw: '1' }, model => {
336
+ const receivable = model;
337
+ if (receivable.hash.toString().toUpperCase() === hash.toUpperCase()) {
338
+ found = receivable;
339
+ controller.abort();
340
+ }
341
+ }, controller.signal);
342
+ }
343
+ catch (error) {
344
+ if (!controller.signal.aborted)
345
+ throw error;
346
+ }
347
+ finally {
348
+ clearTimeout(timer);
349
+ }
350
+ if (!found && controller.signal.aborted) {
351
+ throw new AttoError('RECEIVABLE_LOOKUP_TIMEOUT', 'Checking the pending payment timed out. Retry receiving it; its absence has not been confirmed.');
352
+ }
353
+ return found;
354
+ }
355
+ async receive(request, automatic = false) {
356
+ const index = request.index ?? 0;
357
+ const operation = async () => {
358
+ await this.store.withWalletLock(async () => {
359
+ this.requireMcpWrite();
360
+ this.payments.requireAvailable(index);
361
+ });
362
+ if (automatic && !this.settings().autoReceive)
363
+ throw new AttoError('AUTO_RECEIVE_DISABLED', 'Automatic receiving is disabled.');
364
+ const address = this.address(index, automatic);
365
+ const hash = request.hash.toUpperCase();
366
+ const key = `receive.${this.settings().network}.${hash}`;
367
+ const prior = this.store.get(key);
368
+ if (prior && prior.index !== index)
369
+ throw new AttoError('WRONG_RECEIVER', 'This receivable belongs to a different address.');
370
+ if (prior?.result)
371
+ return prior.result;
372
+ if (prior) {
373
+ const transaction = await this.reader().transaction(prior.blockHash);
374
+ if (transaction && transaction.hash.toString() === prior.blockHash && await transaction.isValid()) {
375
+ const result = this.result(transaction, 'received');
376
+ this.store.set(key, { ...prior, result });
377
+ return result;
378
+ }
379
+ // Refresh pending state below: an unconsumed send permits retrying receive
380
+ // against the current frontier without risking a second debit.
381
+ }
382
+ const receivable = await this.pendingReceivable(address.address, hash);
383
+ if (!receivable)
384
+ throw new AttoError('RECEIVABLE_NOT_PENDING', 'The payment is not pending for this address; it may already have been received.');
385
+ if (receivable.receiverAddress.value !== address.address)
386
+ throw new AttoError('WRONG_RECEIVER', 'The payment belongs to a different address.');
387
+ if (automatic && BigInt(receivable.amount.toString()) < BigInt(this.settings().minReceiveRaw)) {
388
+ throw new AttoError('RECEIVABLE_BELOW_MINIMUM', 'The payment is below the current automatic receiving minimum.');
389
+ }
390
+ const seed = await this.seed();
391
+ let wallet;
392
+ try {
393
+ const execution = await signingWallet(seed, index, this.settings(), async (block) => {
394
+ await this.store.withWalletLock(async () => {
395
+ this.requireMcpWrite();
396
+ this.payments.requireAvailable(index);
397
+ if (automatic && !this.settings().autoReceive)
398
+ throw new AttoError('AUTO_RECEIVE_DISABLED', 'Automatic receiving is disabled.');
399
+ this.store.set(key, { hash, index, blockHash: block.hash.toString() });
400
+ });
401
+ }, this.work.worker());
402
+ wallet = execution.wallet;
403
+ const transaction = await wallet.receive(receivable, parseAddress(request.representative ?? this.settings().representative), null);
404
+ const result = { ...this.result(transaction, 'received'), index, amount: amountOutput(receivable.amount.toString()) };
405
+ this.store.set(key, { hash, index, blockHash: transaction.hash.toString(), result });
406
+ const account = await wallet.getAccountByIndex(toAttoIndex(index));
407
+ if (account)
408
+ this.work.prepare([account]);
409
+ return result;
410
+ }
411
+ finally {
412
+ wallet?.close();
413
+ seed.value.fill(0);
414
+ }
415
+ };
416
+ if (!automatic)
417
+ return this.store.withAccountLocks([index], operation);
418
+ // A busy account must not stall receiving for the rest of the wallet or
419
+ // prevent this session from stopping. The receiver will retry this item.
420
+ const release = this.store.tryAccountLocks([index]);
421
+ if (!release)
422
+ throw new AttoError('WALLET_BUSY', 'This account is busy. Automatic receiving will retry it.');
423
+ try {
424
+ return await operation();
425
+ }
426
+ finally {
427
+ release();
428
+ }
429
+ }
430
+ async receiveAll(input) {
431
+ const index = input.index ?? 0;
432
+ const address = this.address(index).address;
433
+ const list = await this.reader().list({ event: 'receivable', addresses: [address], limit: input.limit ?? 100, timeoutMs: input.timeoutMs ?? 2000 });
434
+ const results = [];
435
+ for (const item of list.items) {
436
+ results.push(await this.receive({ index, hash: item.hash, representative: input.representative }));
437
+ }
438
+ return { results, timedOut: list.timedOut, ...(list.limitReached ? { limitReached: true } : {}) };
439
+ }
440
+ async changeRepresentative(index, representative) {
441
+ return this.store.withAccountLocks([index], async () => {
442
+ await this.store.withWalletLock(async () => {
443
+ this.requireMcpWrite();
444
+ this.payments.requireAvailable(index);
445
+ });
446
+ this.address(index);
447
+ const seed = await this.seed();
448
+ let wallet;
449
+ try {
450
+ const execution = await signingWallet(seed, index, this.settings(), async () => {
451
+ await this.store.withWalletLock(async () => {
452
+ this.requireMcpWrite();
453
+ this.payments.requireAvailable(index);
454
+ });
455
+ }, this.work.worker());
456
+ wallet = execution.wallet;
457
+ const transaction = await wallet.change(toAttoIndex(index), parseAddress(representative), null);
458
+ const account = await wallet.getAccountByIndex(toAttoIndex(index));
459
+ if (account)
460
+ this.work.prepare([account]);
461
+ return this.result(transaction, 'representative_changed');
462
+ }
463
+ finally {
464
+ wallet?.close();
465
+ seed.value.fill(0);
466
+ }
467
+ });
468
+ }
469
+ serializeWatches(operation) {
470
+ const result = this.watchQueue.then(operation);
471
+ this.watchQueue = result.then(() => { }, () => { });
472
+ return result;
473
+ }
474
+ withWatches(operation) {
475
+ return this.serializeWatches(async () => {
476
+ const configuration = JSON.stringify(this.settings());
477
+ if (!this.watchManager || this.watchConfiguration !== configuration) {
478
+ await this.watchManager?.close();
479
+ this.watchManager = new WatchManager(this.reader(), this.store);
480
+ this.watchConfiguration = configuration;
481
+ }
482
+ return operation(this.watchManager);
483
+ });
484
+ }
485
+ async invoke(name, args) {
486
+ const reader = this.reader();
487
+ switch (name) {
488
+ case 'doctor': return runDoctor({ directory: this.store.directory, access: this.mcp ? 'mcp' : undefined, signal: this.doctorAbort.signal, globalDirectory: args.globalDirectory });
489
+ case 'wallet_status': return { directory: this.store.directory, initialized: Boolean(this.identity()), identity: this.identity() ?? null, settings: this.settings(), addresses: this.addresses(), autoReceive: this.auto.status(), mcpAccess: this.ledger.mcpAccess(), pool: this.ledger.pool(), pendingSends: this.ledger.pending().map(({ id, hash, status }) => ({ requestId: id, hash, status })), resetPending: Boolean(this.store.get(RESET_KEY)) };
490
+ case 'wallet_configure': return this.configure(args);
491
+ case 'address_list': return { addresses: this.addresses() };
492
+ case 'address_add': return this.store.withWalletLock(async () => {
493
+ this.requireMcpWrite();
494
+ const next = this.addresses().reduce((highest, address) => Math.max(highest, address.index), -1) + 1;
495
+ if (next > 2_147_483_647)
496
+ throw new AttoError('INDEX_LIMIT', 'The wallet has reached its last account index.');
497
+ return this.deriveAddress(next, true);
498
+ });
499
+ case 'address_derive': return this.derive(args.index);
500
+ case 'address_activate': return this.derive(args.index, true);
501
+ case 'address_deactivate': return this.store.withWalletLock(async () => {
502
+ this.requireMcpWrite();
503
+ const index = args.index;
504
+ this.address(index);
505
+ this.store.set('addresses', this.addresses().map(address => address.index === index ? { ...address, active: false } : address));
506
+ return this.address(index);
507
+ });
508
+ case 'labels_set': {
509
+ const address = args.address !== undefined ? parseAddress(args.address).value : this.address(args.index).address;
510
+ return { network: this.settings().network, ...this.personal.set(this.settings().network, address, args.label) };
511
+ }
512
+ case 'labels_remove': {
513
+ const address = args.address !== undefined ? parseAddress(args.address).value : this.address(args.index).address;
514
+ this.personal.remove(this.settings().network, address);
515
+ return { network: this.settings().network, address, removed: true };
516
+ }
517
+ case 'labels_get': {
518
+ const address = args.address !== undefined ? parseAddress(args.address).value : this.address(args.index).address;
519
+ if (this.settings().network === 'LIVE')
520
+ await this.labels.global.refresh(args.refresh);
521
+ return { network: this.settings().network, address, addressLabels: this.labels.dictionary(this.settings().network, [address]), globalDirectory: this.labels.status(this.settings().network) };
522
+ }
523
+ case 'labels_list': {
524
+ if (this.settings().network === 'LIVE' && (args.all || args.refresh))
525
+ await this.labels.global.refresh(args.refresh);
526
+ return this.labels.list(this.settings().network, args.all, args.search);
527
+ }
528
+ case 'account_get': return { account: publicModel(await reader.account(args.address ?? this.address(args.index).address)) };
529
+ case 'balances_get': {
530
+ const addresses = this.selectedAddresses(args);
531
+ const accounts = await Promise.all(addresses.map(address => reader.account(address)));
532
+ const raw = accounts.reduce((sum, account) => sum + BigInt(account?.balance.toString() ?? '0'), 0n).toString();
533
+ return { balances: addresses.map((address, i) => {
534
+ const saved = this.addresses().find(value => value.address === address);
535
+ return { address, ...(saved ? { index: saved.index, active: saved.active } : {}), found: Boolean(accounts[i]), balance: amountOutput(accounts[i]?.balance.toString() ?? '0') };
536
+ }), total: amountOutput(raw) };
537
+ }
538
+ case 'transaction_get': return { transaction: publicModel(await reader.transaction(args.hash)) };
539
+ case 'entry_get': return { entry: publicModel(await reader.entry(args.hash)) };
540
+ case 'representative_weight': return reader.voterWeight(args.address);
541
+ case 'history_list': {
542
+ const addresses = this.selectedAddresses(args);
543
+ if (!addresses.length)
544
+ return { items: [], timedOut: false };
545
+ return reader.list({ ...args, addresses });
546
+ }
547
+ case 'receivables_list': {
548
+ const addresses = this.selectedAddresses(args);
549
+ if (!addresses.length)
550
+ return { items: [], timedOut: false };
551
+ return reader.list({ ...args, event: 'receivable', addresses });
552
+ }
553
+ case 'send': return this.payments.send({ ...args,
554
+ destination: args.destinationIndex !== undefined ? this.address(args.destinationIndex).address : args.destination,
555
+ });
556
+ case 'receive': return this.receive(args);
557
+ case 'receive_all': return this.receiveAll(args);
558
+ case 'representative_change': return this.changeRepresentative(args.index, args.representative);
559
+ case 'limits_get':
560
+ await this.payments.reconcile();
561
+ return this.store.withWalletLock(async () => this.ledger.usage());
562
+ case 'pool_get': return this.payments.poolStatus();
563
+ case 'journal_list': return this.ledger.journalList(args);
564
+ case 'journal_get': {
565
+ const record = this.ledger.journalGet(args.requestId);
566
+ if (!record)
567
+ throw new AttoError('JOURNAL_NOT_FOUND', 'This payment request is not in the local journal.');
568
+ return { record };
569
+ }
570
+ case 'limits_propose': return this.store.withWalletLock(async () => ({ proposal: this.ledger.proposePolicy(args.policy, args.access, this.proposalWallet(), args.pool) }));
571
+ case 'metrics_get': return this.market.metrics();
572
+ case 'price_quote': return this.market.quoteUsd(args.amount);
573
+ case 'terms_get': return { ...marketTerms, accepted: this.store.get('market.terms')?.version === marketTerms.version };
574
+ case 'terms_accept': return this.store.withWalletLock(async () => {
575
+ this.requireMcpWrite();
576
+ if (args.version !== marketTerms.version || args.accepted !== true)
577
+ throw new AttoError('TERMS_VERSION', 'Read and acknowledge the current market-data terms version.');
578
+ const acceptance = { version: marketTerms.version, acceptedAt: new Date().toISOString() };
579
+ this.store.set('market.terms', acceptance);
580
+ return { ...acceptance, accepted: true };
581
+ });
582
+ case 'watch_start': {
583
+ const filter = { ...args };
584
+ if (!args.hash && !args.networkWide) {
585
+ filter.addresses = this.selectedAddresses(args);
586
+ if (!filter.addresses.length)
587
+ throw new AttoError('NO_ACTIVE_ACCOUNTS', 'No active wallet accounts. Add or activate an address, specify addresses, or select a network-wide watch.');
588
+ }
589
+ return this.withWatches(manager => manager.start(filter));
590
+ }
591
+ case 'watch_list': return this.withWatches(manager => manager.list());
592
+ case 'watch_read': return this.withWatches(manager => manager.read(args.id, args.cursor, args.limit));
593
+ case 'watch_stop':
594
+ await this.withWatches(manager => manager.stop(args.id));
595
+ return { stopped: true };
596
+ default: throw new AttoError('UNKNOWN_OPERATION', 'Unknown Atto operation.');
597
+ }
598
+ }
599
+ async call(name, input = {}) {
600
+ if (name === 'wallet_status' || name === 'doctor')
601
+ this.requireSession();
602
+ else
603
+ this.requireReady();
604
+ const args = parseOperation(name, input);
605
+ if (!operations.find(operation => operation.name === name).readOnly && name !== 'limits_propose' && !['labels_set', 'labels_remove'].includes(name) && !name.startsWith('watch_'))
606
+ this.requireMcpWrite();
607
+ const call = (async () => {
608
+ const result = await this.invoke(name, args);
609
+ if (name === 'doctor' || ['labels_get', 'labels_list'].includes(name))
610
+ return result;
611
+ if (this.settings().network === 'LIVE' && ['address_list', 'account_get', 'balances_get', 'transaction_get', 'entry_get', 'representative_weight', 'history_list', 'receivables_list'].includes(name))
612
+ await this.labels.global.refresh();
613
+ return this.labels.decorate(result, this.settings().network);
614
+ })();
615
+ this.calls.add(call);
616
+ try {
617
+ return await call;
618
+ }
619
+ finally {
620
+ this.calls.delete(call);
621
+ }
622
+ }
623
+ // The receiver observes current MCP access on every snapshot, and receive()
624
+ // rechecks it under the wallet lock before signing any queued payment.
625
+ async start() {
626
+ if (this.closed)
627
+ return;
628
+ this.requireReady();
629
+ this.started = true;
630
+ this.auto.start();
631
+ await this.preparePoolWork();
632
+ }
633
+ async preparePoolWork() {
634
+ if (this.mcp && this.ledger.mcpAccess() !== 'spend')
635
+ return;
636
+ const indexes = this.ledger.pool().indexes;
637
+ await Promise.allSettled(this.addresses().filter(address => indexes.includes(address.index)).map(async (address) => {
638
+ const account = await this.reader().account(address.address);
639
+ if (account && !this.closed)
640
+ this.work.prepare([account]);
641
+ }));
642
+ }
643
+ async close() {
644
+ if (this.closed)
645
+ return;
646
+ this.closed = true;
647
+ this.doctorAbort.abort();
648
+ await this.auto.close();
649
+ await Promise.allSettled([...this.calls]);
650
+ await this.watchManager?.close();
651
+ await this.work.close();
652
+ this.store.close();
653
+ }
654
+ }
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export interface Operation {
3
+ name: string;
4
+ description: string;
5
+ schema: z.ZodObject;
6
+ readOnly: boolean;
7
+ }
8
+ export declare const operations: readonly Operation[];
9
+ export declare function parseOperation(name: string, input?: unknown): Record<string, unknown>;