@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.
- package/LICENSE +28 -0
- package/README.md +707 -0
- package/dist/application/app.d.ts +138 -0
- package/dist/application/app.js +654 -0
- package/dist/application/operations.d.ts +9 -0
- package/dist/application/operations.js +96 -0
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.js +460 -0
- package/dist/cli/help.d.ts +4 -0
- package/dist/cli/help.js +49 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +13 -0
- package/dist/cli/onboarding.d.ts +14 -0
- package/dist/cli/onboarding.js +144 -0
- package/dist/cli/output.d.ts +2 -0
- package/dist/cli/output.js +231 -0
- package/dist/cli/terminal.d.ts +6 -0
- package/dist/cli/terminal.js +92 -0
- package/dist/cli/update-check.d.ts +1 -0
- package/dist/cli/update-check.js +12 -0
- package/dist/cli/updates.d.ts +2 -0
- package/dist/cli/updates.js +98 -0
- package/dist/core.d.ts +14 -0
- package/dist/core.js +14 -0
- package/dist/doctor/credential-probe.d.ts +7 -0
- package/dist/doctor/credential-probe.js +49 -0
- package/dist/doctor/doctor.d.ts +4 -0
- package/dist/doctor/doctor.js +213 -0
- package/dist/doctor/keyring.d.ts +7 -0
- package/dist/doctor/keyring.js +150 -0
- package/dist/doctor/profile.d.ts +19 -0
- package/dist/doctor/profile.js +73 -0
- package/dist/doctor/types.d.ts +40 -0
- package/dist/doctor/types.js +1 -0
- package/dist/domain/amount.d.ts +6 -0
- package/dist/domain/amount.js +27 -0
- package/dist/domain/errors.d.ts +10 -0
- package/dist/domain/errors.js +16 -0
- package/dist/labels/directory.d.ts +87 -0
- package/dist/labels/directory.js +140 -0
- package/dist/labels/personal.d.ts +17 -0
- package/dist/labels/personal.js +56 -0
- package/dist/labels/presentation.d.ts +154 -0
- package/dist/labels/presentation.js +90 -0
- package/dist/network/reader.d.ts +31 -0
- package/dist/network/reader.js +370 -0
- package/dist/network/retry.d.ts +7 -0
- package/dist/network/retry.js +53 -0
- package/dist/network/work.d.ts +3 -0
- package/dist/network/work.js +66 -0
- package/dist/pricing/market.d.ts +29 -0
- package/dist/pricing/market.js +150 -0
- package/dist/pricing/terms.d.ts +6 -0
- package/dist/pricing/terms.js +12 -0
- package/dist/spending/destination.d.ts +16 -0
- package/dist/spending/destination.js +42 -0
- package/dist/spending/journal.d.ts +28 -0
- package/dist/spending/journal.js +69 -0
- package/dist/spending/ledger.d.ts +118 -0
- package/dist/spending/ledger.js +444 -0
- package/dist/spending/payments.d.ts +67 -0
- package/dist/spending/payments.js +424 -0
- package/dist/spending/pool.d.ts +13 -0
- package/dist/spending/pool.js +38 -0
- package/dist/spending/reconcile.d.ts +18 -0
- package/dist/spending/reconcile.js +64 -0
- package/dist/storage/profiles.d.ts +13 -0
- package/dist/storage/profiles.js +86 -0
- package/dist/storage/secrets.d.ts +16 -0
- package/dist/storage/secrets.js +104 -0
- package/dist/storage/state.d.ts +32 -0
- package/dist/storage/state.js +255 -0
- package/dist/wallet/auto-receive.d.ts +57 -0
- package/dist/wallet/auto-receive.js +140 -0
- package/dist/wallet/defaults.d.ts +3 -0
- package/dist/wallet/defaults.js +26 -0
- package/dist/wallet/signing.d.ts +17 -0
- package/dist/wallet/signing.js +128 -0
- package/dist/wallet/types.d.ts +65 -0
- package/dist/wallet/types.js +1 -0
- package/dist/wallet/work.d.ts +29 -0
- package/dist/wallet/work.js +154 -0
- package/dist/watches/manager.d.ts +75 -0
- package/dist/watches/manager.js +197 -0
- package/node_modules/@attocash/commons-core/Kotlin-DateTime-library-kotlinx-datetime.mjs +6678 -0
- package/node_modules/@attocash/commons-core/Kotlin-DateTime-library-kotlinx-datetime.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/LICENSE +28 -0
- package/node_modules/@attocash/commons-core/README.md +118 -0
- package/node_modules/@attocash/commons-core/commons-commons-core.d.mts +1036 -0
- package/node_modules/@attocash/commons-core/commons-commons-core.mjs +7701 -0
- package/node_modules/@attocash/commons-core/commons-commons-core.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlin-kotlin-stdlib.mjs +17681 -0
- package/node_modules/@attocash/commons-core/kotlin-kotlin-stdlib.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlin_org_jetbrains_kotlin_kotlin_dom_api_compat.mjs +4 -0
- package/node_modules/@attocash/commons-core/kotlin_org_jetbrains_kotlin_kotlin_dom_api_compat.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-bytestring.mjs +209 -0
- package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-bytestring.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-core.mjs +2284 -0
- package/node_modules/@attocash/commons-core/kotlinx-io-kotlinx-io-core.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-core.mjs +6042 -0
- package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-core.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-core/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-core/package.json +27 -0
- package/node_modules/@attocash/commons-node/LICENSE +28 -0
- package/node_modules/@attocash/commons-node/README.md +92 -0
- package/node_modules/@attocash/commons-node/commons-commons-node.d.mts +255 -0
- package/node_modules/@attocash/commons-node/commons-commons-node.mjs +2977 -0
- package/node_modules/@attocash/commons-node/commons-commons-node.mjs.map +1 -0
- package/node_modules/@attocash/commons-node/kotlin-logging.mjs +432 -0
- package/node_modules/@attocash/commons-node/kotlin-logging.mjs.map +1 -0
- package/node_modules/@attocash/commons-node/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-node/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-node/package.json +29 -0
- package/node_modules/@attocash/commons-node-remote/LICENSE +28 -0
- package/node_modules/@attocash/commons-node-remote/README.md +61 -0
- package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.d.mts +122 -0
- package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.mjs +1810 -0
- package/node_modules/@attocash/commons-node-remote/commons-commons-node-remote.mjs.map +1 -0
- package/node_modules/@attocash/commons-node-remote/kotlin-logging.mjs +432 -0
- package/node_modules/@attocash/commons-node-remote/kotlin-logging.mjs.map +1 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-browser.mjs +8 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-browser.mjs.map +1 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-node-remote/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-node-remote/package.json +31 -0
- package/node_modules/@attocash/commons-transport/LICENSE +28 -0
- package/node_modules/@attocash/commons-transport/README.md +5 -0
- package/node_modules/@attocash/commons-transport/commons-commons-transport.d.mts +64 -0
- package/node_modules/@attocash/commons-transport/commons-commons-transport.mjs +249 -0
- package/node_modules/@attocash/commons-transport/commons-commons-transport.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/kotlinx-atomicfu.mjs +263 -0
- package/node_modules/@attocash/commons-transport/kotlinx-atomicfu.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/kotlinx-browser.mjs +8 -0
- package/node_modules/@attocash/commons-transport/kotlinx-browser.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/kotlinx-coroutines-core.mjs +11604 -0
- package/node_modules/@attocash/commons-transport/kotlinx-coroutines-core.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
- package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-transport/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-client-content-negotiation.mjs +499 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-client-content-negotiation.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-client-core.mjs +6456 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-client-core.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-events.mjs +83 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-events.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-http-cio.mjs +1714 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-http-cio.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-http.mjs +3197 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-http.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-io.mjs +2290 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-io.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx-json.mjs +46 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx.mjs +482 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization-kotlinx.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization.mjs +165 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-serialization.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-sse.mjs +4 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-sse.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-utils.mjs +3222 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-utils.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-websocket-serialization.mjs +4 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-websocket-serialization.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-websockets.mjs +1485 -0
- package/node_modules/@attocash/commons-transport/ktor-ktor-websockets.mjs.map +1 -0
- package/node_modules/@attocash/commons-transport/package.json +29 -0
- package/node_modules/@attocash/commons-worker/LICENSE +28 -0
- package/node_modules/@attocash/commons-worker/README.md +48 -0
- package/node_modules/@attocash/commons-worker/commons-commons-worker.d.mts +73 -0
- package/node_modules/@attocash/commons-worker/commons-commons-worker.mjs +702 -0
- package/node_modules/@attocash/commons-worker/commons-commons-worker.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker/kotlin-logging.mjs +432 -0
- package/node_modules/@attocash/commons-worker/kotlin-logging.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-worker/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker/package.json +29 -0
- package/node_modules/@attocash/commons-worker-remote/LICENSE +28 -0
- package/node_modules/@attocash/commons-worker-remote/README.md +60 -0
- package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.d.mts +93 -0
- package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.mjs +289 -0
- package/node_modules/@attocash/commons-worker-remote/commons-commons-worker-remote.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker-remote/kotlin-logging.mjs +432 -0
- package/node_modules/@attocash/commons-worker-remote/kotlin-logging.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-browser.mjs +8 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-browser.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs +4 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json-io.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json.mjs +5294 -0
- package/node_modules/@attocash/commons-worker-remote/kotlinx-serialization-kotlinx-serialization-json.mjs.map +1 -0
- package/node_modules/@attocash/commons-worker-remote/package.json +31 -0
- package/node_modules/@js-joda/core/CHANGELOG.md +363 -0
- package/node_modules/@js-joda/core/CheatSheet.md +947 -0
- package/node_modules/@js-joda/core/LICENSE +34 -0
- package/node_modules/@js-joda/core/README.md +155 -0
- package/node_modules/@js-joda/core/bower.json +21 -0
- package/node_modules/@js-joda/core/dist/js-joda.d.ts +2452 -0
- package/node_modules/@js-joda/core/dist/js-joda.esm.js +13564 -0
- package/node_modules/@js-joda/core/dist/js-joda.flow.js +949 -0
- package/node_modules/@js-joda/core/dist/js-joda.js +13630 -0
- package/node_modules/@js-joda/core/dist/js-joda.js.map +1 -0
- package/node_modules/@js-joda/core/dist/js-joda.min.js +5 -0
- package/node_modules/@js-joda/core/package.json +76 -0
- package/node_modules/@js-joda/core/src/Clock.js +330 -0
- package/node_modules/@js-joda/core/src/DayOfWeek.js +451 -0
- package/node_modules/@js-joda/core/src/Duration.js +1205 -0
- package/node_modules/@js-joda/core/src/Enum.js +30 -0
- package/node_modules/@js-joda/core/src/Instant.js +1012 -0
- package/node_modules/@js-joda/core/src/LocalDate.js +1703 -0
- package/node_modules/@js-joda/core/src/LocalDateTime.js +1686 -0
- package/node_modules/@js-joda/core/src/LocalTime.js +1415 -0
- package/node_modules/@js-joda/core/src/MathUtil.js +236 -0
- package/node_modules/@js-joda/core/src/Month.js +600 -0
- package/node_modules/@js-joda/core/src/MonthDay.js +730 -0
- package/node_modules/@js-joda/core/src/OffsetDateTime.js +757 -0
- package/node_modules/@js-joda/core/src/OffsetTime.js +621 -0
- package/node_modules/@js-joda/core/src/Period.js +933 -0
- package/node_modules/@js-joda/core/src/StringUtil.js +43 -0
- package/node_modules/@js-joda/core/src/Year.js +1015 -0
- package/node_modules/@js-joda/core/src/YearConstants.js +21 -0
- package/node_modules/@js-joda/core/src/YearMonth.js +1096 -0
- package/node_modules/@js-joda/core/src/ZoneId.js +236 -0
- package/node_modules/@js-joda/core/src/ZoneIdFactory.js +201 -0
- package/node_modules/@js-joda/core/src/ZoneOffset.js +486 -0
- package/node_modules/@js-joda/core/src/ZoneRegion.js +72 -0
- package/node_modules/@js-joda/core/src/ZonedDateTime.js +2007 -0
- package/node_modules/@js-joda/core/src/_init.js +68 -0
- package/node_modules/@js-joda/core/src/assert.js +33 -0
- package/node_modules/@js-joda/core/src/chrono/ChronoLocalDate.js +230 -0
- package/node_modules/@js-joda/core/src/chrono/ChronoLocalDateTime.js +130 -0
- package/node_modules/@js-joda/core/src/chrono/ChronoZonedDateTime.js +194 -0
- package/node_modules/@js-joda/core/src/chrono/IsoChronology.js +235 -0
- package/node_modules/@js-joda/core/src/convert.js +83 -0
- package/node_modules/@js-joda/core/src/errors.js +54 -0
- package/node_modules/@js-joda/core/src/format/DateTimeBuilder.js +535 -0
- package/node_modules/@js-joda/core/src/format/DateTimeFormatter.js +728 -0
- package/node_modules/@js-joda/core/src/format/DateTimeFormatterBuilder.js +1545 -0
- package/node_modules/@js-joda/core/src/format/DateTimeParseContext.js +297 -0
- package/node_modules/@js-joda/core/src/format/DateTimePrintContext.js +138 -0
- package/node_modules/@js-joda/core/src/format/DecimalStyle.js +113 -0
- package/node_modules/@js-joda/core/src/format/EnumMap.js +70 -0
- package/node_modules/@js-joda/core/src/format/ParsePosition.js +31 -0
- package/node_modules/@js-joda/core/src/format/ResolverStyle.js +93 -0
- package/node_modules/@js-joda/core/src/format/SignStyle.js +38 -0
- package/node_modules/@js-joda/core/src/format/StringBuilder.js +47 -0
- package/node_modules/@js-joda/core/src/format/TextStyle.js +114 -0
- package/node_modules/@js-joda/core/src/format/parser/CharLiteralPrinterParser.js +46 -0
- package/node_modules/@js-joda/core/src/format/parser/CompositePrinterParser.js +89 -0
- package/node_modules/@js-joda/core/src/format/parser/FractionPrinterParser.js +162 -0
- package/node_modules/@js-joda/core/src/format/parser/NumberPrinterParser.js +367 -0
- package/node_modules/@js-joda/core/src/format/parser/OffsetIdPrinterParser.js +177 -0
- package/node_modules/@js-joda/core/src/format/parser/PadPrinterParserDecorator.js +81 -0
- package/node_modules/@js-joda/core/src/format/parser/SettingsParser.js +44 -0
- package/node_modules/@js-joda/core/src/format/parser/StringLiteralPrinterParser.js +39 -0
- package/node_modules/@js-joda/core/src/format/parser/ZoneIdPrinterParser.js +218 -0
- package/node_modules/@js-joda/core/src/js-joda.js +210 -0
- package/node_modules/@js-joda/core/src/license-preamble.js +3 -0
- package/node_modules/@js-joda/core/src/temporal/ChronoField.js +470 -0
- package/node_modules/@js-joda/core/src/temporal/ChronoUnit.js +310 -0
- package/node_modules/@js-joda/core/src/temporal/DefaultInterfaceTemporal.js +118 -0
- package/node_modules/@js-joda/core/src/temporal/IsoFields.js +859 -0
- package/node_modules/@js-joda/core/src/temporal/NativeJsTemporal.js +105 -0
- package/node_modules/@js-joda/core/src/temporal/Temporal.js +346 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalAccessor.js +125 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalAdjuster.js +92 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalAdjusters.js +464 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalAmount.js +166 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalField.js +248 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalQueries.js +223 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalQueriesFactory.js +77 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalQuery.js +107 -0
- package/node_modules/@js-joda/core/src/temporal/TemporalUnit.js +179 -0
- package/node_modules/@js-joda/core/src/temporal/ValueRange.js +257 -0
- package/node_modules/@js-joda/core/src/use.js +20 -0
- package/node_modules/@js-joda/core/src/zone/SystemDefaultZoneId.js +31 -0
- package/node_modules/@js-joda/core/src/zone/SystemDefaultZoneRules.js +162 -0
- package/node_modules/@js-joda/core/src/zone/ZoneOffsetTransition.js +289 -0
- package/node_modules/@js-joda/core/src/zone/ZoneRules.js +464 -0
- package/node_modules/@js-joda/core/src/zone/ZoneRulesProvider.js +36 -0
- package/node_modules/@noble/hashes/LICENSE +21 -0
- package/node_modules/@noble/hashes/README.md +563 -0
- package/node_modules/@noble/hashes/_blake.d.ts +21 -0
- package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_blake.js +52 -0
- package/node_modules/@noble/hashes/_blake.js.map +1 -0
- package/node_modules/@noble/hashes/_md.d.ts +99 -0
- package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_md.js +202 -0
- package/node_modules/@noble/hashes/_md.js.map +1 -0
- package/node_modules/@noble/hashes/_u64.d.ts +63 -0
- package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
- package/node_modules/@noble/hashes/_u64.js +84 -0
- package/node_modules/@noble/hashes/_u64.js.map +1 -0
- package/node_modules/@noble/hashes/argon2.d.ts +112 -0
- package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/argon2.js +517 -0
- package/node_modules/@noble/hashes/argon2.js.map +1 -0
- package/node_modules/@noble/hashes/blake1.d.ts +156 -0
- package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake1.js +560 -0
- package/node_modules/@noble/hashes/blake1.js.map +1 -0
- package/node_modules/@noble/hashes/blake2.d.ts +184 -0
- package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake2.js +501 -0
- package/node_modules/@noble/hashes/blake2.js.map +1 -0
- package/node_modules/@noble/hashes/blake3.d.ts +68 -0
- package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/blake3.js +284 -0
- package/node_modules/@noble/hashes/blake3.js.map +1 -0
- package/node_modules/@noble/hashes/eskdf.d.ts +92 -0
- package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/eskdf.js +218 -0
- package/node_modules/@noble/hashes/eskdf.js.map +1 -0
- package/node_modules/@noble/hashes/hkdf.d.ts +64 -0
- package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
- package/node_modules/@noble/hashes/hkdf.js +120 -0
- package/node_modules/@noble/hashes/hkdf.js.map +1 -0
- package/node_modules/@noble/hashes/hmac.d.ts +47 -0
- package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
- package/node_modules/@noble/hashes/hmac.js +93 -0
- package/node_modules/@noble/hashes/hmac.js.map +1 -0
- package/node_modules/@noble/hashes/index.d.ts +2 -0
- package/node_modules/@noble/hashes/index.d.ts.map +1 -0
- package/node_modules/@noble/hashes/index.js +35 -0
- package/node_modules/@noble/hashes/index.js.map +1 -0
- package/node_modules/@noble/hashes/legacy.d.ts +102 -0
- package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
- package/node_modules/@noble/hashes/legacy.js +327 -0
- package/node_modules/@noble/hashes/legacy.js.map +1 -0
- package/node_modules/@noble/hashes/package.json +97 -0
- package/node_modules/@noble/hashes/pbkdf2.d.ts +56 -0
- package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/pbkdf2.js +135 -0
- package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
- package/node_modules/@noble/hashes/scrypt.d.ts +65 -0
- package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
- package/node_modules/@noble/hashes/scrypt.js +257 -0
- package/node_modules/@noble/hashes/scrypt.js.map +1 -0
- package/node_modules/@noble/hashes/sha2.d.ts +249 -0
- package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha2.js +458 -0
- package/node_modules/@noble/hashes/sha2.js.map +1 -0
- package/node_modules/@noble/hashes/sha3-addons.d.ts +461 -0
- package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha3-addons.js +783 -0
- package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
- package/node_modules/@noble/hashes/sha3.d.ts +199 -0
- package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
- package/node_modules/@noble/hashes/sha3.js +431 -0
- package/node_modules/@noble/hashes/sha3.js.map +1 -0
- package/node_modules/@noble/hashes/src/_blake.ts +57 -0
- package/node_modules/@noble/hashes/src/_md.ts +222 -0
- package/node_modules/@noble/hashes/src/_u64.ts +117 -0
- package/node_modules/@noble/hashes/src/argon2.ts +667 -0
- package/node_modules/@noble/hashes/src/blake1.ts +614 -0
- package/node_modules/@noble/hashes/src/blake2.ts +582 -0
- package/node_modules/@noble/hashes/src/blake3.ts +317 -0
- package/node_modules/@noble/hashes/src/eskdf.ts +259 -0
- package/node_modules/@noble/hashes/src/hkdf.ts +133 -0
- package/node_modules/@noble/hashes/src/hmac.ts +126 -0
- package/node_modules/@noble/hashes/src/index.ts +33 -0
- package/node_modules/@noble/hashes/src/legacy.ts +339 -0
- package/node_modules/@noble/hashes/src/pbkdf2.ts +175 -0
- package/node_modules/@noble/hashes/src/scrypt.ts +315 -0
- package/node_modules/@noble/hashes/src/sha2.ts +530 -0
- package/node_modules/@noble/hashes/src/sha3-addons.ts +983 -0
- package/node_modules/@noble/hashes/src/sha3.ts +485 -0
- package/node_modules/@noble/hashes/src/utils.ts +848 -0
- package/node_modules/@noble/hashes/src/webcrypto.ts +239 -0
- package/node_modules/@noble/hashes/utils.d.ts +519 -0
- package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
- package/node_modules/@noble/hashes/utils.js +578 -0
- package/node_modules/@noble/hashes/utils.js.map +1 -0
- package/node_modules/@noble/hashes/webcrypto.d.ts +120 -0
- package/node_modules/@noble/hashes/webcrypto.d.ts.map +1 -0
- package/node_modules/@noble/hashes/webcrypto.js +165 -0
- package/node_modules/@noble/hashes/webcrypto.js.map +1 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +530 -0
- package/node_modules/ws/lib/receiver.js +743 -0
- package/node_modules/ws/lib/sender.js +607 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +562 -0
- package/node_modules/ws/lib/websocket.js +1407 -0
- package/node_modules/ws/package.json +74 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/package.json +53 -0
package/dist/cli/help.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Keep nested parser errors attached to the command whose input was invalid. */
|
|
2
|
+
export function configureHelp(program, examples) {
|
|
3
|
+
let failedCommand = program;
|
|
4
|
+
function visit(command, prefix = '') {
|
|
5
|
+
const path = `${prefix} ${command.name()}`.trim();
|
|
6
|
+
command.exitOverride(error => { failedCommand = command; throw error; });
|
|
7
|
+
if (examples[path])
|
|
8
|
+
command.addHelpText('after', `\nExample:\n ${examples[path]}`);
|
|
9
|
+
for (const argument of command.registeredArguments) {
|
|
10
|
+
if (!argument.description)
|
|
11
|
+
argument.description = {
|
|
12
|
+
address: 'Atto address', destination: 'Recipient Atto address', amount: 'Exact amount (default unit: ATTO)',
|
|
13
|
+
hash: '64-character transaction hash', id: 'Proposal ID', 'request-id': 'Saved payment request ID',
|
|
14
|
+
'address-or-index': 'Atto address or existing saved wallet index',
|
|
15
|
+
event: 'Event type', name: command.parent?.name() === 'labels' ? 'Personal name (1–128 characters after trimming)' : 'Shared operation name', operation: 'Shared operation name; inspect it with atto operations <name>',
|
|
16
|
+
}[argument.name()] ?? argument.name();
|
|
17
|
+
}
|
|
18
|
+
for (const option of command.options) {
|
|
19
|
+
if (option.long === '--unit')
|
|
20
|
+
option.choices(command.name() === 'send' ? ['ATTO', 'RAW', 'USD'] : ['ATTO', 'RAW']);
|
|
21
|
+
if (option.long === '--network')
|
|
22
|
+
option.choices(['LIVE', 'BETA', 'DEV', 'LOCAL']);
|
|
23
|
+
if (option.long === '--access')
|
|
24
|
+
option.choices(['read-only', 'spend']);
|
|
25
|
+
if (option.long === '--status')
|
|
26
|
+
option.choices(['reserved', 'signed', 'published', 'unknown', 'failed']);
|
|
27
|
+
}
|
|
28
|
+
if (command.name() === 'history')
|
|
29
|
+
command.registeredArguments[0]?.choices(['entry', 'transaction']).default('entry');
|
|
30
|
+
if (command.name() === 'watch')
|
|
31
|
+
command.registeredArguments[0]?.choices(['account', 'transaction', 'entry', 'receivable']);
|
|
32
|
+
command.commands.forEach(child => visit(child, path));
|
|
33
|
+
}
|
|
34
|
+
visit(program);
|
|
35
|
+
return () => failedCommand;
|
|
36
|
+
}
|
|
37
|
+
export function commandErrorMessage(error) {
|
|
38
|
+
if (['commander.missingArgument', 'commander.optionMissingArgument', 'commander.missingMandatoryOptionValue'].includes(error.code)) {
|
|
39
|
+
return error.message.replace(/^error: /, '');
|
|
40
|
+
}
|
|
41
|
+
// Other Commander messages can contain supplied values, including secrets.
|
|
42
|
+
return {
|
|
43
|
+
'commander.help': 'Missing subcommand. Choose one of the available commands.',
|
|
44
|
+
'commander.unknownCommand': 'Unknown command.',
|
|
45
|
+
'commander.unknownOption': 'Unknown option.',
|
|
46
|
+
'commander.invalidArgument': 'Invalid argument value. Check the accepted values in this command\'s help.',
|
|
47
|
+
'commander.excessArguments': 'Too many arguments.',
|
|
48
|
+
}[error.code] ?? 'Invalid command arguments.';
|
|
49
|
+
}
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Set this before dynamic imports: Commons' Kotlin logger initializes lazily.
|
|
3
|
+
process.env.KOTLIN_LOGGING_STARTUP_MESSAGE = 'false';
|
|
4
|
+
console.log = console.info = console.debug = console.error.bind(console);
|
|
5
|
+
try {
|
|
6
|
+
const { runCli } = await import('./cli.js');
|
|
7
|
+
await runCli();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
process.stderr.write('Atto could not start. Check runtime, password store, and state directory availability.\n');
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { formatHumanResult } from './output.js';
|
|
2
|
+
export { configureHelp, commandErrorMessage } from './help.js';
|
|
3
|
+
interface ProposalOptions {
|
|
4
|
+
id: string;
|
|
5
|
+
directory?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Deliberately outside the core facade: only local terminal workflows can approve proposals. */
|
|
8
|
+
export declare function approveLimitsProposal({ id, directory }: ProposalOptions): Promise<unknown>;
|
|
9
|
+
export declare function rejectLimitsProposal({ id, directory }: ProposalOptions): Promise<unknown>;
|
|
10
|
+
/** Returns only public host configuration; recovery material is displayed directly on the TTY. */
|
|
11
|
+
export declare function setupMcp({ version, directory }: {
|
|
12
|
+
version: string;
|
|
13
|
+
directory?: string;
|
|
14
|
+
}): Promise<unknown>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { AttoApplication } from '../application/app.js';
|
|
3
|
+
import { amountRaw } from '../domain/amount.js';
|
|
4
|
+
import { AttoError } from '../domain/errors.js';
|
|
5
|
+
import { defaultCliDirectory, dedicatedMcpDirectory, resolveWalletProfile } from '../storage/profiles.js';
|
|
6
|
+
import { hiddenPrompt, requireTerminal, showRecovery, terminalPrompt } from './terminal.js';
|
|
7
|
+
import { formatHumanResult } from './output.js';
|
|
8
|
+
export { formatHumanResult } from './output.js';
|
|
9
|
+
export { configureHelp, commandErrorMessage } from './help.js';
|
|
10
|
+
function display(value) {
|
|
11
|
+
process.stderr.write(formatHumanResult(value));
|
|
12
|
+
}
|
|
13
|
+
async function confirm(prompt) {
|
|
14
|
+
if (await terminalPrompt(prompt) !== 'yes')
|
|
15
|
+
throw new AttoError('CANCELLED', 'No approval was granted.');
|
|
16
|
+
}
|
|
17
|
+
async function choose(prompt) {
|
|
18
|
+
const answer = await terminalPrompt(prompt) || '1';
|
|
19
|
+
if (answer !== '1' && answer !== '2')
|
|
20
|
+
throw new AttoError('INVALID_INPUT', 'Choose 1 or 2.');
|
|
21
|
+
return answer;
|
|
22
|
+
}
|
|
23
|
+
function formatPolicy(policy) {
|
|
24
|
+
const perPayment = policy.perRequest ? `${policy.perRequest.amount} ${policy.perRequest.unit}` : 'Unlimited';
|
|
25
|
+
const rolling = policy.rolling.length
|
|
26
|
+
? policy.rolling.map(rule => `${rule.amount} ${rule.unit} / ${rule.days} day${rule.days === 1 ? '' : 's'}`).join(', ')
|
|
27
|
+
: 'Unlimited';
|
|
28
|
+
return `Per payment: ${perPayment}; rolling: ${rolling}`;
|
|
29
|
+
}
|
|
30
|
+
function showProposal(review) {
|
|
31
|
+
const { proposal } = review;
|
|
32
|
+
process.stderr.write([
|
|
33
|
+
`Wallet: ${review.identity ? JSON.stringify(review.identity.address) : 'Not initialized'}`,
|
|
34
|
+
`Network: ${JSON.stringify(review.network)}`,
|
|
35
|
+
`Profile: ${JSON.stringify(review.directory)}`,
|
|
36
|
+
`Proposal: ${JSON.stringify(proposal.id)} (${proposal.status})`,
|
|
37
|
+
`Expires: ${new Date(proposal.expiresAt).toISOString()}`,
|
|
38
|
+
...(review.mcpAccess !== 'read-only' || proposal.access !== 'read-only' ? [`MCP access: ${review.mcpAccess} → ${proposal.access}`] : []),
|
|
39
|
+
`Current limits: ${formatPolicy(review.policy)}`,
|
|
40
|
+
`Requested limits: ${formatPolicy(proposal.policy)}`,
|
|
41
|
+
`Current pool: indexes ${review.pool.indexes.join(', ')}; consolidation ${review.pool.consolidate ? 'enabled' : 'disabled'}`,
|
|
42
|
+
`Requested pool: indexes ${(proposal.pool ?? review.pool).indexes.join(', ')}; consolidation ${(proposal.pool ?? review.pool).consolidate ? 'enabled' : 'disabled'}`,
|
|
43
|
+
'',
|
|
44
|
+
].join('\n'));
|
|
45
|
+
}
|
|
46
|
+
async function approve(application, id) {
|
|
47
|
+
process.stderr.write('\nReview this exact limits proposal. These spending limits are shared with CLI payments in this profile.\n');
|
|
48
|
+
showProposal(await application.reviewLimitsProposal(id));
|
|
49
|
+
await confirm('Type yes to approve this exact proposal: ');
|
|
50
|
+
return application.approveLimitsProposal(id);
|
|
51
|
+
}
|
|
52
|
+
/** Deliberately outside the core facade: only local terminal workflows can approve proposals. */
|
|
53
|
+
export async function approveLimitsProposal({ id, directory }) {
|
|
54
|
+
requireTerminal();
|
|
55
|
+
const application = new AttoApplication({ directory });
|
|
56
|
+
try {
|
|
57
|
+
return await approve(application, id);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await application.close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function rejectLimitsProposal({ id, directory }) {
|
|
64
|
+
requireTerminal();
|
|
65
|
+
const application = new AttoApplication({ directory });
|
|
66
|
+
try {
|
|
67
|
+
showProposal(await application.reviewLimitsProposal(id));
|
|
68
|
+
await confirm('Type yes to reject this exact proposal: ');
|
|
69
|
+
return await application.rejectLimitsProposal(id);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await application.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function initializeWallet(application, directory) {
|
|
76
|
+
const status = await application.call('wallet_status');
|
|
77
|
+
if (status.initialized) {
|
|
78
|
+
process.stderr.write('This profile already has a wallet. Setup will reuse its funds and spending history.\n');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const method = await choose('Wallet is not initialized. [1] Create a new wallet (default), [2] Import a recovery phrase: ');
|
|
82
|
+
display({ directory, action: method === '1' ? 'Create a new wallet' : 'Import a wallet' });
|
|
83
|
+
await confirm('Type yes to store this wallet in the OS password store: ');
|
|
84
|
+
if (method === '1') {
|
|
85
|
+
await application.createWallet();
|
|
86
|
+
showRecovery(await application.backupMnemonic());
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await application.createWallet(await hiddenPrompt('Recovery phrase (hidden): '));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function boundedPolicy() {
|
|
93
|
+
const perRequest = await terminalPrompt('Maximum ATTO per payment: ');
|
|
94
|
+
amountRaw(perRequest);
|
|
95
|
+
const daily = await terminalPrompt('Maximum ATTO across a rolling 24 hours: ');
|
|
96
|
+
amountRaw(daily);
|
|
97
|
+
return { perRequest: { amount: perRequest, unit: 'ATTO' }, rolling: [{ days: 1, amount: daily, unit: 'ATTO' }] };
|
|
98
|
+
}
|
|
99
|
+
async function configurePool(current) {
|
|
100
|
+
process.stderr.write(`Current payment pool: indexes ${current.indexes.join(', ')}; consolidation ${current.consolidate ? 'enabled' : 'disabled'}.\n`);
|
|
101
|
+
if (await choose('Account pool: [1] Keep current pool (default), [2] Configure account pool: ') === '1')
|
|
102
|
+
return current;
|
|
103
|
+
const input = await terminalPrompt(`Account indexes, separated by commas [${current.indexes.join(',')}]: `) || current.indexes.join(',');
|
|
104
|
+
const indexes = input.split(',').map(value => /^\d+$/.test(value.trim()) ? Number(value.trim()) : NaN);
|
|
105
|
+
process.stderr.write('Consolidation allows automatic payments to move funds between pool accounts when no single account has enough. Explicit source indexes never consolidate. Newly approved indexes are derived but are not activated for automatic receiving.\n');
|
|
106
|
+
const consolidate = await choose('Consolidation: [1] Disabled (default), [2] Enabled: ') === '2';
|
|
107
|
+
return { indexes, consolidate };
|
|
108
|
+
}
|
|
109
|
+
/** Returns only public host configuration; recovery material is displayed directly on the TTY. */
|
|
110
|
+
export async function setupMcp({ version, directory }) {
|
|
111
|
+
requireTerminal();
|
|
112
|
+
process.stderr.write('Atto MCP setup. Recovery phrases stay in your OS password store and this terminal.\n');
|
|
113
|
+
const wallet = await choose('Wallet: [1] Dedicated MCP wallet (default), [2] Existing CLI wallet: ');
|
|
114
|
+
let selected = directory;
|
|
115
|
+
if (!selected && wallet === '2') {
|
|
116
|
+
const defaultDirectory = defaultCliDirectory();
|
|
117
|
+
selected = await terminalPrompt(`CLI wallet directory [${JSON.stringify(defaultDirectory)}]: `) || defaultDirectory;
|
|
118
|
+
}
|
|
119
|
+
const selectedDirectory = resolve(selected ?? dedicatedMcpDirectory());
|
|
120
|
+
if (wallet === '1' && selectedDirectory === resolve(defaultCliDirectory())) {
|
|
121
|
+
throw new AttoError('PROFILE_CONFLICT', 'This is the default CLI wallet directory. Choose the existing CLI wallet option to share it.');
|
|
122
|
+
}
|
|
123
|
+
const profile = resolveWalletProfile(selectedDirectory);
|
|
124
|
+
display({ directory: profile.directory, credentialService: profile.credentialService });
|
|
125
|
+
if (wallet === '2')
|
|
126
|
+
process.stderr.write('This shares funds, payment history, and spending limits with that CLI wallet.\n');
|
|
127
|
+
const application = new AttoApplication({ directory: profile.directory });
|
|
128
|
+
try {
|
|
129
|
+
await initializeWallet(application, profile.directory);
|
|
130
|
+
const usage = await application.call('limits_get');
|
|
131
|
+
const pool = await configurePool(usage.pool);
|
|
132
|
+
process.stderr.write('Read-only can view data, watch events, and propose limits. Bounded spending also permits wallet changes and payments within approved limits.\n');
|
|
133
|
+
const choice = await choose('MCP access: [1] Read-only (default), [2] Bounded spending: ');
|
|
134
|
+
const access = choice === '1' ? 'read-only' : 'spend';
|
|
135
|
+
const policy = access === 'read-only' ? usage.policy : await boundedPolicy();
|
|
136
|
+
const { proposal } = await application.call('limits_propose', { policy, access, pool });
|
|
137
|
+
await approve(application, proposal.id);
|
|
138
|
+
process.stderr.write('\nAdd this public configuration to your MCP client. The explicit data directory preserves your wallet selection.\n');
|
|
139
|
+
return { mcpServers: { atto: { command: 'npx', args: ['--yes', `@attocash/mcp@${version}`, '--data-dir', profile.directory] } } };
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
await application.close();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { modelAddress } from '../labels/presentation.js';
|
|
2
|
+
import { AttoBlock } from '@attocash/commons-core';
|
|
3
|
+
import { amountOutput } from '../domain/amount.js';
|
|
4
|
+
function record(value) {
|
|
5
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
/** Public network data and caller metadata must not control the terminal. */
|
|
8
|
+
function text(value) {
|
|
9
|
+
return String(value).replace(/[\u0000-\u001f\u007f-\u009f\u2028-\u202e\u2066-\u2069]/g, character => `\\u${character.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
10
|
+
}
|
|
11
|
+
function label(key) {
|
|
12
|
+
const names = {
|
|
13
|
+
id: 'ID', requestId: 'Request ID', raw: 'RAW', atto: 'ATTO', usd: 'USD',
|
|
14
|
+
priceUsd: 'Price per ATTO (USD)', nodeUrl: 'Node URL', workerUrl: 'Worker URL',
|
|
15
|
+
mcpAccess: 'Agent access', perRequest: 'Per payment', minReceiveRaw: 'Minimum receive (RAW)',
|
|
16
|
+
weight: 'Weight (RAW)',
|
|
17
|
+
directory: 'Profile', receivingInThisProcess: 'Receiving in this process',
|
|
18
|
+
};
|
|
19
|
+
if (Object.hasOwn(names, key))
|
|
20
|
+
return names[key];
|
|
21
|
+
const words = key.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/_/g, ' ').toLowerCase();
|
|
22
|
+
return text(words.charAt(0).toUpperCase() + words.slice(1));
|
|
23
|
+
}
|
|
24
|
+
function transactionSummary(value) {
|
|
25
|
+
const block = record(value.block) ? value.block : value;
|
|
26
|
+
let hash = value.hash;
|
|
27
|
+
if (!hash && record(value.block)) {
|
|
28
|
+
try {
|
|
29
|
+
hash = AttoBlock.fromJson(JSON.stringify(value.block)).hash.toString();
|
|
30
|
+
}
|
|
31
|
+
catch { /* Partial public results can omit protocol fields. */ }
|
|
32
|
+
}
|
|
33
|
+
return Object.fromEntries(Object.entries({
|
|
34
|
+
type: block.type ?? block.blockType, network: block.network,
|
|
35
|
+
address: modelAddress(block), destination: modelAddress(block, 'receiver'), subject: modelAddress(block, 'subject'),
|
|
36
|
+
representative: modelAddress(block, 'representative'), amount: block.amount,
|
|
37
|
+
balance: block.balance, previousBalance: block.previousBalance,
|
|
38
|
+
height: block.height, timestamp: block.timestamp, hash, sendHash: block.sendHash,
|
|
39
|
+
}).filter(([, value]) => value !== undefined));
|
|
40
|
+
}
|
|
41
|
+
function inline(value, literalKeys) {
|
|
42
|
+
if (value === null || value === undefined)
|
|
43
|
+
return 'None';
|
|
44
|
+
if (typeof value === 'boolean')
|
|
45
|
+
return value ? 'Yes' : 'No';
|
|
46
|
+
if (typeof value !== 'object')
|
|
47
|
+
return text(value);
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
if (!value.length)
|
|
50
|
+
return 'None';
|
|
51
|
+
if (value.every(item => item === null || typeof item !== 'object'))
|
|
52
|
+
return value.map(item => inline(item, literalKeys)).join(', ');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (!Object.keys(value).length)
|
|
56
|
+
return 'None';
|
|
57
|
+
if (!literalKeys && record(value) && Object.keys(value).length === 2
|
|
58
|
+
&& typeof value.atto === 'string' && typeof value.raw === 'string') {
|
|
59
|
+
return `${text(value.atto)} ATTO (${text(value.raw)} RAW)`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
function fields(value, indent = '', literalKeys = false) {
|
|
65
|
+
const short = inline(value, literalKeys);
|
|
66
|
+
if (short !== undefined)
|
|
67
|
+
return [`${indent}${short}`];
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
return value.flatMap((item, index) => [`${indent}${index + 1}.`, ...fields(item, `${indent} `, literalKeys)]);
|
|
70
|
+
}
|
|
71
|
+
const object = value;
|
|
72
|
+
return Object.entries(object).flatMap(([key, value]) => {
|
|
73
|
+
// Serialized journal blocks are recovery/debugging data available in --json.
|
|
74
|
+
if (!literalKeys && ['blockJson', 'signature', 'work', 'addressLabels', 'globalDirectory'].includes(key))
|
|
75
|
+
return [];
|
|
76
|
+
const literal = literalKeys || key === 'metadata';
|
|
77
|
+
// Core monetary fields use RAW unless they include units or an ATTO/RAW pair.
|
|
78
|
+
const raw = ['amount', 'balance', 'previousBalance'].includes(key) && typeof value !== 'object' && !Object.hasOwn(object, 'unit');
|
|
79
|
+
const name = literalKeys ? text(key) : label(key);
|
|
80
|
+
const displayValue = raw && !literal && typeof value === 'string' && /^\d+$/.test(value) ? amountOutput(value) : value;
|
|
81
|
+
const short = value === null && key === 'perRequest' && !literal ? 'Unlimited' : inline(displayValue, literal);
|
|
82
|
+
return short === undefined
|
|
83
|
+
? [`${indent}${name}:`, ...fields(value, `${indent} `, literal)]
|
|
84
|
+
: [`${indent}${name}: ${short}`];
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function addressSummary(value) {
|
|
88
|
+
if (!record(value))
|
|
89
|
+
return value;
|
|
90
|
+
return { index: value.index, address: value.address, active: value.active };
|
|
91
|
+
}
|
|
92
|
+
function receiveProgress(progress) {
|
|
93
|
+
if (progress.event === 'reconnecting') {
|
|
94
|
+
return `Receiving connection interrupted: ${text(progress.error.code)}: ${text(progress.error.message)} Retrying in ${progress.retryInMs / 1000}s.\n`;
|
|
95
|
+
}
|
|
96
|
+
const payment = `${text(progress.amount.atto)} ATTO for account ${text(progress.index)} ${text(progress.address)} (send ${text(progress.sendHash)})`;
|
|
97
|
+
switch (progress.event) {
|
|
98
|
+
case 'pending': return `Pending: ${payment}\n`;
|
|
99
|
+
case 'receiving': return `Receiving: ${payment}\n`;
|
|
100
|
+
case 'received': return `Received: ${payment}\n${progress.receiveHash ? `Receive transaction: ${text(progress.receiveHash)}\n` : ''}`;
|
|
101
|
+
case 'retry': return `Receive delayed: ${payment}\n${text(progress.error.code)}: ${text(progress.error.message)} Retrying in ${progress.retryInMs / 1000}s.\n`;
|
|
102
|
+
case 'skipped': return `Skipped: ${payment}\n${text(progress.error.code)}: ${text(progress.error.message)}\n`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Human presentation belongs to the CLI; engine and MCP results stay intact. */
|
|
106
|
+
function formatUnlabeledHumanResult(result, operation) {
|
|
107
|
+
if (operation === 'receive_progress')
|
|
108
|
+
return receiveProgress(result);
|
|
109
|
+
if (record(result)) {
|
|
110
|
+
if (operation === 'doctor' && Array.isArray(result.checks)) {
|
|
111
|
+
const checks = result.checks.filter(record).map(check => {
|
|
112
|
+
const heading = `[${text(check.status).toUpperCase()}] ${text(check.id)} (${text(check.code)}): ${text(check.message)}`;
|
|
113
|
+
const evidence = record(check.evidence) ? fields(check.evidence, ' ').join('\n') + '\n' : '';
|
|
114
|
+
const remediation = record(check.remediation) ? check.remediation : undefined;
|
|
115
|
+
const steps = Array.isArray(remediation?.steps) ? remediation.steps.map(step => ` ${text(step)}\n`).join('') : '';
|
|
116
|
+
const quoteArgument = (value) => {
|
|
117
|
+
const argument = String(value);
|
|
118
|
+
if (/^[a-z\d_./:@=-]+$/i.test(argument))
|
|
119
|
+
return argument;
|
|
120
|
+
return `'${argument.replace(/'/g, process.platform === 'win32' ? "''" : "'\\''")}'`;
|
|
121
|
+
};
|
|
122
|
+
const command = Array.isArray(remediation?.command)
|
|
123
|
+
? ` Command${process.platform === 'win32' ? ' (PowerShell)' : ''}: ${text(remediation.command.map(quoteArgument).join(' '))}\n` : '';
|
|
124
|
+
const env = record(remediation?.suggestedEnv) ? ` Verified MCP env configuration:\n${fields(remediation.suggestedEnv, ' ', true).join('\n')}\n` : '';
|
|
125
|
+
return `${heading}\n${evidence}${steps}${command}${env}`;
|
|
126
|
+
});
|
|
127
|
+
return `Doctor: ${text(result.status).toUpperCase()}\n${fields(result.context).join('\n')}\n\n${checks.join('\n')}\nCompleted in ${text(result.durationMs)} ms. Diagnostics only; no repairs applied.\n`;
|
|
128
|
+
}
|
|
129
|
+
if (['wallet_create', 'wallet_import'].includes(operation ?? '') && record(result.identity)) {
|
|
130
|
+
return `Wallet ${operation === 'wallet_create' ? 'created' : 'imported'}.\nAddress: ${text(result.identity.address)}\n`;
|
|
131
|
+
}
|
|
132
|
+
if ((operation === 'wallet_status' || operation === 'wallet_receive') && record(result.settings)) {
|
|
133
|
+
const receiver = record(result.autoReceive) ? result.autoReceive : {};
|
|
134
|
+
const values = {
|
|
135
|
+
directory: result.directory,
|
|
136
|
+
status: result.resetPending ? 'Reset unfinished; run wallet reset to finish cleanup' : result.initialized ? 'Initialized' : 'Not initialized',
|
|
137
|
+
address: record(result.identity) ? result.identity.address : null,
|
|
138
|
+
network: result.settings.network,
|
|
139
|
+
automaticReceiving: result.settings.autoReceive ? 'Enabled' : 'Disabled',
|
|
140
|
+
...(operation === 'wallet_status' ? { receivingInThisProcess: receiver.running, lastReceiveError: receiver.lastError } : {}),
|
|
141
|
+
representative: result.settings.representative,
|
|
142
|
+
minReceiveRaw: result.settings.minReceiveRaw,
|
|
143
|
+
nodeUrl: result.settings.nodeUrl,
|
|
144
|
+
workerUrl: result.settings.workerUrl,
|
|
145
|
+
addresses: Array.isArray(result.addresses) ? result.addresses.map(addressSummary) : result.addresses,
|
|
146
|
+
pool: result.pool,
|
|
147
|
+
pendingPayments: result.pendingSends,
|
|
148
|
+
};
|
|
149
|
+
const notice = operation === 'wallet_receive' ? 'Automatic receiving session. Press Ctrl+C to stop.\n' : '';
|
|
150
|
+
return notice + fields(values).join('\n') + '\n';
|
|
151
|
+
}
|
|
152
|
+
if (operation === 'address_list' && Array.isArray(result.addresses)) {
|
|
153
|
+
if (!result.addresses.length)
|
|
154
|
+
return 'No wallet addresses. Create or import a wallet first.\n';
|
|
155
|
+
return fields({ addresses: result.addresses.map(addressSummary) }).join('\n') + '\n';
|
|
156
|
+
}
|
|
157
|
+
if (['address_add', 'address_derive', 'address_activate', 'address_deactivate'].includes(operation ?? '')) {
|
|
158
|
+
return fields(addressSummary(result)).join('\n') + '\n';
|
|
159
|
+
}
|
|
160
|
+
if (['send', 'receive', 'representative_change'].includes(operation ?? '') && record(result.transaction)) {
|
|
161
|
+
const transaction = transactionSummary(result.transaction);
|
|
162
|
+
const summary = {
|
|
163
|
+
status: result.status, requestId: result.requestId, index: result.index,
|
|
164
|
+
amount: result.amount ?? transaction.amount, source: result.sourceAddress ?? transaction.address,
|
|
165
|
+
destination: result.destination ?? transaction.destination, destinationBinding: result.destinationBinding, representative: transaction.representative,
|
|
166
|
+
hash: result.hash, sendHash: transaction.sendHash,
|
|
167
|
+
quote: result.quote, metadata: result.metadata, consolidation: result.consolidation,
|
|
168
|
+
};
|
|
169
|
+
const notice = record(result.quote) ? 'Indicative conversion only; this is not an executable exchange quote.\n' : '';
|
|
170
|
+
return notice + fields(Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== undefined))).join('\n') + '\n';
|
|
171
|
+
}
|
|
172
|
+
if (['labels_get', 'labels_list'].includes(operation ?? '') && record(result.addressLabels)) {
|
|
173
|
+
return fields({ network: result.network, labels: Object.entries(result.addressLabels).map(([address, value]) => ({ address, ...(record(value) ? value : {}) })), directoryStatus: result.globalDirectory }).join('\n') + '\n';
|
|
174
|
+
}
|
|
175
|
+
if (operation === 'account_get') {
|
|
176
|
+
if (!record(result.account))
|
|
177
|
+
return 'Account is not open on the network. Receiving funds opens an account.\n';
|
|
178
|
+
return fields({ ...transactionSummary(result.account), lastTransactionHash: result.account.lastTransactionHash }).join('\n') + '\n';
|
|
179
|
+
}
|
|
180
|
+
if (['transaction_get', 'entry_get'].includes(operation ?? '')) {
|
|
181
|
+
const value = result.transaction ?? result.entry;
|
|
182
|
+
return record(value) ? fields(transactionSummary(value)).join('\n') + '\n' : 'No matching network record found.\n';
|
|
183
|
+
}
|
|
184
|
+
if (operation === 'balances_get' && Array.isArray(result.balances) && !result.balances.length) {
|
|
185
|
+
return 'No matching wallet accounts. Use address add, address activate, or balances --all.\n';
|
|
186
|
+
}
|
|
187
|
+
if (['history_list', 'receivables_list', 'journal_list'].includes(operation ?? '') && Array.isArray(result.items)) {
|
|
188
|
+
const items = operation === 'journal_list' ? result.items : result.items.map(value => record(value) ? transactionSummary(value) : value);
|
|
189
|
+
const body = items.length ? fields({ items }).join('\n') + '\n'
|
|
190
|
+
: operation === 'receivables_list' ? 'No pending payments found during this scan.\n'
|
|
191
|
+
: operation === 'journal_list' ? 'No payment journal records found.\n' : 'No matching account history found.\n';
|
|
192
|
+
return body + (result.timedOut ? 'Scan window ended; results may be incomplete.\n' : '')
|
|
193
|
+
+ (result.limitReached ? 'Record limit reached; more payments may remain.\n' : '')
|
|
194
|
+
+ (result.nextCursor ? `Next cursor: ${text(result.nextCursor)}\n` : '');
|
|
195
|
+
}
|
|
196
|
+
if (operation === 'watch_read' && Array.isArray(result.events)) {
|
|
197
|
+
return fields({ ...result, events: result.events.map(event => record(event)
|
|
198
|
+
? { ...event, data: record(event.data) ? transactionSummary(event.data) : event.data } : event) }).join('\n') + '\n';
|
|
199
|
+
}
|
|
200
|
+
if (operation === 'receive_all' && Array.isArray(result.results)) {
|
|
201
|
+
return `Received ${result.results.length} payment${result.results.length === 1 ? '' : 's'}.\n`
|
|
202
|
+
+ result.results.map(value => formatHumanResult(value, 'receive')).join('')
|
|
203
|
+
+ (result.timedOut || result.limitReached ? `${result.limitReached ? 'Batch limit reached' : 'Scan window ended'}; more payments may remain. Run receive-all again or wallet receive for continuous receiving.\n` : '');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (operation === 'operations' && Array.isArray(result)) {
|
|
207
|
+
return result.map(item => record(item)
|
|
208
|
+
? `${text(item.name)} (${item.readOnly ? 'read-only' : 'write'})\n ${text(item.description)}`
|
|
209
|
+
: text(item)).join('\n') + '\n';
|
|
210
|
+
}
|
|
211
|
+
const indicative = record(result) && (result.informational === true || (record(result.quote) && result.quote.informational === true));
|
|
212
|
+
const notice = indicative ? 'Indicative conversion only; this is not an executable exchange quote.\n' : '';
|
|
213
|
+
return notice + fields(result).join('\n') + '\n';
|
|
214
|
+
}
|
|
215
|
+
/** Render names next to full addresses only at the human-output boundary. */
|
|
216
|
+
export function formatHumanResult(result, operation) {
|
|
217
|
+
const output = formatUnlabeledHumanResult(result, operation);
|
|
218
|
+
if (!record(result) || !record(result.addressLabels))
|
|
219
|
+
return output;
|
|
220
|
+
const dictionary = result.addressLabels;
|
|
221
|
+
return output.replace(/atto:\/\/[a-z2-7]+/g, address => {
|
|
222
|
+
const labels = dictionary[address];
|
|
223
|
+
if (!record(labels))
|
|
224
|
+
return address;
|
|
225
|
+
const binding = record(result.destinationBinding) && result.destinationBinding.address === address ? result.destinationBinding : undefined;
|
|
226
|
+
const personal = binding?.label ?? (record(labels.personal) ? labels.personal.label : undefined);
|
|
227
|
+
const global = Array.isArray(labels.global) ? labels.global.filter(record).map(value => `${text(value.label)} [global${value.stale ? ', stale' : ''}]`) : [];
|
|
228
|
+
const names = [...(personal ? [`${text(personal)} [personal]`] : []), ...global];
|
|
229
|
+
return names.length ? `${address} (${names.join('; ')})` : address;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function requireTerminal(): void;
|
|
2
|
+
/** Public choices and confirmations stay on the terminal; stdout remains machine-readable. */
|
|
3
|
+
export declare function terminalPrompt(prompt: string): Promise<string>;
|
|
4
|
+
/** Recovery input is read in raw mode without echoing or entering shell history. */
|
|
5
|
+
export declare function hiddenPrompt(prompt: string): Promise<string>;
|
|
6
|
+
export declare function showRecovery(mnemonic: string): void;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { emitKeypressEvents } from 'node:readline';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
import { AttoError } from '../domain/errors.js';
|
|
4
|
+
export function requireTerminal() {
|
|
5
|
+
if (!process.stdin.isTTY || !process.stderr.isTTY) {
|
|
6
|
+
throw new AttoError('TERMINAL_REQUIRED', 'This operation requires an interactive terminal.');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Public choices and confirmations stay on the terminal; stdout remains machine-readable. */
|
|
10
|
+
export async function terminalPrompt(prompt) {
|
|
11
|
+
requireTerminal();
|
|
12
|
+
const wasPaused = process.stdin.isPaused();
|
|
13
|
+
const terminal = createInterface({ input: process.stdin, output: process.stderr });
|
|
14
|
+
const controller = new AbortController();
|
|
15
|
+
const cancel = () => controller.abort();
|
|
16
|
+
terminal.once('SIGINT', cancel);
|
|
17
|
+
terminal.once('close', cancel);
|
|
18
|
+
process.once('SIGINT', cancel);
|
|
19
|
+
process.once('SIGTERM', cancel);
|
|
20
|
+
try {
|
|
21
|
+
return (await terminal.question(prompt, { signal: controller.signal })).trim();
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (controller.signal.aborted)
|
|
25
|
+
throw new AttoError('CANCELLED', 'Terminal operation cancelled.');
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
terminal.removeListener('SIGINT', cancel);
|
|
30
|
+
terminal.removeListener('close', cancel);
|
|
31
|
+
process.removeListener('SIGINT', cancel);
|
|
32
|
+
process.removeListener('SIGTERM', cancel);
|
|
33
|
+
terminal.close();
|
|
34
|
+
if (wasPaused)
|
|
35
|
+
process.stdin.pause();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Recovery input is read in raw mode without echoing or entering shell history. */
|
|
39
|
+
export async function hiddenPrompt(prompt) {
|
|
40
|
+
requireTerminal();
|
|
41
|
+
const input = process.stdin;
|
|
42
|
+
const wasRaw = input.isRaw;
|
|
43
|
+
const wasFlowing = input.readableFlowing === true;
|
|
44
|
+
emitKeypressEvents(input);
|
|
45
|
+
process.stderr.write(prompt);
|
|
46
|
+
input.setRawMode(true);
|
|
47
|
+
input.resume();
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
let value = '';
|
|
50
|
+
const cleanup = () => {
|
|
51
|
+
input.removeListener('keypress', onKey);
|
|
52
|
+
process.removeListener('SIGINT', cancel);
|
|
53
|
+
process.removeListener('SIGTERM', cancel);
|
|
54
|
+
input.setRawMode(wasRaw);
|
|
55
|
+
if (!wasFlowing)
|
|
56
|
+
input.pause();
|
|
57
|
+
process.stderr.write('\n');
|
|
58
|
+
};
|
|
59
|
+
const cancel = () => {
|
|
60
|
+
value = '';
|
|
61
|
+
cleanup();
|
|
62
|
+
reject(new AttoError('CANCELLED', 'Wallet import cancelled.'));
|
|
63
|
+
};
|
|
64
|
+
const onKey = (text, key) => {
|
|
65
|
+
if (key.ctrl && (key.name === 'c' || key.name === 'd'))
|
|
66
|
+
return cancel();
|
|
67
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
68
|
+
cleanup();
|
|
69
|
+
const result = value.trim().replace(/\s+/g, ' ');
|
|
70
|
+
value = '';
|
|
71
|
+
resolve(result);
|
|
72
|
+
}
|
|
73
|
+
else if (key.name === 'backspace') {
|
|
74
|
+
value = value.slice(0, -1);
|
|
75
|
+
}
|
|
76
|
+
else if (key.ctrl && key.name === 'u') {
|
|
77
|
+
value = '';
|
|
78
|
+
}
|
|
79
|
+
else if (!key.ctrl && !key.meta && text && !/[\x00-\x1f\x7f]/.test(text)) {
|
|
80
|
+
if (value.length + text.length <= 2048)
|
|
81
|
+
value += text;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
input.on('keypress', onKey);
|
|
85
|
+
process.once('SIGINT', cancel);
|
|
86
|
+
process.once('SIGTERM', cancel);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
export function showRecovery(mnemonic) {
|
|
90
|
+
requireTerminal();
|
|
91
|
+
process.stderr.write(`\nRecovery phrase (keep a private offline copy):\n${mnemonic}\n\n`);
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { refreshUpdateCache } from './updates.js';
|
|
2
|
+
// Bound the entire worker lifetime as well as the HTTP request, including any
|
|
3
|
+
// sockets left open by the HTTP client. This never runs in the wallet process.
|
|
4
|
+
setTimeout(() => process.exit(0), 5000).unref();
|
|
5
|
+
try {
|
|
6
|
+
const file = process.argv[2];
|
|
7
|
+
if (file)
|
|
8
|
+
await refreshUpdateCache(file);
|
|
9
|
+
}
|
|
10
|
+
finally {
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|