@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,90 @@
1
+ import { AttoAlgorithm, AttoPublicKey } from '@attocash/commons-core';
2
+ import { parseAddress } from '../network/reader.js';
3
+ import { DIRECTORY_URL } from './directory.js';
4
+ export function modelAddress(value, prefix = '') {
5
+ const publicKey = value[prefix ? `${prefix}PublicKey` : 'publicKey'];
6
+ const algorithm = value[prefix ? `${prefix}Algorithm` : 'algorithm'];
7
+ if (typeof publicKey !== 'string' || typeof algorithm !== 'string')
8
+ return;
9
+ try {
10
+ return AttoPublicKey.Companion.parse(publicKey).toAddress(AttoAlgorithm.valueOf(algorithm)).value;
11
+ }
12
+ catch {
13
+ return;
14
+ }
15
+ }
16
+ /** Read protocol keys without rewriting network objects or interpreting metadata. */
17
+ export function resultAddresses(value) {
18
+ const addresses = new Set();
19
+ const visit = (value) => {
20
+ if (typeof value === 'string' && value.startsWith('atto://')) {
21
+ try {
22
+ addresses.add(parseAddress(value).value);
23
+ }
24
+ catch { /* Not an address. */ }
25
+ }
26
+ else if (Array.isArray(value))
27
+ value.forEach(visit);
28
+ else if (value && typeof value === 'object') {
29
+ const object = value;
30
+ for (const prefix of ['', 'receiver', 'representative', 'subject']) {
31
+ const address = modelAddress(object, prefix);
32
+ if (address)
33
+ addresses.add(address);
34
+ }
35
+ for (const [key, child] of Object.entries(object)) {
36
+ if (!['metadata', 'blockJson', 'destinationBinding', 'addressLabels', 'globalDirectory'].includes(key))
37
+ visit(child);
38
+ }
39
+ }
40
+ };
41
+ visit(value);
42
+ return [...addresses];
43
+ }
44
+ export class AddressLabels {
45
+ personal;
46
+ global;
47
+ constructor(personal, global) {
48
+ this.personal = personal;
49
+ this.global = global;
50
+ }
51
+ dictionary(network, addresses) {
52
+ const personal = new Map(this.personal.list(network).map(row => [row.address, row.label]));
53
+ const { snapshot, status } = this.global.cached();
54
+ const entries = network === 'LIVE' && snapshot ? [
55
+ ...snapshot.addresses.map(value => ({ ...value, kind: 'address' })),
56
+ ...snapshot.voters.map(value => ({ ...value, kind: 'voter' })),
57
+ ] : [];
58
+ const entities = new Map(snapshot?.entities.map(value => [value.entity, value]));
59
+ return Object.fromEntries([...new Set(addresses)].map(address => [address, {
60
+ ...(personal.has(address) ? { personal: { source: 'personal', label: personal.get(address) } } : {}),
61
+ global: entries.filter(entry => entry.address === address).map(entry => ({ ...entry, source: DIRECTORY_URL,
62
+ entityInfo: entities.get(entry.entity), stale: status.stale })),
63
+ // A payout relationship says nothing about ownership of its destination.
64
+ payoutFor: entries.filter(entry => 'payToAddress' in entry && entry.payToAddress === address)
65
+ .map(entry => ({ voterAddress: entry.address, label: entry.label, entity: entry.entity, source: DIRECTORY_URL, stale: status.stale })),
66
+ }]));
67
+ }
68
+ status(network) { return network === 'LIVE' ? this.global.cached().status : { network: 'LIVE', applicable: false }; }
69
+ list(network, all = false, search) {
70
+ const addresses = this.personal.list(network).map(row => row.address);
71
+ if (all && network === 'LIVE') {
72
+ const snapshot = this.global.cached().snapshot;
73
+ addresses.push(...(snapshot?.addresses.map(row => row.address) ?? []), ...(snapshot?.voters.map(row => row.address) ?? []));
74
+ }
75
+ const dictionary = this.dictionary(network, addresses);
76
+ const term = search?.trim().toLowerCase();
77
+ const items = Object.entries(dictionary).filter(([address, labels]) => !term || [address, labels.personal?.label,
78
+ ...labels.global.flatMap(row => [row.label, row.entity, row.entityInfo?.label, row.entityInfo?.organization])]
79
+ .some(value => value?.toLowerCase().includes(term))).map(([address]) => ({ address }));
80
+ return { network, items, addressLabels: Object.fromEntries(items.map(({ address }) => [address, dictionary[address]])), globalDirectory: this.status(network) };
81
+ }
82
+ decorate(result, network) {
83
+ if (Array.isArray(result))
84
+ return result.map(value => this.decorate(value, network));
85
+ const addresses = resultAddresses(result);
86
+ if (!addresses.length || !result || typeof result !== 'object' || Array.isArray(result))
87
+ return result;
88
+ return { ...result, addressLabels: this.dictionary(network, addresses), globalDirectory: this.status(network) };
89
+ }
90
+ }
@@ -0,0 +1,31 @@
1
+ import { AttoAccount, AttoAccountEntry, AttoAddress, AttoInstant, AttoReceivable, AttoTransaction } from '@attocash/commons-core';
2
+ import type { ListRequest, StreamFilter, WalletSettings } from '../wallet/types.js';
3
+ type Model = AttoAccount | AttoAccountEntry | AttoReceivable | AttoTransaction;
4
+ export declare function publicModel(model: unknown): unknown;
5
+ export declare function parseAddress(value: string): AttoAddress;
6
+ export declare function normalizeFilter(filter: StreamFilter): StreamFilter;
7
+ export declare function isReplayable(filter: StreamFilter): boolean;
8
+ export declare function eventPosition(model: unknown): {
9
+ address: string;
10
+ height: string;
11
+ } | undefined;
12
+ export declare class NodeReader {
13
+ readonly settings: WalletSettings;
14
+ private readonly headers;
15
+ constructor(settings: WalletSettings, headers?: Record<string, string>);
16
+ private request;
17
+ private get;
18
+ account(address: string, signal?: AbortSignal): Promise<AttoAccount | null>;
19
+ now(signal?: AbortSignal): Promise<AttoInstant>;
20
+ transaction(hash: string, signal?: AbortSignal): Promise<AttoTransaction | null>;
21
+ entry(hash: string, signal?: AbortSignal): Promise<AttoAccountEntry | null>;
22
+ voterWeight(address: string): Promise<unknown>;
23
+ stream(filter: StreamFilter, onEvent: (model: Model) => void, signal: AbortSignal): Promise<void>;
24
+ list(request: ListRequest, signal?: AbortSignal): Promise<{
25
+ items: unknown[];
26
+ nextCursor?: string;
27
+ timedOut: boolean;
28
+ limitReached?: boolean;
29
+ }>;
30
+ }
31
+ export {};
@@ -0,0 +1,370 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createRequire } from 'node:module';
3
+ import { AttoAccount, AttoAccountEntry, AttoAddress, AttoAmount, AttoHash, AttoInstant, AttoTransaction, AttoUnit, toAttoHeight } from '@attocash/commons-core';
4
+ import { AccountHeightSearch, HeightSearch } from '@attocash/commons-node';
5
+ import { AttoNodeClientAsyncBuilder } from '@attocash/commons-node-remote';
6
+ import { AttoError } from '../domain/errors.js';
7
+ import { amountRaw } from '../domain/amount.js';
8
+ // Ktor's Node engine uses require while Commons is imported as ESM.
9
+ Object.assign(globalThis, { require: createRequire(import.meta.url) });
10
+ const MAX_RESPONSE_BYTES = 1024 * 1024;
11
+ const MAX_HEIGHT = 18446744073709551615n;
12
+ const numericStrings = new Set(['amount', 'balance', 'previousBalance', 'height', 'fromHeight', 'toHeight', 'weight']);
13
+ function jsonExact(text) {
14
+ return JSON.parse(text, (key, value, context) => {
15
+ if (typeof value === 'number' && (numericStrings.has(key) || !Number.isSafeInteger(value))) {
16
+ if (!context?.source)
17
+ throw new AttoError('UNSUPPORTED_RUNTIME', 'Exact JSON numbers require Node.js 24 or later.');
18
+ return context.source;
19
+ }
20
+ return value;
21
+ });
22
+ }
23
+ export function publicModel(model) {
24
+ if (model === null || model === undefined)
25
+ return null;
26
+ if (typeof model === 'object' && 'toJson' in model && typeof model.toJson === 'function') {
27
+ return jsonExact(model.toJson());
28
+ }
29
+ return jsonExact(JSON.stringify(model, (_key, value) => typeof value === 'bigint' ? value.toString() : value));
30
+ }
31
+ export function parseAddress(value) {
32
+ try {
33
+ return AttoAddress.parse(value);
34
+ }
35
+ catch {
36
+ throw new AttoError('INVALID_ADDRESS', 'Provide a valid Atto address.');
37
+ }
38
+ }
39
+ function parseHash(value) {
40
+ if (!/^[0-9a-fA-F]{64}$/.test(value))
41
+ throw new AttoError('INVALID_HASH', 'Provide a 64-character hexadecimal hash.');
42
+ return value.toUpperCase();
43
+ }
44
+ function height(value, allowZero = false) {
45
+ if (!/^\d+$/.test(value) || BigInt(value) > MAX_HEIGHT || (!allowZero && BigInt(value) === 0n)) {
46
+ throw new AttoError('INVALID_HEIGHT', 'Height must be a positive unsigned 64-bit integer string.');
47
+ }
48
+ return BigInt(value).toString();
49
+ }
50
+ export function normalizeFilter(filter) {
51
+ if (!['account', 'transaction', 'entry', 'receivable'].includes(filter.event)) {
52
+ throw new AttoError('INVALID_FILTER', 'Unknown network event type.');
53
+ }
54
+ const addresses = filter.addresses?.length ? [...new Set(filter.addresses.map(value => parseAddress(value).value))] : undefined;
55
+ if (addresses && addresses.length > 100)
56
+ throw new AttoError('INVALID_FILTER', 'Use at most 100 addresses per request.');
57
+ if (filter.hash && (addresses || !['transaction', 'entry'].includes(filter.event))) {
58
+ throw new AttoError('INVALID_FILTER', 'Hash filters support transactions or entries and cannot include addresses.');
59
+ }
60
+ if ((filter.fromHeight || filter.toHeight) && (!addresses || !['transaction', 'entry'].includes(filter.event))) {
61
+ throw new AttoError('INVALID_FILTER', 'Height ranges require address-specific transactions or entries.');
62
+ }
63
+ if (filter.event === 'receivable' && !addresses)
64
+ throw new AttoError('INVALID_FILTER', 'Receivable streams require at least one address.');
65
+ if (filter.minAmountRaw !== undefined && filter.event !== 'receivable') {
66
+ throw new AttoError('INVALID_FILTER', 'Minimum amounts apply only to receivables.');
67
+ }
68
+ const fromHeight = addresses && ['transaction', 'entry'].includes(filter.event) ? height(filter.fromHeight ?? '1') : undefined;
69
+ const toHeight = filter.toHeight !== undefined ? height(filter.toHeight) : undefined;
70
+ if (fromHeight && toHeight && BigInt(fromHeight) > BigInt(toHeight))
71
+ throw new AttoError('INVALID_HEIGHT', 'From height must not exceed to height.');
72
+ return {
73
+ event: filter.event,
74
+ ...(addresses ? { addresses } : {}),
75
+ ...(filter.hash ? { hash: parseHash(filter.hash) } : {}),
76
+ ...(fromHeight ? { fromHeight } : {}),
77
+ ...(toHeight ? { toHeight } : {}),
78
+ ...(filter.event === 'receivable' ? { minAmountRaw: amountRaw(filter.minAmountRaw ?? '0', 'RAW', true) } : {}),
79
+ };
80
+ }
81
+ export function isReplayable(filter) {
82
+ return Boolean(filter.addresses?.length && ['transaction', 'entry'].includes(filter.event));
83
+ }
84
+ export function eventPosition(model) {
85
+ if (typeof model !== 'object' || model === null || !('address' in model) || !('height' in model))
86
+ return;
87
+ const address = model.address;
88
+ return { address: address.value, height: String(model.height) };
89
+ }
90
+ export class NodeReader {
91
+ settings;
92
+ headers;
93
+ constructor(settings, headers = {}) {
94
+ this.settings = settings;
95
+ this.headers = headers;
96
+ }
97
+ async request(path, signal, firstEvent) {
98
+ try {
99
+ const response = await fetch(`${this.settings.nodeUrl.replace(/\/$/, '')}/${path}`, {
100
+ redirect: 'error', signal,
101
+ headers: { ...this.headers, accept: firstEvent ? 'application/x-ndjson' : 'application/json' },
102
+ });
103
+ if (!response.ok) {
104
+ await response.body?.cancel();
105
+ throw new AttoError(response.status === 404 ? 'NOT_FOUND' : 'NODE_HTTP_ERROR', `The node returned HTTP ${response.status}.`, { httpStatus: response.status });
106
+ }
107
+ return response;
108
+ }
109
+ catch (error) {
110
+ if (error instanceof AttoError)
111
+ throw error;
112
+ if (signal.aborted)
113
+ throw new AttoError('CANCELLED', 'The network request was cancelled.');
114
+ throw new AttoError('NODE_UNAVAILABLE', 'The node could not be reached.');
115
+ }
116
+ }
117
+ // Commons' Promise reads do not expose cancellation or HTTP status; finite
118
+ // lookups retain those caller contracts here.
119
+ async get(path, parse, signal, firstEvent = false) {
120
+ const timeout = AbortSignal.timeout(10_000);
121
+ const combined = signal ? AbortSignal.any([signal, timeout]) : timeout;
122
+ try {
123
+ const response = await this.request(path, combined, firstEvent);
124
+ let body = '';
125
+ const decoder = new TextDecoder();
126
+ let size = 0;
127
+ if (!response.body)
128
+ throw new AttoError('INVALID_NODE_RESPONSE', 'The node response has no body.');
129
+ const reader = response.body.getReader();
130
+ try {
131
+ while (true) {
132
+ const { value, done } = await reader.read();
133
+ if (done)
134
+ break;
135
+ size += value.length;
136
+ if (size > MAX_RESPONSE_BYTES)
137
+ throw new AttoError('INVALID_NODE_RESPONSE', 'The node response exceeded the size limit.');
138
+ body += decoder.decode(value, { stream: true });
139
+ if (firstEvent && body.includes('\n')) {
140
+ body = body.slice(0, body.indexOf('\n'));
141
+ break;
142
+ }
143
+ }
144
+ }
145
+ finally {
146
+ await reader.cancel().catch(() => undefined);
147
+ reader.releaseLock();
148
+ }
149
+ body += decoder.decode();
150
+ if (firstEvent && !body.trim())
151
+ return null;
152
+ try {
153
+ return parse(body);
154
+ }
155
+ catch {
156
+ throw new AttoError('INVALID_NODE_RESPONSE', 'The node returned an invalid response.');
157
+ }
158
+ }
159
+ catch (error) {
160
+ if (error instanceof AttoError && error.code === 'NOT_FOUND')
161
+ return null;
162
+ if (signal?.aborted)
163
+ throw new AttoError('CANCELLED', 'The network request was cancelled.');
164
+ if (timeout.aborted)
165
+ throw new AttoError('NODE_TIMEOUT', 'The node request timed out.');
166
+ if (error instanceof AttoError)
167
+ throw error;
168
+ throw new AttoError('NODE_UNAVAILABLE', 'The node connection failed.');
169
+ }
170
+ }
171
+ account(address, signal) {
172
+ return this.get(`accounts/${parseAddress(address).publicKey}`, AttoAccount.fromJson, signal);
173
+ }
174
+ async now(signal) {
175
+ const requested = AttoInstant.Companion.now().toString();
176
+ const result = await this.get(`instants/${encodeURIComponent(requested)}`, text => {
177
+ const value = JSON.parse(text);
178
+ if (typeof value.clientInstant !== 'string' || typeof value.serverInstant !== 'string'
179
+ || AttoInstant.Companion.fromIso(value.clientInstant).toEpochMilliseconds() !== AttoInstant.Companion.fromIso(requested).toEpochMilliseconds())
180
+ throw new Error();
181
+ return AttoInstant.Companion.fromIso(value.serverInstant);
182
+ }, signal);
183
+ if (!result)
184
+ throw new AttoError('NODE_TIME_UNAVAILABLE', 'The node time API is unavailable. Check the configured node URL.');
185
+ return result;
186
+ }
187
+ transaction(hash, signal) {
188
+ return this.get(`transactions/${parseHash(hash)}`, AttoTransaction.fromJson, signal);
189
+ }
190
+ entry(hash, signal) {
191
+ return this.get(`accounts/entries/${parseHash(hash)}/stream`, AttoAccountEntry.fromJson, signal, true);
192
+ }
193
+ voterWeight(address) {
194
+ return this.get(`vote-weights/${parseAddress(address).path}`, jsonExact);
195
+ }
196
+ async stream(filter, onEvent, signal) {
197
+ const normalized = normalizeFilter(filter);
198
+ if (signal.aborted)
199
+ return;
200
+ const builder = new AttoNodeClientAsyncBuilder(this.settings.nodeUrl);
201
+ for (const [name, value] of Object.entries(this.headers))
202
+ builder.header(name, value);
203
+ const client = builder.build();
204
+ const addresses = normalized.addresses?.map(parseAddress);
205
+ const one = addresses?.length === 1 ? addresses[0] : undefined;
206
+ const hash = normalized.hash ? AttoHash.Companion.parse(normalized.hash) : undefined;
207
+ let job;
208
+ let callbackFailure;
209
+ let complete;
210
+ const cancel = () => {
211
+ // Cancellation before Commons starts its coroutine may omit onCancel.
212
+ // Joining the job also settles that case and waits for transport cleanup.
213
+ void job?.cancelAndJoin().then(() => complete(), complete);
214
+ };
215
+ const emit = (model) => {
216
+ if (signal.aborted || callbackFailure)
217
+ return;
218
+ // Commons catches Kotlin exceptions; a JS callback error must not escape
219
+ // into its coroutine and leave the subscription promise unresolved.
220
+ try {
221
+ onEvent(model);
222
+ }
223
+ catch (error) {
224
+ callbackFailure = { error };
225
+ cancel();
226
+ }
227
+ };
228
+ try {
229
+ await new Promise((resolve, reject) => {
230
+ complete = (error) => {
231
+ if (callbackFailure)
232
+ reject(callbackFailure.error);
233
+ else if (error && !signal.aborted)
234
+ reject(error);
235
+ else
236
+ resolve();
237
+ };
238
+ if (normalized.event === 'receivable') {
239
+ const minimum = AttoAmount.from(AttoUnit.RAW, normalized.minAmountRaw);
240
+ job = one
241
+ ? client.onReceivableByPublicKey(one.publicKey, minimum, emit, complete)
242
+ : client.onReceivableByAddresses(addresses, minimum, emit, complete);
243
+ }
244
+ else if (normalized.event === 'account') {
245
+ job = one ? client.onAccountByPublicKey(one.publicKey, emit, complete)
246
+ : addresses ? client.onAccountByAddresses(addresses, emit, complete)
247
+ : client.onAccountAll(emit, complete);
248
+ }
249
+ else {
250
+ const from = toAttoHeight(normalized.fromHeight ?? '1');
251
+ const to = normalized.toHeight ? toAttoHeight(normalized.toHeight) : undefined;
252
+ const search = addresses && !one ? HeightSearch.Companion.fromArray(addresses.map(address => new AccountHeightSearch(address, from, to))) : undefined;
253
+ if (normalized.event === 'entry') {
254
+ job = hash ? client.onAccountEntryByHash(hash, emit, complete)
255
+ : one ? client.onAccountEntryByPublicKey(one.publicKey, from, to, emit, complete)
256
+ : search ? client.onAccountEntryByHeightSearch(search, emit, complete)
257
+ : client.onAccountEntryAll(emit, complete);
258
+ }
259
+ else {
260
+ job = hash ? client.onTransactionByHash(hash, emit, complete)
261
+ : one ? client.onTransactionByPublicKey(one.publicKey, from, to, emit, complete)
262
+ : search ? client.onTransactionByHeightSearch(search, emit, complete)
263
+ : client.onTransactionAll(emit, complete);
264
+ }
265
+ }
266
+ signal.addEventListener('abort', cancel, { once: true });
267
+ if (signal.aborted)
268
+ cancel();
269
+ });
270
+ }
271
+ catch (error) {
272
+ if (signal.aborted)
273
+ return;
274
+ if (error instanceof AttoError)
275
+ throw error;
276
+ // SDK errors may include URLs, headers, and response bodies. Keep them private.
277
+ throw new AttoError('NODE_STREAM_ERROR', 'The node stream failed. Check endpoint availability and node responses.');
278
+ }
279
+ finally {
280
+ signal.removeEventListener('abort', cancel);
281
+ await job?.cancelAndJoin();
282
+ }
283
+ }
284
+ async list(request, signal) {
285
+ const filter = normalizeFilter(request);
286
+ const limit = request.limit ?? 100;
287
+ const timeoutMs = request.timeoutMs ?? 3_000;
288
+ if (!Number.isInteger(limit) || limit < 1 || limit > 1000 || !Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60_000) {
289
+ throw new AttoError('INVALID_LIST', 'Use a limit from 1 to 1000 and timeoutMs from 1 to 60000.');
290
+ }
291
+ const timeout = AbortSignal.timeout(timeoutMs);
292
+ const done = new AbortController();
293
+ const combined = AbortSignal.any([timeout, done.signal, ...(signal ? [signal] : [])]);
294
+ const items = [];
295
+ if (!isReplayable(filter)) {
296
+ if (request.cursor)
297
+ throw new AttoError('INVALID_CURSOR', 'Continuation cursors require address-specific transaction or entry history.');
298
+ await this.stream(filter, model => { items.push(publicModel(model)); if (items.length === limit)
299
+ done.abort(); }, combined);
300
+ if (signal?.aborted)
301
+ throw new AttoError('CANCELLED', 'The network request was cancelled.');
302
+ return { items, timedOut: timeout.aborted && !done.signal.aborted, ...(done.signal.aborted ? { limitReached: true } : {}) };
303
+ }
304
+ const scope = createHash('sha256').update(JSON.stringify([this.settings.nodeUrl, this.settings.network, filter])).digest('hex');
305
+ const addresses = filter.addresses;
306
+ let cursor = { version: 1, scope, addressIndex: 0, nextHeight: filter.fromHeight, upper: addresses.map(() => null) };
307
+ if (request.cursor) {
308
+ try {
309
+ if (request.cursor.length > 20_000)
310
+ throw new Error();
311
+ const parsed = JSON.parse(Buffer.from(request.cursor, 'base64url').toString('utf8'));
312
+ if (parsed.version !== 1 || parsed.scope !== scope || !Number.isInteger(parsed.addressIndex) || parsed.addressIndex < 0 || parsed.addressIndex >= addresses.length || !Array.isArray(parsed.upper) || parsed.upper.length !== addresses.length)
313
+ throw new Error();
314
+ height(parsed.nextHeight);
315
+ for (const upper of parsed.upper)
316
+ if (upper !== null)
317
+ height(upper, true);
318
+ cursor = parsed;
319
+ }
320
+ catch {
321
+ throw new AttoError('INVALID_CURSOR', 'The continuation cursor is invalid or belongs to a different query.');
322
+ }
323
+ }
324
+ try {
325
+ while (cursor.addressIndex < addresses.length && !combined.aborted) {
326
+ const index = cursor.addressIndex;
327
+ const address = addresses[index];
328
+ if (cursor.upper[index] === null) {
329
+ const current = await this.account(address, combined);
330
+ const currentHeight = current ? BigInt(String(current.height)) : 0n;
331
+ cursor.upper[index] = (filter.toHeight && BigInt(filter.toHeight) < currentHeight ? BigInt(filter.toHeight) : currentHeight).toString();
332
+ }
333
+ const upper = cursor.upper[index];
334
+ if (BigInt(cursor.nextHeight) <= BigInt(upper)) {
335
+ await this.stream({ ...filter, addresses: [address], fromHeight: cursor.nextHeight, toHeight: upper }, model => {
336
+ const position = eventPosition(model);
337
+ if (!position || position.address !== address || BigInt(position.height) > BigInt(upper))
338
+ throw new AttoError('INVALID_NODE_RESPONSE', 'The node returned an event outside the requested account range.');
339
+ if (BigInt(position.height) < BigInt(cursor.nextHeight))
340
+ return;
341
+ // Each account stream is height ordered. Never advance over a missing block.
342
+ if (position.height !== cursor.nextHeight)
343
+ throw new AttoError('HISTORY_GAP', 'The node returned a gap in account history. Retry with a fully synchronized node.');
344
+ items.push(publicModel(model));
345
+ cursor.nextHeight = (BigInt(position.height) + 1n).toString();
346
+ if (items.length === limit)
347
+ done.abort();
348
+ }, combined);
349
+ }
350
+ if (BigInt(cursor.nextHeight) > BigInt(upper)) {
351
+ cursor.addressIndex++;
352
+ cursor.nextHeight = filter.fromHeight;
353
+ }
354
+ else if (!combined.aborted) {
355
+ throw new AttoError('HISTORY_GAP', 'The node closed the stream before the requested history was complete.');
356
+ }
357
+ }
358
+ }
359
+ catch (error) {
360
+ if (!combined.aborted)
361
+ throw error;
362
+ }
363
+ if (signal?.aborted)
364
+ throw new AttoError('CANCELLED', 'The network request was cancelled.');
365
+ return {
366
+ items, timedOut: timeout.aborted && !done.signal.aborted,
367
+ ...(cursor.addressIndex < addresses.length ? { nextCursor: Buffer.from(JSON.stringify(cursor)).toString('base64url') } : {}),
368
+ };
369
+ }
370
+ }
@@ -0,0 +1,7 @@
1
+ import { AttoError } from '../domain/errors.js';
2
+ export interface SendRetry {
3
+ signal: AbortSignal;
4
+ onRetry: (error: AttoError, delayMs: number) => void;
5
+ }
6
+ /** Retry only a network operation, never rebuild a signed payment. Opt-in for CLI sends. */
7
+ export declare function retryNetwork<T>(operation: () => Promise<T>, retry?: SendRetry): Promise<T>;
@@ -0,0 +1,53 @@
1
+ import { setTimeout as delay } from 'node:timers/promises';
2
+ import { AttoError } from '../domain/errors.js';
3
+ function networkError(error) {
4
+ if (error instanceof AttoError)
5
+ return error;
6
+ if (!(error instanceof Error))
7
+ return;
8
+ // Commons exposes standard Error names, but not a public JS HTTP status
9
+ // accessor. Never inspect Kotlin internals or print dependency messages.
10
+ if (error.name === 'ClientRequestException')
11
+ return new AttoError('NODE_CLIENT_ERROR', 'The node returned an HTTP 4xx error.');
12
+ if (error.name === 'ServerResponseException')
13
+ return new AttoError('NODE_SERVER_ERROR', 'The node returned an HTTP 5xx error.');
14
+ if (['HttpRequestTimeoutException', 'ConnectTimeoutException', 'SocketTimeoutException'].includes(error.name)) {
15
+ return new AttoError('NODE_TIMEOUT', 'The node request timed out.');
16
+ }
17
+ if ((error.name === 'TypeError' && error.message === 'fetch failed')
18
+ || (error.cause instanceof Error && error.cause.name === 'TypeError' && error.cause.message === 'fetch failed')
19
+ || error.name === 'EOFException') {
20
+ return new AttoError('NODE_UNAVAILABLE', 'The node connection failed.');
21
+ }
22
+ }
23
+ function retryable(error) {
24
+ const status = error.details?.httpStatus;
25
+ if (status !== undefined)
26
+ return status >= 500 && status <= 599;
27
+ return ['NODE_SERVER_ERROR', 'NODE_TIMEOUT', 'NODE_UNAVAILABLE', 'WORK_TIMEOUT', 'WORK_FAILED', 'MARKET_DATA_UNAVAILABLE'].includes(error.code);
28
+ }
29
+ /** Retry only a network operation, never rebuild a signed payment. Opt-in for CLI sends. */
30
+ export async function retryNetwork(operation, retry) {
31
+ let delayMs = 1000;
32
+ for (;;) {
33
+ if (retry?.signal.aborted)
34
+ throw new AttoError('CANCELLED', 'Send cancelled.');
35
+ try {
36
+ return await operation();
37
+ }
38
+ catch (error) {
39
+ if (!retry)
40
+ throw error;
41
+ if (retry.signal.aborted)
42
+ throw new AttoError('CANCELLED', 'Send cancelled.');
43
+ const failure = networkError(error);
44
+ if (!failure || !retryable(failure))
45
+ throw failure ?? error;
46
+ retry.onRetry(failure, delayMs);
47
+ await delay(delayMs, undefined, { signal: retry.signal }).catch(() => {
48
+ throw new AttoError('CANCELLED', 'Send cancelled.');
49
+ });
50
+ delayMs = Math.min(delayMs * 2, 30_000);
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,3 @@
1
+ import { AttoBlock, AttoWork } from '@attocash/commons-core';
2
+ /** Request and validate public work without caching, signing, or wallet state. */
3
+ export declare function requestWork(block: AttoBlock, url: string, signal: AbortSignal): Promise<AttoWork>;
@@ -0,0 +1,66 @@
1
+ import { AttoWork, attoBlockWorkTarget } from '@attocash/commons-core';
2
+ import { AttoError } from '../domain/errors.js';
3
+ const RESPONSE_LIMIT = 2048;
4
+ /** Request and validate public work without caching, signing, or wallet state. */
5
+ export async function requestWork(block, url, signal) {
6
+ try {
7
+ const timestamp = Number(block.timestamp.toEpochMilliseconds());
8
+ if (!Number.isSafeInteger(timestamp))
9
+ throw new AttoError('INVALID_WORK', 'The work timestamp cannot be represented exactly.');
10
+ // Commons WorkerOperations.Request serializes this public network/time/
11
+ // target tuple. Fetch supplies cancellation absent from its JS worker API.
12
+ const response = await fetch(`${url.replace(/\/+$/, '')}/works`, {
13
+ method: 'POST', redirect: 'error', signal,
14
+ headers: { 'content-type': 'application/json', accept: 'application/json' },
15
+ body: JSON.stringify({ network: block.network.name, timestamp, target: attoBlockWorkTarget(block) }),
16
+ });
17
+ if (!response.ok) {
18
+ await response.body?.cancel();
19
+ throw new AttoError('WORK_FAILED', `The worker returned HTTP ${response.status}.`, { httpStatus: response.status });
20
+ }
21
+ const value = await readResponse(response);
22
+ if (typeof value !== 'object' || value === null || !('work' in value)
23
+ || typeof value.work !== 'string' || !/^[0-9a-f]{16}$/i.test(value.work)) {
24
+ throw new AttoError('INVALID_WORK', 'The worker returned malformed proof of work.');
25
+ }
26
+ const work = AttoWork.Companion.parse(value.work);
27
+ if (!work.isValid(block))
28
+ throw new AttoError('INVALID_WORK', 'The worker returned invalid proof of work.');
29
+ return work;
30
+ }
31
+ catch (error) {
32
+ if (signal.aborted)
33
+ throw new AttoError('WORK_TIMEOUT', 'The work request was cancelled or timed out.');
34
+ if (error instanceof AttoError)
35
+ throw error;
36
+ throw new AttoError('WORK_FAILED', 'Proof-of-work generation failed. Check the worker endpoint. Run doctor for diagnostics.');
37
+ }
38
+ }
39
+ async function readResponse(response) {
40
+ if (!response.body)
41
+ throw new AttoError('INVALID_WORK', 'The worker returned an empty response.');
42
+ const reader = response.body.getReader();
43
+ const chunks = [];
44
+ let size = 0;
45
+ try {
46
+ for (;;) {
47
+ const { done, value } = await reader.read();
48
+ if (done)
49
+ break;
50
+ size += value.byteLength;
51
+ if (size > RESPONSE_LIMIT)
52
+ throw new AttoError('INVALID_WORK', 'The worker response exceeds the allowed size.');
53
+ chunks.push(value);
54
+ }
55
+ try {
56
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'));
57
+ }
58
+ catch {
59
+ throw new AttoError('INVALID_WORK', 'The worker returned malformed JSON.');
60
+ }
61
+ }
62
+ finally {
63
+ await reader.cancel().catch(() => undefined);
64
+ reader.releaseLock();
65
+ }
66
+ }
@@ -0,0 +1,29 @@
1
+ export declare const DEFAULT_METRICS_URL = "https://gatekeeper.live.application.atto.cash/projections/metrics";
2
+ export interface MarketMetric {
3
+ name: string;
4
+ date: string;
5
+ value: string;
6
+ }
7
+ export interface MarketMetrics {
8
+ metrics: MarketMetric[];
9
+ source: string;
10
+ fetchedAt: string;
11
+ }
12
+ export declare class MarketData {
13
+ private readonly fetchImpl;
14
+ private readonly source;
15
+ constructor(url?: string, fetchImpl?: typeof fetch);
16
+ metrics(signal?: AbortSignal): Promise<MarketMetrics>;
17
+ quoteUsd(amount: string, signal?: AbortSignal): Promise<{
18
+ usd: string;
19
+ priceUsd: string;
20
+ priceDate: string;
21
+ source: string;
22
+ fetchedAt: string;
23
+ amount: {
24
+ raw: string;
25
+ atto: string;
26
+ };
27
+ informational: true;
28
+ }>;
29
+ }