@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,16 @@
1
+ export interface SecretStore {
2
+ get(): Promise<string | null>;
3
+ set(mnemonic: string): Promise<void>;
4
+ remove?(): Promise<void>;
5
+ }
6
+ /** Dedicated credential namespace; neither reads nor overwrites the desktop wallet. */
7
+ export declare class OsSecretStore implements SecretStore {
8
+ private readonly account;
9
+ private readonly service;
10
+ constructor(account?: string, service?: 'Atto CLI' | 'Atto MCP');
11
+ get(): Promise<string | null>;
12
+ set(mnemonic: string): Promise<void>;
13
+ remove(): Promise<void>;
14
+ private nativeEntry;
15
+ private secretTool;
16
+ }
@@ -0,0 +1,104 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { AttoError } from '../domain/errors.js';
3
+ function unavailable() {
4
+ return new AttoError('SECRET_STORE_UNAVAILABLE', 'The operating-system password store is unavailable or locked. Unlock it and, on Linux, install secret-tool. Run doctor in the failing environment for diagnostics.');
5
+ }
6
+ /** Dedicated credential namespace; neither reads nor overwrites the desktop wallet. */
7
+ export class OsSecretStore {
8
+ account;
9
+ service;
10
+ constructor(account = 'default', service = 'Atto MCP') {
11
+ this.account = account;
12
+ this.service = service;
13
+ if (!account || account.length > 200 || /[\r\n\0]/.test(account))
14
+ throw new AttoError('INVALID_ACCOUNT', 'Use a nonempty credential account identifier.');
15
+ if (service !== 'Atto CLI' && service !== 'Atto MCP')
16
+ throw new AttoError('INVALID_SERVICE', 'Use an Atto CLI or Atto MCP credential service.');
17
+ }
18
+ async get() {
19
+ if (process.platform === 'linux') {
20
+ const result = await this.secretTool('lookup');
21
+ if (result.code === 1 && !result.output && !result.error)
22
+ return null;
23
+ if (result.code !== 0 || result.error)
24
+ throw unavailable();
25
+ return result.output.replace(/\r?\n$/, '') || null;
26
+ }
27
+ try {
28
+ return await (await this.nativeEntry()).getPassword() ?? null;
29
+ }
30
+ catch {
31
+ throw unavailable();
32
+ }
33
+ }
34
+ async set(mnemonic) {
35
+ if (!mnemonic || /[\r\n\0]/.test(mnemonic))
36
+ throw new AttoError('INVALID_MNEMONIC', 'The recovery phrase must be a single nonempty line.');
37
+ if (process.platform === 'linux') {
38
+ const result = await this.secretTool('store', mnemonic);
39
+ if (result.code !== 0 || result.error)
40
+ throw unavailable();
41
+ }
42
+ else {
43
+ try {
44
+ await (await this.nativeEntry()).setPassword(mnemonic);
45
+ }
46
+ catch {
47
+ throw unavailable();
48
+ }
49
+ }
50
+ // Verify durability before wallet setup reports success.
51
+ if (await this.get() !== mnemonic)
52
+ throw unavailable();
53
+ }
54
+ async remove() {
55
+ // An interrupted reset may have removed the credential before committing
56
+ // its public-state cleanup. Native keyrings need not accept deleting twice.
57
+ if (await this.get() === null)
58
+ return;
59
+ if (process.platform === 'linux') {
60
+ const result = await this.secretTool('clear');
61
+ if (result.code !== 0 && !(result.code === 1 && !result.error))
62
+ throw unavailable();
63
+ }
64
+ else {
65
+ try {
66
+ await (await this.nativeEntry()).deleteCredential();
67
+ }
68
+ catch {
69
+ throw unavailable();
70
+ }
71
+ }
72
+ if (await this.get() !== null)
73
+ throw unavailable();
74
+ }
75
+ async nativeEntry() {
76
+ if (process.platform !== 'darwin' && process.platform !== 'win32')
77
+ throw unavailable();
78
+ const { AsyncEntry } = await import('@napi-rs/keyring');
79
+ return new AsyncEntry(this.service, this.account);
80
+ }
81
+ secretTool(operation, secret) {
82
+ return new Promise((resolve, reject) => {
83
+ const args = operation === 'store' ? ['store', `--label=${this.service}`] : [operation];
84
+ args.push('service', this.service, 'account', this.account, 'key_type', 'mnemonic');
85
+ const child = spawn('secret-tool', args, { stdio: ['pipe', 'pipe', 'pipe'], signal: AbortSignal.timeout(60_000), windowsHide: true });
86
+ let output = '';
87
+ let error = false;
88
+ child.stdout.setEncoding('utf8');
89
+ child.stdout.on('data', (chunk) => {
90
+ output += chunk;
91
+ if (output.length > 16_384) {
92
+ error = true;
93
+ child.kill();
94
+ }
95
+ });
96
+ // Do not preserve dependency diagnostics, which may contain secret values.
97
+ child.stderr.on('data', () => { error = true; });
98
+ child.on('error', () => reject(unavailable()));
99
+ child.stdin.on('error', () => { error = true; });
100
+ child.on('close', (code) => resolve({ code, output, error }));
101
+ child.stdin.end(secret);
102
+ });
103
+ }
104
+ }
@@ -0,0 +1,32 @@
1
+ export declare function defaultDataDirectory(): string;
2
+ /** Public wallet state only. Recovery material belongs exclusively in SecretStore. */
3
+ export declare class StateStore {
4
+ readonly directory: string;
5
+ private readonly state;
6
+ private readonly coordination;
7
+ private readonly lifecycle;
8
+ private queue;
9
+ private closed;
10
+ private lockRequests;
11
+ private exclusiveReset;
12
+ get busy(): boolean;
13
+ constructor(directory: string);
14
+ get<T>(key: string): T | undefined;
15
+ set(key: string, value: unknown): void;
16
+ /** Only synchronous state work belongs here; network work uses withWalletLock. */
17
+ transaction<T>(fn: () => T): T;
18
+ /** Terminal-only lifecycle operation. Once the shared lease is released this
19
+ * store closes, even if another session prevents acquiring exclusivity. */
20
+ withExclusiveReset<T>(fn: () => Promise<T>): Promise<T>;
21
+ /** Keep database and lock file identities intact; caller owns the transaction. */
22
+ clearForReset(): void;
23
+ private requireOpen;
24
+ withWalletLock<T>(fn: () => Promise<T>): Promise<T>;
25
+ /** Never wait for account locks while holding the wallet lock. This immediate
26
+ * attempt is safe during short wallet selection/reservation transactions. */
27
+ tryAccountLocks(indexes: readonly number[]): (() => void) | undefined;
28
+ /** Acquire account locks first; short wallet reservations may run inside fn.
29
+ * Closing the connection (including process death) releases every lock. */
30
+ withAccountLocks<T>(indexes: readonly number[], fn: () => Promise<T>): Promise<T>;
31
+ close(): void;
32
+ }
@@ -0,0 +1,255 @@
1
+ import { chmodSync, closeSync, mkdirSync, openSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join, resolve } from 'node:path';
4
+ import { DatabaseSync } from 'node:sqlite';
5
+ import { setTimeout as delay } from 'node:timers/promises';
6
+ import { AttoError } from '../domain/errors.js';
7
+ export function defaultDataDirectory() {
8
+ if (process.platform === 'win32')
9
+ return join(process.env.LOCALAPPDATA || join(homedir(), 'AppData', 'Local'), 'Atto MCP');
10
+ if (process.platform === 'darwin')
11
+ return join(homedir(), 'Library', 'Application Support', 'Atto MCP');
12
+ return join(process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share'), 'atto-mcp');
13
+ }
14
+ /** Public wallet state only. Recovery material belongs exclusively in SecretStore. */
15
+ export class StateStore {
16
+ directory;
17
+ state;
18
+ coordination;
19
+ lifecycle;
20
+ queue = Promise.resolve();
21
+ closed = false;
22
+ lockRequests = 0;
23
+ exclusiveReset = false;
24
+ get busy() { return this.lockRequests !== 0 || this.exclusiveReset; }
25
+ constructor(directory) {
26
+ this.directory = resolve(directory);
27
+ mkdirSync(this.directory, { recursive: true, mode: 0o700 });
28
+ const connections = [];
29
+ const open = (name) => {
30
+ const path = join(this.directory, name);
31
+ closeSync(openSync(path, 'a', 0o600));
32
+ if (process.platform !== 'win32')
33
+ chmodSync(path, 0o600);
34
+ const connection = new DatabaseSync(path);
35
+ connections.push(connection);
36
+ return connection;
37
+ };
38
+ try {
39
+ // A lifetime read lease prevents reset while another wallet session exists.
40
+ // This separate database must use rollback journaling: WAL readers do not
41
+ // exclude writers. Acquire the lease before opening any wallet state.
42
+ this.lifecycle = open('lifecycle.sqlite');
43
+ this.lifecycle.exec('PRAGMA busy_timeout = 0; PRAGMA journal_mode = DELETE; CREATE TABLE IF NOT EXISTS lease (id INTEGER PRIMARY KEY); BEGIN; SELECT COUNT(*) FROM lease;');
44
+ this.state = open('state.sqlite');
45
+ this.state.exec('PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL;');
46
+ const version = this.state.prepare('PRAGMA user_version').get()?.user_version;
47
+ if (version !== 0 && version !== 1)
48
+ throw new AttoError('STATE_VERSION', 'This wallet state requires a newer Atto CLI.');
49
+ this.state.exec('CREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT NOT NULL); PRAGMA user_version = 1;');
50
+ this.coordination = open('coordination.sqlite');
51
+ this.coordination.exec('PRAGMA busy_timeout = 0;');
52
+ }
53
+ catch (error) {
54
+ for (const connection of connections.reverse()) {
55
+ try {
56
+ connection.close();
57
+ }
58
+ catch { /* Preserve the startup failure. */ }
59
+ }
60
+ const code = error.errcode;
61
+ if (code === 5 || code === 6)
62
+ throw new AttoError('WALLET_BUSY', 'The wallet is busy. Wait for reset or other wallet operations to finish.');
63
+ throw error;
64
+ }
65
+ }
66
+ get(key) {
67
+ this.requireOpen();
68
+ const row = this.state.prepare('SELECT value FROM settings WHERE key = ?').get(key);
69
+ return row ? JSON.parse(row.value) : undefined;
70
+ }
71
+ set(key, value) {
72
+ this.requireOpen();
73
+ const json = JSON.stringify(value);
74
+ if (json === undefined)
75
+ throw new AttoError('INVALID_STATE', 'Persistent state must be JSON serializable.');
76
+ this.state.prepare('INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value').run(key, json);
77
+ }
78
+ /** Only synchronous state work belongs here; network work uses withWalletLock. */
79
+ transaction(fn) {
80
+ this.requireOpen();
81
+ this.state.exec('BEGIN IMMEDIATE');
82
+ try {
83
+ const result = fn();
84
+ this.state.exec('COMMIT');
85
+ return result;
86
+ }
87
+ catch (error) {
88
+ this.state.exec('ROLLBACK');
89
+ throw error;
90
+ }
91
+ }
92
+ /** Terminal-only lifecycle operation. Once the shared lease is released this
93
+ * store closes, even if another session prevents acquiring exclusivity. */
94
+ async withExclusiveReset(fn) {
95
+ this.requireOpen();
96
+ if (this.lockRequests !== 0 || this.exclusiveReset)
97
+ throw new AttoError('WALLET_BUSY', 'Wait for wallet operations before resetting this profile.');
98
+ try {
99
+ this.lifecycle.exec('ROLLBACK;');
100
+ try {
101
+ this.lifecycle.exec('BEGIN EXCLUSIVE;');
102
+ }
103
+ catch (error) {
104
+ const code = error.errcode;
105
+ if (code === 5 || code === 6)
106
+ throw new AttoError('WALLET_BUSY', 'Stop other sessions using this wallet before resetting.');
107
+ throw error;
108
+ }
109
+ this.exclusiveReset = true;
110
+ return await fn();
111
+ }
112
+ finally {
113
+ this.close();
114
+ }
115
+ }
116
+ /** Keep database and lock file identities intact; caller owns the transaction. */
117
+ clearForReset() {
118
+ this.requireOpen();
119
+ if (!this.exclusiveReset)
120
+ throw new AttoError('LOCAL_APPROVAL_REQUIRED', 'Clearing wallet state requires an exclusive local reset.');
121
+ this.state.exec('DELETE FROM settings;');
122
+ }
123
+ requireOpen() {
124
+ if (this.closed)
125
+ throw new AttoError('STATE_CLOSED', 'The wallet state is closed.');
126
+ }
127
+ async withWalletLock(fn) {
128
+ if (this.closed)
129
+ throw new AttoError('STATE_CLOSED', 'The wallet state is closed.');
130
+ this.lockRequests++;
131
+ const previous = this.queue;
132
+ let release;
133
+ this.queue = new Promise((resolveQueue) => { release = resolveQueue; });
134
+ await previous;
135
+ let locked = false;
136
+ try {
137
+ // Separate coordination lets short reservations commit durably without
138
+ // keeping the state database transaction open during other async work.
139
+ for (;;) {
140
+ try {
141
+ this.coordination.exec('BEGIN IMMEDIATE');
142
+ locked = true;
143
+ break;
144
+ }
145
+ catch (error) {
146
+ const code = error.errcode;
147
+ if (code !== 5 && code !== 6)
148
+ throw error;
149
+ await delay(25);
150
+ }
151
+ }
152
+ return await fn();
153
+ }
154
+ finally {
155
+ try {
156
+ if (locked)
157
+ this.coordination.exec('ROLLBACK');
158
+ }
159
+ finally {
160
+ this.lockRequests--;
161
+ release();
162
+ }
163
+ }
164
+ }
165
+ /** Never wait for account locks while holding the wallet lock. This immediate
166
+ * attempt is safe during short wallet selection/reservation transactions. */
167
+ tryAccountLocks(indexes) {
168
+ if (this.closed)
169
+ throw new AttoError('STATE_CLOSED', 'The wallet state is closed.');
170
+ if (!Array.isArray(indexes) || indexes.length < 1 || indexes.length > 100
171
+ || indexes.some(index => !Number.isSafeInteger(index) || index < 0 || index > 0x7fff_ffff)) {
172
+ throw new AttoError('INVALID_INDEX', 'Account locks require between 1 and 100 valid wallet indexes.');
173
+ }
174
+ const directory = join(this.directory, 'account-locks');
175
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
176
+ const connections = [];
177
+ const closeConnections = () => {
178
+ let failure;
179
+ for (const connection of connections.reverse()) {
180
+ try {
181
+ connection.close();
182
+ }
183
+ catch (error) {
184
+ failure ??= error;
185
+ }
186
+ }
187
+ connections.length = 0;
188
+ if (failure)
189
+ throw failure;
190
+ };
191
+ try {
192
+ // Sorted acquisition prevents cycles when payments consolidate accounts.
193
+ for (const index of [...new Set(indexes)].sort((left, right) => left - right)) {
194
+ const file = join(directory, `${index}.sqlite`);
195
+ closeSync(openSync(file, 'a', 0o600));
196
+ if (process.platform !== 'win32')
197
+ chmodSync(file, 0o600);
198
+ const connection = new DatabaseSync(file);
199
+ connections.push(connection);
200
+ connection.exec('PRAGMA busy_timeout = 0; BEGIN IMMEDIATE;');
201
+ }
202
+ }
203
+ catch (error) {
204
+ closeConnections();
205
+ const code = error.errcode;
206
+ if (code === 5 || code === 6)
207
+ return undefined;
208
+ throw error;
209
+ }
210
+ this.lockRequests++;
211
+ let held = true;
212
+ return () => {
213
+ if (!held)
214
+ return;
215
+ held = false;
216
+ try {
217
+ closeConnections();
218
+ }
219
+ finally {
220
+ this.lockRequests--;
221
+ }
222
+ };
223
+ }
224
+ /** Acquire account locks first; short wallet reservations may run inside fn.
225
+ * Closing the connection (including process death) releases every lock. */
226
+ async withAccountLocks(indexes, fn) {
227
+ if (this.closed)
228
+ throw new AttoError('STATE_CLOSED', 'The wallet state is closed.');
229
+ this.lockRequests++;
230
+ let release;
231
+ try {
232
+ while (!(release = this.tryAccountLocks(indexes)))
233
+ await delay(25);
234
+ return await fn();
235
+ }
236
+ finally {
237
+ try {
238
+ release?.();
239
+ }
240
+ finally {
241
+ this.lockRequests--;
242
+ }
243
+ }
244
+ }
245
+ close() {
246
+ if (this.closed)
247
+ return;
248
+ if (this.lockRequests !== 0)
249
+ throw new AttoError('WALLET_BUSY', 'Wait for wallet operations before closing state.');
250
+ this.coordination.close();
251
+ this.state.close();
252
+ this.lifecycle.close();
253
+ this.closed = true;
254
+ }
255
+ }
@@ -0,0 +1,57 @@
1
+ import type { AddressLabels } from '../labels/presentation.js';
2
+ import { errorResult } from '../domain/errors.js';
3
+ import { amountOutput } from '../domain/amount.js';
4
+ import type { WalletAddress, WalletSettings } from './types.js';
5
+ interface PendingPayment {
6
+ index: number;
7
+ address: string;
8
+ sendHash: string;
9
+ amount: ReturnType<typeof amountOutput>;
10
+ }
11
+ export type ReceiveProgress = ((PendingPayment & {
12
+ event: 'pending' | 'receiving';
13
+ }) | (PendingPayment & {
14
+ event: 'received';
15
+ receiveHash?: string;
16
+ }) | (PendingPayment & {
17
+ event: 'retry';
18
+ error: ReturnType<typeof errorResult>;
19
+ retryInMs: number;
20
+ }) | (PendingPayment & {
21
+ event: 'skipped';
22
+ error: ReturnType<typeof errorResult>;
23
+ }) | {
24
+ event: 'reconnecting';
25
+ error: ReturnType<typeof errorResult>;
26
+ retryInMs: number;
27
+ }) & {
28
+ addressLabels?: ReturnType<AddressLabels['dictionary']>;
29
+ globalDirectory?: ReturnType<AddressLabels['status']>;
30
+ };
31
+ /** Session-owned supervision; every receive goes through the shared mutation gate. */
32
+ export declare class AutoReceiver {
33
+ private readonly snapshot;
34
+ private readonly receive;
35
+ private readonly onProgress?;
36
+ private controller?;
37
+ private loop?;
38
+ private lastError;
39
+ private active;
40
+ constructor(snapshot: () => {
41
+ settings: WalletSettings;
42
+ addresses: WalletAddress[];
43
+ }, receive: (index: number, hash: string) => Promise<unknown>, onProgress?: ((event: ReceiveProgress) => void) | undefined);
44
+ status(): {
45
+ running: boolean;
46
+ lastError: {
47
+ code: string;
48
+ message: string;
49
+ details?: unknown;
50
+ } | null;
51
+ };
52
+ private report;
53
+ start(): void;
54
+ private run;
55
+ close(): Promise<void>;
56
+ }
57
+ export {};
@@ -0,0 +1,140 @@
1
+ import { NodeReader } from '../network/reader.js';
2
+ import { AttoError, errorResult } from '../domain/errors.js';
3
+ import { amountOutput } from '../domain/amount.js';
4
+ /** Session-owned supervision; every receive goes through the shared mutation gate. */
5
+ export class AutoReceiver {
6
+ snapshot;
7
+ receive;
8
+ onProgress;
9
+ controller;
10
+ loop;
11
+ lastError = null;
12
+ active = false;
13
+ constructor(snapshot, receive, onProgress) {
14
+ this.snapshot = snapshot;
15
+ this.receive = receive;
16
+ this.onProgress = onProgress;
17
+ }
18
+ status() { return { running: this.active, lastError: this.lastError }; }
19
+ report(event) {
20
+ // Output failures must never turn a completed payment into another attempt.
21
+ try {
22
+ this.onProgress?.(event);
23
+ }
24
+ catch { /* Receiving is independent of its observer. */ }
25
+ }
26
+ start() {
27
+ if (this.loop)
28
+ return;
29
+ this.controller = new AbortController();
30
+ this.loop = this.run(this.controller.signal).finally(() => { this.active = false; });
31
+ }
32
+ async run(signal) {
33
+ let configuration = '';
34
+ let subscription;
35
+ let stream;
36
+ const pending = new Map();
37
+ let retryAt = 0;
38
+ let delayMs = 1000;
39
+ let connected = false;
40
+ try {
41
+ while (!signal.aborted) {
42
+ const { settings, addresses } = this.snapshot();
43
+ const active = addresses.filter(address => address.active);
44
+ const next = JSON.stringify({ settings, active });
45
+ if (configuration !== next) {
46
+ subscription?.abort();
47
+ await stream;
48
+ pending.clear();
49
+ configuration = next;
50
+ retryAt = 0;
51
+ delayMs = 1000;
52
+ connected = false;
53
+ }
54
+ this.active = settings.autoReceive && active.length > 0;
55
+ if (this.active && !connected && Date.now() >= retryAt) {
56
+ subscription = new AbortController();
57
+ const child = subscription;
58
+ connected = true;
59
+ let streamError;
60
+ const byAddress = new Map(active.map(address => [address.publicKey.toUpperCase(), address.index]));
61
+ stream = new NodeReader(settings).stream({ event: 'receivable', addresses: active.map(address => address.address), minAmountRaw: settings.minReceiveRaw }, model => {
62
+ const receivable = model;
63
+ const index = byAddress.get(receivable.receiverPublicKey.toString().toUpperCase());
64
+ if (index === undefined)
65
+ return;
66
+ const hash = receivable.hash.toString();
67
+ // A bounded queue; reconnecting replays outstanding receivables.
68
+ if (pending.size >= 1000 && !pending.has(hash)) {
69
+ child.abort();
70
+ return;
71
+ }
72
+ if (!pending.has(hash)) {
73
+ const payment = { index, address: receivable.receiverAddress.value, sendHash: hash, amount: amountOutput(receivable.amount.toString()) };
74
+ pending.set(hash, { payment, retryAt: 0 });
75
+ this.report({ event: 'pending', ...payment });
76
+ }
77
+ delayMs = 1000;
78
+ }, child.signal).catch(error => {
79
+ if (!child.signal.aborted && !signal.aborted)
80
+ this.lastError = streamError = errorResult(error);
81
+ }).finally(() => {
82
+ connected = false;
83
+ retryAt = Date.now() + delayMs;
84
+ if (!child.signal.aborted && !signal.aborted)
85
+ this.report({
86
+ event: 'reconnecting',
87
+ error: streamError ?? errorResult(new AttoError('NODE_UNAVAILABLE', 'The node stream ended.')),
88
+ retryInMs: delayMs,
89
+ });
90
+ delayMs = Math.min(delayMs * 2, 30_000);
91
+ });
92
+ }
93
+ for (const [hash, item] of pending) {
94
+ if (signal.aborted)
95
+ break;
96
+ if (Date.now() < item.retryAt)
97
+ continue;
98
+ this.report({ event: 'receiving', ...item.payment });
99
+ try {
100
+ const result = await this.receive(item.payment.index, hash);
101
+ pending.delete(hash);
102
+ this.lastError = null;
103
+ const receiveHash = result && typeof result === 'object' && 'hash' in result && typeof result.hash === 'string' ? result.hash : undefined;
104
+ this.report({ event: 'received', ...item.payment, ...(receiveHash ? { receiveHash } : {}) });
105
+ }
106
+ catch (error) {
107
+ if (error instanceof AttoError && ['RECEIVABLE_NOT_PENDING', 'ADDRESS_INACTIVE', 'AUTO_RECEIVE_DISABLED', 'RECEIVABLE_BELOW_MINIMUM'].includes(error.code)) {
108
+ pending.delete(hash);
109
+ if (!signal.aborted)
110
+ this.report({ event: 'skipped', ...item.payment, error: errorResult(error) });
111
+ }
112
+ else {
113
+ item.retryAt = Date.now() + 10_000;
114
+ this.lastError = errorResult(error);
115
+ if (!signal.aborted)
116
+ this.report({ event: 'retry', ...item.payment, error: this.lastError, retryInMs: 10_000 });
117
+ }
118
+ }
119
+ // Return to the settings/cancellation check between mutations.
120
+ break;
121
+ }
122
+ if (!signal.aborted)
123
+ await new Promise(resolve => {
124
+ const finish = () => { clearTimeout(timer); signal.removeEventListener('abort', finish); resolve(); };
125
+ const timer = setTimeout(finish, 250);
126
+ signal.addEventListener('abort', finish, { once: true });
127
+ });
128
+ }
129
+ }
130
+ finally {
131
+ subscription?.abort();
132
+ await stream;
133
+ }
134
+ }
135
+ async close() {
136
+ this.controller?.abort();
137
+ await this.loop;
138
+ this.loop = undefined;
139
+ }
140
+ }
@@ -0,0 +1,3 @@
1
+ import type { WalletSettings } from './types.js';
2
+ export declare const representativePublicKeys: string[];
3
+ export declare function defaultSettings(): WalletSettings;
@@ -0,0 +1,26 @@
1
+ import { AttoAddress, AttoAlgorithm, AttoPublicKey } from '@attocash/commons-core';
2
+ // Same LIVE representative pool as the desktop wallet. Choose once per installation.
3
+ export const representativePublicKeys = [
4
+ 'd50d27281df93e71e6e7a279fc308d5e90891c27a1129cd0bf24bf94731f547f',
5
+ 'ebc906cc473fce6a5bc1e58622d6d807cb4bc820ac13169d88f96ee26d29b982',
6
+ 'e7877ac47b475989f3c24783e2d5c0ffc4943d1d0c48c02ba152305b0d42ff5b',
7
+ 'e00ba25f78dcd0f229a9335060256cef12609d161daf2fd614dc32c37ccdc56a',
8
+ 'a73f0b55a50d3bb89eead7b47005fd488cc2f540f342f893b72dd357200b4432',
9
+ '5df80120502f2eac7cbf1af12555b5a82990a66745ff89573d6093f535ac25e8',
10
+ '6c9a4b64bbb6ed51a305d1185d83288a62378dbE761e932e38c05c17623d74b1',
11
+ '1d7948c4d449ac8151d7855f44276308e98c899c6f066eb9324dffaa15901929',
12
+ '853380ff0f905b3801f3a32fa193250395b4bd0ca6d83e76eea7389ec9d4ba10',
13
+ '58d293037fdfe6318ac97215e3e8a202cb27637a17831cbfb1964a4534343c48',
14
+ '45eb652403ca618c5f1cff92b2bb1f4c7d86b903e880721937f07ea9e0e5648f',
15
+ '096523285e1fe5755daabb94ecab124d0e395e1d2e613e97d10aa2717b82a4ce',
16
+ ];
17
+ export function defaultSettings() {
18
+ return {
19
+ network: 'LIVE',
20
+ nodeUrl: 'https://gatekeeper.live.application.atto.cash',
21
+ workerUrl: 'https://gatekeeper.live.application.atto.cash',
22
+ representative: new AttoAddress(AttoAlgorithm.V1, AttoPublicKey.Companion.parse(representativePublicKeys[Math.floor(Math.random() * representativePublicKeys.length)])).value,
23
+ autoReceive: true,
24
+ minReceiveRaw: '1',
25
+ };
26
+ }
@@ -0,0 +1,17 @@
1
+ import { AttoSeed, AttoBlock, AttoSigner, AttoAccount, AttoAddress, AttoAmount, AttoInstant, AttoKeyIndex, AttoReceivable, AttoTransaction } from '@attocash/commons-core';
2
+ import { type SendRetry } from '../network/retry.js';
3
+ import type { WalletSettings } from './types.js';
4
+ import type { BlockWorker } from './work.js';
5
+ export declare function mnemonicSeed(phrase: string): Promise<AttoSeed>;
6
+ export declare function derivedSigner(seed: AttoSeed, index: number): Promise<AttoSigner>;
7
+ export declare function signingWallet(seed: AttoSeed, index: number, settings: WalletSettings, beforeSign: (block: AttoBlock) => void | Promise<void>, suppliedWorker?: BlockWorker, retry?: SendRetry): Promise<{
8
+ wallet: {
9
+ sendByIndex(value: AttoKeyIndex, destination: AttoAddress, amount: AttoAmount, timestamp?: AttoInstant | null): Promise<AttoTransaction>;
10
+ receive(receivable: AttoReceivable, representative?: AttoAddress | null, timestamp?: AttoInstant | null): Promise<AttoTransaction>;
11
+ change(value: AttoKeyIndex, representative: AttoAddress, timestamp?: AttoInstant | null): Promise<AttoTransaction>;
12
+ getAccountByIndex(value: AttoKeyIndex): Promise<AttoAccount | null>;
13
+ close(): void;
14
+ };
15
+ client: import("@attocash/commons-node").AttoNodeClientAsync;
16
+ address: AttoAddress;
17
+ }>;