@kashdao/cli 0.1.1 → 0.2.1
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/CHANGELOG.md +96 -0
- package/README.md +78 -27
- package/dist/{account-CVJZ3HVT.js → account-QHPOIZ6I.js} +9 -9
- package/dist/{auth-V5WVZBCO.js → auth-TE7BCN5Q.js} +12 -12
- package/dist/{auth-V5WVZBCO.js.map → auth-TE7BCN5Q.js.map} +1 -1
- package/dist/{chunk-MQUJG224.js → chunk-2HFKULGG.js} +2 -2
- package/dist/{chunk-BVFDUI73.js → chunk-2SR77BYA.js} +10 -9
- package/dist/chunk-2SR77BYA.js.map +1 -0
- package/dist/chunk-6QSTFU4R.js +9 -0
- package/dist/{chunk-KAM6KOFD.js.map → chunk-6QSTFU4R.js.map} +1 -1
- package/dist/{chunk-R4NGUZKN.js → chunk-6UU43MF5.js} +5 -3
- package/dist/chunk-6UU43MF5.js.map +1 -0
- package/dist/{chunk-A3IH5HUV.js → chunk-AROIP4EQ.js} +3 -3
- package/dist/chunk-AROIP4EQ.js.map +1 -0
- package/dist/{chunk-QALDZHTX.js → chunk-H2QGFDZP.js} +9 -11
- package/dist/chunk-H2QGFDZP.js.map +1 -0
- package/dist/{chunk-L4AFV2HK.js → chunk-IOLKGV45.js} +3 -3
- package/dist/chunk-IOLKGV45.js.map +1 -0
- package/dist/{chunk-KADB3OKE.js → chunk-VFBQVUL4.js} +2 -2
- package/dist/{chunk-X2VM6VKM.js → chunk-WL7XUYPH.js} +19 -20
- package/dist/chunk-WL7XUYPH.js.map +1 -0
- package/dist/{chunk-N26VGVGB.js → chunk-ZSMI63N3.js} +109 -37
- package/dist/chunk-ZSMI63N3.js.map +1 -0
- package/dist/client-REDY6K7J.js +14 -0
- package/dist/{completion-PK74S3EZ.js → completion-MXTJYK3D.js} +4 -4
- package/dist/{config-T5U6E6KU.js → config-TIJXUJ5N.js} +32 -23
- package/dist/config-TIJXUJ5N.js.map +1 -0
- package/dist/{config-store-UTFDUCKW.js → config-store-INJY4DDT.js} +6 -4
- package/dist/{docs-VA7CJ2ZF.js → docs-M5RZAQ6P.js} +5 -5
- package/dist/{eoa-RL3NLN3H.js → eoa-N55DYIN3.js} +18 -16
- package/dist/eoa-N55DYIN3.js.map +1 -0
- package/dist/{errors-2NNXRNES.js → errors-SMR7X5DU.js} +2 -2
- package/dist/{explain-3SPMWDYX.js → explain-HIDEZVLV.js} +31 -8
- package/dist/explain-HIDEZVLV.js.map +1 -0
- package/dist/{global-options-WFQ6CEFK.js → global-options-YONBFB7N.js} +4 -4
- package/dist/{health-2KD6XUTJ.js → health-LSJKP3NH.js} +9 -9
- package/dist/index.js +31 -28
- package/dist/index.js.map +1 -1
- package/dist/{markets-H6EK2XDE.js → markets-AGL6Q2ES.js} +23 -12
- package/dist/markets-AGL6Q2ES.js.map +1 -0
- package/dist/{output-FGTXXZEQ.js → output-M4NFSWGW.js} +4 -4
- package/dist/{portfolio-R63D5QB2.js → portfolio-RBRVUEYP.js} +11 -11
- package/dist/{portfolio-R63D5QB2.js.map → portfolio-RBRVUEYP.js.map} +1 -1
- package/dist/{protocol-ZB6R25IM.js → protocol-WYQAKN6N.js} +18 -16
- package/dist/protocol-WYQAKN6N.js.map +1 -0
- package/dist/{quote-OF6BTAPQ.js → quote-6CNHU36A.js} +10 -10
- package/dist/redeem-JESSTZ46.js +108 -0
- package/dist/redeem-JESSTZ46.js.map +1 -0
- package/dist/{schema-3HQN4RFL.js → schema-6EXADLRW.js} +12 -8
- package/dist/{schema-3HQN4RFL.js.map → schema-6EXADLRW.js.map} +1 -1
- package/dist/{setup-IIPQXLPL.js → setup-H46GTSVW.js} +8 -8
- package/dist/{trace-WMO3KDHS.js → trace-VDBWWTYL.js} +10 -10
- package/dist/{trade-YBCI6XD2.js → trade-FTSY23QG.js} +10 -10
- package/dist/trade-FTSY23QG.js.map +1 -0
- package/dist/{version-WB2ACHMU.js → version-JTLF3464.js} +7 -7
- package/dist/{version-check-PRAVPFC6.js → version-check-7JGBY6FZ.js} +4 -4
- package/dist/{webhooks-DVS55O4T.js → webhooks-JEWNX5HZ.js} +10 -10
- package/dist/{webhooks-DVS55O4T.js.map → webhooks-JEWNX5HZ.js.map} +1 -1
- package/dist/{with-retry-2MD2CNK2.js → with-retry-DYSHNLG7.js} +12 -6
- package/dist/with-retry-DYSHNLG7.js.map +1 -0
- package/package.json +5 -5
- package/dist/chunk-A3IH5HUV.js.map +0 -1
- package/dist/chunk-BVFDUI73.js.map +0 -1
- package/dist/chunk-KAM6KOFD.js +0 -9
- package/dist/chunk-L4AFV2HK.js.map +0 -1
- package/dist/chunk-N26VGVGB.js.map +0 -1
- package/dist/chunk-QALDZHTX.js.map +0 -1
- package/dist/chunk-R4NGUZKN.js.map +0 -1
- package/dist/chunk-X2VM6VKM.js.map +0 -1
- package/dist/client-75FVHGOH.js +0 -14
- package/dist/config-T5U6E6KU.js.map +0 -1
- package/dist/eoa-RL3NLN3H.js.map +0 -1
- package/dist/explain-3SPMWDYX.js.map +0 -1
- package/dist/markets-H6EK2XDE.js.map +0 -1
- package/dist/protocol-ZB6R25IM.js.map +0 -1
- package/dist/trade-YBCI6XD2.js.map +0 -1
- package/dist/with-retry-2MD2CNK2.js.map +0 -1
- /package/dist/{account-CVJZ3HVT.js.map → account-QHPOIZ6I.js.map} +0 -0
- /package/dist/{chunk-MQUJG224.js.map → chunk-2HFKULGG.js.map} +0 -0
- /package/dist/{chunk-KADB3OKE.js.map → chunk-VFBQVUL4.js.map} +0 -0
- /package/dist/{client-75FVHGOH.js.map → client-REDY6K7J.js.map} +0 -0
- /package/dist/{completion-PK74S3EZ.js.map → completion-MXTJYK3D.js.map} +0 -0
- /package/dist/{config-store-UTFDUCKW.js.map → config-store-INJY4DDT.js.map} +0 -0
- /package/dist/{docs-VA7CJ2ZF.js.map → docs-M5RZAQ6P.js.map} +0 -0
- /package/dist/{errors-2NNXRNES.js.map → errors-SMR7X5DU.js.map} +0 -0
- /package/dist/{global-options-WFQ6CEFK.js.map → global-options-YONBFB7N.js.map} +0 -0
- /package/dist/{health-2KD6XUTJ.js.map → health-LSJKP3NH.js.map} +0 -0
- /package/dist/{output-FGTXXZEQ.js.map → output-M4NFSWGW.js.map} +0 -0
- /package/dist/{quote-OF6BTAPQ.js.map → quote-6CNHU36A.js.map} +0 -0
- /package/dist/{setup-IIPQXLPL.js.map → setup-H46GTSVW.js.map} +0 -0
- /package/dist/{trace-WMO3KDHS.js.map → trace-VDBWWTYL.js.map} +0 -0
- /package/dist/{version-WB2ACHMU.js.map → version-JTLF3464.js.map} +0 -0
- /package/dist/{version-check-PRAVPFC6.js.map → version-check-7JGBY6FZ.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -17,6 +17,102 @@ the test, which surfaces in this changelog.
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [0.2.1] — 2026-10-02
|
|
21
|
+
|
|
22
|
+
**0.2.0 was tagged but never published to npm.** 0.2.1 is its first published
|
|
23
|
+
form: every change listed under 0.2.0 below — including its breaking changes
|
|
24
|
+
and the downgrade note — ships here. It depends on `@kashdao/sdk` 0.2.1 and
|
|
25
|
+
`@kashdao/protocol-sdk` 0.3.2, the first published forms of the SDK releases
|
|
26
|
+
0.2.0 was built against.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **The SDK dependencies are caret ranges in the published package.** 0.1.1
|
|
31
|
+
declared `@kashdao/sdk` and `@kashdao/protocol-sdk` as exact versions
|
|
32
|
+
(`0.1.1`), so an install never picked up an SDK patch (`@kashdao/sdk` 0.1.3
|
|
33
|
+
included) without a new CLI release — while the public mirror's
|
|
34
|
+
`package.json` declares caret ranges. 0.2.1 declares `^0.2.1` and `^0.3.2`
|
|
35
|
+
on npm too, and the publish script now
|
|
36
|
+
packs the tarball once, refuses it unless both ranges are carets on the
|
|
37
|
+
current SDK versions, and uploads that same tarball.
|
|
38
|
+
- The `KASH_CHAIN_ID` refusal names 0.2.1, the first published release that
|
|
39
|
+
replaced it with `KASH_CHAIN`.
|
|
40
|
+
|
|
41
|
+
## [0.2.0] — 2026-10-01
|
|
42
|
+
|
|
43
|
+
Solana is Kash's canonical chain from 2026-10-01. This release makes the CLI
|
|
44
|
+
see it by default. **Breaking** (a `0.x` minor): the config and JSON envelope
|
|
45
|
+
change shape, with an automatic migration for existing config files.
|
|
46
|
+
|
|
47
|
+
**Where Solana visibility comes from:** the API-version pin, not the chain
|
|
48
|
+
setting. The API-backed commands (`kash markets`, `kash quote`, `kash trade`,
|
|
49
|
+
`kash redeem`, `kash portfolio`) see every market the pinned API version
|
|
50
|
+
serves, Solana and Base alike, whatever `defaultChain` says. `defaultChain` is
|
|
51
|
+
**display-only in API mode**; it only selects a chain for `kash protocol` and
|
|
52
|
+
`kash eoa`.
|
|
53
|
+
|
|
54
|
+
**Downgrade note:** a config file rewritten by 0.2.0 (any `kash config set`,
|
|
55
|
+
`kash auth set-key` or `kash config import`) stores `defaultChain` and may
|
|
56
|
+
store `apiVersion`, and 0.1.x's strict config schema rejects both. To go back
|
|
57
|
+
to 0.1.x, remove those keys from `~/.kash/config.json` (and set
|
|
58
|
+
`defaultChainId` if you need it), or run `kash config reset`.
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- **BREAKING: depends on `@kashdao/sdk` 0.2.0**, which pins API version
|
|
63
|
+
`2026-08-19`, and the CLI now always sends the resolved API version. That pin
|
|
64
|
+
is what makes `kash markets list` include Solana markets and `kash markets
|
|
65
|
+
get` / `kash quote` serve them instead of failing with `CHAIN_NOT_SUPPORTED`.
|
|
66
|
+
Pinning `2026-04-29` (`--api-version`, `KASH_API_VERSION` or the profile's
|
|
67
|
+
`apiVersion`) hides them again regardless of `defaultChain`.
|
|
68
|
+
- **BREAKING: `defaultChainId` (number) is replaced by `defaultChain`, a chain
|
|
69
|
+
reference** — `solana:mainnet-beta` (the new default), `solana:devnet`,
|
|
70
|
+
`evm:8453` — the spelling the API returns in `chainRef`. `kash config set
|
|
71
|
+
defaultChain` also accepts a bare numeric EVM chain id (stored as `evm:<n>`)
|
|
72
|
+
and the CAIP-2 `eip155:<n>` spelling, normalised to `evm:`. Existing
|
|
73
|
+
`~/.kash/config.json` files migrate transparently on read (`8453` →
|
|
74
|
+
`evm:8453`) and are rewritten in the new shape on the next write;
|
|
75
|
+
`kash config import` migrates 0.1.x bundles the same way. In API mode the
|
|
76
|
+
value is display-only (shown by `kash config show` / `kash auth status`); it
|
|
77
|
+
selects the chain only for `kash protocol` and `kash eoa`. See the downgrade
|
|
78
|
+
note above before going back to 0.1.x.
|
|
79
|
+
- **BREAKING: `KASH_CHAIN_ID` is replaced by `KASH_CHAIN`** (chain reference or
|
|
80
|
+
numeric EVM id). The CLI refuses to run while `KASH_CHAIN_ID` is set, naming
|
|
81
|
+
the replacement, rather than silently moving a CI job onto the Solana default.
|
|
82
|
+
- **BREAKING: `kash config show --json` and `kash auth status --json`** emit
|
|
83
|
+
`defaultChain` and `apiVersion` in place of `defaultChainId`, and
|
|
84
|
+
`sources.defaultChain` / `sources.apiVersion` in place of
|
|
85
|
+
`sources.defaultChainId`. `CliConfigEnvelopeSchema` is updated to match.
|
|
86
|
+
- `kash markets get` prints the market's chain reference. 0.1.x printed
|
|
87
|
+
`String(market.chainId)`, which read `undefined` for every Solana market.
|
|
88
|
+
`kash markets list` gains a **Chain** column.
|
|
89
|
+
- `kash portfolio show` labels the address **Wallet**: it is a base58 Solana
|
|
90
|
+
wallet for a user whose funds live on Solana.
|
|
91
|
+
- `--outcome` accepts indexes `0`-`99` on every command. Markets carry 2-100
|
|
92
|
+
outcomes; the old `0`-`7` ceiling refused every outcome past the eighth.
|
|
93
|
+
- `kash protocol …` and `kash eoa …` are labelled **EVM/Base only** in their
|
|
94
|
+
help. They are unchanged in behaviour: they run on `defaultChain` when it is
|
|
95
|
+
an `evm:` chain and on Base mainnet otherwise, which is what 0.1.x's
|
|
96
|
+
`defaultChainId: 8453` default did. A `customChain` profile must name an
|
|
97
|
+
`evm:` chain.
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
|
|
101
|
+
- **`kash redeem <marketId> --outcome <i>`** — redeem a settled position
|
|
102
|
+
(`POST /v1/redemptions`), on Solana or Base. Requires the `trades:write`
|
|
103
|
+
scope. Mirrors `kash trade buy|sell`: `--idempotency-key <key>`,
|
|
104
|
+
`--auto-idempotency-key` (generates a UUID v4), and `--dry-run` (prints the
|
|
105
|
+
would-be body, endpoint and key without sending or needing an API key). The
|
|
106
|
+
idempotency key used is printed, and included in `--json` output, so a retry
|
|
107
|
+
can reuse it; with neither flag the SDK keys the request itself.
|
|
108
|
+
`POSITION_NOT_CLAIMABLE` covers both an unredeemable position and a previous
|
|
109
|
+
redemption that failed and must be cleared by support; the message says
|
|
110
|
+
which.
|
|
111
|
+
- **Per-profile `apiVersion`** (`kash config set apiVersion 2026-08-19`) and
|
|
112
|
+
the `KASH_API_VERSION` env var. Precedence: `--api-version` flag, then the
|
|
113
|
+
env var, then the profile, then the SDK's pinned default (`2026-08-19`). The
|
|
114
|
+
resolved version is now always sent; 0.1.x sent none unless the flag was set.
|
|
115
|
+
|
|
20
116
|
## [0.1.1] — 2026-06-18
|
|
21
117
|
|
|
22
118
|
### Changed
|
package/README.md
CHANGED
|
@@ -66,8 +66,13 @@ kash trade buy <market-id> --outcome 0 --amount 10 --wait
|
|
|
66
66
|
> 🚀 **Live on mainnet.** The production API (`api.kash.bot`) is live.
|
|
67
67
|
> Create an API key under **Settings → API Keys** in the
|
|
68
68
|
> [Kash app](https://app.kash.bot): a `kash_live_*` key auto-routes to
|
|
69
|
-
> production (
|
|
70
|
-
> (`api-staging.kash.bot`,
|
|
69
|
+
> production (Solana mainnet), a `kash_test_*` key auto-routes to staging
|
|
70
|
+
> (`api-staging.kash.bot`, Solana devnet) for dry-runs.
|
|
71
|
+
>
|
|
72
|
+
> **Solana is Kash's canonical chain** since 2026-10-01 — every new market is
|
|
73
|
+
> created there. Markets created on Base before the cutover keep trading and
|
|
74
|
+
> resolving on Base, and the API-backed commands serve both. `kash markets get`
|
|
75
|
+
> shows each market's chain (`solana:mainnet-beta`, `evm:8453`).
|
|
71
76
|
|
|
72
77
|
## Install
|
|
73
78
|
|
|
@@ -115,13 +120,16 @@ kash trade buy <market-id> --outcome 0 --amount 10 --wait
|
|
|
115
120
|
# 4. Inspect your portfolio
|
|
116
121
|
kash portfolio show
|
|
117
122
|
kash portfolio positions
|
|
123
|
+
|
|
124
|
+
# 5. Once a market resolves, redeem the winning outcome
|
|
125
|
+
kash redeem <market-id> --outcome 0
|
|
118
126
|
```
|
|
119
127
|
|
|
120
128
|
## Authentication
|
|
121
129
|
|
|
122
130
|
Create an API key under **Settings → API Keys** in the
|
|
123
|
-
[Kash app](https://app.kash.bot) — `kash_live_*` for
|
|
124
|
-
`kash_test_*` for
|
|
131
|
+
[Kash app](https://app.kash.bot) — `kash_live_*` for Solana mainnet or
|
|
132
|
+
`kash_test_*` for Solana devnet — then store it locally with one of:
|
|
125
133
|
|
|
126
134
|
```sh
|
|
127
135
|
# Persisted in ~/.kash/config.json (mode 0600)
|
|
@@ -151,26 +159,27 @@ attribution apply on every request.
|
|
|
151
159
|
|
|
152
160
|
## Commands
|
|
153
161
|
|
|
154
|
-
| Group | Subcommands
|
|
155
|
-
| ------------ |
|
|
156
|
-
| `auth` | `set-key`, `status`, `logout`
|
|
157
|
-
| `markets` | `list`, `get`, `predictions`
|
|
158
|
-
| `quote` | `buy`, `sell` — AMM price quotes (`markets:quote` scope)
|
|
159
|
-
| `trade` | `buy`, `sell`, `status`, `list`, `confirm`
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
162
|
+
| Group | Subcommands |
|
|
163
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
164
|
+
| `auth` | `set-key`, `status`, `logout` |
|
|
165
|
+
| `markets` | `list`, `get`, `predictions` |
|
|
166
|
+
| `quote` | `buy`, `sell` — AMM price quotes (`markets:quote` scope) |
|
|
167
|
+
| `trade` | `buy`, `sell`, `status`, `list`, `confirm` |
|
|
168
|
+
| `redeem` | `<marketId> --outcome <i>` — redeem a settled position (Solana or Base) |
|
|
169
|
+
| `portfolio` | `show`, `positions` |
|
|
170
|
+
| `webhooks` | `list`, `rotate-secret`, `redeliver`, `verify`, `replay` |
|
|
171
|
+
| `protocol` | `balance`, `market`, `quote`, `position`, `allowance`, `smart-account`, `fees`, `token-id`, `decode-revert`, `trade`, `userop`, `watch` — **EVM/Base only** direct mode (ERC-4337) |
|
|
172
|
+
| `eoa` | `balance`, `market`, `quote`, `position`, `allowance`, `fees`, `trade` — **EVM/Base only** direct mode (vanilla EOA, EIP-1559) |
|
|
173
|
+
| `config` | `show`, `set`, `profiles`, `use`, `remove`, `reset`, `export`, `import` |
|
|
174
|
+
| `health` | (top-level; honors `--timeout-ms`, exits 1 when down) |
|
|
175
|
+
| `version` | (top-level; also accepts `--json`) |
|
|
176
|
+
| `explain` | `[codes...]` — error code lookup (multi-code allowed) |
|
|
177
|
+
| `schema` | `[name]` — JSON Schema for SDK + CLI envelopes |
|
|
178
|
+
| `setup` | first-run interactive wizard (auth + verify + completion) |
|
|
179
|
+
| `trace` | `<correlationId>` — curated event timeline for a trade |
|
|
180
|
+
| `with-retry` | `-- <command> [args...]` — retry on recoverable failures |
|
|
181
|
+
| `docs` | full command tree (use `--json` for the agent surface) |
|
|
182
|
+
| `completion` | `install`, `uninstall` |
|
|
174
183
|
|
|
175
184
|
Run `kash <command> --help` for full option reference. Every command's `--help`
|
|
176
185
|
includes worked examples for both human and `--json --quiet` invocations.
|
|
@@ -419,6 +428,13 @@ production-shaped Fastify receiver.
|
|
|
419
428
|
|
|
420
429
|
## Direct mode (`kash protocol …`)
|
|
421
430
|
|
|
431
|
+
> **EVM/Base only.** `kash protocol` and `kash eoa` drive the EVM contracts
|
|
432
|
+
> through ERC-4337 smart accounts or vanilla EOAs, so they serve the Base
|
|
433
|
+
> markets created before the 2026-10-01 Solana cutover. They run on the
|
|
434
|
+
> profile's `defaultChain` when it is an `evm:` chain, and on Base mainnet
|
|
435
|
+
> (`evm:8453`) otherwise. For Solana markets use the API-backed commands
|
|
436
|
+
> (`kash markets`, `kash trade`, `kash redeem`).
|
|
437
|
+
|
|
422
438
|
Direct mode bypasses the Kash backend entirely and talks to the on-chain
|
|
423
439
|
contracts via [`@kashdao/protocol-sdk`](https://www.npmjs.com/package/@kashdao/protocol-sdk). It's for users
|
|
424
440
|
who want to read AMM state, quote trades, or submit UserOps from their
|
|
@@ -507,7 +523,8 @@ transactions (no smart account, no bundler). Same surface as
|
|
|
507
523
|
| `kash eoa fees` | Same as `kash protocol fees`. |
|
|
508
524
|
| `kash eoa trade {buy,sell,close,approve}` | Vanilla tx (no UserOp). |
|
|
509
525
|
|
|
510
|
-
Required config: `rpcUrl`, `
|
|
526
|
+
Required config: `rpcUrl`, `signerKeyRef`, and an `evm:` `defaultChain`
|
|
527
|
+
(Base mainnet when the profile names Solana). EOA mode
|
|
511
528
|
ignores `smartAccount`, `bundlerUrl`, and `bundlerProvider`.
|
|
512
529
|
|
|
513
530
|
```sh
|
|
@@ -561,7 +578,8 @@ kash protocol quote 0xMarket… --side buy --outcome 0 --amount 10 --json
|
|
|
561
578
|
| ----------------- | --------- | ------------------------- | --------------------------------------------------- |
|
|
562
579
|
| `apiKey` | `string?` | unset | Must start with `kash_`. Stored at mode `0600`. |
|
|
563
580
|
| `baseUrl` | `string?` | `https://api.kash.bot/v1` | Validated as a URL. |
|
|
564
|
-
| `
|
|
581
|
+
| `apiVersion` | `string?` | `2026-08-19` | Public-API version pin (`YYYY-MM-DD`). |
|
|
582
|
+
| `defaultChain` | `string?` | `solana:mainnet-beta` | Chain reference — see below. |
|
|
565
583
|
| `rpcUrl` | `string?` | unset | Direct-mode EVM RPC URL. |
|
|
566
584
|
| `smartAccount` | `string?` | unset | Direct-mode smart account address (`0x…`). |
|
|
567
585
|
| `bundlerUrl` | `string?` | unset | ERC-4337 bundler URL (write paths only). |
|
|
@@ -574,7 +592,8 @@ kash protocol quote 0xMarket… --side buy --outcome 0 --amount 10 --json
|
|
|
574
592
|
| ----------------------- | ------------------- | --------------------------------------------------------- |
|
|
575
593
|
| `KASH_API_KEY` | `apiKey` | Highest precedence for the auth key. |
|
|
576
594
|
| `KASH_BASE_URL` | `baseUrl` | |
|
|
577
|
-
| `
|
|
595
|
+
| `KASH_CHAIN` | `defaultChain` | Chain reference, or a numeric EVM chain id. |
|
|
596
|
+
| `KASH_API_VERSION` | `apiVersion` | `YYYY-MM-DD`. `--api-version` overrides it. |
|
|
578
597
|
| `KASH_DEBUG` | (mirrors `--debug`) | Set to `1`/`true`/`yes`/`on` to enable lifecycle traces. |
|
|
579
598
|
| `KASH_RPC_URL` | `rpcUrl` | Direct-mode RPC URL. |
|
|
580
599
|
| `KASH_SMART_ACCOUNT` | `smartAccount` | Direct-mode smart account address. |
|
|
@@ -585,6 +604,38 @@ kash protocol quote 0xMarket… --side buy --outcome 0 --amount 10 --json
|
|
|
585
604
|
| `KASH_CONFIG` | (config path) | Equivalent to `--config <path>`. |
|
|
586
605
|
| `NO_COLOR` | (color output) | Set to anything truthy to disable ANSI escapes. |
|
|
587
606
|
|
|
607
|
+
### Chains and API versions
|
|
608
|
+
|
|
609
|
+
`defaultChain` is a chain reference: `solana:mainnet-beta` (the default),
|
|
610
|
+
`solana:devnet`, or `evm:<chainId>` for an EVM chain (`evm:8453` Base
|
|
611
|
+
mainnet, `evm:84532` Base Sepolia, `evm:31337` Anvil) — the same spelling the
|
|
612
|
+
API returns in `chainRef`. A bare number is accepted as a legacy EVM chain id
|
|
613
|
+
and stored as `evm:<n>`; the CAIP-2 `eip155:<n>` spelling is normalised the
|
|
614
|
+
same way.
|
|
615
|
+
|
|
616
|
+
```sh
|
|
617
|
+
kash config set defaultChain solana:devnet --profile staging
|
|
618
|
+
kash config set defaultChain 84532 --profile mm # stored as evm:84532
|
|
619
|
+
kash config set apiVersion 2026-08-19
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
**Upgrading from 0.1.x:** a profile's numeric `defaultChainId` is read as
|
|
623
|
+
`defaultChain` (`8453` → `evm:8453`) and rewritten in the new shape on the
|
|
624
|
+
next `kash config set`; `kash config import` migrates old bundles the same way.
|
|
625
|
+
`KASH_CHAIN_ID` is no longer read — set `KASH_CHAIN` instead (the CLI refuses
|
|
626
|
+
to run while the old variable is set, rather than silently ignoring it).
|
|
627
|
+
|
|
628
|
+
**Downgrading to 0.1.x:** once 0.2.x has rewritten the file it stores
|
|
629
|
+
`defaultChain` (and possibly `apiVersion`), which 0.1.x rejects. Remove those
|
|
630
|
+
keys from `~/.kash/config.json`, or run `kash config reset`.
|
|
631
|
+
|
|
632
|
+
`apiVersion` defaults to `2026-08-19`, the version that serves Solana markets.
|
|
633
|
+
**That pin — not `defaultChain` — is what makes Solana markets visible**:
|
|
634
|
+
`defaultChain` is display-only for the API-backed commands and selects a chain
|
|
635
|
+
only for `kash protocol` / `kash eoa`. Pinning `2026-04-29` hides Solana
|
|
636
|
+
markets from `kash markets list` and makes `kash markets get` refuse them, so
|
|
637
|
+
only do that for a Base-only workflow.
|
|
638
|
+
|
|
588
639
|
### Resolution order
|
|
589
640
|
|
|
590
641
|
For each field, highest precedence first:
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildClient
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-H2QGFDZP.js";
|
|
5
|
+
import "./chunk-ZSMI63N3.js";
|
|
6
|
+
import "./chunk-2SR77BYA.js";
|
|
7
|
+
import "./chunk-6QSTFU4R.js";
|
|
8
8
|
import {
|
|
9
9
|
readGlobals
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AROIP4EQ.js";
|
|
11
11
|
import {
|
|
12
12
|
print,
|
|
13
13
|
printJson,
|
|
14
14
|
style
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-2HFKULGG.js";
|
|
16
|
+
import "./chunk-VFBQVUL4.js";
|
|
17
17
|
import {
|
|
18
18
|
toCliError
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-WL7XUYPH.js";
|
|
20
20
|
|
|
21
21
|
// src/commands/account/index.ts
|
|
22
22
|
import { Command as Command2 } from "commander";
|
|
@@ -87,4 +87,4 @@ var accountCommand = new Command2("account").description("Read-only account surf
|
|
|
87
87
|
export {
|
|
88
88
|
accountCommand
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=account-
|
|
90
|
+
//# sourceMappingURL=account-QHPOIZ6I.js.map
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
redact
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6UU43MF5.js";
|
|
5
5
|
import {
|
|
6
6
|
clearConfigField,
|
|
7
7
|
readConfig,
|
|
8
8
|
setCurrentProfile,
|
|
9
9
|
updateConfig
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-ZSMI63N3.js";
|
|
11
|
+
import "./chunk-2SR77BYA.js";
|
|
12
12
|
import {
|
|
13
13
|
readGlobals
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-AROIP4EQ.js";
|
|
15
15
|
import {
|
|
16
16
|
log,
|
|
17
17
|
print,
|
|
18
18
|
printJson,
|
|
19
19
|
style
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-2HFKULGG.js";
|
|
21
|
+
import "./chunk-VFBQVUL4.js";
|
|
22
22
|
import {
|
|
23
23
|
CliValidationError,
|
|
24
24
|
toCliError
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-WL7XUYPH.js";
|
|
26
26
|
|
|
27
27
|
// src/commands/auth/index.ts
|
|
28
28
|
import { Command as Command4 } from "commander";
|
|
@@ -195,7 +195,8 @@ Examples:
|
|
|
195
195
|
apiKey: config.apiKey ? redact(config.apiKey) : null,
|
|
196
196
|
profile: config.profile,
|
|
197
197
|
baseUrl: config.baseUrl,
|
|
198
|
-
|
|
198
|
+
apiVersion: config.apiVersion,
|
|
199
|
+
defaultChain: config.defaultChain,
|
|
199
200
|
// Direct-mode fields (`kash protocol …` / `kash eoa …`). Always
|
|
200
201
|
// emitted (`null` when unset) so direct-mode operators can
|
|
201
202
|
// introspect their own profile via JSON without falling back
|
|
@@ -226,9 +227,8 @@ Examples:
|
|
|
226
227
|
print(` ${style.dim("API key ")} ${redact(config.apiKey)} (${config.sources.apiKey})`);
|
|
227
228
|
print(` ${style.dim("Profile ")} ${config.profile} (${config.sources.profile})`);
|
|
228
229
|
print(` ${style.dim("Base URL ")} ${config.baseUrl} (${config.sources.baseUrl})`);
|
|
229
|
-
print(
|
|
230
|
-
|
|
231
|
-
);
|
|
230
|
+
print(` ${style.dim("API ver. ")} ${config.apiVersion} (${config.sources.apiVersion})`);
|
|
231
|
+
print(` ${style.dim("Chain ")} ${config.defaultChain} (${config.sources.defaultChain})`);
|
|
232
232
|
});
|
|
233
233
|
|
|
234
234
|
// src/commands/auth/index.ts
|
|
@@ -236,4 +236,4 @@ var authCommand = new Command4("auth").description("Manage local API credentials
|
|
|
236
236
|
export {
|
|
237
237
|
authCommand
|
|
238
238
|
};
|
|
239
|
-
//# sourceMappingURL=auth-
|
|
239
|
+
//# sourceMappingURL=auth-TE7BCN5Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/auth/index.ts","../src/commands/auth/logout.ts","../src/commands/auth/set-key.ts","../src/commands/auth/status.ts"],"sourcesContent":["/**\n * `kash auth` — credential management.\n *\n * Users issue a key from the Kash dashboard and run `auth set-key`\n * (or set `KASH_API_KEY` in their environment). A future browser-based\n * login flow may be added; for now, key issuance lives on the dashboard.\n */\n\nimport { Command } from 'commander';\n\nimport { logoutCommand } from './logout.js';\nimport { setKeyCommand } from './set-key.js';\nimport { statusCommand } from './status.js';\n\nexport const authCommand = new Command('auth')\n .description('Manage local API credentials.')\n .addCommand(setKeyCommand)\n .addCommand(statusCommand)\n .addCommand(logoutCommand);\n","/**\n * `kash auth logout` — remove the stored API key.\n *\n * Only clears the `apiKey` field; the rest of the config (baseUrl,\n * chain id) survives so logging back in doesn't lose unrelated\n * preferences. If `KASH_API_KEY` is set in the environment, we warn\n * the user that env vars take precedence so the \"logout\" is partial.\n */\n\nimport { Command } from 'commander';\n\nimport { clearConfigField, readConfig } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\nexport const logoutCommand = new Command('logout')\n .description('Remove the stored API key from ~/.kash/config.json.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash auth logout\n $ kash auth logout --profile staging\n`\n )\n .action(async (_opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const scope = {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n };\n const before = await readConfig(scope);\n await clearConfigField('apiKey', scope);\n\n const envWillOverride = Boolean(process.env['KASH_API_KEY']);\n\n if (globals.json) {\n printJson({\n ok: true,\n profile: before.profile,\n cleared: Boolean(before.apiKey && before.sources.apiKey === 'file'),\n envOverride: envWillOverride,\n });\n return;\n }\n\n if (before.apiKey === undefined) {\n log.info(`No API key was stored for profile \"${before.profile}\".`);\n } else {\n log.success(`API key cleared from profile \"${before.profile}\".`);\n }\n if (envWillOverride) {\n log.warn('KASH_API_KEY is still set in your environment. Unset it to fully log out.');\n }\n });\n","/**\n * `kash auth set-key [key]` — store an API key in `~/.kash/config.json`.\n *\n * Three input paths, each leaves no trace of the key in shell history:\n *\n * 1. Positional `<key>` — convenient for one-off use, but shows up\n * in `~/.bash_history`. Kept for backward compat.\n * 2. `--from-stdin` — pipe a key from a secret-store (`pass kash`,\n * `1password read`, `aws secretsmanager`, …). The key is\n * `.trim()`-ed so trailing newlines from the source are ignored.\n * 3. Interactive prompt (no positional, no flag, TTY available) —\n * reads from stderr-bound readline so the prompt doesn't taint\n * stdout pipes. Single newline of input.\n *\n * Validates the prefix client-side (the SDK's config schema enforces\n * the same shape, but failing here gives a clearer error than the\n * generic config error chain). The persisted file is `0600`.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { setCurrentProfile, updateConfig } from '../../utils/config-store.js';\nimport { redact } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\ntype SetKeyOptions = {\n fromStdin?: boolean;\n activate?: boolean;\n};\n\nexport const setKeyCommand = new Command('set-key')\n .description('Store an API key in ~/.kash/config.json (mode 0600).')\n .argument('[key]', 'API key starting with \"kash_\" (omit to read from stdin or prompt)')\n .option('--from-stdin', 'read the key from stdin (preferred for secret-store integration)')\n .option(\n '--activate',\n \"also switch the active profile to the one being written (default: leave the active profile unchanged — `kash auth set-key --profile staging` updates 'staging' but doesn't make it active; pass --activate or run `kash config use staging` separately)\"\n )\n .addHelpText(\n 'after',\n `\nExamples:\n # Interactive prompt (no shell history footprint).\n $ kash auth set-key\n\n # Pipe from a secret store.\n $ pass show kash/api-key | kash auth set-key --from-stdin\n $ op read \"op://Private/kash/api-key\" | kash auth set-key --from-stdin\n\n # Positional (convenient but shows up in ~/.bash_history).\n $ kash auth set-key kash_live_abc...\n $ kash auth set-key kash_test_abc... --profile staging\n`\n )\n .action(async (positional: string | undefined, options: SetKeyOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const key = await resolveKey(positional, options);\n\n if (!key.startsWith('kash_')) {\n throw new CliValidationError(\n 'API keys must start with \"kash_\".',\n 'Create a key under Settings → API Keys at https://app.kash.bot — `kash_live_*` for Base mainnet or `kash_test_*` for Base Sepolia.'\n );\n }\n let result;\n try {\n result = await updateConfig(\n { apiKey: key },\n {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n }\n );\n // `--activate` flips the file's `currentProfile` so the next\n // command picks up this profile without needing\n // `kash config use <name>`. Mirrors the all-in-one wizard\n // behaviour of `kash setup`.\n if (options.activate === true) {\n await setCurrentProfile(\n result.profile,\n globals.configPath === undefined ? undefined : { configPath: globals.configPath }\n );\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n // Surface the actually-written profile (resolved from --profile,\n // KASH_PROFILE, file's currentProfile, or \"default\") so the JSON\n // contract reports truth, not the unresolved flag value.\n printJson({\n ok: true,\n apiKey: redact(key),\n profile: result.profile,\n // Whether this run also flipped the file's currentProfile.\n // Agents driving multi-profile workflows can chain off this\n // to know if a follow-up `kash config use` is needed.\n activated: options.activate === true,\n });\n return;\n }\n log.success(`API key saved to profile \"${result.profile}\" (${redact(key)}).`);\n log.detail('Location', globals.configPath ?? '~/.kash/config.json (mode 0600)');\n if (options.activate === true) {\n log.success(`Active profile is now \"${result.profile}\".`);\n }\n });\n\n/**\n * Resolve the API key from the three supported sources. Order:\n * 1. Positional argument (legacy, less secure — still works).\n * 2. `--from-stdin` (read until EOF, trim, single key per stream).\n * 3. Interactive prompt (TTY only).\n *\n * **Mutual-exclusion guard.** Pre-fix, `kash auth set-key <key>\n * --from-stdin` silently used the positional and dropped the piped\n * secret. That's a real footgun: the operator sees \"API key saved\"\n * for the WRONG key (the one on argv, possibly a stale value from\n * shell history). We refuse to guess and require the operator to\n * pick one source.\n */\nasync function resolveKey(positional: string | undefined, options: SetKeyOptions): Promise<string> {\n if (positional !== undefined && positional !== '' && options.fromStdin === true) {\n throw new CliValidationError(\n 'Pass either the positional <key> OR --from-stdin, not both.',\n 'The positional key would silently win and the piped value would be dropped.'\n );\n }\n if (positional !== undefined && positional !== '') {\n return positional;\n }\n if (options.fromStdin === true) {\n return readFromStdin();\n }\n if (process.stdin.isTTY) {\n return promptInteractively();\n }\n // No positional, no --from-stdin, no TTY — caller's intent is\n // ambiguous. Surface a clear validation error rather than reading\n // stdin silently (which would surprise CI runs that pipe other\n // data into the command).\n throw new CliValidationError(\n 'No API key provided.',\n 'Pass the key positionally, use --from-stdin to read it from a pipe, or run interactively for a prompt.'\n );\n}\n\nasync function readFromStdin(): Promise<string> {\n // Use the shared BOM-aware reader. Notepad-saved files (and VSCode\n // with `files.encoding=utf8bom`) prepend U+FEFF; without the strip,\n // the leading three bytes leak into the API key and fail the\n // `kash_` prefix check.\n const { readStdinTrimmed } = await import('../../utils/stdin.js');\n return readStdinTrimmed();\n}\n\nasync function promptInteractively(): Promise<string> {\n // Use the masked-input prompt so the key never echoes to the\n // terminal (defends against shoulder-surfing, screen recordings,\n // and scroll-back capture). The previous `readline.question` path\n // echoed every keystroke which defeated the \"no shell history\"\n // promise of this command. Lazy-load `@inquirer/prompts` to keep\n // it off the cold path for non-interactive invocations.\n const { password } = await import('@inquirer/prompts');\n const answer = await password({\n message: 'Paste your API key (kash_live_… or kash_test_…):',\n mask: '*',\n });\n return answer.trim();\n}\n","/**\n * `kash auth status` — report the locally-stored credentials.\n *\n * Does NOT call the API. There is no `whoami` endpoint on the public\n * API today (the only auth-flavoured route is webhook-secret rotation,\n * which is a write). Reporting purely-local state keeps the command\n * cheap and side-effect-free; the moment the user issues a real call\n * (e.g. `kash markets list`) the SDK raises `KashAuthenticationError`\n * if the key is invalid.\n */\n\nimport { Command } from 'commander';\n\nimport { readConfig } from '../../utils/config-store.js';\nimport { redact } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\n\nexport const statusCommand = new Command('status')\n .description('Show locally-configured credentials. Does not call the API.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash auth status\n $ kash auth status --profile prod\n $ kash auth status --json --quiet | jq -r '.apiKey'\n`\n )\n .action(async (_opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const config = await readConfig({\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n if (globals.json) {\n printJson({\n // Pure local-state field. `true` means \"an API key is in\n // scope for this profile\" (file or env), NOT \"this key is\n // accepted by the server\" — `kash auth status` is offline by\n // design. Use `kash health --json --quiet | jq .ok` for a\n // server-side check.\n configured: Boolean(config.apiKey),\n // Backward-compat alias. Same value as `configured`. Kept\n // for downstream scripts that pin to the old field name —\n // will be removed in a major bump after the rename has\n // burned in.\n authenticated: Boolean(config.apiKey),\n apiKey: config.apiKey ? redact(config.apiKey) : null,\n profile: config.profile,\n baseUrl: config.baseUrl,\n defaultChainId: config.defaultChainId,\n // Direct-mode fields (`kash protocol …` / `kash eoa …`). Always\n // emitted (`null` when unset) so direct-mode operators can\n // introspect their own profile via JSON without falling back\n // to reading `~/.kash/config.json` directly. The signerKeyRef\n // is the reference shape (`file:<path>` / `env:<NAME>`),\n // never the raw private key — the CLI never persists keys.\n rpcUrl: config.rpcUrl ?? null,\n smartAccount: config.smartAccount ?? null,\n bundlerUrl: config.bundlerUrl ?? null,\n bundlerProvider: config.bundlerProvider ?? null,\n signerKeyRef: config.signerKeyRef ?? null,\n sources: config.sources,\n });\n return;\n }\n\n if (!config.apiKey) {\n log.warn(`No API key configured for profile \"${config.profile}\".`);\n log.detail(\n 'Hint',\n \"Run 'kash setup' for the wizard, or 'kash auth set-key' for the bare key. Or set KASH_API_KEY.\"\n );\n return;\n }\n\n print(`${style.success('✓')} API key configured (profile: ${config.profile})`);\n print(\n ` ${style.dim('Note ')} not verified against the server — run \\`kash health\\` to probe`\n );\n print(` ${style.dim('API key ')} ${redact(config.apiKey)} (${config.sources.apiKey})`);\n print(` ${style.dim('Profile ')} ${config.profile} (${config.sources.profile})`);\n print(` ${style.dim('Base URL ')} ${config.baseUrl} (${config.sources.baseUrl})`);\n print(\n ` ${style.dim('Chain id ')} ${String(config.defaultChainId)} (${config.sources.defaultChainId})`\n );\n });\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/auth/index.ts","../src/commands/auth/logout.ts","../src/commands/auth/set-key.ts","../src/commands/auth/status.ts"],"sourcesContent":["/**\n * `kash auth` — credential management.\n *\n * Users issue a key from the Kash dashboard and run `auth set-key`\n * (or set `KASH_API_KEY` in their environment). A future browser-based\n * login flow may be added; for now, key issuance lives on the dashboard.\n */\n\nimport { Command } from 'commander';\n\nimport { logoutCommand } from './logout.js';\nimport { setKeyCommand } from './set-key.js';\nimport { statusCommand } from './status.js';\n\nexport const authCommand = new Command('auth')\n .description('Manage local API credentials.')\n .addCommand(setKeyCommand)\n .addCommand(statusCommand)\n .addCommand(logoutCommand);\n","/**\n * `kash auth logout` — remove the stored API key.\n *\n * Only clears the `apiKey` field; the rest of the config (baseUrl,\n * chain id) survives so logging back in doesn't lose unrelated\n * preferences. If `KASH_API_KEY` is set in the environment, we warn\n * the user that env vars take precedence so the \"logout\" is partial.\n */\n\nimport { Command } from 'commander';\n\nimport { clearConfigField, readConfig } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\nexport const logoutCommand = new Command('logout')\n .description('Remove the stored API key from ~/.kash/config.json.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash auth logout\n $ kash auth logout --profile staging\n`\n )\n .action(async (_opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const scope = {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n };\n const before = await readConfig(scope);\n await clearConfigField('apiKey', scope);\n\n const envWillOverride = Boolean(process.env['KASH_API_KEY']);\n\n if (globals.json) {\n printJson({\n ok: true,\n profile: before.profile,\n cleared: Boolean(before.apiKey && before.sources.apiKey === 'file'),\n envOverride: envWillOverride,\n });\n return;\n }\n\n if (before.apiKey === undefined) {\n log.info(`No API key was stored for profile \"${before.profile}\".`);\n } else {\n log.success(`API key cleared from profile \"${before.profile}\".`);\n }\n if (envWillOverride) {\n log.warn('KASH_API_KEY is still set in your environment. Unset it to fully log out.');\n }\n });\n","/**\n * `kash auth set-key [key]` — store an API key in `~/.kash/config.json`.\n *\n * Three input paths, each leaves no trace of the key in shell history:\n *\n * 1. Positional `<key>` — convenient for one-off use, but shows up\n * in `~/.bash_history`. Kept for backward compat.\n * 2. `--from-stdin` — pipe a key from a secret-store (`pass kash`,\n * `1password read`, `aws secretsmanager`, …). The key is\n * `.trim()`-ed so trailing newlines from the source are ignored.\n * 3. Interactive prompt (no positional, no flag, TTY available) —\n * reads from stderr-bound readline so the prompt doesn't taint\n * stdout pipes. Single newline of input.\n *\n * Validates the prefix client-side (the SDK's config schema enforces\n * the same shape, but failing here gives a clearer error than the\n * generic config error chain). The persisted file is `0600`.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { setCurrentProfile, updateConfig } from '../../utils/config-store.js';\nimport { redact } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\ntype SetKeyOptions = {\n fromStdin?: boolean;\n activate?: boolean;\n};\n\nexport const setKeyCommand = new Command('set-key')\n .description('Store an API key in ~/.kash/config.json (mode 0600).')\n .argument('[key]', 'API key starting with \"kash_\" (omit to read from stdin or prompt)')\n .option('--from-stdin', 'read the key from stdin (preferred for secret-store integration)')\n .option(\n '--activate',\n \"also switch the active profile to the one being written (default: leave the active profile unchanged — `kash auth set-key --profile staging` updates 'staging' but doesn't make it active; pass --activate or run `kash config use staging` separately)\"\n )\n .addHelpText(\n 'after',\n `\nExamples:\n # Interactive prompt (no shell history footprint).\n $ kash auth set-key\n\n # Pipe from a secret store.\n $ pass show kash/api-key | kash auth set-key --from-stdin\n $ op read \"op://Private/kash/api-key\" | kash auth set-key --from-stdin\n\n # Positional (convenient but shows up in ~/.bash_history).\n $ kash auth set-key kash_live_abc...\n $ kash auth set-key kash_test_abc... --profile staging\n`\n )\n .action(async (positional: string | undefined, options: SetKeyOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const key = await resolveKey(positional, options);\n\n if (!key.startsWith('kash_')) {\n throw new CliValidationError(\n 'API keys must start with \"kash_\".',\n 'Create a key under Settings → API Keys at https://app.kash.bot — `kash_live_*` for Base mainnet or `kash_test_*` for Base Sepolia.'\n );\n }\n let result;\n try {\n result = await updateConfig(\n { apiKey: key },\n {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n }\n );\n // `--activate` flips the file's `currentProfile` so the next\n // command picks up this profile without needing\n // `kash config use <name>`. Mirrors the all-in-one wizard\n // behaviour of `kash setup`.\n if (options.activate === true) {\n await setCurrentProfile(\n result.profile,\n globals.configPath === undefined ? undefined : { configPath: globals.configPath }\n );\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n // Surface the actually-written profile (resolved from --profile,\n // KASH_PROFILE, file's currentProfile, or \"default\") so the JSON\n // contract reports truth, not the unresolved flag value.\n printJson({\n ok: true,\n apiKey: redact(key),\n profile: result.profile,\n // Whether this run also flipped the file's currentProfile.\n // Agents driving multi-profile workflows can chain off this\n // to know if a follow-up `kash config use` is needed.\n activated: options.activate === true,\n });\n return;\n }\n log.success(`API key saved to profile \"${result.profile}\" (${redact(key)}).`);\n log.detail('Location', globals.configPath ?? '~/.kash/config.json (mode 0600)');\n if (options.activate === true) {\n log.success(`Active profile is now \"${result.profile}\".`);\n }\n });\n\n/**\n * Resolve the API key from the three supported sources. Order:\n * 1. Positional argument (legacy, less secure — still works).\n * 2. `--from-stdin` (read until EOF, trim, single key per stream).\n * 3. Interactive prompt (TTY only).\n *\n * **Mutual-exclusion guard.** Pre-fix, `kash auth set-key <key>\n * --from-stdin` silently used the positional and dropped the piped\n * secret. That's a real footgun: the operator sees \"API key saved\"\n * for the WRONG key (the one on argv, possibly a stale value from\n * shell history). We refuse to guess and require the operator to\n * pick one source.\n */\nasync function resolveKey(positional: string | undefined, options: SetKeyOptions): Promise<string> {\n if (positional !== undefined && positional !== '' && options.fromStdin === true) {\n throw new CliValidationError(\n 'Pass either the positional <key> OR --from-stdin, not both.',\n 'The positional key would silently win and the piped value would be dropped.'\n );\n }\n if (positional !== undefined && positional !== '') {\n return positional;\n }\n if (options.fromStdin === true) {\n return readFromStdin();\n }\n if (process.stdin.isTTY) {\n return promptInteractively();\n }\n // No positional, no --from-stdin, no TTY — caller's intent is\n // ambiguous. Surface a clear validation error rather than reading\n // stdin silently (which would surprise CI runs that pipe other\n // data into the command).\n throw new CliValidationError(\n 'No API key provided.',\n 'Pass the key positionally, use --from-stdin to read it from a pipe, or run interactively for a prompt.'\n );\n}\n\nasync function readFromStdin(): Promise<string> {\n // Use the shared BOM-aware reader. Notepad-saved files (and VSCode\n // with `files.encoding=utf8bom`) prepend U+FEFF; without the strip,\n // the leading three bytes leak into the API key and fail the\n // `kash_` prefix check.\n const { readStdinTrimmed } = await import('../../utils/stdin.js');\n return readStdinTrimmed();\n}\n\nasync function promptInteractively(): Promise<string> {\n // Use the masked-input prompt so the key never echoes to the\n // terminal (defends against shoulder-surfing, screen recordings,\n // and scroll-back capture). The previous `readline.question` path\n // echoed every keystroke which defeated the \"no shell history\"\n // promise of this command. Lazy-load `@inquirer/prompts` to keep\n // it off the cold path for non-interactive invocations.\n const { password } = await import('@inquirer/prompts');\n const answer = await password({\n message: 'Paste your API key (kash_live_… or kash_test_…):',\n mask: '*',\n });\n return answer.trim();\n}\n","/**\n * `kash auth status` — report the locally-stored credentials.\n *\n * Does NOT call the API. There is no `whoami` endpoint on the public\n * API today (the only auth-flavoured route is webhook-secret rotation,\n * which is a write). Reporting purely-local state keeps the command\n * cheap and side-effect-free; the moment the user issues a real call\n * (e.g. `kash markets list`) the SDK raises `KashAuthenticationError`\n * if the key is invalid.\n */\n\nimport { Command } from 'commander';\n\nimport { readConfig } from '../../utils/config-store.js';\nimport { redact } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\n\nexport const statusCommand = new Command('status')\n .description('Show locally-configured credentials. Does not call the API.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash auth status\n $ kash auth status --profile prod\n $ kash auth status --json --quiet | jq -r '.apiKey'\n`\n )\n .action(async (_opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const config = await readConfig({\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n if (globals.json) {\n printJson({\n // Pure local-state field. `true` means \"an API key is in\n // scope for this profile\" (file or env), NOT \"this key is\n // accepted by the server\" — `kash auth status` is offline by\n // design. Use `kash health --json --quiet | jq .ok` for a\n // server-side check.\n configured: Boolean(config.apiKey),\n // Backward-compat alias. Same value as `configured`. Kept\n // for downstream scripts that pin to the old field name —\n // will be removed in a major bump after the rename has\n // burned in.\n authenticated: Boolean(config.apiKey),\n apiKey: config.apiKey ? redact(config.apiKey) : null,\n profile: config.profile,\n baseUrl: config.baseUrl,\n apiVersion: config.apiVersion,\n defaultChain: config.defaultChain,\n // Direct-mode fields (`kash protocol …` / `kash eoa …`). Always\n // emitted (`null` when unset) so direct-mode operators can\n // introspect their own profile via JSON without falling back\n // to reading `~/.kash/config.json` directly. The signerKeyRef\n // is the reference shape (`file:<path>` / `env:<NAME>`),\n // never the raw private key — the CLI never persists keys.\n rpcUrl: config.rpcUrl ?? null,\n smartAccount: config.smartAccount ?? null,\n bundlerUrl: config.bundlerUrl ?? null,\n bundlerProvider: config.bundlerProvider ?? null,\n signerKeyRef: config.signerKeyRef ?? null,\n sources: config.sources,\n });\n return;\n }\n\n if (!config.apiKey) {\n log.warn(`No API key configured for profile \"${config.profile}\".`);\n log.detail(\n 'Hint',\n \"Run 'kash setup' for the wizard, or 'kash auth set-key' for the bare key. Or set KASH_API_KEY.\"\n );\n return;\n }\n\n print(`${style.success('✓')} API key configured (profile: ${config.profile})`);\n print(\n ` ${style.dim('Note ')} not verified against the server — run \\`kash health\\` to probe`\n );\n print(` ${style.dim('API key ')} ${redact(config.apiKey)} (${config.sources.apiKey})`);\n print(` ${style.dim('Profile ')} ${config.profile} (${config.sources.profile})`);\n print(` ${style.dim('Base URL ')} ${config.baseUrl} (${config.sources.baseUrl})`);\n print(` ${style.dim('API ver. ')} ${config.apiVersion} (${config.sources.apiVersion})`);\n print(` ${style.dim('Chain ')} ${config.defaultChain} (${config.sources.defaultChain})`);\n });\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
applyFilter,
|
|
4
4
|
projectFields
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VFBQVUL4.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/output.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -91,4 +91,4 @@ export {
|
|
|
91
91
|
isQuiet,
|
|
92
92
|
writeNdjson
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
94
|
+
//# sourceMappingURL=chunk-2HFKULGG.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CliValidationError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WL7XUYPH.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/trade-input.ts
|
|
7
|
+
import { MAX_UINT256 } from "@kashdao/protocol-sdk";
|
|
7
8
|
var HEX_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
|
|
8
9
|
var HEX_HASH_REGEX = /^0x[0-9a-fA-F]{64}$/;
|
|
9
10
|
var BIGINT_STRING_REGEX = /^\d+$/;
|
|
10
11
|
var USDC_DECIMAL_REGEX = /^\d+(\.\d{1,6})?$/;
|
|
11
12
|
var DEFAULT_SLIPPAGE_BPS = 50;
|
|
12
|
-
var MAX_UINT256 = 2n ** 256n - 1n;
|
|
13
13
|
function validateAddress(value, field) {
|
|
14
14
|
if (!HEX_ADDRESS_REGEX.test(value)) {
|
|
15
15
|
throw new CliValidationError(
|
|
@@ -24,22 +24,23 @@ function validateAddressOptional(value, field) {
|
|
|
24
24
|
return value === void 0 ? void 0 : validateAddress(value, field);
|
|
25
25
|
}
|
|
26
26
|
var UNSIGNED_INT_REGEX = /^\+?\d+$/;
|
|
27
|
+
var MAX_OUTCOME_INDEX = 99;
|
|
27
28
|
function parseOutcomeIndex(raw) {
|
|
28
29
|
if (raw === void 0) {
|
|
29
30
|
throw new CliValidationError("--outcome is required.", void 0, "outcome");
|
|
30
31
|
}
|
|
31
32
|
if (!UNSIGNED_INT_REGEX.test(raw)) {
|
|
32
33
|
throw new CliValidationError(
|
|
33
|
-
|
|
34
|
+
`--outcome must be an integer between 0 and ${MAX_OUTCOME_INDEX}.`,
|
|
34
35
|
`Got "${raw}". Pass digits only \u2014 no decimals (\`1.5\` would silently round to 1) or scientific notation.`,
|
|
35
36
|
"outcome"
|
|
36
37
|
);
|
|
37
38
|
}
|
|
38
39
|
const n = Number.parseInt(raw, 10);
|
|
39
|
-
if (!Number.isFinite(n) || n < 0 || n >
|
|
40
|
+
if (!Number.isFinite(n) || n < 0 || n > MAX_OUTCOME_INDEX) {
|
|
40
41
|
throw new CliValidationError(
|
|
41
|
-
|
|
42
|
-
"Markets carry 2-
|
|
42
|
+
`--outcome must be an integer between 0 and ${MAX_OUTCOME_INDEX}.`,
|
|
43
|
+
"Markets carry 2-100 outcomes; the index is 0-based.",
|
|
43
44
|
"outcome"
|
|
44
45
|
);
|
|
45
46
|
}
|
|
@@ -144,7 +145,6 @@ export {
|
|
|
144
145
|
BIGINT_STRING_REGEX,
|
|
145
146
|
USDC_DECIMAL_REGEX,
|
|
146
147
|
DEFAULT_SLIPPAGE_BPS,
|
|
147
|
-
MAX_UINT256,
|
|
148
148
|
validateAddress,
|
|
149
149
|
validateAddressOptional,
|
|
150
150
|
parseOutcomeIndex,
|
|
@@ -154,6 +154,7 @@ export {
|
|
|
154
154
|
validateUsdcDecimalShape,
|
|
155
155
|
extractPartialHash,
|
|
156
156
|
decimalToAtomicUsdc,
|
|
157
|
-
decimalToAtomicWad
|
|
157
|
+
decimalToAtomicWad,
|
|
158
|
+
MAX_UINT256
|
|
158
159
|
};
|
|
159
|
-
//# sourceMappingURL=chunk-
|
|
160
|
+
//# sourceMappingURL=chunk-2SR77BYA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/trade-input.ts"],"sourcesContent":["/**\n * Shared input parsers for every trade-execution command.\n *\n * Three modes share these primitives:\n *\n * - SA mode (`kash protocol trade …`, `kash protocol userop build …`)\n * — converts to atomic units (bigint) for the protocol-sdk.\n * - EOA mode (`kash eoa trade …`) — same atomic-unit conversion.\n * - Public-API mode (`kash trade buy/sell`) — ships the raw string\n * to the hosted-API SDK, so it uses the shape validators\n * (`validateUsdcDecimalShape`, `parseOutcomeIndex`) rather than\n * the atomic-unit converters.\n *\n * Centralising the parsers eliminates three sources of drift:\n *\n * 1. **Validation messages** — the same flag should produce the\n * same error wording regardless of mode.\n * 2. **Bounds** — slippage caps, outcome-index ceilings, USDC\n * decimal precision must be identical across modes (otherwise\n * operators get different errors for the same value).\n * 3. **Real-money correctness** — these inputs feed the SDK's\n * atomic-unit math (or the API's server-side conversion); one\n * drift between modes would silently change a trade's effective\n * amount.\n */\n\nimport { CliValidationError } from '../errors.js';\n\n/** Standard 0x-prefixed 40-char EVM address. */\nexport const HEX_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;\n/** 32-byte hash (UserOp hashes, tx hashes). */\nexport const HEX_HASH_REGEX = /^0x[0-9a-fA-F]{64}$/;\n/**\n * Stringified non-negative bigint (canonical decimal). Used by Zod\n * envelopes that must round-trip a `bigint` field through JSON without\n * losing precision — the wire shape is \"every digit, no scientific\n * notation, no leading sign\". Single source of truth so the SA-mode\n * direct-client envelopes (`OnChainBalanceSchema`, `MarketStateSchema`,\n * `QuoteSchema`) can't drift on what counts as a valid encoding.\n */\nexport const BIGINT_STRING_REGEX = /^\\d+$/;\n/**\n * Human USDC decimal: whole digits with up to 6 fractional digits.\n * Backs both the `validateUsdcDecimalShape` runtime check and the\n * `kash trade buy/sell --dry-run --json` envelope schema, so the\n * runtime parser and the JSON contract can't disagree on what\n * counts as a valid amount.\n */\nexport const USDC_DECIMAL_REGEX = /^\\d+(\\.\\d{1,6})?$/;\n\n/** Default slippage tolerance in basis points (50 = 0.5%). */\nexport const DEFAULT_SLIPPAGE_BPS = 50;\n/**\n * ERC-20's `MAX_UINT256` — sentinel for \"infinite\" approval.\n *\n * Re-exported from `@kashdao/protocol-sdk` rather than re-declared: the CLI\n * builds the approvals that SDK encodes, so the two cannot be allowed to hold\n * separate copies of the sentinel they compare against.\n */\nexport { MAX_UINT256 } from '@kashdao/protocol-sdk';\n\n/**\n * Validate a market / spender / account address. Throws\n * `INVALID_INPUT` with the supplied field name (so the structured\n * error envelope's `check_input` action points at the right flag).\n */\nexport function validateAddress(value: string, field: string): `0x${string}` {\n if (!HEX_ADDRESS_REGEX.test(value)) {\n throw new CliValidationError(\n `<${field}> must be a 0x-prefixed 40-char hex address.`,\n `Got \"${value}\".`,\n field\n );\n }\n return value as `0x${string}`;\n}\n\n/**\n * Optional variant of {@link validateAddress}. Returns `undefined`\n * when the input is `undefined` (the common \"default to active\n * profile's account\" pattern); otherwise validates and returns the\n * narrowed type.\n */\nexport function validateAddressOptional(\n value: string | undefined,\n field: string\n): `0x${string}` | undefined {\n return value === undefined ? undefined : validateAddress(value, field);\n}\n\n/**\n * Strict-shape regex for unsigned integer flag values. Bare digits\n * only (with optional leading `+`). Anything else — `1.5`, `1e3`,\n * `0x10`, ` 42`, `42 `, `1 2` — must be rejected.\n *\n * Plain `Number.parseInt('1.5', 10)` returns `1` and\n * `Number.parseInt('1e3', 10)` returns `1` too. Both are silent\n * precision losses on inputs that look like real-money typos:\n * - `--outcome 1.5` would buy outcome 1 (wrong outcome).\n * - `--slippage-bps 1e3` would use 1 bps instead of 1000 (10%\n * slippage clipped to 0.01% — catastrophic).\n *\n * Every flag-parser in this module that consumes integers MUST\n * gate its `Number.parseInt` call on this regex.\n */\nconst UNSIGNED_INT_REGEX = /^\\+?\\d+$/;\n\n/**\n * Highest valid 0-based outcome index. Markets carry 2-100 outcomes (the\n * AMM's `MAX_OUTCOMES`, on Base and Solana alike); 96-outcome markets exist.\n */\nconst MAX_OUTCOME_INDEX = 99;\n\n/**\n * Outcome index in `[0, 99]`. Throws `INVALID_INPUT` on missing or\n * out-of-range.\n */\nexport function parseOutcomeIndex(raw: string | undefined): number {\n if (raw === undefined) {\n throw new CliValidationError('--outcome is required.', undefined, 'outcome');\n }\n if (!UNSIGNED_INT_REGEX.test(raw)) {\n throw new CliValidationError(\n `--outcome must be an integer between 0 and ${MAX_OUTCOME_INDEX}.`,\n `Got \"${raw}\". Pass digits only — no decimals (\\`1.5\\` would silently round to 1) or scientific notation.`,\n 'outcome'\n );\n }\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n) || n < 0 || n > MAX_OUTCOME_INDEX) {\n throw new CliValidationError(\n `--outcome must be an integer between 0 and ${MAX_OUTCOME_INDEX}.`,\n 'Markets carry 2-100 outcomes; the index is 0-based.',\n 'outcome'\n );\n }\n return n;\n}\n\n/**\n * `--side` parser shared by `kash protocol quote` and `kash eoa trade`.\n * Returns the canonical uppercase form (`'BUY' | 'SELL'`) the SDKs\n * expect. Case-insensitive on input.\n *\n * The lowercase variant (`'buy' | 'sell'`) used by the public-API\n * predictions feed (`kash markets predictions --side buy`) lives at\n * its sole call site — it has different semantics (filter rather\n * than execute) and routes through a separate API endpoint.\n */\nexport function parseUppercaseSide(raw: string, name = 'side'): 'BUY' | 'SELL' {\n const upper = raw.toUpperCase();\n if (upper !== 'BUY' && upper !== 'SELL') {\n throw new CliValidationError(\n `--${name} must be one of: BUY, SELL (case-insensitive).`,\n `Got \"${raw}\".`,\n name\n );\n }\n return upper;\n}\n\n/**\n * One-shot trade-execution side. SA mode (`kash protocol trade …`)\n * and EOA mode (`kash eoa trade …`) share this enum — `close` is the\n * \"sell my entire balance for outcome N\" sugar.\n */\nexport type TradeOpSide = 'buy' | 'sell' | 'close';\n\n/**\n * Slippage in basis points (0..10000 → 0%..100%).\n *\n * Strict integer shape: `parseInt('1e3', 10)` returns 1, which would\n * silently clip 10% slippage to 0.01% (catastrophic for any real\n * trade). The shape check rejects any non-bare-integer before the\n * range check runs.\n */\nexport function parseSlippageBps(raw: string): number {\n if (!UNSIGNED_INT_REGEX.test(raw)) {\n throw new CliValidationError(\n '--slippage-bps must be an integer between 0 and 10000.',\n `Got \"${raw}\". Pass digits only — \\`1e3\\` would silently parse as 1 (0.01%) instead of 1000 (10%).`,\n 'slippage-bps'\n );\n }\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n) || n < 0 || n > 10_000) {\n throw new CliValidationError(\n '--slippage-bps must be an integer between 0 and 10000.',\n `Got \"${raw}\". 50 = 0.5%, 100 = 1%, 10000 = 100%.`,\n 'slippage-bps'\n );\n }\n return n;\n}\n\n/**\n * Unix-seconds deadline as a bigint. Caps the value at\n * `Number.MAX_SAFE_INTEGER` to catch the common ms-vs-sec confusion\n * (a JS `Date.now()` value passed verbatim would overflow into the\n * year 50000+ AD, which the AMM treats as \"no deadline\" and is\n * indistinguishable from the user's intent).\n */\nexport function parseDeadlineSec(raw: string): bigint {\n let parsed: bigint;\n try {\n parsed = BigInt(raw);\n } catch {\n throw new CliValidationError(\n '--deadline-sec must be a unix timestamp in seconds.',\n `Got \"${raw}\".`,\n 'deadline-sec'\n );\n }\n if (parsed <= 0n) {\n throw new CliValidationError(\n '--deadline-sec must be positive.',\n `Got \"${raw}\".`,\n 'deadline-sec'\n );\n }\n // Sanity check: the largest value that fits in a JS safe integer is\n // ~9e15. Anything above that is almost certainly the user passing\n // milliseconds instead of seconds, and `Number(parsed)` would lose\n // precision in downstream code.\n if (parsed > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new CliValidationError(\n '--deadline-sec is impossibly far in the future.',\n `Got ${String(parsed)}. Did you pass milliseconds by mistake? Convert to seconds first.`,\n 'deadline-sec'\n );\n }\n return parsed;\n}\n\n/**\n * Validate that a string is a well-formed USDC decimal (whole or up\n * to 6 fractional digits). Used by call sites that need the\n * shape check but pass the raw string downstream rather than\n * converting to atomic units (e.g. `kash trade buy/sell` ships the\n * decimal verbatim to the public-API SDK, which handles atomic\n * conversion server-side).\n */\nexport function validateUsdcDecimalShape(decimal: string, name: string): void {\n if (!USDC_DECIMAL_REGEX.test(decimal)) {\n throw new CliValidationError(\n `--${name} must be a USDC decimal with up to 6 fractional digits.`,\n `Got \"${decimal}\". USDC accepts up to 6 fractional digits (e.g. \"10\", \"12.50\", \"0.000001\").`,\n name\n );\n }\n}\n\n/**\n * Generic partial-completion hash extractor. SA-mode and EOA-mode\n * trade runners catch SDK errors that may carry an already-landed\n * hash (`userOpHash` for SA, `transactionHash` for EOA) in the\n * cause's `context` field — we surface that hash so the operator\n * can resume rather than pay for a duplicate sign/submit cycle.\n *\n * **Discrimination matters here.** Multiple SDK error classes\n * populate `context.<hash>` with the same shape, so we narrow on\n * the SDK's own `code` enum first:\n *\n * - SA mode: `code === 'BUNDLER_RECEIPT_TIMEOUT'` (genuine partial\n * completion — submit succeeded, wait timed out). Other SA\n * errors like `KashSignerError` (`SIGNER_SIGN_FAILED`) ALSO\n * carry `context.userOpHash` but happen pre-submit, so reporting\n * them as partial completions would be actively misleading.\n * - EOA mode: `code === 'WAIT_RECEIPT_FAILED'` (post-submit wait\n * timeout). Other `KashChainError` variants like\n * `CHAIN_RPC_FAILED` carry no transactionHash and would fail\n * the `contextKey` lookup anyway, but the code-narrow catches\n * them earlier.\n *\n * The `cause` argument is `unknown` because it crosses the SDK ↔\n * CLI boundary; reads are defensive at every step.\n */\nexport function extractPartialHash(\n cause: unknown,\n options: { code: string; contextKey: 'userOpHash' | 'transactionHash' }\n): `0x${string}` | undefined {\n if (cause === null || typeof cause !== 'object') return undefined;\n const code = (cause as { code?: unknown }).code;\n if (code !== options.code) return undefined;\n const ctx = (cause as { context?: unknown }).context;\n if (ctx === null || typeof ctx !== 'object') return undefined;\n const hash = (ctx as Record<string, unknown>)[options.contextKey];\n return typeof hash === 'string' && HEX_HASH_REGEX.test(hash)\n ? (hash as `0x${string}`)\n : undefined;\n}\n\n/**\n * Convert a USDC decimal string (`\"10\"`, `\"12.50\"`, `\"0.000001\"`)\n * to the 6-decimal atomic representation the AMM expects.\n *\n * Rejects strings with more than 6 fractional digits — silently\n * truncating could lose precision the user expected to preserve.\n */\nexport function decimalToAtomicUsdc(decimal: string, name: string): bigint {\n validateUsdcDecimalShape(decimal, name);\n const [whole, frac = ''] = decimal.split('.');\n const fracPadded = frac.padEnd(6, '0');\n return BigInt(`${whole}${fracPadded}`);\n}\n\n/**\n * Convert a token decimal string (`\"1.5\"`, `\"0.0001\"`) to WAD-18\n * atomic units. Outcome tokens use 18-decimal precision throughout\n * the protocol.\n */\nexport function decimalToAtomicWad(decimal: string, name: string): bigint {\n if (!/^\\d+(\\.\\d{1,18})?$/.test(decimal)) {\n throw new CliValidationError(\n `--${name} must be a token decimal with up to 18 fractional digits.`,\n `Got \"${decimal}\". Outcome tokens use WAD-18 precision.`,\n name\n );\n }\n const [whole, frac = ''] = decimal.split('.');\n const fracPadded = frac.padEnd(18, '0');\n return BigInt(`${whole}${fracPadded}`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Package version stamp.\n *\n * Hardcoded rather than imported from `package.json` because:\n *\n * 1. JSON imports vary across runtimes; the bundled CLI must work\n * under Node 22+ regardless of how the consumer's tsconfig is\n * shaped.\n * 2. tsup's JSON-bundling behaviour is bundler-version-specific and\n * we'd rather not depend on it.\n * 3. A simple constant is auditable: `git grep CLI_VERSION` finds\n * every reference instantly.\n *\n * **Maintenance**: bumped in lockstep with `package.json#version` by\n * the changesets release flow. The unit test in\n * `tests/unit/version.test.ts` reads `package.json` and asserts the\n * two stay in sync, so a forgotten bump fails CI before the bad\n * release ships to npm.\n */\nexport const CLI_VERSION = '0.
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Package version stamp.\n *\n * Hardcoded rather than imported from `package.json` because:\n *\n * 1. JSON imports vary across runtimes; the bundled CLI must work\n * under Node 22+ regardless of how the consumer's tsconfig is\n * shaped.\n * 2. tsup's JSON-bundling behaviour is bundler-version-specific and\n * we'd rather not depend on it.\n * 3. A simple constant is auditable: `git grep CLI_VERSION` finds\n * every reference instantly.\n *\n * **Maintenance**: bumped in lockstep with `package.json#version` by\n * the changesets release flow. The unit test in\n * `tests/unit/version.test.ts` reads `package.json` and asserts the\n * two stay in sync, so a forgotten bump fails CI before the bad\n * release ships to npm.\n */\nexport const CLI_VERSION = '0.2.1';\n"],"mappings":";;;AAmBO,IAAM,cAAc;","names":[]}
|