@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.
Files changed (93) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +78 -27
  3. package/dist/{account-CVJZ3HVT.js → account-QHPOIZ6I.js} +9 -9
  4. package/dist/{auth-V5WVZBCO.js → auth-TE7BCN5Q.js} +12 -12
  5. package/dist/{auth-V5WVZBCO.js.map → auth-TE7BCN5Q.js.map} +1 -1
  6. package/dist/{chunk-MQUJG224.js → chunk-2HFKULGG.js} +2 -2
  7. package/dist/{chunk-BVFDUI73.js → chunk-2SR77BYA.js} +10 -9
  8. package/dist/chunk-2SR77BYA.js.map +1 -0
  9. package/dist/chunk-6QSTFU4R.js +9 -0
  10. package/dist/{chunk-KAM6KOFD.js.map → chunk-6QSTFU4R.js.map} +1 -1
  11. package/dist/{chunk-R4NGUZKN.js → chunk-6UU43MF5.js} +5 -3
  12. package/dist/chunk-6UU43MF5.js.map +1 -0
  13. package/dist/{chunk-A3IH5HUV.js → chunk-AROIP4EQ.js} +3 -3
  14. package/dist/chunk-AROIP4EQ.js.map +1 -0
  15. package/dist/{chunk-QALDZHTX.js → chunk-H2QGFDZP.js} +9 -11
  16. package/dist/chunk-H2QGFDZP.js.map +1 -0
  17. package/dist/{chunk-L4AFV2HK.js → chunk-IOLKGV45.js} +3 -3
  18. package/dist/chunk-IOLKGV45.js.map +1 -0
  19. package/dist/{chunk-KADB3OKE.js → chunk-VFBQVUL4.js} +2 -2
  20. package/dist/{chunk-X2VM6VKM.js → chunk-WL7XUYPH.js} +19 -20
  21. package/dist/chunk-WL7XUYPH.js.map +1 -0
  22. package/dist/{chunk-N26VGVGB.js → chunk-ZSMI63N3.js} +109 -37
  23. package/dist/chunk-ZSMI63N3.js.map +1 -0
  24. package/dist/client-REDY6K7J.js +14 -0
  25. package/dist/{completion-PK74S3EZ.js → completion-MXTJYK3D.js} +4 -4
  26. package/dist/{config-T5U6E6KU.js → config-TIJXUJ5N.js} +32 -23
  27. package/dist/config-TIJXUJ5N.js.map +1 -0
  28. package/dist/{config-store-UTFDUCKW.js → config-store-INJY4DDT.js} +6 -4
  29. package/dist/{docs-VA7CJ2ZF.js → docs-M5RZAQ6P.js} +5 -5
  30. package/dist/{eoa-RL3NLN3H.js → eoa-N55DYIN3.js} +18 -16
  31. package/dist/eoa-N55DYIN3.js.map +1 -0
  32. package/dist/{errors-2NNXRNES.js → errors-SMR7X5DU.js} +2 -2
  33. package/dist/{explain-3SPMWDYX.js → explain-HIDEZVLV.js} +31 -8
  34. package/dist/explain-HIDEZVLV.js.map +1 -0
  35. package/dist/{global-options-WFQ6CEFK.js → global-options-YONBFB7N.js} +4 -4
  36. package/dist/{health-2KD6XUTJ.js → health-LSJKP3NH.js} +9 -9
  37. package/dist/index.js +31 -28
  38. package/dist/index.js.map +1 -1
  39. package/dist/{markets-H6EK2XDE.js → markets-AGL6Q2ES.js} +23 -12
  40. package/dist/markets-AGL6Q2ES.js.map +1 -0
  41. package/dist/{output-FGTXXZEQ.js → output-M4NFSWGW.js} +4 -4
  42. package/dist/{portfolio-R63D5QB2.js → portfolio-RBRVUEYP.js} +11 -11
  43. package/dist/{portfolio-R63D5QB2.js.map → portfolio-RBRVUEYP.js.map} +1 -1
  44. package/dist/{protocol-ZB6R25IM.js → protocol-WYQAKN6N.js} +18 -16
  45. package/dist/protocol-WYQAKN6N.js.map +1 -0
  46. package/dist/{quote-OF6BTAPQ.js → quote-6CNHU36A.js} +10 -10
  47. package/dist/redeem-JESSTZ46.js +108 -0
  48. package/dist/redeem-JESSTZ46.js.map +1 -0
  49. package/dist/{schema-3HQN4RFL.js → schema-6EXADLRW.js} +12 -8
  50. package/dist/{schema-3HQN4RFL.js.map → schema-6EXADLRW.js.map} +1 -1
  51. package/dist/{setup-IIPQXLPL.js → setup-H46GTSVW.js} +8 -8
  52. package/dist/{trace-WMO3KDHS.js → trace-VDBWWTYL.js} +10 -10
  53. package/dist/{trade-YBCI6XD2.js → trade-FTSY23QG.js} +10 -10
  54. package/dist/trade-FTSY23QG.js.map +1 -0
  55. package/dist/{version-WB2ACHMU.js → version-JTLF3464.js} +7 -7
  56. package/dist/{version-check-PRAVPFC6.js → version-check-7JGBY6FZ.js} +4 -4
  57. package/dist/{webhooks-DVS55O4T.js → webhooks-JEWNX5HZ.js} +10 -10
  58. package/dist/{webhooks-DVS55O4T.js.map → webhooks-JEWNX5HZ.js.map} +1 -1
  59. package/dist/{with-retry-2MD2CNK2.js → with-retry-DYSHNLG7.js} +12 -6
  60. package/dist/with-retry-DYSHNLG7.js.map +1 -0
  61. package/package.json +5 -5
  62. package/dist/chunk-A3IH5HUV.js.map +0 -1
  63. package/dist/chunk-BVFDUI73.js.map +0 -1
  64. package/dist/chunk-KAM6KOFD.js +0 -9
  65. package/dist/chunk-L4AFV2HK.js.map +0 -1
  66. package/dist/chunk-N26VGVGB.js.map +0 -1
  67. package/dist/chunk-QALDZHTX.js.map +0 -1
  68. package/dist/chunk-R4NGUZKN.js.map +0 -1
  69. package/dist/chunk-X2VM6VKM.js.map +0 -1
  70. package/dist/client-75FVHGOH.js +0 -14
  71. package/dist/config-T5U6E6KU.js.map +0 -1
  72. package/dist/eoa-RL3NLN3H.js.map +0 -1
  73. package/dist/explain-3SPMWDYX.js.map +0 -1
  74. package/dist/markets-H6EK2XDE.js.map +0 -1
  75. package/dist/protocol-ZB6R25IM.js.map +0 -1
  76. package/dist/trade-YBCI6XD2.js.map +0 -1
  77. package/dist/with-retry-2MD2CNK2.js.map +0 -1
  78. /package/dist/{account-CVJZ3HVT.js.map → account-QHPOIZ6I.js.map} +0 -0
  79. /package/dist/{chunk-MQUJG224.js.map → chunk-2HFKULGG.js.map} +0 -0
  80. /package/dist/{chunk-KADB3OKE.js.map → chunk-VFBQVUL4.js.map} +0 -0
  81. /package/dist/{client-75FVHGOH.js.map → client-REDY6K7J.js.map} +0 -0
  82. /package/dist/{completion-PK74S3EZ.js.map → completion-MXTJYK3D.js.map} +0 -0
  83. /package/dist/{config-store-UTFDUCKW.js.map → config-store-INJY4DDT.js.map} +0 -0
  84. /package/dist/{docs-VA7CJ2ZF.js.map → docs-M5RZAQ6P.js.map} +0 -0
  85. /package/dist/{errors-2NNXRNES.js.map → errors-SMR7X5DU.js.map} +0 -0
  86. /package/dist/{global-options-WFQ6CEFK.js.map → global-options-YONBFB7N.js.map} +0 -0
  87. /package/dist/{health-2KD6XUTJ.js.map → health-LSJKP3NH.js.map} +0 -0
  88. /package/dist/{output-FGTXXZEQ.js.map → output-M4NFSWGW.js.map} +0 -0
  89. /package/dist/{quote-OF6BTAPQ.js.map → quote-6CNHU36A.js.map} +0 -0
  90. /package/dist/{setup-IIPQXLPL.js.map → setup-H46GTSVW.js.map} +0 -0
  91. /package/dist/{trace-WMO3KDHS.js.map → trace-VDBWWTYL.js.map} +0 -0
  92. /package/dist/{version-WB2ACHMU.js.map → version-JTLF3464.js.map} +0 -0
  93. /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 (Base mainnet), a `kash_test_*` key auto-routes to staging
70
- > (`api-staging.kash.bot`, Base Sepolia) for dry-runs.
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 Base mainnet or
124
- `kash_test_*` for Base Sepolia — then store it locally with one of:
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
- | `portfolio` | `show`, `positions` |
161
- | `webhooks` | `list`, `rotate-secret`, `redeliver`, `verify`, `replay` |
162
- | `protocol` | `balance`, `market`, `quote`, `position`, `allowance`, `smart-account`, `fees`, `token-id`, `decode-revert`, `trade`, `userop`, `watch` — direct mode (smart account, ERC-4337) |
163
- | `eoa` | `balance`, `market`, `quote`, `position`, `allowance`, `fees`, `trade` — direct mode (vanilla EOA, EIP-1559) |
164
- | `config` | `show`, `set`, `profiles`, `use`, `remove`, `reset`, `export`, `import` |
165
- | `health` | (top-level; honors `--timeout-ms`, exits 1 when down) |
166
- | `version` | (top-level; also accepts `--json`) |
167
- | `explain` | `[codes...]` — error code lookup (multi-code allowed) |
168
- | `schema` | `[name]` — JSON Schema for SDK + CLI envelopes |
169
- | `setup` | first-run interactive wizard (auth + verify + completion) |
170
- | `trace` | `<correlationId>` — curated event timeline for a trade |
171
- | `with-retry` | `-- <command> [args...]` — retry on recoverable failures |
172
- | `docs` | full command tree (use `--json` for the agent surface) |
173
- | `completion` | `install`, `uninstall` |
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`, `defaultChainId`, `signerKeyRef`. EOA mode
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
- | `defaultChainId` | `number?` | `8453` (Base mainnet) | Used when chain id matters; positive integer. |
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
- | `KASH_CHAIN_ID` | `defaultChainId` | Must parse as a positive integer. |
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-QALDZHTX.js";
5
- import "./chunk-N26VGVGB.js";
6
- import "./chunk-BVFDUI73.js";
7
- import "./chunk-KAM6KOFD.js";
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-A3IH5HUV.js";
10
+ } from "./chunk-AROIP4EQ.js";
11
11
  import {
12
12
  print,
13
13
  printJson,
14
14
  style
15
- } from "./chunk-MQUJG224.js";
16
- import "./chunk-KADB3OKE.js";
15
+ } from "./chunk-2HFKULGG.js";
16
+ import "./chunk-VFBQVUL4.js";
17
17
  import {
18
18
  toCliError
19
- } from "./chunk-X2VM6VKM.js";
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-CVJZ3HVT.js.map
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-R4NGUZKN.js";
4
+ } from "./chunk-6UU43MF5.js";
5
5
  import {
6
6
  clearConfigField,
7
7
  readConfig,
8
8
  setCurrentProfile,
9
9
  updateConfig
10
- } from "./chunk-N26VGVGB.js";
11
- import "./chunk-BVFDUI73.js";
10
+ } from "./chunk-ZSMI63N3.js";
11
+ import "./chunk-2SR77BYA.js";
12
12
  import {
13
13
  readGlobals
14
- } from "./chunk-A3IH5HUV.js";
14
+ } from "./chunk-AROIP4EQ.js";
15
15
  import {
16
16
  log,
17
17
  print,
18
18
  printJson,
19
19
  style
20
- } from "./chunk-MQUJG224.js";
21
- import "./chunk-KADB3OKE.js";
20
+ } from "./chunk-2HFKULGG.js";
21
+ import "./chunk-VFBQVUL4.js";
22
22
  import {
23
23
  CliValidationError,
24
24
  toCliError
25
- } from "./chunk-X2VM6VKM.js";
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
- defaultChainId: config.defaultChainId,
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
- ` ${style.dim("Chain id ")} ${String(config.defaultChainId)} (${config.sources.defaultChainId})`
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-V5WVZBCO.js.map
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-KADB3OKE.js";
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-MQUJG224.js.map
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-X2VM6VKM.js";
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
- "--outcome must be an integer between 0 and 7.",
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 > 7) {
40
+ if (!Number.isFinite(n) || n < 0 || n > MAX_OUTCOME_INDEX) {
40
41
  throw new CliValidationError(
41
- "--outcome must be an integer between 0 and 7.",
42
- "Markets carry 2-8 outcomes; the index is 0-based.",
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-BVFDUI73.js.map
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":[]}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version.ts
4
+ var CLI_VERSION = "0.2.1";
5
+
6
+ export {
7
+ CLI_VERSION
8
+ };
9
+ //# sourceMappingURL=chunk-6QSTFU4R.js.map
@@ -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.1';\n"],"mappings":";;;AAmBO,IAAM,cAAc;","names":[]}
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":[]}