@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
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/config-store.ts"],"sourcesContent":["/**\n * Persistent CLI configuration with multi-profile support.\n *\n * The on-disk shape (v1+):\n *\n * {\n * \"version\": 1,\n * \"currentProfile\": \"default\",\n * \"profiles\": {\n * \"default\": { \"apiKey\": \"kash_live_…\", \"baseUrl\": \"…\", \"defaultChainId\": 8453 },\n * \"test\": { \"apiKey\": \"kash_test_…\" }\n * }\n * }\n *\n * Flat-shape configs from earlier CLI versions are migrated transparently\n * on first read into a `default` profile. The on-disk file is rewritten\n * in the new shape only on the next write — readers don't mutate state.\n *\n * The file is created and re-written at mode `0600` on POSIX. The\n * directory is created with `0700`. chmod is best-effort — Windows and\n * some network filesystems silently ignore it.\n *\n * Resolution order (highest precedence first):\n *\n * 1. Environment variables: `KASH_API_KEY`, `KASH_BASE_URL`,\n * `KASH_CHAIN_ID`. Always win.\n * 2. The active profile's fields.\n * 3. Built-in defaults (api.kash.bot/v1, chain 8453).\n *\n * Active-profile resolution (highest precedence first):\n *\n * 1. Explicit `--profile <name>` flag (via `options.profile`).\n * 2. `KASH_PROFILE` env var.\n * 3. `currentProfile` field in the config file.\n * 4. `'default'`.\n *\n * Pinning env-var precedence makes CI runs predictable and lets a\n * human override a profile field without editing the file.\n */\n\nimport { existsSync } from 'node:fs';\nimport { chmod, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nimport { z } from 'zod';\n\nimport { CliConfigurationError } from '../errors.js';\n\nimport { HEX_ADDRESS_REGEX } from './trade-input.js';\n\n/**\n * Return a shallow copy of `obj` without the named property. Cleaner\n * than the `const { [k]: _removed, ...rest } = obj` rest-spread idiom\n * because it avoids the unused-variable lint dance.\n */\nfunction omitKey<T extends Record<string, unknown>, K extends keyof T>(obj: T, key: K): Omit<T, K> {\n const result: Record<string, unknown> = {};\n for (const k of Object.keys(obj)) {\n if (k !== key) result[k] = obj[k];\n }\n return result as Omit<T, K>;\n}\n\n/** Filesystem layout for the config — exposed for tests to override `home`. */\nexport type ConfigPaths = {\n readonly home: string;\n readonly dir: string;\n readonly file: string;\n};\n\nexport function resolveConfigPaths(home: string = homedir()): ConfigPaths {\n const dir = join(home, '.kash');\n return { home, dir, file: join(dir, 'config.json') };\n}\n\n/**\n * Resolve config paths with an optional explicit override path\n * (typically from the `--config` flag or `KASH_CONFIG` env var). The\n * explicit override sets the file directly and derives `dir`/`home`\n * from it for chmod-on-write.\n */\nexport function resolveConfigPathsForOverride(\n override: string | undefined,\n envOverride: string | undefined = process.env['KASH_CONFIG']\n): ConfigPaths {\n const explicit = override ?? envOverride;\n if (explicit) {\n const dir = dirname(explicit);\n return { home: dirname(dir), dir, file: explicit };\n }\n return resolveConfigPaths();\n}\n\nexport const DEFAULT_PROFILE = 'default';\n\n/**\n * Profile-name reserved words. Even though the regex below already\n * blocks the most-dangerous shapes (no `[`, no `<`, no whitespace),\n * the `__proto__` / `constructor` / `prototype` strings ARE allowed\n * by `[A-Za-z0-9_.-]+` — and using them as keys on a plain object\n * (`file.profiles`) walks the prototype chain on read. The denylist\n * makes the prototype-walk impossible at the schema layer.\n *\n * Defence-in-depth: the file format already uses `Object.create(null)`\n * boundaries downstream where possible, but pinning the validator\n * here makes the invariant grep-discoverable.\n */\nconst RESERVED_PROFILE_NAMES = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Profile name validator — keeps file structure deterministic. */\nconst profileNameSchema = z\n .string()\n .min(1, 'profile name cannot be empty')\n .max(64, 'profile name must be ≤ 64 characters')\n .regex(/^[A-Za-z0-9_.-]+$/, 'profile name allows letters, digits, underscore, dot, and dash only')\n .refine((name) => !RESERVED_PROFILE_NAMES.has(name), {\n message:\n 'profile name uses a reserved word (__proto__, constructor, prototype) — would walk the object prototype chain',\n });\n\n/**\n * Schema for a single profile. Every field is optional so the profile\n * can hold partial state — e.g. only override `baseUrl` while\n * inheriting the API key from env.\n */\n/**\n * Reference to a private key the CLI will load when constructing the\n * direct-mode signer. We never persist the raw key — only a reference\n * to where to read it from at invocation time:\n *\n * - `file:<path>` — read the key from a file (mode 0600 enforced\n * at read time, not write).\n * - `env:<name>` — read the key from an environment variable.\n *\n * This keeps `~/.kash/config.json` free of secret material; the\n * config file itself is only `0600`-protected for the API key, not\n * for arbitrary private keys that could fund-drain a smart account.\n *\n * Future extensions: `keystore:<path>`, `aws-kms:<key-id>`,\n * `gcp-kms:<resource>`, `ledger:<derivation-path>`.\n */\nconst signerKeyRefSchema = z\n .string()\n .regex(/^(file:|env:)\\S+$/, 'signerKeyRef must start with \"file:<path>\" or \"env:<NAME>\"');\n\n/** Bundler provider preset. */\nconst bundlerProviderSchema = z.enum(['flashbots', 'pimlico', 'alchemy', 'generic']);\n\nconst hexAddressSchema = z\n .string()\n .regex(HEX_ADDRESS_REGEX, 'must be a 0x-prefixed 40-char hex address');\n\n/**\n * Custom-chain config — bypasses the protocol-sdk's static chain\n * registry. Required for any chain Kash hasn't deployed canonical\n * contracts on (local Anvil, Hardhat, Tenderly forks, sidechains).\n *\n * The CLI derives the `viemChain` argument the SDK needs from the\n * profile's `defaultChainId` + `rpcUrl` + `customChain.name`; the\n * consumer never has to hand-construct a viem Chain. `addresses`\n * mirrors the SDK's `CustomChainAddresses`. `smartAccount` is required\n * only when the consumer is using SA mode (`kash protocol …`) on a\n * custom chain — EOA mode ignores it.\n */\n/**\n * Custom-chain schema. Every field is optional at the persistence\n * layer because `kash config set customChain.<leaf>` writes one leaf\n * at a time — requiring the full shape at write time would force the\n * user into a single mega-set call. Completeness (name +\n * factoryAddress + usdcAddress required, smartAccount triple all-or-\n * nothing) is enforced at use time in `resolveCliCustomChain`,\n * where the missing field has actionable error context (the SDK call\n * that needs it).\n */\nconst customChainSchema = z\n .object({\n /** Human-readable label, surfaced on `client.addresses.name`. */\n name: z.string().min(1, 'customChain.name must not be empty').optional(),\n factoryAddress: hexAddressSchema.optional(),\n usdcAddress: hexAddressSchema.optional(),\n oracleAddress: hexAddressSchema.optional(),\n vaultAddress: hexAddressSchema.optional(),\n tokens1155Address: hexAddressSchema.optional(),\n paramRegistryAddress: hexAddressSchema.optional(),\n /** Smart-account factory + EntryPoint config (SA mode only). */\n smartAccount: z\n .object({\n factoryAddress: hexAddressSchema.optional(),\n implementationAddress: hexAddressSchema.optional(),\n entryPointAddress: hexAddressSchema.optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\nexport const cliConfigSchema = z\n .object({\n // ── Kash-orchestrated mode (API-backed) ─────────────────────────────\n apiKey: z\n .string()\n .startsWith('kash_', 'API keys start with \"kash_\"')\n .min(16, 'API key looks too short')\n .optional(),\n baseUrl: z.string().url('baseUrl must be a valid URL').optional(),\n defaultChainId: z.number().int().positive().optional(),\n\n // ── Direct mode (`kash protocol …`, on-chain) ───────────────\n /** RPC endpoint for the chain. Consumer-owned; the CLI never proxies. */\n rpcUrl: z.string().url('rpcUrl must be a valid URL').optional(),\n /** Smart account address (the ERC-4337 account whose funds are used). */\n smartAccount: z\n .string()\n .regex(HEX_ADDRESS_REGEX, 'smartAccount must be a 0x-prefixed 40-char hex address')\n .optional(),\n /** Bundler URL (overrides the protocol-sdk's Flashbots Protect default). */\n bundlerUrl: z.string().url('bundlerUrl must be a valid URL').optional(),\n /** Bundler provider preset (selects the right header dialect). */\n bundlerProvider: bundlerProviderSchema.optional(),\n /** Reference to the EOA private key that owns the smart account. */\n signerKeyRef: signerKeyRefSchema.optional(),\n /**\n * Custom-chain addresses for chains outside the static registry\n * (local Anvil, forks, sidechains). When present, the CLI's\n * direct-mode and EOA-mode commands use these addresses instead\n * of looking the chain up in the registry. Required for chainId\n * 31337 (Anvil); optional for Base mainnet/testnet (registry covers them).\n */\n customChain: customChainSchema.optional(),\n })\n .strict();\n\nexport type CliConfig = z.infer<typeof cliConfigSchema>;\n\n/**\n * Schema for the v1 multi-profile file shape.\n *\n * `currentProfile` is intentionally optional (no `.default()`) so the\n * source-attribution logic in `pickProfileName` can distinguish\n * \"user explicitly persisted `default` via `kash config use default`\"\n * (source: 'file') from \"we fell through to the built-in default\n * because the file didn't carry a `currentProfile` field\" (source:\n * 'default'). Both result in `'default'` as the active profile, but\n * the source attribution they report is different.\n */\nconst cliFileSchema = z\n .object({\n version: z.literal(1),\n currentProfile: profileNameSchema.optional(),\n profiles: z.record(profileNameSchema, cliConfigSchema).default({}),\n })\n .strict();\n\nexport type CliFile = z.infer<typeof cliFileSchema>;\n\n/**\n * Canonical API base URLs by environment. The CLI auto-routes based on\n * the API-key prefix: a `kash_test_*` key targets staging, a\n * `kash_live_*` key (or no key) targets production. An explicit\n * `baseUrl` config or `KASH_BASE_URL` env var always wins so consumers\n * can target a private mirror, a local mock, or a future region.\n *\n * Mirrors the `inferBaseUrlFromApiKey()` logic in `@kashdao/sdk`'s\n * `internal/config.ts` so the CLI and the SDK route a given key to the\n * same environment without the user having to configure two places.\n */\nexport const PRODUCTION_BASE_URL = 'https://api.kash.bot/v1' as const;\nexport const STAGING_BASE_URL = 'https://api-staging.kash.bot/v1' as const;\n\n/**\n * Derive the API base URL from an API key when neither config nor env\n * sets one explicitly. Returns `undefined` if the key shape isn't\n * recognised — the caller then falls back to {@link DEFAULTS.baseUrl}.\n */\nexport function inferBaseUrlFromApiKey(apiKey: string | undefined): string | undefined {\n if (!apiKey) return undefined;\n if (apiKey.startsWith('kash_test_')) return STAGING_BASE_URL;\n if (apiKey.startsWith('kash_live_')) return PRODUCTION_BASE_URL;\n return undefined;\n}\n\n/** Default values applied when a field is missing from both file and env. */\nexport const DEFAULTS = {\n baseUrl: PRODUCTION_BASE_URL,\n defaultChainId: 8453,\n} as const;\n\nexport type ResolvedConfig = {\n // ── Kash-orchestrated fields ──────────────────────────────────────────\n readonly apiKey: string | undefined;\n readonly baseUrl: string;\n readonly defaultChainId: number;\n // ── Direct-mode fields (`kash protocol …`) ────────────────────\n readonly rpcUrl: string | undefined;\n readonly smartAccount: string | undefined;\n readonly bundlerUrl: string | undefined;\n readonly bundlerProvider: 'flashbots' | 'pimlico' | 'alchemy' | 'generic' | undefined;\n readonly signerKeyRef: string | undefined;\n /**\n * Custom-chain config — present only when the profile explicitly sets\n * `customChain.*`. Bypasses the protocol-sdk's static chain registry\n * and is required for chains the registry doesn't cover (Anvil,\n * forks, sidechains).\n */\n readonly customChain: CliConfig['customChain'];\n // ── Meta ──────────────────────────────────────────────────────\n /** Active profile name. */\n readonly profile: string;\n /** Where each non-default value came from — useful for `kash config show`. */\n readonly sources: {\n readonly apiKey: 'env' | 'file' | 'unset';\n readonly baseUrl: 'env' | 'file' | 'inferred' | 'default';\n readonly defaultChainId: 'env' | 'file' | 'default';\n readonly profile: 'flag' | 'env' | 'file' | 'default';\n readonly rpcUrl: 'env' | 'file' | 'unset';\n readonly smartAccount: 'env' | 'file' | 'unset';\n readonly bundlerUrl: 'env' | 'file' | 'unset';\n readonly bundlerProvider: 'env' | 'file' | 'unset';\n readonly signerKeyRef: 'env' | 'file' | 'unset';\n readonly customChain: 'file' | 'unset';\n };\n};\n\nexport type ReadConfigOptions = {\n /** Override which profile to read; takes precedence over env + file. */\n readonly profile?: string;\n /** Override the config file path; takes precedence over `KASH_CONFIG`. */\n readonly configPath?: string;\n};\n\n/**\n * Read the config file and return the resolved active profile merged\n * with environment variables and defaults.\n */\nexport async function readConfig(opts: ReadConfigOptions = {}): Promise<ResolvedConfig> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n return resolveActive(file, opts.profile);\n}\n\nasync function readFileConfig(paths: ConfigPaths): Promise<CliFile> {\n if (!existsSync(paths.file)) return emptyFile();\n let raw: string;\n try {\n raw = await readFile(paths.file, 'utf8');\n } catch (cause) {\n throw new CliConfigurationError(\n `Failed to read config file at ${paths.file}: ${(cause as Error).message}`,\n \"Run 'kash config reset' to start fresh.\"\n );\n }\n return parseFileContents(raw, paths.file);\n}\n\nfunction parseFileContents(raw: string, file: string): CliFile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new CliConfigurationError(\n `Config file at ${file} is not valid JSON: ${(cause as Error).message}`,\n \"Run 'kash config reset' to overwrite it with defaults.\"\n );\n }\n // Guard against valid-JSON-but-wrong-top-level (e.g. someone wrote\n // a string, a number, an array, or `null` to the file). Without this,\n // the v1 schema's \"Expected object, received string\" Zod error\n // bubbles up with no actionable hint.\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new CliConfigurationError(\n `Config file at ${file} must contain a JSON object at the top level (got ${describeJsonRoot(parsed)}).`,\n \"Run 'kash config reset' to overwrite it with defaults.\"\n );\n }\n const migrated = migrateLegacyShape(parsed);\n const result = cliFileSchema.safeParse(migrated);\n if (!result.success) {\n const first = result.error.issues[0];\n const path = first?.path.join('.') ?? '(root)';\n throw new CliConfigurationError(\n `Config file at ${file} is invalid (${path}): ${first?.message ?? 'validation failed'}`,\n \"Run 'kash config reset' to overwrite it with defaults.\"\n );\n }\n return result.data;\n}\n\n/** Describe a non-object JSON root for the user-facing error message. */\nfunction describeJsonRoot(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value;\n}\n\n/**\n * If the file looks like the legacy flat shape ({ apiKey?, baseUrl?,\n * defaultChainId? } at the root), wrap it as the default profile of a\n * v1 file. Otherwise pass through.\n */\nfunction migrateLegacyShape(parsed: unknown): unknown {\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return parsed;\n }\n const obj = parsed as Record<string, unknown>;\n if ('version' in obj || 'profiles' in obj) {\n return parsed; // already in v1 shape\n }\n // Legacy flat shape — wrap it as the default profile.\n const flat = cliConfigSchema.safeParse(obj);\n if (!flat.success) {\n return parsed; // let the v1 schema raise the structured error\n }\n return {\n version: 1,\n currentProfile: DEFAULT_PROFILE,\n profiles: { [DEFAULT_PROFILE]: flat.data },\n };\n}\n\nfunction emptyFile(): CliFile {\n return cliFileSchema.parse({ version: 1 });\n}\n\n/**\n * Compute the active profile name. Order: explicit flag > env >\n * file's `currentProfile` (when present) > built-in `'default'`.\n *\n * Crucially, when the file persists `currentProfile: \"default\"`\n * (e.g. after `kash config use default`), source is `'file'` — not\n * `'default'`. That keeps the JSON contract honest: agents debugging\n * \"why is my profile X?\" need to know it came from a write, not a\n * fallback.\n */\nfunction pickProfileName(\n file: CliFile,\n flagOverride: string | undefined\n): { name: string; source: 'flag' | 'env' | 'file' | 'default' } {\n if (flagOverride !== undefined) {\n validateProfileName(flagOverride, '--profile flag');\n return { name: flagOverride, source: 'flag' };\n }\n const env = process.env['KASH_PROFILE'];\n if (env !== undefined && env.length > 0) {\n validateProfileName(env, 'KASH_PROFILE environment variable');\n return { name: env, source: 'env' };\n }\n if (file.currentProfile !== undefined) {\n return { name: file.currentProfile, source: 'file' };\n }\n return { name: DEFAULT_PROFILE, source: 'default' };\n}\n\n/**\n * Wrap `profileNameSchema.parse` so a malformed value surfaces as a\n * typed `CliConfigurationError` with a `check_input`-friendly\n * suggestion, instead of a raw `ZodError` that the top-level\n * boundary maps to `UNEXPECTED`.\n */\nfunction validateProfileName(value: string, source: string): void {\n const result = profileNameSchema.safeParse(value);\n if (!result.success) {\n const issue = result.error.issues[0];\n throw new CliConfigurationError(\n `Profile name from ${source} is invalid: ${issue?.message ?? 'validation failed'}.`,\n 'Profile names accept letters, digits, underscore, dot, and dash; must be 1-64 characters.'\n );\n }\n}\n\nfunction resolveActive(file: CliFile, flagOverride: string | undefined): ResolvedConfig {\n const { name: profileName, source: profileSource } = pickProfileName(file, flagOverride);\n const profile = file.profiles[profileName];\n // It's not an error to ask for a profile that isn't in the file —\n // env-only setups (CI, agents) are normal. We surface this via the\n // `sources.apiKey === 'unset'` value if no env var fills the gap.\n //\n // BUT: when the missing profile was named via `KASH_PROFILE` or\n // `--profile`, an intentional env-only setup is the rare case and\n // a typo (e.g. `KASH_PROFILE=staing` vs `staging`) is the common\n // case. The operator otherwise sees an empty config + a confusing\n // `AUTH_REQUIRED` later. Nudge them on stderr (no JSON pollution,\n // no behaviour change). `KASH_QUIET=1` mutes the warning for CI.\n if (\n profile === undefined &&\n (profileSource === 'env' || profileSource === 'flag') &&\n Object.keys(file.profiles).length > 0 &&\n !isTruthyEnv(process.env['KASH_QUIET'])\n ) {\n const known = Object.keys(file.profiles).sort().join(', ');\n const sourceLabel = profileSource === 'env' ? 'KASH_PROFILE' : '--profile';\n process.stderr.write(\n `\\u26a0 Profile \"${profileName}\" (${sourceLabel}) is not in the config file. ` +\n `Known profiles: ${known}. ` +\n `Did you typo the name? (Set KASH_QUIET=1 to mute this warning.)\\n`\n );\n }\n return mergeWithEnv(profile ?? {}, profileName, profileSource);\n}\n\n/** Same truthy-env recognizer as `utils/global-options.ts:isTruthyEnv`. */\nfunction isTruthyEnv(value: string | undefined): boolean {\n if (value === undefined) return false;\n const v = value.trim().toLowerCase();\n return v === '1' || v === 'true' || v === 'yes' || v === 'on';\n}\n\nfunction mergeWithEnv(\n profile: CliConfig,\n profileName: string,\n profileSource: 'flag' | 'env' | 'file' | 'default'\n): ResolvedConfig {\n const envApiKey = process.env['KASH_API_KEY'];\n const envBaseUrl = process.env['KASH_BASE_URL'];\n const envChainIdRaw = process.env['KASH_CHAIN_ID'];\n // Direct-mode env vars\n const envRpcUrl = process.env['KASH_RPC_URL'];\n const envSmartAccount = process.env['KASH_SMART_ACCOUNT'];\n const envBundlerUrl = process.env['KASH_BUNDLER_URL'];\n const envBundlerProviderRaw = process.env['KASH_BUNDLER_PROVIDER'];\n const envSignerKeyRef = process.env['KASH_SIGNER_KEY_REF'];\n\n let envChainId: number | undefined;\n if (envChainIdRaw !== undefined) {\n const n = Number.parseInt(envChainIdRaw, 10);\n if (Number.isNaN(n) || n <= 0) {\n throw new CliConfigurationError(\n `KASH_CHAIN_ID is not a positive integer: ${envChainIdRaw}`,\n 'Set KASH_CHAIN_ID to a chain id like 8453 or 84532, or unset it to use the default.'\n );\n }\n envChainId = n;\n }\n\n let envBundlerProvider: ResolvedConfig['bundlerProvider'];\n if (envBundlerProviderRaw !== undefined) {\n const allowed = ['flashbots', 'pimlico', 'alchemy', 'generic'] as const;\n if (!(allowed as readonly string[]).includes(envBundlerProviderRaw)) {\n throw new CliConfigurationError(\n `KASH_BUNDLER_PROVIDER must be one of ${allowed.join(', ')} (got \"${envBundlerProviderRaw}\").`,\n 'Unset the variable or set it to a supported preset.'\n );\n }\n envBundlerProvider = envBundlerProviderRaw as ResolvedConfig['bundlerProvider'];\n }\n\n const apiKey = envApiKey ?? profile.apiKey;\n // Resolution order for `baseUrl`:\n // 1. KASH_BASE_URL env var — always wins\n // 2. profile.baseUrl — explicit profile config\n // 3. inferred from apiKey prefix — kash_test_* → staging, kash_live_* → production\n // 4. DEFAULTS.baseUrl — production (final fallback)\n //\n // Step 3 mirrors `@kashdao/sdk`'s `inferBaseUrlFromApiKey()` so the\n // CLI and the SDK route the same key to the same environment without\n // requiring the user to configure two places. Without this, a user\n // with only a `kash_test_*` key would hit the production host until\n // they remembered to also set `--base-url`.\n const baseUrl =\n envBaseUrl ?? profile.baseUrl ?? inferBaseUrlFromApiKey(apiKey) ?? DEFAULTS.baseUrl;\n const defaultChainId = envChainId ?? profile.defaultChainId ?? DEFAULTS.defaultChainId;\n const rpcUrl = envRpcUrl ?? profile.rpcUrl;\n const smartAccount = envSmartAccount ?? profile.smartAccount;\n const bundlerUrl = envBundlerUrl ?? profile.bundlerUrl;\n const bundlerProvider = envBundlerProvider ?? profile.bundlerProvider;\n const signerKeyRef = envSignerKeyRef ?? profile.signerKeyRef;\n // customChain has no env-var override — it's a structured object,\n // not a single string, and the right place to set it is `kash\n // config set customChain.<leaf>` so partial sets compose. CI use\n // cases that need a custom chain mount the config file directly\n // (KASH_CONFIG=...).\n const customChain = profile.customChain;\n\n return {\n apiKey,\n baseUrl,\n defaultChainId,\n rpcUrl,\n smartAccount,\n bundlerUrl,\n bundlerProvider,\n signerKeyRef,\n customChain,\n profile: profileName,\n sources: {\n apiKey: envApiKey ? 'env' : profile.apiKey ? 'file' : 'unset',\n baseUrl: envBaseUrl\n ? 'env'\n : profile.baseUrl\n ? 'file'\n : inferBaseUrlFromApiKey(apiKey)\n ? 'inferred'\n : 'default',\n defaultChainId:\n envChainId !== undefined\n ? 'env'\n : profile.defaultChainId !== undefined\n ? 'file'\n : 'default',\n profile: profileSource,\n rpcUrl: envRpcUrl ? 'env' : profile.rpcUrl ? 'file' : 'unset',\n smartAccount: envSmartAccount ? 'env' : profile.smartAccount ? 'file' : 'unset',\n bundlerUrl: envBundlerUrl ? 'env' : profile.bundlerUrl ? 'file' : 'unset',\n bundlerProvider: envBundlerProvider ? 'env' : profile.bundlerProvider ? 'file' : 'unset',\n signerKeyRef: envSignerKeyRef ? 'env' : profile.signerKeyRef ? 'file' : 'unset',\n customChain: profile.customChain ? 'file' : 'unset',\n },\n };\n}\n\nexport type WriteConfigOptions = {\n /** Profile to write to. Defaults to the current active profile. */\n readonly profile?: string;\n /** Override the config file path. */\n readonly configPath?: string;\n};\n\n/**\n * Result of {@link updateConfig} / {@link clearConfigField}. Carries\n * the resolved profile name so callers can render an accurate\n * \"wrote to profile X\" message instead of guessing — important for\n * the JSON contract that `kash auth set-key --json` ships, since\n * `--profile` may be unset and we want to report the actually-written\n * profile (which falls back to the file's `currentProfile`).\n */\nexport type UpdateConfigResult = {\n readonly profile: string;\n readonly stored: CliConfig;\n};\n\n/**\n * Mutate (and persist) a single field of the active (or named) profile.\n * Used by `auth set-key`, `auth logout`, `config set`. Writes the file\n * with `0600` permissions.\n */\nexport async function updateConfig(\n patch: Partial<CliConfig>,\n opts: WriteConfigOptions = {}\n): Promise<UpdateConfigResult> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n const profileName = opts.profile ?? file.currentProfile ?? DEFAULT_PROFILE;\n profileNameSchema.parse(profileName);\n const current = file.profiles[profileName] ?? {};\n const next = cliConfigSchema.parse({ ...current, ...patch });\n const updated: CliFile = {\n ...file,\n profiles: { ...file.profiles, [profileName]: next },\n };\n await writeFileConfig(paths, updated);\n return { profile: profileName, stored: next };\n}\n\n/** Wipe a single field from a profile (used by `auth logout`). */\nexport async function clearConfigField(\n field: keyof CliConfig,\n opts: WriteConfigOptions = {}\n): Promise<UpdateConfigResult> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n const profileName = opts.profile ?? file.currentProfile ?? DEFAULT_PROFILE;\n const current = file.profiles[profileName] ?? {};\n if (!(field in current)) return { profile: profileName, stored: current };\n const next = cliConfigSchema.parse(omitKey(current, field));\n const updated: CliFile = {\n ...file,\n profiles: { ...file.profiles, [profileName]: next },\n };\n await writeFileConfig(paths, updated);\n return { profile: profileName, stored: next };\n}\n\n/** List every profile name present in the config file. */\nexport async function listProfiles(\n opts: { configPath?: string } = {}\n): Promise<{ readonly current: string; readonly profiles: readonly string[] }> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n return {\n current: file.currentProfile ?? DEFAULT_PROFILE,\n profiles: Object.keys(file.profiles).sort(),\n };\n}\n\n/** Set the file's `currentProfile` field. Validates the name. */\nexport async function setCurrentProfile(\n name: string,\n opts: { configPath?: string } = {}\n): Promise<CliFile> {\n profileNameSchema.parse(name);\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n const updated: CliFile = { ...file, currentProfile: name };\n await writeFileConfig(paths, updated);\n return updated;\n}\n\n/** Remove a named profile. Refuses to remove the active one. */\nexport async function deleteProfile(\n name: string,\n opts: { configPath?: string } = {}\n): Promise<CliFile> {\n profileNameSchema.parse(name);\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const file = await readFileConfig(paths);\n if (file.currentProfile === name) {\n throw new CliConfigurationError(\n `Cannot delete the active profile \"${name}\".`,\n 'Switch to another profile first with `kash config use <name>`.'\n );\n }\n if (!(name in file.profiles)) {\n return file;\n }\n const updated: CliFile = { ...file, profiles: omitKey(file.profiles, name) };\n await writeFileConfig(paths, updated);\n return updated;\n}\n\n/** Delete the entire config file. Used by `config reset`. */\nexport async function deleteConfig(opts: { configPath?: string } = {}): Promise<void> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n if (!existsSync(paths.file)) return;\n await unlink(paths.file);\n}\n\n/**\n * Return the full multi-profile file as-is. Used by `kash config\n * export` to dump every profile (vs `readConfig` which resolves a\n * single active profile). When the file doesn't exist, returns an\n * empty file shape so callers don't have to special-case \"no config\n * yet\".\n */\nexport async function readWholeFile(opts: { configPath?: string } = {}): Promise<CliFile> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n return await readFileConfig(paths);\n}\n\n/**\n * Replace the entire on-disk file with the supplied shape. Used by\n * `kash config import`. Validates against the `cliFileSchema` to\n * prevent garbage from landing on disk.\n *\n * Caller-side concerns (merge vs. overwrite, redaction policy, etc.)\n * are handled in the import command — this helper is pure persistence.\n */\nexport async function writeWholeFile(\n file: CliFile,\n opts: { configPath?: string } = {}\n): Promise<void> {\n const paths = resolveConfigPathsForOverride(opts.configPath);\n const validated = cliFileSchema.parse(file);\n await writeFileConfig(paths, validated);\n}\n\n/** Public re-export of the file-level schema for the import command. */\nexport { cliFileSchema };\n\nasync function writeFileConfig(paths: ConfigPaths, file: CliFile): Promise<void> {\n await ensureDir(paths.dir);\n // Use writeFile + chmod rather than writeFile({mode}) because the\n // mode flag only takes effect on first creation; rewrites would\n // keep the old (potentially looser) permissions.\n await writeFile(paths.file, JSON.stringify(file, null, 2), 'utf8');\n await chmodSafe(paths.file, 0o600);\n}\n\nasync function ensureDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true, mode: 0o700 });\n await chmodSafe(dir, 0o700);\n}\n\nasync function chmodSafe(target: string, mode: number | undefined): Promise<void> {\n if (mode === undefined) return;\n if (process.platform === 'win32') return;\n try {\n await chmod(target, mode);\n } catch {\n // chmod can fail on some filesystems (e.g. mounted FAT volumes,\n // network shares). Treat as best-effort — the user's data still\n // landed, we just couldn't tighten perms.\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/client.ts"],"sourcesContent":["/**\n * Build a `KashClient` from the resolved CLI configuration plus\n * per-invocation global flag overrides.\n *\n * Centralised here so command modules don't each have to know how to\n * read config, surface \"missing API key\" errors, or thread base URLs.\n * Every command that hits `api.kash.bot` must pass `requireAuth: true`\n * so a missing API key fails fast at the call site with a structured\n * `CliError` pointing the user at `kash auth set-key`. Only the offline\n * commands (`kash explain`, `kash --version`, `kash --help`) and the\n * `kash health` probe construct a client without `requireAuth`.\n *\n * Three layers feed the final SDK config:\n *\n * 1. The active profile + env vars (resolved by config-store).\n * 2. Per-invocation `--profile` / `--config` overrides (which select\n * *which* profile and file feed step 1).\n * 3. Per-invocation `--base-url` / `--max-retries` / `--timeout-ms`\n * flags, which override the SDK's runtime config directly.\n *\n * `--debug` wires a stderr-emitting hook into the SDK's lifecycle so\n * a developer or AI agent can see request/response/retry/error\n * traces without instrumenting the SDK.\n */\n\nimport { KashClient, type KashClientHooks } from '@kashdao/sdk';\n\nimport { CliError, EXIT_CODES } from '../errors.js';\nimport { CLI_VERSION } from '../version.js';\n\nimport { readConfig, type ResolvedConfig } from './config-store.js';\nimport { style } from './output.js';\n\nimport type { GlobalOptions } from './global-options.js';\n\nexport type ClientOptions = {\n /** When true, throw `CliError` if no API key is configured. */\n readonly requireAuth?: boolean;\n /**\n * Global flags from the root program. Optional so internal callers\n * (and tests) can build a client without going through Commander.\n */\n readonly globals?: GlobalOptions;\n};\n\nexport type BuiltClient = {\n readonly client: KashClient;\n readonly config: ResolvedConfig;\n};\n\nexport async function buildClient(opts: ClientOptions = {}): Promise<BuiltClient> {\n const globals = opts.globals;\n const config = await readConfig({\n ...(globals?.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals?.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n if (opts.requireAuth && !config.apiKey) {\n throw new CliError('No API key configured.', {\n code: 'AUTH_REQUIRED',\n exitCode: EXIT_CODES.AUTH,\n suggestion:\n \"First-time setup: run 'kash setup' (interactive wizard). Otherwise: 'kash auth set-key' or set KASH_API_KEY.\",\n });\n }\n\n // Per-invocation overrides win over the resolved profile+env config.\n const baseUrl = globals?.baseUrl ?? config.baseUrl;\n\n const client = new KashClient({\n ...(config.apiKey === undefined ? {} : { apiKey: config.apiKey }),\n baseUrl,\n ...(globals?.maxRetries === undefined ? {} : { maxRetries: globals.maxRetries }),\n ...(globals?.timeoutMs === undefined ? {} : { timeoutMs: globals.timeoutMs }),\n // Forward the public-API contract pin from `--api-version` (or\n // `KASH_API_VERSION` env, if a future iteration plumbs it). The\n // SDK validates the date format and sends the value as the\n // `X-Kash-Api-Version` request header; the public-api routes the\n // request through a version-appropriate code path.\n ...(globals?.apiVersion === undefined ? {} : { apiVersion: globals.apiVersion }),\n userAgentSuffix: `kash-cli/${CLI_VERSION}`,\n ...(globals?.debug === true ? { hooks: buildDebugHooks(globals.json) } : {}),\n });\n\n return { client, config };\n}\n\n/**\n * Build SDK lifecycle hooks that emit traces to stderr.\n *\n * In `--debug --json` mode each event is a one-line JSON record so an\n * AI agent can stream-parse them. In human mode they're a compact\n * prefix plus method/path/status — close to what an HTTP client like\n * `curl -v` would surface, but at the SDK boundary so retries are\n * visible.\n *\n * Quiet mode silences nothing here: `--debug` is opt-in and the user\n * who passed it wants to see traces, full stop.\n */\nfunction buildDebugHooks(json: boolean): KashClientHooks {\n // Use stderr directly rather than the `log` helpers because the\n // hooks fire synchronously inside the SDK and we want zero overhead\n // in the common case (no quiet check, no chalk wrapping).\n const emit = (record: Record<string, unknown>): void => {\n if (json) {\n process.stderr.write(`${JSON.stringify(record)}\\n`);\n return;\n }\n const { event, method, url, status, attempt, durationMs, reason, delayMs, code } = record;\n const prefix = style.dim('[debug]');\n const path = typeof url === 'string' ? url : '';\n const tag = String(event);\n if (event === 'request') {\n process.stderr.write(\n `${prefix} ${tag} ${String(method)} ${path} (attempt ${String(attempt)})\\n`\n );\n } else if (event === 'response') {\n process.stderr.write(\n `${prefix} ${tag} ${String(status)} ${String(method)} ${path} ${String(durationMs)}ms\\n`\n );\n } else if (event === 'retry') {\n process.stderr.write(\n `${prefix} ${tag} ${String(method)} ${path} reason=${String(reason)} delay=${String(delayMs)}ms\\n`\n );\n } else if (event === 'error') {\n process.stderr.write(\n `${prefix} ${tag} ${String(code)} ${String(method)} ${path} ${String(status ?? '-')} ${String(durationMs)}ms\\n`\n );\n }\n };\n\n return {\n onRequest: (event) => {\n emit({\n event: 'request',\n method: event.method,\n url: event.url,\n attempt: event.attempt,\n idempotencyKey: event.idempotencyKey ?? null,\n });\n },\n onResponse: (event) => {\n emit({\n event: 'response',\n method: event.method,\n url: event.url,\n attempt: event.attempt,\n status: event.status,\n durationMs: event.durationMs,\n requestId: event.requestId ?? null,\n });\n },\n onRetry: (event) => {\n emit({\n event: 'retry',\n method: event.method,\n url: event.url,\n attempt: event.attempt,\n reason: event.reason,\n delayMs: event.delayMs,\n });\n },\n onError: (event) => {\n emit({\n event: 'error',\n method: event.method,\n url: event.url,\n attempt: event.attempt,\n status: event.status ?? null,\n code: event.code,\n durationMs: event.durationMs,\n });\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/formatting.ts"],"sourcesContent":["/**\n * Display formatters: tables, addresses, USDC amounts, status colors.\n *\n * Atomic USDC values from the API are integer strings (6 decimals). The\n * SDK does not assume a math library, so we format with simple integer\n * division here — the precision constraint is purely cosmetic.\n */\n\nimport Table from 'cli-table3';\n\nimport { style } from './output.js';\n\n/**\n * ASCII ellipsis used for all truncation glyphs. We use three dots\n * rather than the Unicode horizontal-ellipsis (U+2026) because the\n * latter renders as `?` on Windows cmd.exe and in restricted locales\n * — `gh`, `aws`, and `stripe` all standardise on ASCII.\n */\nconst ELLIPSIS = '...';\n\n/**\n * Code-point-safe slice. `String.prototype.slice` operates on UTF-16\n * code units, so an emoji or other surrogate pair near a boundary\n * could split. None of the inputs we slice (API keys, hex addresses,\n * UUIDs) carry surrogates today — but defensive slicing matches\n * `gh`/`aws` and the cost is negligible.\n */\nfunction codepointSlice(s: string, start: number, end?: number): string {\n return Array.from(s).slice(start, end).join('');\n}\n\nfunction codepointLength(s: string): number {\n return Array.from(s).length;\n}\n\n/** Truncate a UUID/long ID to \"abcdef12...\" for tables. */\nexport function shortId(id: string, prefix = 8): string {\n if (codepointLength(id) <= prefix + ELLIPSIS.length) return id;\n return `${codepointSlice(id, 0, prefix)}${ELLIPSIS}`;\n}\n\n/**\n * Truncate a free-form string to fit within a column. Appends an\n * ellipsis when shortened so the user sees that data was elided.\n * Different from `shortId`, which uses a leading-prefix heuristic\n * suited to UUIDs and tx hashes.\n */\nexport function truncate(s: string, max: number): string {\n return codepointLength(s) > max ? `${codepointSlice(s, 0, max - ELLIPSIS.length)}${ELLIPSIS}` : s;\n}\n\n/**\n * Redact an API key for display. Always shows enough leading\n * characters (`kash_live_` / `kash_test_` prefix) to confirm the key\n * type, plus the last four characters so users can match it to a\n * value they have on record. Inputs shorter than 8 characters are\n * masked entirely so we never accidentally leak a partial key from\n * truncated input.\n */\nexport function redact(key: string): string {\n if (codepointLength(key) <= 8) return '***';\n return `${codepointSlice(key, 0, 8)}${ELLIPSIS}${codepointSlice(key, -4)}`;\n}\n\n/** Capitalise the first letter. Empty strings pass through. */\nexport function capitalize(s: string): string {\n if (s.length === 0) return s;\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/** Format an EVM address as `0x1234...abcd`. */\nexport function formatAddress(address: string, lead = 6, tail = 4): string {\n if (codepointLength(address) <= lead + tail + ELLIPSIS.length) return address;\n return `${codepointSlice(address, 0, lead)}${ELLIPSIS}${codepointSlice(address, -tail)}`;\n}\n\n/** Format a UTC ISO string as a local-readable date+time. */\nexport function formatDate(value: string | Date | null | undefined): string {\n if (!value) return '-';\n const d = typeof value === 'string' ? new Date(value) : value;\n if (Number.isNaN(d.getTime())) return '-';\n return d.toLocaleString();\n}\n\n/**\n * Format a USDC value as `$1,234.56`.\n *\n * Two input shapes are accepted:\n *\n * 1. **Atomic** — bigint, integer string, or finite Number,\n * interpreted as micro-USDC (6 decimals). This is the canonical\n * shape on every API response (`totalCostBasisAtomic`,\n * `tokensOut`, etc.). Formatted with bigint math so values past\n * Number.MAX_SAFE_INTEGER round-trip exactly.\n * 2. **Decimal string** — only used by analytics endpoints that\n * return human-formatted dollar amounts (e.g. `\"1234.56\"`).\n * These pass through `Number.parseFloat`, which means values\n * with more than ~15 significant decimal digits round at IEEE-754\n * precision. This is acceptable for *display* (the underlying\n * authoritative value is always atomic), but consumers writing\n * reconciliation logic should call the upstream atomic field\n * directly rather than re-parsing a formatted decimal.\n *\n * The atomic branch rounds the cents column **toward zero** (cheaper\n * than half-even for tables; the trade engine reconciles to atomic\n * precision elsewhere). Cosmetic only.\n */\nexport function formatUsdcAtomic(atomic: string | bigint | number): string {\n if (typeof atomic === 'string' && atomic.includes('.')) {\n // Decimal-string branch (analytics only). Documented loss: values\n // > 15 significant digits round at parseFloat precision.\n const n = Number.parseFloat(atomic);\n if (Number.isNaN(n)) return '$0.00';\n return n.toLocaleString('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n }\n let big: bigint;\n try {\n big = typeof atomic === 'bigint' ? atomic : BigInt(atomic);\n } catch {\n return '$0.00';\n }\n const negative = big < 0n;\n const abs = negative ? -big : big;\n const whole = abs / 1_000_000n;\n const frac = abs % 1_000_000n;\n const wholeStr = whole.toLocaleString('en-US');\n const cents = (frac / 10_000n).toString().padStart(2, '0');\n return `${negative ? '-' : ''}$${wholeStr}.${cents}`;\n}\n\n/**\n * Format a human USDC decimal string (e.g. `'12.5'`) as `$12.50`.\n * Used when the API hands back already-decimal amounts (the trade\n * resource's `amount` field).\n */\nexport function formatUsdcDecimal(value: string): string {\n const n = Number.parseFloat(value);\n if (Number.isNaN(n)) return value;\n return n.toLocaleString('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n}\n\n/** Format a probability in [0,1] as a percentage string. */\nexport function formatProbability(p: number | null | undefined): string {\n if (p === null || p === undefined || Number.isNaN(p)) return '-';\n return `${(p * 100).toFixed(1)}%`;\n}\n\n/**\n * Generic fixed-point bigint→decimal-display formatter. Used by every\n * CLI helper that needs to render an atomic-units bigint (WAD-18,\n * gwei-9, ETH-18, USDC-6) as a human-readable decimal string.\n *\n * Two parameters control shape:\n *\n * - `baseDecimals` — the unit's atomic precision (18 for WAD/ETH,\n * 9 for gwei, 6 for USDC).\n * - `displayDecimals` — how many fractional digits to emit. Must\n * be ≤ `baseDecimals`. Truncates rather than rounds — display\n * only, `--json` preserves the full atomic-string precision.\n *\n * Sign is extracted before the magnitude split so `-` rendering\n * lives at one site. The whole part is rendered with thousand-\n * separator commas via `toLocaleString` (consistent with\n * `formatUsdcAtomic`); call sites that need the raw integer-shape\n * (e.g. `formatGwei`'s historical \"no commas\" form) opt out via\n * `thousandSeparator: false`.\n *\n * Accepts `string | bigint` for the same reason `formatWad` did:\n * direct-mode SDKs return `bigint`, indexer-backed views return\n * integer-string. The `try/catch` around `BigInt(value)` is the\n * defensive never-throw guarantee on display paths — a malformed\n * input falls through to the input itself rather than crashing.\n */\nexport function formatBigDecimal(\n value: string | bigint,\n options: { baseDecimals: number; displayDecimals: number; thousandSeparator?: boolean }\n): string {\n const { baseDecimals, displayDecimals } = options;\n const useThousandSeparator = options.thousandSeparator ?? true;\n let big: bigint;\n try {\n big = typeof value === 'bigint' ? value : BigInt(value);\n } catch {\n return typeof value === 'string' ? value : '0';\n }\n const negative = big < 0n;\n const abs = negative ? -big : big;\n const baseScale = 10n ** BigInt(baseDecimals);\n const whole = abs / baseScale;\n const frac = abs % baseScale;\n const truncated = (frac / 10n ** BigInt(baseDecimals - displayDecimals))\n .toString()\n .padStart(displayDecimals, '0');\n const wholeStr = useThousandSeparator ? whole.toLocaleString('en-US') : whole.toString();\n return `${negative ? '-' : ''}${wholeStr}.${truncated}`;\n}\n\n/**\n * Format a WAD-18 (1e18) value as a 4-decimal token display string.\n * Twin of `formatUsdcAtomic` but for outcome-token quantities.\n * Direct-mode SDK returns bigint; indexer-backed views return string.\n */\nexport function formatWad(wad: string | bigint): string {\n return formatBigDecimal(wad, { baseDecimals: 18, displayDecimals: 4 });\n}\n\n/**\n * Format a wei bigint as a 3-decimal gwei display string. Used by\n * direct-mode commands that emit gas balances and fee estimates.\n * Truncates rather than rounds — fees are display-only and operators\n * who need exact wei should use `--json` (which preserves the bigint\n * as a decimal string).\n *\n * No thousand-separator on the whole part: the gwei convention in\n * the broader EVM ecosystem (etherscan, foundry, viem's display\n * helpers) renders bare integers, and operators piping our output\n * through `awk '{print $2 + 0}'` or similar rely on it.\n */\nexport function formatGwei(wei: bigint): string {\n return formatBigDecimal(wei, {\n baseDecimals: 9,\n displayDecimals: 3,\n thousandSeparator: false,\n });\n}\n\n/** Apply a status color (green/yellow/red/blue/gray) by status string. */\nexport function colorStatus(value: string | null | undefined): string {\n if (!value) return style.dim('-');\n switch (value.toUpperCase()) {\n case 'ACTIVE':\n case 'COMPLETED':\n return style.success(value);\n case 'EXECUTING':\n case 'VALIDATING':\n case 'PENDING':\n return style.cyan(value);\n case 'PENDING_CONFIRMATION':\n return style.warn(value);\n case 'RESOLVED':\n return style.info(value);\n case 'REJECTED':\n case 'FAILED':\n return style.error(value);\n case 'UNSEEDED':\n case 'FROZEN':\n return style.dim(value);\n default:\n return value;\n }\n}\n\n/** Build a cli-table3 with bold headers and consistent style. */\nexport function createTable(headers: string[]): Table.Table {\n return new Table({\n head: headers.map((h) => style.bold(h)),\n style: { head: [], border: [] },\n });\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/error-catalog.ts"],"sourcesContent":["/**\n * CLI error hierarchy + SDK-error mapper.\n *\n * The CliError shape is **the contract** between this CLI and any\n * agent or script that consumes it. The fields below are SemVer-stable\n * — additions are minor bumps, removals/renames are major bumps.\n *\n * Exit code convention:\n * 0 — success\n * 1 — generic error (validation, server, network, etc.)\n * 2 — auth failure (missing/invalid API key, missing scope)\n *\n * Mapping a `KashRateLimitError` to exit 1 is deliberate: a rate-limit\n * is recoverable, but the CLI should still fail loudly so scripts\n * don't silently move on. The `recoverable` boolean and `retryAfterMs`\n * field tell agents how to handle it.\n *\n * The `actions` array is the agent-friendly recovery path. Each entry\n * is one of a small, well-defined set of variants — agents can branch\n * on `actions[0].type` without parsing prose.\n *\n * **Catalog as source of truth.** Static fields (`recoverable`,\n * `docsUrl`, base `actions`) are read from\n * `error-catalog.ts#ERROR_CATALOG` based on the error's `code`, so\n * `kash explain RATE_LIMITED` always shows the same metadata as the\n * envelope on a real `RATE_LIMITED` failure. The `toCliError` mapper\n * adds runtime-only data (`retryAfterMs` from the server's\n * `Retry-After`, an extra `wait_and_retry` action derived from it).\n * Callers can override any field explicitly, but the default path\n * pulls from the catalog so drift is structurally impossible.\n */\n\nimport {\n KashAbortedError,\n KashAuthenticationError,\n KashAuthorizationError,\n KashConfigurationError as SdkKashConfigurationError,\n KashConflictError,\n KashError,\n KashMaintenanceError,\n KashNetworkError,\n KashNotFoundError,\n KashRateLimitError,\n KashServerError,\n KashTimeoutError,\n KashValidationError,\n} from '@kashdao/sdk';\n\nimport { lookupErrorCodeWithFallback } from './error-catalog.js';\n\n/** Exit codes used by the CLI. */\nexport const EXIT_CODES = {\n OK: 0,\n GENERIC: 1,\n AUTH: 2,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n\n/**\n * Machine-readable next-step hint. Agents inspect `type` and act\n * without parsing the human-prose `suggestion`. Adding new variants\n * is a minor bump (agents that don't recognise them ignore them);\n * removing or renaming is a major bump.\n *\n * **Templates.** A `run_command` action MAY carry `template: true` to\n * signal that `command` contains `<placeholder>` substrings that the\n * agent must substitute (or skip) before executing. Templates exist\n * because the static error catalog can't always know the concrete\n * command id / trade id / market id at the point the catalog is\n * authored — they're carved at runtime when the SDK error is mapped.\n * Agents that auto-execute `run_command` actions MUST honour the\n * `template` flag: substitute, prompt, or skip. Treating templated\n * commands as concrete will literally shell `kash trade status <id>`\n * (with the angle brackets) and fail.\n */\nexport type CliErrorAction =\n | {\n readonly type: 'run_command';\n readonly command: string;\n readonly description: string;\n /**\n * `true` when `command` contains `<placeholder>` tokens the\n * caller must substitute. Absent or `false` means the command\n * is concrete and safe to auto-execute. Agents that lack\n * substitution support should skip templated commands and fall\n * back to the catalog's `description` / `suggestion`.\n */\n readonly template?: boolean;\n }\n | { readonly type: 'set_env'; readonly variable: string; readonly description: string }\n | { readonly type: 'wait_and_retry'; readonly delayMs: number; readonly description: string }\n | { readonly type: 'open_url'; readonly url: string; readonly description: string }\n | { readonly type: 'check_input'; readonly field: string; readonly description: string };\n\nexport type CliErrorOptions = {\n readonly code: string;\n readonly suggestion?: string | undefined;\n readonly exitCode?: ExitCode;\n readonly requestId?: string | undefined;\n /**\n * Override the catalog's `recoverable`. If omitted the catalog's\n * value is used; if the code isn't in the catalog, defaults to\n * `false` via the UNEXPECTED fallback.\n */\n readonly recoverable?: boolean;\n /** Suggested delay before retrying. No catalog default. */\n readonly retryAfterMs?: number | undefined;\n /** Override the catalog's `docsUrl`. */\n readonly docsUrl?: string | undefined;\n /**\n * Additional `actions` to append to the catalog's static set. Use\n * this for runtime-derived hints (e.g. a `wait_and_retry` with the\n * server's exact Retry-After). Pass `actionsOverride` to replace\n * the catalog set entirely.\n */\n readonly actions?: readonly CliErrorAction[];\n /**\n * Replace the catalog's `actions` entirely (instead of appending\n * via `actions`). Use sparingly — the catalog is the source of\n * truth for static actions.\n */\n readonly actionsOverride?: readonly CliErrorAction[];\n readonly cause?: unknown;\n};\n\nexport class CliError extends Error {\n readonly code: string;\n readonly suggestion: string | undefined;\n readonly exitCode: ExitCode;\n readonly requestId: string | undefined;\n /** True iff a sensible retry/recovery path exists. */\n readonly recoverable: boolean;\n /** Suggested delay before retrying (rate limit, server error). */\n readonly retryAfterMs: number | undefined;\n /** Stable docs URL agents can fetch for richer context. */\n readonly docsUrl: string | undefined;\n /** Machine-readable next-step hints. Empty array if none. */\n readonly actions: readonly CliErrorAction[];\n override readonly cause: unknown;\n\n constructor(message: string, options: CliErrorOptions) {\n super(message);\n this.name = 'CliError';\n const catalogEntry = lookupErrorCodeWithFallback(options.code);\n this.code = options.code;\n this.suggestion = options.suggestion;\n this.exitCode = options.exitCode ?? EXIT_CODES.GENERIC;\n this.requestId = options.requestId;\n this.recoverable = options.recoverable ?? catalogEntry.recoverable;\n this.retryAfterMs = options.retryAfterMs;\n this.docsUrl = options.docsUrl ?? catalogEntry.docsUrl;\n if (options.actionsOverride !== undefined) {\n this.actions = options.actionsOverride;\n } else {\n // Caller-provided actions first (they're contextually specific:\n // a `wait_and_retry` derived from the server's actual\n // Retry-After, or a `check_input` naming a concrete bad field),\n // catalog actions second (generic fallbacks). Agents act on the\n // first applicable hint, so the more specific one needs to win.\n this.actions = [...(options.actions ?? []), ...catalogEntry.actions];\n }\n this.cause = options.cause;\n Error.captureStackTrace?.(this, this.constructor);\n }\n\n /**\n * Render the error as the stable JSON envelope agents pin to. Kept\n * as a method so the index.ts emitError can serialise consistently\n * regardless of caller.\n */\n toEnvelope(): Record<string, unknown> {\n return {\n ok: false,\n error: {\n code: this.code,\n message: this.message,\n recoverable: this.recoverable,\n ...(this.suggestion === undefined ? {} : { suggestion: this.suggestion }),\n ...(this.retryAfterMs === undefined ? {} : { retryAfterMs: this.retryAfterMs }),\n ...(this.docsUrl === undefined ? {} : { docsUrl: this.docsUrl }),\n ...(this.requestId === undefined ? {} : { requestId: this.requestId }),\n actions: this.actions,\n },\n };\n }\n}\n\nexport class CliValidationError extends CliError {\n constructor(message: string, suggestion?: string, field?: string) {\n super(message, {\n code: 'INVALID_INPUT',\n ...(suggestion === undefined ? {} : { suggestion }),\n ...(field === undefined\n ? {}\n : {\n actions: [\n {\n type: 'check_input' as const,\n field,\n description: `Verify the value of \"${field}\".`,\n },\n ],\n }),\n });\n this.name = 'CliValidationError';\n }\n}\n\nexport class CliConfigurationError extends CliError {\n constructor(message: string, suggestion?: string) {\n super(message, {\n code: 'CONFIGURATION',\n ...(suggestion === undefined ? {} : { suggestion }),\n });\n this.name = 'CliConfigurationError';\n }\n}\n\n/**\n * Translate any `unknown` error coming out of the SDK or the CLI\n * itself into a `CliError`. Pass-through for existing `CliError`\n * instances so callers can re-throw without re-wrapping.\n *\n * Each branch only sets runtime fields (suggestion, requestId,\n * retryAfterMs, runtime-derived actions). Static fields like\n * `recoverable`, `docsUrl`, and base `actions` come from the catalog\n * via the CliError constructor.\n */\nexport function toCliError(err: unknown): CliError {\n if (err instanceof CliError) {\n return err;\n }\n // Commander-thrown errors (we call `program.exitOverride()` so\n // unknown commands / unknown options surface here instead of\n // exiting via process.exit). Help and version short-circuits also\n // come through — they're not errors and exit cleanly.\n const commander = mapCommanderError(err);\n if (commander) return commander;\n if (err instanceof KashAuthenticationError) {\n return new CliError(err.message, {\n code: 'AUTH_REQUIRED',\n exitCode: EXIT_CODES.AUTH,\n suggestion:\n \"First-time setup: run 'kash setup' (interactive wizard). Otherwise: 'kash auth set-key' or set KASH_API_KEY.\",\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashAuthorizationError) {\n return new CliError(err.message, {\n code: 'INSUFFICIENT_SCOPE',\n exitCode: EXIT_CODES.AUTH,\n suggestion:\n 'The API key is valid but is missing the scope this command needs. Issue a key with broader scope under Settings → API Keys at https://app.kash.bot.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashRateLimitError) {\n const retrySec = err.retryAfterSeconds;\n const retryAfterMs = retrySec === undefined ? undefined : retrySec * 1000;\n const suggestion =\n retrySec !== undefined\n ? `Retry in ${String(retrySec)}s. Upgrade for higher limits: https://kash.bot/pricing`\n : 'Slow down request rate. Upgrade for higher limits: https://kash.bot/pricing';\n return new CliError(err.message, {\n code: 'RATE_LIMITED',\n suggestion,\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n ...(retryAfterMs === undefined\n ? {}\n : {\n actions: [\n {\n type: 'wait_and_retry' as const,\n delayMs: retryAfterMs,\n description: `Wait ${String(retrySec)}s then re-run the same command.`,\n },\n ],\n }),\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashNotFoundError) {\n return new CliError(err.message, {\n code: 'NOT_FOUND',\n suggestion: 'Double-check the resource id (markets and trades use UUIDs).',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashConflictError) {\n return new CliError(err.message, {\n code: 'CONFLICT',\n suggestion:\n 'A conflicting request is already in flight or the resource state changed underneath you. Inspect the trade with `kash trade status <id>` before retrying.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashValidationError) {\n return new CliError(err.message, {\n code: 'INVALID_INPUT',\n suggestion: 'Verify the request shape matches `kash <command> --help`.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashMaintenanceError) {\n const retrySec = err.retryAfterSeconds;\n const retryAfterMs = retrySec === undefined ? undefined : retrySec * 1000;\n return new CliError(err.message, {\n code: 'MAINTENANCE',\n suggestion:\n 'The Kash trade pipeline is temporarily disabled (incident response or planned maintenance). Honor `retryAfterMs` and retry once the window closes.',\n ...(retryAfterMs === undefined ? {} : { retryAfterMs }),\n ...(retryAfterMs === undefined\n ? {}\n : {\n actions: [\n {\n type: 'wait_and_retry' as const,\n delayMs: retryAfterMs,\n description: `Wait ${String(retrySec)}s before retrying.`,\n },\n ],\n }),\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashTimeoutError) {\n return new CliError(err.message, {\n code: 'TIMEOUT',\n suggestion:\n 'The request exceeded the configured timeout. Retry, or pass --timeout-ms to raise the cap.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashNetworkError) {\n // Inspect the underlying cause for DNS-resolution failures so we\n // can route the user to the right recovery action — remind them that\n // the key prefix picks the host (live → production, test → staging)\n // rather than emitting a generic \"check connectivity\" line.\n const causeStr = `${String(err.message ?? '')} ${String((err.cause as Error)?.message ?? '')}`;\n const isDnsError =\n causeStr.includes('ENOTFOUND') ||\n causeStr.includes('getaddrinfo') ||\n causeStr.includes('EAI_AGAIN') ||\n causeStr.includes('Could not resolve');\n const suggestion = isDnsError\n ? 'The configured API host did not resolve in DNS. ' +\n 'A `kash_live_*` key auto-routes to production ' +\n '(`https://api.kash.bot/v1`); a `kash_test_*` key auto-routes to ' +\n 'staging (`https://api-staging.kash.bot/v1`). ' +\n 'For a custom host, pass `--base-url <url>` or set `KASH_BASE_URL`. ' +\n 'Check your network/DNS and retry.'\n : 'The request did not reach the API. Check network connectivity and retry.';\n return new CliError(err.message, {\n code: 'NETWORK',\n suggestion,\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashAbortedError) {\n return new CliError(err.message, {\n code: 'ABORTED',\n suggestion:\n 'The request was cancelled before it completed. If the command is idempotent, you can safely retry with the same Idempotency-Key.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof KashServerError) {\n return new CliError(err.message, {\n code: 'SERVER_ERROR',\n suggestion:\n 'The API returned a 5xx after retries. The request is safe to retry; if the failure persists, file a bug at https://github.com/KashDAO/cli/issues with the requestId.',\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof SdkKashConfigurationError) {\n // Surface the first Zod issue's path as a check_input action so\n // an agent can localise the broken field without parsing prose.\n const firstIssue = err.issues[0];\n const fieldPath = firstIssue?.path.join('.') ?? '';\n return new CliError(err.message, {\n code: 'CONFIGURATION',\n suggestion:\n firstIssue !== undefined\n ? `SDK rejected ${fieldPath || '(root)'}: ${firstIssue.message}`\n : 'The SDK rejected the configuration provided to the client.',\n ...(fieldPath\n ? {\n actions: [\n {\n type: 'check_input' as const,\n field: fieldPath,\n description: `Fix the value of \"${fieldPath}\" and re-run.`,\n },\n ],\n }\n : {}),\n cause: err,\n });\n }\n // ── Protocol-SDK (`@kashdao/protocol-sdk`) errors ───────────────\n // We don't eager-import the protocol-sdk just to use `instanceof`\n // checks (it pulls in viem). Duck-type on `err.name` instead — the\n // protocol-sdk's error classes set their `name` field deterministically\n // in the base constructor.\n const protocolErrorMapping = mapProtocolError(err);\n if (protocolErrorMapping !== undefined) {\n return protocolErrorMapping;\n }\n if (err instanceof KashError) {\n // Any KashError subclass we haven't enumerated above. Falls back\n // to the catalog's UNEXPECTED entry for `recoverable`/`docsUrl`\n // (so `kash explain` always returns *something*) but preserves\n // the SDK's `isRetryable` value.\n return new CliError(err.message, {\n code: 'UNEXPECTED',\n recoverable: err.isRetryable,\n ...(err.requestId === undefined ? {} : { requestId: err.requestId }),\n cause: err,\n });\n }\n if (err instanceof Error) {\n return new CliError(err.message, { code: 'UNEXPECTED', cause: err });\n }\n return new CliError(String(err), { code: 'UNEXPECTED', cause: err });\n}\n\n/**\n * Structural shape of Commander's `CommanderError`. Commander documents\n * `code` and `message` as stable public API and namespaces every code\n * with the `commander.` prefix (`commander.unknownCommand`,\n * `commander.help`, etc.).\n *\n * We type-guard against this shape rather than `instanceof CommanderError`\n * because importing the constructor here would force the Commander\n * module to load on the cold path even for invocations that never\n * touch it. Going through a structural check keeps the import lazy\n * AND keeps TypeScript safety at every use site.\n */\nexport type CommanderErrorLike = {\n readonly code: string;\n readonly message: string;\n};\n\n/**\n * Type guard — true iff `err` looks like a Commander-thrown error.\n * Commander always sets `code` to a string starting with `commander.`,\n * so the prefix check is the load-bearing test (filters out other\n * errors that happen to have a `code` field, e.g. `EACCES`).\n */\nexport function isCommanderError(err: unknown): err is CommanderErrorLike {\n if (!(err instanceof Error)) return false;\n const candidate = err as { code?: unknown; message?: unknown };\n return (\n typeof candidate.code === 'string' &&\n candidate.code.startsWith('commander.') &&\n typeof candidate.message === 'string'\n );\n}\n\n/**\n * Map a Commander-thrown error to either a clean exit (help/version)\n * or a structured `CliError` (unknown command, unknown option, missing\n * argument, etc.). Returns undefined for non-Commander errors so the\n * outer mapper can keep walking its switch.\n */\nfunction mapCommanderError(err: unknown): CliError | undefined {\n if (!isCommanderError(err)) return undefined;\n const { code, message } = err;\n\n // `commander.help`, `commander.helpDisplayed`, `commander.version` —\n // user asked for `--help` or `--version`. Commander already wrote\n // the output; surfacing this as a real error would be wrong. Use\n // `EXIT_CODES.OK` and code `'NOOP'` so the top-level boundary in\n // `index.ts` exits cleanly and prints nothing extra.\n if (\n code === 'commander.help' ||\n code === 'commander.helpDisplayed' ||\n code === 'commander.version'\n ) {\n return new CliError('', {\n code: 'NOOP',\n exitCode: EXIT_CODES.OK,\n recoverable: false,\n cause: err,\n });\n }\n\n // Unknown command — the most common typo case. Commander appends\n // a \"Did you mean X?\" suggestion to the message; we extract it so\n // the structured envelope carries a `run_command` recovery action\n // an agent can execute directly.\n if (code === 'commander.unknownCommand') {\n const match = /Did you mean (\\S+?)\\??\\)?$/m.exec(message);\n const suggested = match?.[1];\n const suggestion = suggested\n ? `Did you mean \\`kash ${suggested}\\`? Run \\`kash --help\\` for the full command tree.`\n : 'Run `kash --help` for the full command tree.';\n return new CliError(stripTrailingNewlines(message), {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion,\n ...(suggested === undefined\n ? {}\n : {\n actions: [\n {\n type: 'run_command' as const,\n command: `kash ${suggested}`,\n description: 'Run the suggested command instead.',\n },\n ],\n }),\n cause: err,\n });\n }\n\n // Unknown option — adjacent typo case. Commander doesn't always\n // include a suggestion for options; fall back to a generic check.\n if (code === 'commander.unknownOption') {\n return new CliError(stripTrailingNewlines(message), {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion:\n 'Run `kash <command> --help` for the supported flags, or `kash docs --json` for the full surface.',\n cause: err,\n });\n }\n\n // Missing required argument / option — Commander surfaces these\n // before the action runs. Keep the original message (it names the\n // flag) and add a generic check_input action.\n if (\n code === 'commander.missingArgument' ||\n code === 'commander.missingMandatoryOptionValue' ||\n code === 'commander.optionMissingArgument'\n ) {\n return new CliError(stripTrailingNewlines(message), {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion: 'Run the command with `--help` to see required arguments.',\n cause: err,\n });\n }\n\n // Anything else from Commander (excess arguments, invalid choice,\n // etc.) — generic mapping with the original message preserved.\n return new CliError(stripTrailingNewlines(message), {\n code: 'INVALID_INPUT',\n recoverable: true,\n cause: err,\n });\n}\n\n/** Trim trailing newlines so error messages don't render double-spaced. */\nfunction stripTrailingNewlines(s: string): string {\n return s.replace(/\\n+$/, '');\n}\n\n/**\n * Map an `@kashdao/protocol-sdk` error to the corresponding CLI code,\n * by class name. Returns `undefined` if the error is not a recognised\n * protocol-sdk error.\n *\n * **Why duck-typing instead of `instanceof`?** Importing the\n * protocol-sdk eagerly here would defeat the cold-start optimisation\n * that lazy-loads `@kashdao/protocol-sdk` only when `kash protocol …`\n * commands run. Kash-orchestrated-only invocations (markets/trade/portfolio)\n * keep their fast path. The protocol-sdk's error base class sets\n * `name` to the constructor name in its constructor, so a name check\n * is reliable across module-instance boundaries.\n */\nfunction mapProtocolError(err: unknown): CliError | undefined {\n if (!(err instanceof Error)) return undefined;\n switch (err.name) {\n case 'KashConfigError': {\n const cliErr = new CliError(err.message, {\n code: 'DIRECT_CONFIG_MISSING',\n suggestion:\n 'Set the missing field via `kash config set <field> <value>` (rpcUrl, smartAccount, signerKeyRef, defaultChainId).',\n cause: err,\n });\n return cliErr;\n }\n case 'KashSignerError':\n return new CliError(err.message, {\n code: 'SIGNER_FAILED',\n suggestion: 'Verify the signerKeyRef target is readable (file:<path>) or set (env:<NAME>).',\n cause: err,\n });\n case 'KashChainError':\n return new CliError(err.message, {\n code: 'CHAIN_ERROR',\n suggestion: 'On-chain read or contract interaction failed unexpectedly.',\n cause: err,\n });\n case 'KashBundlerError':\n return new CliError(err.message, {\n code: 'BUNDLER_REJECTED',\n suggestion: 'Inspect the bundler-specific reason in the message and adjust.',\n cause: err,\n });\n case 'KashSimulationRevertedError':\n return new CliError(err.message, {\n code: 'TRANSACTION_REVERTED',\n suggestion: 'Re-run with `kash protocol simulate` to see the decoded revert reason.',\n cause: err,\n });\n case 'KashProtocolError':\n // Base class — ChainError is the closest fallback for any\n // protocol-sdk error not covered above.\n return new CliError(err.message, {\n code: 'CHAIN_ERROR',\n suggestion: 'Unrecognised protocol-sdk error. File an issue with `kash version --json`.',\n cause: err,\n });\n default:\n return undefined;\n }\n}\n","/**\n * Single source of truth for every error `code` the CLI emits.\n *\n * Both `toCliError` (the SDK-error mapper) and `kash explain <code>`\n * read from this catalog so an AI agent that hits a `RATE_LIMITED`\n * error and asks `kash explain RATE_LIMITED --json` gets the same\n * `recoverable`, `docsUrl`, and `actions` it would have seen on the\n * error envelope.\n *\n * Adding a new code: append an entry. Removing one: major bump.\n * Renaming a field: major bump.\n *\n * Runtime-only data (the server's `retryAfterMs`, the specific\n * `requestId`, an extra `wait_and_retry` action computed from the\n * Retry-After header) is layered on top by `toCliError` — the\n * catalog is for static metadata only.\n */\n\nimport type { CliErrorAction } from './errors.js';\n\nexport type ErrorCatalogEntry = {\n /** Stable machine-readable code. */\n readonly code: string;\n /** One-sentence summary in plain English. */\n readonly summary: string;\n /** Longer explanation suitable for human troubleshooting. */\n readonly description: string;\n /** Whether retrying the original request might succeed. */\n readonly recoverable: boolean;\n /** Stable docs URL, when one exists. */\n readonly docsUrl?: string;\n /**\n * Concrete recovery steps the agent can take. These are the\n * *static* actions for this code; runtime-only actions (e.g. a\n * `wait_and_retry` derived from the server's Retry-After header)\n * are appended by `toCliError`.\n */\n readonly actions: readonly CliErrorAction[];\n};\n\nexport const ERROR_CATALOG: readonly ErrorCatalogEntry[] = [\n {\n code: 'AUTH_REQUIRED',\n summary: 'No API key was provided, or the key is invalid / expired / revoked.',\n description:\n 'The Kash public API requires a kash_live_… or kash_test_… key on every authenticated route. First-time users should run `kash setup` (interactive wizard). Existing users can `kash auth set-key`, set KASH_API_KEY, or pass --profile to switch to a stored profile.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/authentication',\n actions: [\n {\n type: 'run_command',\n command: 'kash setup',\n description: 'First-run wizard — issues a key, configures profile, validates it.',\n },\n {\n type: 'run_command',\n command: 'kash auth set-key',\n description:\n 'Store an API key for the active profile (paste interactively or pipe via stdin).',\n },\n {\n type: 'set_env',\n variable: 'KASH_API_KEY',\n description: 'Provide the key via environment variable.',\n },\n {\n type: 'open_url',\n url: 'https://app.kash.bot',\n description:\n 'Create an API key under Settings → API Keys in the Kash app (`Live` for Base mainnet, `Test` for Base Sepolia).',\n },\n ],\n },\n {\n code: 'INSUFFICIENT_SCOPE',\n summary: 'The API key is valid but lacks the scope this command requires.',\n description:\n \"Authentication succeeded but the key's scope (read-only / trade / admin) doesn't cover the route. Request a key with broader scope, or move to a tier that includes it.\",\n recoverable: true,\n docsUrl: 'https://docs.kash.bot/developer-docs/rest-api/authentication',\n actions: [\n {\n type: 'open_url',\n url: 'https://app.kash.bot',\n description: 'Issue a key with broader scope under Settings → API Keys in the Kash app.',\n },\n ],\n },\n {\n code: 'RATE_LIMITED',\n summary: 'You have exceeded the per-key rate limit for this tier.',\n description:\n 'Slow down or upgrade for higher limits. The error envelope carries `retryAfterMs`; honor it via `kash --max-retries` or back off in your application.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/api/rate-limits',\n actions: [\n {\n type: 'open_url',\n url: 'https://kash.bot/pricing',\n description: 'Upgrade tier for higher rate limits.',\n },\n ],\n },\n {\n code: 'NOT_FOUND',\n summary: 'The requested resource (market, trade, position) does not exist.',\n description:\n 'Markets and trades are identified by UUID. Confirm the id is correct (especially after copy-paste truncation) and that the resource is visible to the active key.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/api/errors',\n actions: [],\n },\n {\n code: 'CONFLICT',\n summary: 'A conflicting request is already in flight or the resource state changed.',\n description:\n 'Common cases: you sent a duplicate Idempotency-Key, the trade is awaiting high-value confirmation, or the market closed between fetch and trade. Inspect the resource before retrying.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/api/errors',\n actions: [\n {\n type: 'run_command',\n command: 'kash trade status <id>',\n description: 'Inspect the conflicting trade resource. Substitute <id> with the trade UUID.',\n template: true,\n },\n ],\n },\n {\n code: 'INVALID_INPUT',\n summary: 'The request body or arguments failed validation.',\n description:\n 'Check the field names and types against `kash <command> --help` or `kash schema <command>`. USDC amounts are decimal strings with up to 6 fractional digits.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/commands',\n actions: [\n {\n type: 'run_command',\n command: 'kash <command> --help',\n description:\n 'Inspect the command signature. Substitute <command> with the failing path (e.g. `trade buy`, `markets list`).',\n template: true,\n },\n {\n type: 'run_command',\n command: 'kash schema <command>',\n description:\n 'Get the JSON Schema for the command inputs. Substitute <command> with the failing path.',\n template: true,\n },\n ],\n },\n {\n code: 'MAINTENANCE',\n summary: 'The Kash trade pipeline is temporarily disabled (kill switch).',\n description:\n 'API trade processing is halted, typically during incident response or planned maintenance. Read state is unaffected. Honor the `retryAfterMs` and retry once the window closes.',\n recoverable: true,\n docsUrl: 'https://docs.kash.bot/developer-docs/api-errors/API_TRADE_PROCESSING_HALTED',\n actions: [\n {\n type: 'wait_and_retry',\n delayMs: 30_000,\n description: 'Wait 30s then retry. Surface the requestId if the failure persists.',\n },\n ],\n },\n {\n code: 'TIMEOUT',\n summary: 'The request exceeded the SDK timeout (default 30s).',\n description:\n 'Either the server is slow or the network path is degraded. Retry, or pass --timeout-ms to raise the cap. Repeated timeouts are worth investigating against the status page.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/troubleshooting',\n actions: [\n {\n type: 'run_command',\n command: 'kash --timeout-ms 60000 <same command>',\n description:\n 'Re-run with a longer timeout. Substitute <same command> with the original invocation tail.',\n template: true,\n },\n ],\n },\n {\n code: 'NETWORK',\n summary: 'A transport-layer failure (DNS, TLS, connection refused) before any HTTP response.',\n description:\n 'The SDK never received a response. Check connectivity to api.kash.bot. The CLI retries network errors automatically; this means retries were exhausted.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/troubleshooting',\n actions: [],\n },\n {\n code: 'ABORTED',\n summary: 'The request was cancelled by the caller before it completed.',\n description:\n 'An AbortSignal you passed (or the spinner you cancelled) fired while the request was in flight. The server may or may not have processed the request — if it did, the side effect already landed. Idempotent requests can be safely retried with the same Idempotency-Key.',\n recoverable: false,\n docsUrl: 'https://kash.bot/docs/cli/troubleshooting',\n actions: [],\n },\n {\n code: 'SERVER_ERROR',\n summary: 'The API returned a 5xx response after retries.',\n description:\n 'The request is safe to retry. If the issue persists, file a bug at https://github.com/KashDAO/cli/issues with the requestId on the error envelope.',\n recoverable: true,\n docsUrl: 'https://docs.kash.bot/developer-docs/api-errors/DEPENDENCY_UNAVAILABLE',\n actions: [\n {\n type: 'wait_and_retry',\n delayMs: 5_000,\n description: 'Wait 5s and retry. The CLI may have already exhausted its retry budget.',\n },\n ],\n },\n {\n code: 'CONFIGURATION',\n summary: 'The CLI configuration file or environment is invalid.',\n description:\n \"The on-disk ~/.kash/config.json failed to parse, an env var (KASH_CHAIN_ID) doesn't match its expected shape, or a per-invocation flag (--max-retries, --timeout-ms, --base-url) was rejected by the SDK. Run `kash config show` to inspect what loaded.\",\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/configuration',\n actions: [\n {\n type: 'run_command',\n command: 'kash config show',\n description: 'Inspect the loaded configuration and its sources.',\n },\n ],\n },\n // ─── Direct-mode (kash protocol ...) ─────────────────────────────\n {\n code: 'DIRECT_CONFIG_MISSING',\n summary: 'Direct-mode configuration is incomplete.',\n description:\n \"Direct-mode commands (`kash protocol ...`) require RPC URL, smart account address, signer key reference, and chain ID. One or more of these is missing from the active profile and the environment. Run `kash config show` to see what's loaded; set the missing fields with `kash config set rpcUrl …`, `kash config set smartAccount 0x…`, etc.\",\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/direct-mode',\n actions: [\n {\n type: 'run_command',\n command: 'kash config show',\n description: 'Inspect the loaded configuration and source attribution.',\n },\n {\n type: 'run_command',\n command: 'kash config set rpcUrl https://your-rpc.example.com',\n description: 'Set the RPC URL for direct-mode operations.',\n },\n ],\n },\n {\n code: 'SIGNER_FAILED',\n summary: 'The configured signer (file/env/KMS) failed to load or sign.',\n description:\n \"The signer adapter referenced by `signerKeyRef` couldn't load the private key, or signing the UserOp hash failed. Common causes: missing/unreadable file, missing env var, malformed hex, or a KMS permission denial.\",\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/direct-mode',\n actions: [\n {\n type: 'check_input',\n field: 'signerKeyRef',\n description: 'Verify the signer reference (file:<path> or env:<VAR>) and its target.',\n },\n ],\n },\n {\n code: 'RPC_FAILED',\n summary: 'The RPC endpoint refused the request or timed out.',\n description:\n 'Network call to the configured `rpcUrl` failed. Could be a rate-limit at the RPC provider, a transient network issue, or a misconfigured URL. The protocol-sdk does NOT retry RPC calls — fail fast so the operator sees the issue.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/troubleshooting',\n actions: [\n {\n type: 'check_input',\n field: 'rpcUrl',\n description: 'Verify the RPC URL is reachable and the API key (if any) is valid.',\n },\n ],\n },\n {\n code: 'BUNDLER_REJECTED',\n summary: 'The bundler refused to relay the UserOp.',\n description:\n 'Common rejection reasons: replacement-underpriced, sender-mempool-full, gas estimation drift, or a UserOp that the bundler suspects will revert. The error message carries the bundler-specific reason verbatim.',\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/direct-mode',\n actions: [],\n },\n {\n code: 'TRANSACTION_REVERTED',\n summary: 'The UserOp executed but the on-chain call reverted.',\n description:\n 'The transaction landed on-chain but the contract call reverted. The error message carries the decoded revert reason when the protocol-sdk recognises it (e.g. `MarketFrozen`, `InsufficientReserve`). Re-running with `kash protocol simulate` first will catch most reverts before they cost gas.',\n recoverable: false,\n docsUrl: 'https://kash.bot/docs/cli/direct-mode',\n actions: [\n {\n type: 'run_command',\n command:\n 'kash protocol simulate <market-address> --action <buy|sell> --outcome <i> --amount <n>',\n description:\n 'Dry-run the trade against current chain state before re-submitting. Substitute every <placeholder>.',\n template: true,\n },\n ],\n },\n {\n code: 'CHAIN_ERROR',\n summary: 'A protocol-level chain interaction failed.',\n description:\n \"An on-chain read or simulation returned an unexpected shape, decoded to an unknown revert, or the contract addresses don't match the configured chain ID. Verify the chain ID and that the protocol contracts are deployed at the expected addresses for that chain.\",\n recoverable: false,\n docsUrl: 'https://kash.bot/docs/cli/direct-mode',\n actions: [\n {\n type: 'check_input',\n field: 'chainId',\n description: 'Confirm chainId matches the network your RPC and bundler target.',\n },\n ],\n },\n {\n code: 'UNEXPECTED',\n summary: 'An unrecognised error escaped the SDK or the CLI.',\n description:\n \"This means the CLI's error mapper didn't recognise the underlying failure — the most likely cause is an SDK or runtime issue. File an issue with the message, the command, and the runtime info from `kash version --json`.\",\n recoverable: false,\n docsUrl: 'https://github.com/KashDAO/cli/issues',\n actions: [\n {\n type: 'run_command',\n command: 'kash version --json',\n description: 'Capture runtime info to attach to the bug report.',\n },\n ],\n },\n {\n code: 'NOOP',\n summary: 'No-op exit (Commander emitted output and asked us to stop).',\n description:\n \"Commander's help/version paths don't represent a failure — it printed `--help` or `--version` output and signalled the CLI to exit cleanly. This code surfaces in JSON-output contexts so consumers know the run completed without doing real work; the human path exits 0 with no error envelope.\",\n recoverable: true,\n docsUrl: 'https://kash.bot/docs/cli/exit-codes',\n actions: [],\n },\n];\n\nconst CATALOG_BY_CODE = new Map<string, ErrorCatalogEntry>(\n ERROR_CATALOG.map((entry) => [entry.code, entry])\n);\n\nexport function lookupErrorCode(code: string): ErrorCatalogEntry | undefined {\n return CATALOG_BY_CODE.get(code);\n}\n\n/**\n * Resolve the catalog entry for a code, falling back to the\n * `UNEXPECTED` entry when the code isn't recognised.\n *\n * The fallback exists so opaque SDK codes (e.g. a new `KashError`\n * subclass that hasn't been mapped CLI-side yet) still produce a\n * usable `kash explain <code>` response — the agent learns \"we don't\n * recognise this code, file an issue\" instead of \"Unknown error\n * code\", which would be a dead end.\n */\nexport function lookupErrorCodeWithFallback(code: string): ErrorCatalogEntry {\n const entry = CATALOG_BY_CODE.get(code);\n if (entry) return entry;\n // The UNEXPECTED entry is always present; safe to assert.\n return CATALOG_BY_CODE.get('UNEXPECTED')!;\n}\n\n/** Set of every catalog code, exposed for invariant tests. */\nexport const ERROR_CODES: ReadonlySet<string> = new Set(ERROR_CATALOG.map((e) => e.code));\n"],"mappings":"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","names":[]}
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- buildClient
4
- } from "./chunk-QALDZHTX.js";
5
- import "./chunk-N26VGVGB.js";
6
- import "./chunk-BVFDUI73.js";
7
- import "./chunk-KAM6KOFD.js";
8
- import "./chunk-MQUJG224.js";
9
- import "./chunk-KADB3OKE.js";
10
- import "./chunk-X2VM6VKM.js";
11
- export {
12
- buildClient
13
- };
14
- //# sourceMappingURL=client-75FVHGOH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/config/index.ts","../src/commands/config/export.ts","../src/commands/config/import.ts","../src/commands/config/profiles.ts","../src/commands/config/remove.ts","../src/commands/config/reset.ts","../src/commands/config/set.ts","../src/commands/config/show.ts","../src/commands/config/use.ts"],"sourcesContent":["/**\n * `kash config` — inspect and edit the local CLI configuration.\n */\n\nimport { Command } from 'commander';\n\nimport { exportConfigCommand } from './export.js';\nimport { importConfigCommand } from './import.js';\nimport { profilesCommand } from './profiles.js';\nimport { removeProfileCommand } from './remove.js';\nimport { resetConfigCommand } from './reset.js';\nimport { setConfigCommand } from './set.js';\nimport { showConfigCommand } from './show.js';\nimport { useProfileCommand } from './use.js';\n\nexport const configCommand = new Command('config')\n .description('Inspect and edit ~/.kash/config.json (multi-profile).')\n .addCommand(showConfigCommand)\n .addCommand(setConfigCommand)\n .addCommand(profilesCommand)\n .addCommand(useProfileCommand)\n .addCommand(removeProfileCommand)\n .addCommand(resetConfigCommand)\n .addCommand(exportConfigCommand)\n .addCommand(importConfigCommand);\n","/**\n * `kash config export` — dump the entire multi-profile config to\n * stdout (or a file via `--out`).\n *\n * **Default redaction.** API keys are replaced with the literal string\n * `<redacted>` so the dump is safe to commit to a shared bucket or\n * paste into a support ticket. Pass `--include-secrets` to opt into\n * round-trippable export (e.g. moving a profile to a new machine).\n *\n * **Round-trip pairing.** Output of this command is the canonical\n * input for `kash config import`. The file format mirrors the\n * on-disk shape: `{ version: 1, currentProfile, profiles: {...} }`.\n */\n\nimport { writeFile } from 'node:fs/promises';\n\nimport { Command } from 'commander';\n\nimport { CliError, toCliError } from '../../errors.js';\nimport { readWholeFile, type CliFile, type CliConfig } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson } from '../../utils/output.js';\n\nconst REDACTED = '<redacted>';\n\ntype ExportOptions = {\n out?: string;\n includeSecrets?: boolean;\n};\n\nexport const exportConfigCommand = new Command('export')\n .description('Dump the entire multi-profile config (API keys redacted by default).')\n .option('-o, --out <path>', 'write to a file instead of stdout (mode 0600)')\n .option('--include-secrets', 'include raw API keys in the export (round-trippable)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config export # safe-by-default; redacted JSON to stdout\n $ kash config export --out kash-config.json # write to a file (mode 0600)\n $ kash config export --include-secrets --out kash.json # round-trippable (DO NOT commit)\n\nNotes:\n - Without --include-secrets, every \\`apiKey\\` is replaced with \\`${REDACTED}\\` —\n safe to commit and share for debugging without leaking credentials.\n - The output is the canonical input for \\`kash config import\\`. Imports\n refuse to apply a profile whose apiKey is still \\`${REDACTED}\\`.\n - Use --out to route to a file the CLI can write at mode 0600. Stdout\n inherits whatever umask the parent shell has.\n`\n )\n .action(async (options: ExportOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n try {\n const file = await readWholeFile({\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n // Walk every profile and redact apiKey unless the caller asked\n // to include secrets. Other direct-mode fields (rpcUrl,\n // smartAccount, bundlerUrl, signerKeyRef) are kept as-is —\n // they're configuration, not secrets. Raw private keys never\n // live in the config (signerKeyRef is a `file:`/`env:` pointer).\n const sanitized: CliFile = {\n ...file,\n profiles: Object.fromEntries(\n Object.entries(file.profiles).map(([name, profile]) => [\n name,\n sanitizeProfile(profile, options.includeSecrets ?? false),\n ])\n ),\n };\n\n const payload = JSON.stringify(sanitized, null, 2);\n\n if (options.out) {\n try {\n await writeFile(options.out, `${payload}\\n`, { encoding: 'utf8', mode: 0o600 });\n if (!globals.json) {\n log.success(`Wrote ${options.out} (mode 0600).`);\n if (!options.includeSecrets) {\n log.info(\n `Secrets redacted. Pass --include-secrets to produce a round-trippable export.`\n );\n }\n }\n } catch (cause) {\n throw new CliError(`Failed to write ${options.out}.`, {\n code: 'CONFIGURATION',\n recoverable: true,\n suggestion: 'Verify the path is writable and the parent directory exists.',\n cause,\n });\n }\n return;\n }\n\n // No --out: dump JSON to stdout. Honor --json by emitting the\n // file shape (same payload, but routed through printJson so\n // pretty/compact respects --quiet). Without --json we still emit\n // JSON because that's the only sensible export format — but skip\n // the human-mode banner.\n if (globals.json) {\n printJson(sanitized);\n } else {\n // Plain stdout. Append a header to stderr (so it doesn't\n // pollute the JSON pipe) noting the redaction policy.\n if (!options.includeSecrets) {\n log.info(`API keys redacted. Pass --include-secrets for round-trippable export.`);\n }\n print(payload);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nfunction sanitizeProfile(profile: CliConfig, includeSecrets: boolean): CliConfig {\n if (includeSecrets) return profile;\n if (profile.apiKey === undefined) return profile;\n // Use a marker the importer can detect; real keys never collide\n // because they all start with `kash_`.\n return { ...profile, apiKey: REDACTED };\n}\n\nexport { REDACTED as REDACTED_API_KEY_MARKER };\n","/**\n * `kash config import` — merge a config bundle (produced by\n * `kash config export`) into the local config file.\n *\n * **Source.** Reads from `<file>` argument, or stdin when no argument\n * is given. The input must match the v1 file shape; anything else is\n * rejected as INVALID_INPUT.\n *\n * **Merge policy.** Profiles in the imported file are merged into the\n * existing profiles map. By default, existing profiles with the same\n * name are OVERWRITTEN. Pass `--no-overwrite` to skip those — useful\n * when restoring a backup against a partial config.\n *\n * **Redaction guard.** Profiles whose `apiKey` is still the literal\n * marker (`<redacted>` from `config export` without\n * `--include-secrets`) are refused with a clear error. We don't want\n * to silently overwrite a working key with a placeholder string.\n *\n * **currentProfile.** If the imported file specifies a\n * `currentProfile`, we use it — but only if that profile actually\n * lands in the merged file. Otherwise we keep the existing\n * `currentProfile` unchanged.\n */\n\nimport { readFile } from 'node:fs/promises';\n\nimport { Command } from 'commander';\n\nimport { CliError, toCliError } from '../../errors.js';\nimport {\n cliFileSchema,\n readWholeFile,\n writeWholeFile,\n type CliFile,\n type CliConfig,\n} from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\n\nimport { REDACTED_API_KEY_MARKER } from './export.js';\n\ntype ImportOptions = {\n // Commander stores `--no-overwrite` as `{ overwrite: false }` —\n // the default for a `--no-X` boolean option is `true`, so the\n // explicit `false` means the user passed `--no-overwrite`.\n overwrite?: boolean;\n dryRun?: boolean;\n};\n\nexport const importConfigCommand = new Command('import')\n .description('Merge a `kash config export` bundle into the local config (mode 0600).')\n .argument('[file]', 'path to a JSON bundle (omit to read from stdin)')\n .option('--no-overwrite', 'skip profiles whose name already exists locally')\n .option('--dry-run', 'preview the merge without writing to disk')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config import kash.json\n $ kash config export --include-secrets | ssh prod-host kash config import\n $ kash config import kash.json --no-overwrite # never replace existing profiles\n $ kash config import kash.json --dry-run --json # preview the merged result\n\nNotes:\n - The input format is exactly what \\`kash config export\\` produces.\n - Profiles whose apiKey is still \\`${REDACTED_API_KEY_MARKER}\\` are refused — re-export\n with --include-secrets to get a round-trippable bundle.\n - --dry-run emits the merged file shape without persisting it. Useful\n for diffing against the on-disk file before committing to a write.\n`\n )\n .action(async (file: string | undefined, options: ImportOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n try {\n const raw = await readSource(file);\n // Redaction check runs first on the raw JSON so users get the\n // \"you exported without --include-secrets\" message rather than\n // a generic schema-validation error (because `<redacted>`\n // doesn't match the `kash_` prefix the schema enforces).\n validateRedactionRaw(raw);\n const parsed = parseAndValidate(raw);\n\n const existing = await readWholeFile({\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n const merged = mergeFiles(existing, parsed, options.overwrite === false);\n\n if (options.dryRun === true) {\n if (globals.json) {\n printJson({ merged, written: false });\n } else {\n log.info('Dry run — no changes written.');\n print(JSON.stringify(merged, null, 2));\n }\n return;\n }\n\n await writeWholeFile(merged, {\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n if (globals.json) {\n printJson({\n merged,\n written: true,\n profiles: Object.keys(merged.profiles).sort(),\n currentProfile: merged.currentProfile ?? null,\n });\n return;\n }\n\n const importedNames = Object.keys(parsed.profiles);\n const merged_n = Object.keys(merged.profiles).length;\n log.success(\n `Imported ${String(importedNames.length)} profile(s); local config now has ${String(merged_n)} profile(s).`\n );\n if (merged.currentProfile) {\n log.info(`Active profile: ${style.bold(merged.currentProfile)}`);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nasync function readSource(file: string | undefined): Promise<string> {\n if (file !== undefined) {\n try {\n return await readFile(file, 'utf8');\n } catch (cause) {\n throw new CliError(`Failed to read ${file}.`, {\n code: 'CONFIGURATION',\n recoverable: true,\n suggestion: 'Verify the path exists and is readable.',\n cause,\n });\n }\n }\n // No file: read from stdin. process.stdin is async iterable in Node 22+.\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n // process.stdin emits Buffer in binary streams and string in\n // text mode; coerce both into Buffer so concat is well-typed.\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else if (chunk instanceof Buffer) {\n chunks.push(chunk);\n } else {\n chunks.push(Buffer.from(chunk as Uint8Array));\n }\n }\n if (chunks.length === 0) {\n throw new CliError('No input received on stdin.', {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion: 'Pass a path argument or pipe a `kash config export` bundle into stdin.',\n });\n }\n // Strip a leading UTF-8 BOM. Notepad / VSCode-with-utf8bom and many\n // Windows tools prepend U+FEFF to UTF-8 files; without the strip,\n // `JSON.parse` chokes on the leading non-whitespace character.\n const { stripBom } = await import('../../utils/stdin.js');\n return stripBom(Buffer.concat(chunks).toString('utf8'));\n}\n\nfunction parseAndValidate(raw: string): CliFile {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new CliError('Input is not valid JSON.', {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion:\n 'The bundle must match the output of `kash config export`. Re-run that command and pipe the result.',\n cause,\n });\n }\n const result = cliFileSchema.safeParse(parsed);\n if (!result.success) {\n const first = result.error.issues[0];\n throw new CliError(\n `Input does not match the config file shape${\n first ? `: ${first.path.join('.')}: ${first.message}` : '.'\n }`,\n {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion: 'Re-export from a known-good machine via `kash config export`.',\n }\n );\n }\n return result.data;\n}\n\n/**\n * Cheap raw-text scan for the redaction marker before strict schema\n * validation runs. The marker is a literal sentinel that real API\n * keys can't collide with (real keys start with `kash_`), so a\n * substring check is safe.\n */\nfunction validateRedactionRaw(raw: string): void {\n if (raw.includes(`\"apiKey\": \"${REDACTED_API_KEY_MARKER}\"`)) {\n throw new CliError('Bundle contains redacted API keys — cannot import.', {\n code: 'INVALID_INPUT',\n recoverable: true,\n suggestion:\n 'Re-run `kash config export --include-secrets` on the source machine to produce a round-trippable bundle.',\n });\n }\n}\n\nfunction mergeFiles(existing: CliFile, incoming: CliFile, noOverwrite: boolean): CliFile {\n const profiles: Record<string, CliConfig> = { ...existing.profiles };\n for (const [name, profile] of Object.entries(incoming.profiles)) {\n if (noOverwrite && name in profiles) continue;\n profiles[name] = profile;\n }\n\n // Decide currentProfile: incoming wins only if it points at a real\n // profile post-merge. Otherwise keep the existing setting.\n let currentProfile = existing.currentProfile;\n if (incoming.currentProfile && incoming.currentProfile in profiles) {\n currentProfile = incoming.currentProfile;\n }\n\n return {\n version: 1,\n ...(currentProfile === undefined ? {} : { currentProfile }),\n profiles,\n };\n}\n","/**\n * `kash config profiles` — list every profile in the config file.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { listProfiles } from '../../utils/config-store.js';\nimport { createTable } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\n\nexport const profilesCommand = new Command('profiles')\n .description('List configured profiles in the config file.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config profiles\n $ kash config profiles --json --quiet | jq -r '.profiles[]'\n`\n )\n .action(async (_opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n let result;\n try {\n result = await listProfiles({\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson(result);\n return;\n }\n\n if (result.profiles.length === 0) {\n log.info('No profiles configured.');\n log.detail('Hint', \"Run 'kash auth set-key <key>' to create the default profile.\");\n return;\n }\n\n const table = createTable(['Active', 'Profile']);\n for (const name of result.profiles) {\n table.push([name === result.current ? style.success('•') : ' ', name]);\n }\n print(table.toString());\n });\n","/**\n * `kash config remove <profile>` — delete a named profile from the\n * config file. Refuses to delete the active profile (consistent with\n * `kash auth logout` which only clears the apiKey).\n *\n * Symmetric with `kash config use` and `kash config profiles`: every\n * write surface a multi-profile setup needs is now a first-class\n * command.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { deleteProfile } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\nexport const removeProfileCommand = new Command('remove')\n .description('Delete a named profile from the config file.')\n .argument('<profile>', 'profile name to remove')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config remove staging\n $ kash config remove old-profile --json --quiet\n`\n )\n .action(async (profile: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n let updated;\n try {\n updated = await deleteProfile(profile, {\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson({\n ok: true,\n removed: profile,\n profiles: Object.keys(updated.profiles).sort(),\n });\n return;\n }\n log.success(`Profile \"${profile}\" removed.`);\n });\n","/**\n * `kash config reset` — delete the on-disk config file.\n *\n * Asks for confirmation when stdin is a TTY (the common interactive\n * case). In `--json` or `--quiet` mode, runs unconditionally so\n * scripts don't hang waiting for input.\n */\n\nimport readline from 'node:readline/promises';\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { deleteConfig, resolveConfigPathsForOverride } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\ntype ResetOptions = {\n yes?: boolean;\n};\n\nexport const resetConfigCommand = new Command('reset')\n .description('Delete ~/.kash/config.json.')\n .option('-y, --yes', 'skip the interactive confirmation')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config reset\n $ kash config reset --yes --json --quiet\n`\n )\n .action(async (options: ResetOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const paths = resolveConfigPathsForOverride(globals.configPath);\n\n const interactive = process.stdin.isTTY && !globals.quiet && !globals.json;\n const confirmed = options.yes || !interactive ? true : await confirm(paths.file);\n if (!confirmed) {\n log.info('Aborted.');\n return;\n }\n\n try {\n await deleteConfig({\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson({ ok: true, deleted: paths.file });\n return;\n }\n log.success(`Deleted ${paths.file}.`);\n });\n\nasync function confirm(path: string): Promise<boolean> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n try {\n const answer = await rl.question(`Delete ${path}? [y/N] `);\n return answer.trim().toLowerCase().startsWith('y');\n } finally {\n rl.close();\n }\n}\n","/**\n * `kash config set <key> <value>` — write a single config field.\n *\n * The value is parsed and validated by the same Zod schema used to\n * read the file, so corruption is impossible without bypassing the\n * CLI.\n *\n * Three field families:\n *\n * - **Kash-orchestrated** (API-backed): `apiKey`, `baseUrl`, `defaultChainId`.\n * - **Direct mode** (`kash protocol …`): `rpcUrl`, `smartAccount`,\n * `bundlerUrl`, `bundlerProvider`, `signerKeyRef`.\n * - **Custom chain** (Anvil / forks / sidechains, dot-path syntax):\n * `customChain.name`, `customChain.factoryAddress`, etc. Including\n * `customChain.smartAccount.factoryAddress`/`implementationAddress`/\n * `entryPointAddress` for SA mode on chains the protocol-sdk\n * registry doesn't cover.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport {\n cliConfigSchema,\n readConfig,\n updateConfig,\n type CliConfig,\n type UpdateConfigResult,\n} from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\nconst TOP_LEVEL_KEYS = [\n // Kash-orchestrated\n 'apiKey',\n 'baseUrl',\n 'defaultChainId',\n // Direct mode\n 'rpcUrl',\n 'smartAccount',\n 'bundlerUrl',\n 'bundlerProvider',\n 'signerKeyRef',\n] as const;\ntype TopLevelKey = (typeof TOP_LEVEL_KEYS)[number];\n\nconst CUSTOM_CHAIN_LEAVES = [\n 'name',\n 'factoryAddress',\n 'usdcAddress',\n 'oracleAddress',\n 'vaultAddress',\n 'tokens1155Address',\n 'paramRegistryAddress',\n] as const;\ntype CustomChainLeaf = (typeof CUSTOM_CHAIN_LEAVES)[number];\n\nconst CUSTOM_CHAIN_SA_LEAVES = [\n 'factoryAddress',\n 'implementationAddress',\n 'entryPointAddress',\n] as const;\ntype CustomChainSaLeaf = (typeof CUSTOM_CHAIN_SA_LEAVES)[number];\n\nconst ALL_KEYS_FOR_HELP = [\n ...TOP_LEVEL_KEYS,\n ...CUSTOM_CHAIN_LEAVES.map((l) => `customChain.${l}`),\n ...CUSTOM_CHAIN_SA_LEAVES.map((l) => `customChain.smartAccount.${l}`),\n];\n\nexport const setConfigCommand = new Command('set')\n .description('Set a single config field.')\n .argument(\n '<key>',\n 'top-level key OR `customChain.<leaf>` / `customChain.smartAccount.<leaf>` dot-path'\n )\n .argument('<value>', 'value to set')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config set baseUrl https://api-staging.kash.bot/v1 --profile staging\n $ kash config set defaultChainId 84532 --profile staging\n\nDirect-mode (kash protocol …):\n $ kash config set rpcUrl https://base-mainnet.g.alchemy.com/v2/... --profile mm\n $ kash config set smartAccount 0xabc... --profile mm\n $ kash config set signerKeyRef file:~/.kash/keys/mm-owner.key --profile mm\n $ kash config set bundlerProvider flashbots --profile mm\n\nCustom chain (local Anvil / forks / sidechains, bypasses static registry):\n $ kash config set defaultChainId 31337 --profile anvil\n $ kash config set rpcUrl http://localhost:8545 --profile anvil\n $ kash config set customChain.name \"Anvil local\" --profile anvil\n $ kash config set customChain.factoryAddress 0xCf7Ed... --profile anvil\n $ kash config set customChain.usdcAddress 0x5FbDB... --profile anvil\n $ kash config set customChain.smartAccount.factoryAddress 0x3Aa5e... --profile anvil\n`\n )\n .action(async (key: string, value: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n let patch: Partial<CliConfig>;\n try {\n patch = await buildPatchForKey(key, value, {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n let result: UpdateConfigResult;\n try {\n result = await updateConfig(patch, {\n ...(globals.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n // The resolved profile (from updateConfig) is the truth — when\n // the user runs `kash config set foo bar` with no flag, the\n // value lands in whatever profile the file's `currentProfile`\n // points at, NOT in the unconditional 'default'.\n const top = key.split('.', 1)[0] as keyof CliConfig;\n printJson({\n ok: true,\n key,\n value: result.stored[top] ?? null,\n profile: result.profile,\n });\n return;\n }\n log.success(`Set ${key} on profile \"${result.profile}\".`);\n });\n\nfunction isTopLevelKey(value: string): value is TopLevelKey {\n return (TOP_LEVEL_KEYS as readonly string[]).includes(value);\n}\n\nfunction isCustomChainLeaf(value: string): value is CustomChainLeaf {\n return (CUSTOM_CHAIN_LEAVES as readonly string[]).includes(value);\n}\n\nfunction isCustomChainSaLeaf(value: string): value is CustomChainSaLeaf {\n return (CUSTOM_CHAIN_SA_LEAVES as readonly string[]).includes(value);\n}\n\n/**\n * Resolve a (possibly dot-pathed) key to a partial-config patch. For\n * `customChain.*` paths we read-modify-write the existing object so\n * the user can set leaves one at a time without losing prior fields.\n */\nasync function buildPatchForKey(\n key: string,\n value: string,\n readOpts: { readonly profile?: string; readonly configPath?: string }\n): Promise<Partial<CliConfig>> {\n if (isTopLevelKey(key)) {\n return buildTopLevelPatch(key, value);\n }\n\n // customChain.<leaf> or customChain.smartAccount.<leaf> — read the\n // existing customChain object so partial sets compose, then validate\n // the merged shape against the full schema.\n if (key.startsWith('customChain.')) {\n const existing = await readConfig(readOpts);\n const existingChain = existing.customChain ?? {};\n const merged = mergeCustomChainLeaf(existingChain, key, value);\n const candidate: Partial<CliConfig> = { customChain: merged };\n // Validate the merged customChain against the schema. If the\n // user has only set a name + factoryAddress so far this will\n // fail the required usdcAddress check — that's the correct\n // behaviour: customChain on disk is always a complete object.\n cliConfigSchema.parse(candidate);\n return candidate;\n }\n\n throw new CliValidationError(\n `Unknown config key \"${key}\".`,\n `Allowed keys: ${ALL_KEYS_FOR_HELP.join(', ')}.`\n );\n}\n\nfunction buildTopLevelPatch(key: TopLevelKey, value: string): Partial<CliConfig> {\n switch (key) {\n case 'apiKey':\n case 'baseUrl':\n case 'rpcUrl':\n case 'smartAccount':\n case 'bundlerUrl':\n case 'bundlerProvider':\n case 'signerKeyRef': {\n const candidate: Partial<CliConfig> = { [key]: value };\n cliConfigSchema.parse(candidate);\n return candidate;\n }\n case 'defaultChainId': {\n const n = Number.parseInt(value, 10);\n if (!Number.isFinite(n) || n <= 0) {\n throw new CliValidationError(\n 'defaultChainId must be a positive integer.',\n undefined,\n 'defaultChainId'\n );\n }\n const candidate: Partial<CliConfig> = { defaultChainId: n };\n cliConfigSchema.parse(candidate);\n return candidate;\n }\n }\n}\n\n/**\n * Merge a single dot-pathed leaf into the existing `customChain`\n * object. Handles both flat leaves (`customChain.factoryAddress`) and\n * the one nested level (`customChain.smartAccount.factoryAddress`).\n *\n * The returned object is then re-validated against the full\n * `customChainSchema` by the caller — leaves that violate the leaf\n * regex (e.g. malformed hex) surface their schema error there, and\n * the required-field check (factoryAddress + usdcAddress) ensures we\n * never persist a half-built customChain.\n */\nfunction mergeCustomChainLeaf(\n existing: NonNullable<CliConfig['customChain']> | Record<string, unknown>,\n key: string,\n value: string\n): NonNullable<CliConfig['customChain']> {\n const path = key.slice('customChain.'.length);\n\n if (path.startsWith('smartAccount.')) {\n const leaf = path.slice('smartAccount.'.length);\n if (!isCustomChainSaLeaf(leaf)) {\n throw new CliValidationError(\n `Unknown customChain.smartAccount leaf \"${leaf}\".`,\n `Allowed: ${CUSTOM_CHAIN_SA_LEAVES.map((l) => `customChain.smartAccount.${l}`).join(', ')}.`\n );\n }\n const sa = (existing as { smartAccount?: Record<string, unknown> }).smartAccount ?? {};\n return {\n ...(existing as NonNullable<CliConfig['customChain']>),\n smartAccount: { ...sa, [leaf]: value } as NonNullable<\n NonNullable<CliConfig['customChain']>['smartAccount']\n >,\n };\n }\n\n if (!isCustomChainLeaf(path)) {\n throw new CliValidationError(\n `Unknown customChain leaf \"${path}\".`,\n `Allowed: ${CUSTOM_CHAIN_LEAVES.map((l) => `customChain.${l}`).join(', ')}, customChain.smartAccount.<leaf>.`\n );\n }\n return {\n ...(existing as NonNullable<CliConfig['customChain']>),\n [path]: value,\n };\n}\n","/**\n * `kash config show` — print the resolved configuration.\n *\n * Sources are surfaced (env vs file vs default) so users can debug\n * \"why is my key not picking up?\" without reading the source.\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 { print, printJson, style } from '../../utils/output.js';\n\nexport const showConfigCommand = new Command('show')\n .description('Print the resolved CLI configuration.')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config show\n $ kash config show --profile staging\n $ kash config show --json --quiet | jq -r '.baseUrl'\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 // Shape pinned by `CliConfigEnvelopeSchema` in `cli-schemas.ts`.\n // Includes `authenticated` so it agrees with `auth status` —\n // agents that bind one shape can consume the other. Direct-mode\n // fields are always emitted (`null` when unset) so operators\n // can introspect the full profile via JSON.\n printJson({\n profile: config.profile,\n authenticated: Boolean(config.apiKey),\n apiKey: config.apiKey ? redact(config.apiKey) : null,\n baseUrl: config.baseUrl,\n defaultChainId: config.defaultChainId,\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 customChain: config.customChain ?? null,\n sources: config.sources,\n });\n return;\n }\n\n print('');\n print(` ${style.dim('Profile ')} ${config.profile} (${config.sources.profile})`);\n print(\n ` ${style.dim('API key ')} ${config.apiKey ? redact(config.apiKey) : '(unset)'} (${config.sources.apiKey})`\n );\n print(` ${style.dim('Base URL ')} ${config.baseUrl} (${config.sources.baseUrl})`);\n print(\n ` ${style.dim('Default chain ')} ${String(config.defaultChainId)} (${config.sources.defaultChainId})`\n );\n // Surface direct-mode fields when any are set. Skip the section\n // entirely on a Kash-orchestrated-only profile so human output\n // stays terse.\n const hasDirectMode =\n config.rpcUrl !== undefined ||\n config.smartAccount !== undefined ||\n config.bundlerUrl !== undefined ||\n config.bundlerProvider !== undefined ||\n config.signerKeyRef !== undefined;\n if (hasDirectMode) {\n print('');\n print(` ${style.dim('Direct mode ')}`);\n print(\n ` ${style.dim(' RPC URL ')} ${config.rpcUrl ?? '(unset)'} (${config.sources.rpcUrl})`\n );\n print(\n ` ${style.dim(' Smart account')} ${config.smartAccount ?? '(unset)'} (${config.sources.smartAccount})`\n );\n print(\n ` ${style.dim(' Bundler URL ')} ${config.bundlerUrl ?? '(unset)'} (${config.sources.bundlerUrl})`\n );\n print(\n ` ${style.dim(' Bundler kind ')} ${config.bundlerProvider ?? '(unset)'} (${config.sources.bundlerProvider})`\n );\n print(\n ` ${style.dim(' Signer ref ')} ${config.signerKeyRef ?? '(unset)'} (${config.sources.signerKeyRef})`\n );\n }\n\n // Custom-chain section — surfaces when the profile bypasses the\n // protocol-sdk's static chain registry (Anvil / forks / sidechains).\n if (config.customChain !== undefined) {\n const cc = config.customChain;\n print('');\n print(` ${style.dim('Custom chain ')} (${config.sources.customChain})`);\n print(` ${style.dim(' Name ')} ${cc.name}`);\n print(` ${style.dim(' Factory ')} ${cc.factoryAddress}`);\n print(` ${style.dim(' USDC ')} ${cc.usdcAddress}`);\n if (cc.oracleAddress) print(` ${style.dim(' Oracle ')} ${cc.oracleAddress}`);\n if (cc.vaultAddress) print(` ${style.dim(' Vault ')} ${cc.vaultAddress}`);\n if (cc.tokens1155Address) print(` ${style.dim(' Tokens1155 ')} ${cc.tokens1155Address}`);\n if (cc.paramRegistryAddress)\n print(` ${style.dim(' ParamRegistry')} ${cc.paramRegistryAddress}`);\n if (cc.smartAccount) {\n print(` ${style.dim(' Smart account')}`);\n print(` ${style.dim(' Factory ')} ${cc.smartAccount.factoryAddress}`);\n print(` ${style.dim(' Implement. ')} ${cc.smartAccount.implementationAddress}`);\n print(` ${style.dim(' EntryPoint ')} ${cc.smartAccount.entryPointAddress}`);\n }\n }\n });\n","/**\n * `kash config use <profile>` — switch the active profile by writing\n * the file's `currentProfile` field.\n *\n * **Existence check.** By default we refuse to switch to a profile\n * that doesn't already exist — `kash config use staing` (typo) used\n * to silently succeed and the next command would fail with a\n * confusing `AUTH_REQUIRED`. Now we surface the typo with a list of\n * known profile names. The \"set up a fresh profile\" flow opts in via\n * `--allow-new`: `kash config use newprofile --allow-new` followed by\n * `kash auth set-key --profile newprofile <key>`.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { readWholeFile, setCurrentProfile } from '../../utils/config-store.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { log, printJson } from '../../utils/output.js';\n\ntype UseProfileOptions = {\n allowNew?: boolean;\n};\n\nexport const useProfileCommand = new Command('use')\n .description('Switch the active profile (writes currentProfile to the config file).')\n .argument('<profile>', 'profile name')\n .option(\n '--allow-new',\n 'permit switching to a profile that does not yet exist (you must populate it via `kash auth set-key --profile <name>` afterwards)'\n )\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash config use staging\n $ kash config use prod --json --quiet\n $ kash config use newprofile --allow-new # explicitly create a fresh profile\n\nNotes:\n - By default \\`kash config use\\` refuses unknown profile names and\n lists the known ones — a typo of an existing profile name would\n otherwise surface later as a confusing AUTH_REQUIRED.\n - Use \\`--allow-new\\` for the bootstrapping flow when you genuinely\n want to switch to a not-yet-populated profile.\n`\n )\n .action(async (profile: string, options: UseProfileOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const configPathOpt =\n globals.configPath === undefined ? {} : { configPath: globals.configPath };\n\n // Existence check: load the file once to see which profiles\n // exist, then either surface a structured \"did you mean\" error or\n // proceed with the write.\n let knownProfiles: readonly string[];\n try {\n const file = await readWholeFile(configPathOpt);\n knownProfiles = Object.keys(file.profiles).sort();\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (!knownProfiles.includes(profile) && options.allowNew !== true) {\n const known = knownProfiles.length === 0 ? '(none yet)' : knownProfiles.join(', ');\n throw new CliValidationError(\n `Profile \"${profile}\" does not exist.`,\n `Known profiles: ${known}. Pass --allow-new to create + switch to a fresh profile (you'll then need to populate it with \\`kash auth set-key --profile ${profile}\\`).`,\n 'profile'\n );\n }\n\n let updated;\n try {\n updated = await setCurrentProfile(profile, configPathOpt);\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson({\n ok: true,\n currentProfile: updated.currentProfile,\n profiles: Object.keys(updated.profiles).sort(),\n // Surface whether this was a new-profile switch — agents can\n // pipe to `kash auth set-key --profile <p>` automatically when\n // `created` is true.\n created: !knownProfiles.includes(profile),\n });\n return;\n }\n log.success(`Active profile is now \"${profile}\".`);\n if (!knownProfiles.includes(profile)) {\n log.info(`Profile is empty. Populate it with: kash auth set-key --profile ${profile} <key>`);\n }\n });\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/eoa/index.ts","../src/utils/eoa-client.ts"],"sourcesContent":["/**\n * `kash eoa …` — non-custodial direct-to-chain operations using a\n * vanilla EOA (no smart account, no bundler).\n *\n * Wraps `@kashdao/protocol-sdk`'s `createEoaClient`. Best for:\n * - Market makers with existing EIP-1559 signing infra (web3signer,\n * Fireblocks, AWS-KMS, etc.).\n * - Operators who don't want to provision a bundler.\n * - Lowest per-trade gas overhead.\n *\n * Required profile fields:\n * - `rpcUrl` — consumer-owned RPC endpoint\n * - `defaultChainId`— chain to run on\n * - `signerKeyRef` — `file:<path>` or `env:<NAME>` for the EOA key\n *\n * EOA mode does NOT use `smartAccount`, `bundlerUrl`, or\n * `bundlerProvider` — they're SA-mode-only fields.\n *\n * **Surface parity with `kash protocol`.** This namespace mirrors the\n * SA-mode read commands and the trade-execution commands. The\n * UserOp-specific lifecycle (`userop build/simulate/submit/wait/...`)\n * doesn't apply to EOA mode — instead, EOA mode signs serialized\n * EIP-1559 transactions directly. The CLI's `eoa trade {buy,sell,close,approve}`\n * commands run the same all-in-one flow.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { buildEoaClient } from '../../utils/eoa-client.js';\nimport { formatAddress, formatGwei, formatUsdcAtomic } from '../../utils/formatting.js';\nimport {\n parseOptionalPositiveFloat,\n parseOptionalPositiveInt,\n parsePositiveInt,\n readGlobals,\n} from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\nimport {\n DEFAULT_SLIPPAGE_BPS,\n MAX_UINT256,\n type TradeOpSide,\n decimalToAtomicUsdc,\n decimalToAtomicWad,\n extractPartialHash,\n parseDeadlineSec,\n parseOutcomeIndex,\n parseSlippageBps,\n parseUppercaseSide,\n validateAddress,\n validateAddressOptional,\n} from '../../utils/trade-input.js';\n\n// ---------------------------------------------------------------------------\n// Reads: balance, market, quote, position, allowance, fees\n// ---------------------------------------------------------------------------\n\nconst balanceCommand = new Command('balance')\n .description(\n \"Read on-chain USDC + native gas balances for the EOA (defaults to signer's address).\"\n )\n .argument('[account]', \"address to read (default: signer's ownerAddress)\")\n .action(async (account: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const accountAddress = validateAddressOptional(account, 'account');\n try {\n const resolved = await buildEoaClient({ globals });\n const target = accountAddress ?? resolved.account;\n const [usdc, gas] = await Promise.all([\n resolved.client.account.usdcBalance(target),\n resolved.client.account.gasBalance(target),\n ]);\n\n const payload = {\n account: target,\n chainId: resolved.chainId,\n usdcAtomic: usdc.toString(),\n gasWei: gas.toString(),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(` ${style.dim('Account ')} ${formatAddress(target, 10, 8)}`);\n print(` ${style.dim('Chain ')} ${String(resolved.chainId)}`);\n print(` ${style.dim('USDC ')} ${formatUsdcAtomic(usdc.toString())}`);\n print(\n ` ${style.dim('Gas ')} ${formatGwei(gas)} gwei ${style.dim(`(${gas.toString()} wei)`)}`\n );\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst marketCommand = new Command('market')\n .description('Read on-chain market state (reserves, supplies, weights, derived probabilities).')\n .argument('<address>', 'market contract address (0x-prefixed)')\n .action(async (address: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const marketAddress = validateAddress(address, 'address');\n try {\n const resolved = await buildEoaClient({ globals });\n const state = await resolved.client.markets.state(marketAddress);\n const payload = {\n marketAddress: state.marketAddress,\n chainId: resolved.chainId,\n status: state.status,\n readAt: state.readAt.toString(),\n reserveWad: state.reserveWad.toString(),\n outcomes: state.outcomes.map((o) => ({\n index: o.index,\n outstandingTokensWad: o.outstandingTokensWad.toString(),\n weightWad: o.weightWad.toString(),\n probability: o.probability,\n })),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(` ${style.dim('Market ')} ${formatAddress(state.marketAddress, 10, 8)}`);\n print(` ${style.dim('Status ')} ${state.status}`);\n print(` ${style.dim('Outcomes ')} ${String(state.outcomes.length)}`);\n print('');\n for (const outcome of state.outcomes) {\n const pct = (outcome.probability * 100).toFixed(2);\n print(` [${String(outcome.index)}] p=${pct}%`);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\ntype QuoteOptions = { side: string; outcome: string; amount: string };\n\nconst quoteCommand = new Command('quote')\n .description('On-chain price quote for buying or selling an outcome.')\n .argument('<address>', 'market contract address')\n .requiredOption('-s, --side <side>', 'buy | sell')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-a, --amount <decimal>', 'USDC for buy / outcome tokens for sell')\n .action(async (address: string, options: QuoteOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const marketAddress = validateAddress(address, 'address');\n const side = parseUppercaseSide(options.side);\n const outcome = parseOutcomeIndex(options.outcome);\n const amount =\n side === 'BUY'\n ? decimalToAtomicUsdc(options.amount, 'amount')\n : decimalToAtomicWad(options.amount, 'amount');\n\n try {\n const resolved = await buildEoaClient({ globals });\n const quote = await resolved.client.markets.quote(marketAddress, {\n side,\n outcome,\n amount,\n });\n const payload = {\n side: quote.side,\n outcomeIndex: quote.outcomeIndex,\n amountIn: quote.amountIn.toString(),\n amountOut: quote.amountOut.toString(),\n reserveAfterWad: quote.reserveAfterWad.toString(),\n pricesAfterWad: quote.pricesAfterWad.map((p) => p.toString()),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(` ${style.dim('Side ')} ${quote.side}`);\n print(` ${style.dim('Outcome ')} ${String(quote.outcomeIndex)}`);\n print(` ${style.dim('In ')} ${quote.amountIn.toString()}`);\n print(` ${style.dim('Out ')} ${quote.amountOut.toString()}`);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst positionCommand = new Command('position')\n .description('Read on-chain outcome-token holdings (ERC-1155) for a market.')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .argument('[account]', \"address whose holdings to read (default: signer's)\")\n .action(async (market: string, account: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const marketAddress = validateAddress(market, 'market');\n const accountAddress = validateAddressOptional(account, 'account');\n try {\n const resolved = await buildEoaClient({ globals });\n const target = accountAddress ?? resolved.account;\n const position = await resolved.client.account.position(target, marketAddress);\n const payload = {\n account: target,\n marketAddress: position.marketAddress,\n chainId: resolved.chainId,\n numOutcomes: position.numOutcomes,\n holdings: position.holdings.map((h) => ({\n outcomeIndex: h.outcomeIndex,\n balanceWad: h.balanceWad.toString(),\n })),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(` ${style.dim('Account ')} ${formatAddress(target, 10, 8)}`);\n print(` ${style.dim('Market ')} ${formatAddress(position.marketAddress, 10, 8)}`);\n print('');\n for (const h of position.holdings) {\n print(` [${String(h.outcomeIndex)}] balance=${h.balanceWad.toString()} (WAD)`);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst allowanceCommand = new Command('allowance')\n .description('Read the on-chain USDC allowance from `account` to `spender`.')\n .argument('<spender>', 'spender contract address')\n .argument('[account]', \"owner address (default: signer's)\")\n .action(async (spender: string, account: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const spenderAddress = validateAddress(spender, 'spender');\n const accountAddress = validateAddressOptional(account, 'account');\n try {\n const resolved = await buildEoaClient({ globals });\n const owner = accountAddress ?? resolved.account;\n const allowance = await resolved.client.account.usdcAllowance(owner, spenderAddress);\n const payload = {\n owner,\n spender,\n chainId: resolved.chainId,\n allowanceAtomic: allowance.toString(),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(` ${style.dim('Owner ')} ${formatAddress(owner, 10, 8)}`);\n print(` ${style.dim('Spender ')} ${formatAddress(spender, 10, 8)}`);\n print(` ${style.dim('Allowance')} ${formatUsdcAtomic(allowance.toString())}`);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst feesCommand = new Command('fees')\n .description('EIP-1559 fee estimate for the configured chain.')\n .option('--blocks <n>', 'number of recent blocks to sample (default 4)')\n .option('--percentile <n>', 'priority-fee percentile per block (1-99, default 50)')\n .option('--base-multiplier <n>', 'multiplier on predicted next-block base fee (default 2.0)')\n .option('--priority-floor-gwei <n>', 'floor for maxPriorityFeePerGas in gwei (default 1)')\n .action(\n async (\n options: {\n blocks?: string;\n percentile?: string;\n baseMultiplier?: string;\n priorityFloorGwei?: string;\n },\n cmd: Command\n ) => {\n const globals = readGlobals(cmd);\n const blocks = parseOptionalPositiveInt(options.blocks, 'blocks');\n const percentile = parseOptionalPositiveInt(options.percentile, 'percentile');\n if (percentile !== undefined && (percentile < 1 || percentile > 99)) {\n throw new CliValidationError('--percentile must be between 1 and 99.');\n }\n const baseMultiplier = parseOptionalPositiveFloat(options.baseMultiplier, 'base-multiplier');\n const priorityFloorGwei = parseOptionalPositiveInt(\n options.priorityFloorGwei,\n 'priority-floor-gwei'\n );\n\n try {\n const resolved = await buildEoaClient({ globals });\n const estimate = await resolved.client.estimateFees({\n ...(blocks === undefined ? {} : { blockCount: blocks }),\n ...(percentile === undefined ? {} : { rewardPercentile: percentile }),\n ...(baseMultiplier === undefined ? {} : { baseMultiplier }),\n ...(priorityFloorGwei === undefined\n ? {}\n : { priorityFeeFloorWei: BigInt(priorityFloorGwei) * 10n ** 9n }),\n });\n\n const payload = {\n chainId: resolved.chainId,\n maxFeePerGas: estimate.maxFeePerGas.toString(),\n maxPriorityFeePerGas: estimate.maxPriorityFeePerGas.toString(),\n };\n if (globals.json) {\n printJson(payload);\n return;\n }\n print('');\n print(\n ` ${style.dim('maxFee ')} ${formatGwei(estimate.maxFeePerGas)} gwei (${estimate.maxFeePerGas.toString()} wei)`\n );\n print(\n ` ${style.dim('maxPrio ')} ${formatGwei(estimate.maxPriorityFeePerGas)} gwei (${estimate.maxPriorityFeePerGas.toString()} wei)`\n );\n } catch (cause) {\n throw toCliError(cause);\n }\n }\n );\n\n// ---------------------------------------------------------------------------\n// Trade execution: buy, sell, close, approve\n// ---------------------------------------------------------------------------\n\ntype SharedTradeOptions = {\n outcome?: string;\n slippageBps?: string;\n deadlineSec?: string;\n dryRun?: boolean;\n // Commander stores `--no-X` as `{ x: false }`. Default is undefined\n // (meaning the user did not pass the negative flag); explicit `false`\n // means they did. Same idiom as `--no-overwrite` in `config import`.\n simulate?: boolean;\n wait?: boolean;\n waitTimeoutMs?: string;\n};\n\ntype Side = TradeOpSide;\n\nconst tradeBuyCommand = new Command('buy')\n .description('One-shot BUY (EIP-1559 tx, signed locally and submitted to chain).')\n .argument('<market>', 'market contract address')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-a, --amount <usdc>', 'USDC to spend (decimal)')\n .option('--slippage-bps <n>', 'slippage tolerance in bps (default 50)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit')\n .option('--no-simulate', 'skip eth_call preflight')\n .option('--no-wait', 'fire-and-forget: return tx hash without waiting for inclusion')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .action(\n async (market: string, options: SharedTradeOptions & { amount: string }, cmd: Command) => {\n await runTrade('buy', market, options, cmd);\n }\n );\n\nconst tradeSellCommand = new Command('sell')\n .description('One-shot SELL.')\n .argument('<market>', 'market contract address')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-t, --tokens <amount>', 'outcome tokens to sell (WAD decimal)')\n .option('--slippage-bps <n>', 'slippage tolerance in bps (default 50)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit')\n .option('--no-simulate', 'skip eth_call preflight')\n .option('--no-wait', 'fire-and-forget')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .action(\n async (market: string, options: SharedTradeOptions & { tokens: string }, cmd: Command) => {\n await runTrade('sell', market, options, cmd);\n }\n );\n\nconst tradeCloseCommand = new Command('close')\n .description('Sell the entire EOA balance for an outcome.')\n .argument('<market>', 'market contract address')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .option('--slippage-bps <n>', 'slippage tolerance in bps (default 50)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit')\n .option('--no-simulate', 'skip eth_call preflight')\n .option('--no-wait', 'fire-and-forget')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .action(async (market: string, options: SharedTradeOptions, cmd: Command) => {\n await runTrade('close', market, options, cmd);\n });\n\nconst tradeApproveCommand = new Command('approve')\n .description('USDC approval — required once before the first BUY.')\n .argument('<spender>', 'spender contract address (typically a Market)')\n .option('-a, --amount <usdc>', 'atomic-USDC amount (default unlimited)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit')\n .option('--no-simulate', 'skip eth_call preflight')\n .option('--no-wait', 'fire-and-forget')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .action(\n async (\n spender: string,\n options: {\n amount?: string;\n dryRun?: boolean;\n simulate?: boolean;\n wait?: boolean;\n waitTimeoutMs?: string;\n },\n cmd: Command\n ) => {\n const globals = readGlobals(cmd);\n const spenderAddress = validateAddress(spender, 'spender');\n const amount = options.amount ? decimalToAtomicUsdc(options.amount, 'amount') : MAX_UINT256;\n const waitTimeoutMs = options.waitTimeoutMs\n ? parsePositiveInt(options.waitTimeoutMs, 'wait-timeout-ms')\n : undefined;\n\n try {\n const resolved = await buildEoaClient({ globals });\n const params = {\n account: resolved.account,\n spender: spenderAddress,\n amount,\n };\n\n if (options.dryRun === true) {\n const built = await resolved.client.trades.prepareApprove(params, {\n simulate: options.simulate !== false,\n });\n emitDryRun('approve', spender, built, globals.json);\n return;\n }\n\n const sendOptions = {\n simulate: options.simulate !== false,\n wait: options.wait !== false,\n ...(waitTimeoutMs === undefined ? {} : { waitTimeoutMs }),\n };\n let result;\n try {\n result = await resolved.client.trades.send.approve(params, sendOptions);\n } catch (cause) {\n // Approves cost gas — same partial-completion concern as\n // buy/sell/close. The EOA SDK's `sendApproveTransaction`\n // shares `dispatch` with the trade calls, so it throws the\n // identical KashChainError(WAIT_RECEIPT_FAILED) shape on\n // post-submit wait timeout. Surface the hash so the\n // operator can verify inclusion before paying gas for a\n // duplicate approve.\n const partialHash = extractPartialTransactionHash(cause);\n if (partialHash !== undefined) {\n if (globals.json) {\n printJson({ transactionHash: partialHash, waited: false, partial: true });\n } else {\n log.warn(\n `Submit succeeded but wait timed out. The approve tx is on-chain — check inclusion via your block explorer for: ${partialHash}`\n );\n }\n }\n throw cause;\n }\n emitSendResult('approve', spender, result, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n }\n );\n\nconst tradeCommand = new Command('trade')\n .description('Direct-mode trade execution (vanilla EIP-1559 tx, signed locally).')\n .addHelpText(\n 'after',\n `\nWait controls — surface parity with \\`kash protocol trade\\`:\n --wait-timeout-ms <n> Cap on the receipt wait (supported).\n --wait-interval-ms NOT exposed in EOA mode. viem's\n \\`waitForTransactionReceipt\\` controls its\n own polling cadence based on chain block\n time; the EOA SDK does not pass through a\n custom interval. Use SA mode\n (\\`kash protocol trade\\`) if you need\n fine-grained interval control.\n`\n )\n .addCommand(tradeBuyCommand)\n .addCommand(tradeSellCommand)\n .addCommand(tradeCloseCommand)\n .addCommand(tradeApproveCommand);\n\n// ---------------------------------------------------------------------------\n// Top-level eoa namespace\n// ---------------------------------------------------------------------------\n\nexport const eoaCommand = new Command('eoa')\n .description(\n 'Self-orchestrated direct-to-chain operations using a vanilla EOA (no smart account). Like every Kash entry point, this path is non-custodial.'\n )\n .addCommand(balanceCommand)\n .addCommand(marketCommand)\n .addCommand(quoteCommand)\n .addCommand(positionCommand)\n .addCommand(allowanceCommand)\n .addCommand(feesCommand)\n .addCommand(tradeCommand);\n\n// ---------------------------------------------------------------------------\n// Trade runner (shared across buy/sell/close)\n// ---------------------------------------------------------------------------\n\nasync function runTrade(\n side: Side,\n market: string,\n options: SharedTradeOptions & { amount?: string; tokens?: string },\n cmd: Command\n): Promise<void> {\n const globals = readGlobals(cmd);\n const marketAddress = validateAddress(market, 'market');\n const outcome = parseOutcomeIndex(options.outcome);\n const slippageBps = options.slippageBps\n ? parseSlippageBps(options.slippageBps)\n : DEFAULT_SLIPPAGE_BPS;\n const deadline = options.deadlineSec ? parseDeadlineSec(options.deadlineSec) : undefined;\n const waitTimeoutMs = options.waitTimeoutMs\n ? parsePositiveInt(options.waitTimeoutMs, 'wait-timeout-ms')\n : undefined;\n\n let amountUsdc: bigint | undefined;\n let amountTokens: bigint | undefined;\n if (side === 'buy') {\n amountUsdc = decimalToAtomicUsdc(options.amount!, 'amount');\n } else if (side === 'sell') {\n amountTokens = decimalToAtomicWad(options.tokens!, 'tokens');\n }\n\n try {\n const resolved = await buildEoaClient({ globals });\n // **EOA / SA param-shape note.** The shared `BuildBuyParams` /\n // `BuildSellParams` shapes the SDK exposes still use a\n // `smartAccount: Hex` field name in EOA mode for back-compat with\n // SA-mode call sites. The SDK accepts the EOA address here as the\n // signing-account hint — see protocol-sdk's `eoa/trades/build.ts`.\n // The pinning-test in `tests/component/eoa.test.ts` asserts the\n // SDK still respects this aliasing so SDK upgrades that tighten\n // the field name surface as a test failure instead of a silent\n // mis-trade.\n const baseParams = {\n account: resolved.account,\n smartAccount: resolved.account,\n outcome,\n maxSlippageBps: slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n };\n const opts = { simulate: options.simulate !== false };\n\n if (options.dryRun === true) {\n let built;\n if (side === 'buy') {\n built = await resolved.client.trades.prepareBuy(\n marketAddress,\n { ...baseParams, amountUsdc: amountUsdc! },\n opts\n );\n } else if (side === 'sell') {\n built = await resolved.client.trades.prepareSell(\n marketAddress,\n { ...baseParams, amountTokens: amountTokens! },\n opts\n );\n } else {\n built = await resolved.client.trades.prepareClosePosition(marketAddress, baseParams, opts);\n }\n emitDryRun(side, market, built, globals.json);\n return;\n }\n\n const sendOptions = {\n simulate: options.simulate !== false,\n wait: options.wait !== false,\n ...(waitTimeoutMs === undefined ? {} : { waitTimeoutMs }),\n };\n\n let result;\n try {\n if (side === 'buy') {\n result = await resolved.client.trades.send.buy(\n marketAddress,\n { ...baseParams, amountUsdc: amountUsdc! },\n sendOptions\n );\n } else if (side === 'sell') {\n result = await resolved.client.trades.send.sell(\n marketAddress,\n { ...baseParams, amountTokens: amountTokens! },\n sendOptions\n );\n } else {\n result = await resolved.client.trades.send.closePosition(\n marketAddress,\n baseParams,\n sendOptions\n );\n }\n } catch (cause) {\n // Partial-completion guard symmetric to the SA-mode path. The\n // EOA SDK throws KashChainError with `code: 'WAIT_RECEIPT_FAILED'`\n // and `context.transactionHash` when submit succeeded but the\n // wait phase timed out (see\n // `protocol-sdk/src/eoa/trades/send.ts:273-281`). Surface that\n // hash so the operator doesn't pay gas and lose the inclusion\n // pointer. The discriminator is narrow on purpose so unrelated\n // KashChainErrors (chain RPC failures, contract reverts) don't\n // get mis-reported as partial completions.\n const partialHash = extractPartialTransactionHash(cause);\n if (partialHash !== undefined) {\n if (globals.json) {\n printJson({ transactionHash: partialHash, waited: false, partial: true });\n } else {\n log.warn(\n `Submit succeeded but wait timed out. The tx is on-chain — check inclusion via your block explorer for: ${partialHash}`\n );\n }\n }\n throw cause;\n }\n emitSendResult(side, market, result, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n}\n\n/**\n * EOA-mode wrapper around the canonical `extractPartialHash` factory\n * (`utils/trade-input.ts`). Pinned to the wait-receipt-failed code so\n * pre-submit `KashChainError` variants (`CHAIN_RPC_FAILED`, etc.)\n * don't masquerade as partial completions.\n *\n * SDK throw site: `protocol-sdk/src/eoa/trades/send.ts:273-281`.\n */\nfunction extractPartialTransactionHash(cause: unknown): `0x${string}` | undefined {\n return extractPartialHash(cause, {\n code: 'WAIT_RECEIPT_FAILED',\n contextKey: 'transactionHash',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Output emitters\n// ---------------------------------------------------------------------------\n\ntype BuiltTxLike = {\n transaction: Record<string, unknown>;\n transactionHash: `0x${string}`;\n};\n\nfunction emitDryRun(\n side: Side | 'approve',\n target: string,\n built: BuiltTxLike,\n json: boolean\n): void {\n if (json) {\n // `printJson`'s jsonReplacer is the single source of truth for\n // bigint-in-JSON: it coerces every bigint field on `transaction`\n // to a decimal string. No pre-conversion needed here.\n printJson({\n side,\n target,\n transaction: built.transaction,\n transactionHash: built.transactionHash,\n dryRun: true,\n });\n return;\n }\n print('');\n print(` ${style.bold('Dry run')} — transaction prepared but NOT signed/submitted.`);\n print(` ${style.dim('Side ')} ${side}`);\n print(` ${style.dim('Target')} ${formatAddress(target, 10, 8)}`);\n print(` ${style.dim('Hash ')} ${built.transactionHash}`);\n print('');\n print(style.dim('Re-run without --dry-run to sign and submit.'));\n}\n\ntype SendResultLike =\n | { transactionHash: `0x${string}` }\n | {\n transactionHash: `0x${string}`;\n blockNumber: bigint;\n success: boolean;\n gasUsed: bigint;\n };\n\nfunction emitSendResult(\n side: Side | 'approve',\n target: string,\n result: SendResultLike,\n json: boolean\n): void {\n const waited = 'blockNumber' in result;\n const payload = waited\n ? {\n side,\n target,\n transactionHash: result.transactionHash,\n blockNumber: result.blockNumber.toString(),\n success: result.success,\n gasUsed: result.gasUsed.toString(),\n }\n : {\n side,\n target,\n transactionHash: result.transactionHash,\n waited: false,\n };\n\n if (json) {\n printJson(payload);\n return;\n }\n\n print('');\n if (waited) {\n if (result.success) {\n log.success(`${side} included in block ${result.blockNumber.toString()}.`);\n } else {\n log.error(`${side} included but reverted on-chain.`);\n }\n print(` ${style.dim('Tx ')} ${result.transactionHash}`);\n print(` ${style.dim('Block ')} ${result.blockNumber.toString()}`);\n print(` ${style.dim('Gas ')} ${result.gasUsed.toString()}`);\n } else {\n log.success(`${side} submitted (fire-and-forget).`);\n print(` ${style.dim('Tx ')} ${result.transactionHash}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// EOA-mode-only helpers (the shared trade-input parsers live in\n// `utils/trade-input.ts`).\n// ---------------------------------------------------------------------------\n\n// `formatGwei` lives in `utils/formatting.ts` — shared with\n// protocol/fees and balance renderers.\n// `parseOptionalPositiveInt` / `parseOptionalPositiveFloat` live in\n// `utils/global-options.ts` — single source for positive-bound parsers\n// across every CLI command.\n","/**\n * Build a `@kashdao/protocol-sdk` `EoaClient` from the active\n * profile's direct-mode config.\n *\n * EOA mode is the parallel non-custodial path to smart-account mode\n * (`buildDirectClient` in `direct-client.ts`). It signs vanilla\n * EIP-1559 transactions instead of UserOps; the signer's address IS\n * the trading account. Required config:\n *\n * - `rpcUrl` — same field as SA mode\n * - `signerKeyRef` — same field as SA mode (file: or env:)\n * - `defaultChainId` — same field as SA mode\n *\n * EOA mode does NOT need:\n * - `smartAccount` (the EOA address is derived from the signer)\n * - `bundlerUrl` / `bundlerProvider` (no bundler involvement)\n *\n * **Lazy-loaded.** Same cold-start firewall as `direct-client.ts` —\n * the dynamic `import('@kashdao/protocol-sdk')` keeps viem out of the\n * non-EOA paths.\n */\n\nimport { CliError, EXIT_CODES } from '../errors.js';\n\nimport { readConfig, type CliConfig } from './config-store.js';\nimport { resolveCliCustomChain } from './custom-chain.js';\nimport { loadRawPrivateKey } from './signer-key.js';\n\nimport type { GlobalOptions } from './global-options.js';\nimport type { CustomChain, EoaClient, EoaSignerAdapter } from '@kashdao/protocol-sdk';\n\n/**\n * Build a configured `EoaClient`. `requireSigner` is always `true`\n * here — there's no read-only EOA mode (the signer address is the\n * trading account, and reads need the address). Reads against an\n * arbitrary address are still possible by passing the address as a\n * positional argument; the signer just provides the default.\n */\nexport async function buildEoaClient(opts: { readonly globals?: GlobalOptions }): Promise<{\n readonly client: EoaClient;\n readonly chainId: number;\n readonly account: `0x${string}`;\n}> {\n const globals = opts.globals;\n const config = await readConfig({\n ...(globals?.profile === undefined ? {} : { profile: globals.profile }),\n ...(globals?.configPath === undefined ? {} : { configPath: globals.configPath }),\n });\n\n const rpc = globals?.baseUrl ?? config.rpcUrl;\n if (!rpc) {\n throw missingEoaConfig('rpcUrl', '--rpc-url or `kash config set rpcUrl <url>`');\n }\n if (!config.signerKeyRef) {\n throw missingEoaConfig(\n 'signerKeyRef',\n '`kash config set signerKeyRef file:<path>` or `env:<NAME>` (CLI never persists raw keys)'\n );\n }\n\n const { createEoaClient } = await import('@kashdao/protocol-sdk');\n const signer = await loadEoaSigner(config.signerKeyRef);\n\n // If the profile has `customChain` configured, build the SDK\n // CustomChain (viem chain + addresses) so we work against chains\n // outside the static registry — local Anvil, forks, sidechains.\n // EOA mode ignores `customChain.smartAccount`.\n const customChain = await maybeBuildCustomChain(config, rpc);\n\n const client = createEoaClient({\n chainId: config.defaultChainId,\n rpc,\n signer,\n ...(customChain === undefined ? {} : { customChain }),\n });\n\n return {\n client,\n chainId: config.defaultChainId,\n account: signer.ownerAddress,\n };\n}\n\n/**\n * Load an EOA signer from `signerKeyRef`. Mirrors the SA-mode\n * `loadSigner` in `direct-client.ts` but wraps via\n * `viemAccountEoaSigner` for vanilla-tx signing instead of\n * `viemAccountSigner` for UserOp hash signing.\n */\nasync function loadEoaSigner(ref: string): Promise<EoaSignerAdapter> {\n const rawKey = await loadRawPrivateKey(ref);\n // Lazy-load viem + the EOA signer adapter together (matches the\n // SA-mode boundary in `direct-client.ts`). Different adapter, same\n // dynamic-import gate.\n const [{ privateKeyToAccount }, { viemAccountEoaSigner }] = await Promise.all([\n import('viem/accounts'),\n import('@kashdao/protocol-sdk'),\n ]);\n return viemAccountEoaSigner(privateKeyToAccount(rawKey));\n}\n\n/**\n * Build an SDK `CustomChain` from the profile's `customChain` config,\n * if any. The CLI never asks the user to hand-construct a viem Chain\n * — we synthesise one from `defaultChainId + rpcUrl + customChain.name`,\n * which is exactly what the local-anvil quickstart in\n * `packages/protocol-sdk/examples/local-anvil/` does inline.\n */\nasync function maybeBuildCustomChain(\n config: CliConfig,\n rpc: string\n): Promise<CustomChain | undefined> {\n if (config.customChain === undefined) return undefined;\n if (config.defaultChainId === undefined) {\n throw missingEoaConfig(\n 'defaultChainId',\n '`kash config set defaultChainId <id>` (required when customChain is set so the CLI can construct the viem chain)'\n );\n }\n return resolveCliCustomChain({\n customChain: config.customChain,\n chainId: config.defaultChainId,\n rpc,\n });\n}\n\nfunction missingEoaConfig(field: string, hint: string): CliError {\n return new CliError(`EOA-mode config missing: ${field}.`, {\n code: 'DIRECT_CONFIG_MISSING',\n exitCode: EXIT_CODES.GENERIC,\n suggestion: `Set ${field} via ${hint}.`,\n actions: [\n {\n type: 'check_input',\n field,\n description: hint,\n },\n ],\n });\n}\n"],"mappings":"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","names":[]}