@kashdao/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/CONTRIBUTING.md +159 -0
  3. package/LICENSE +21 -0
  4. package/README.md +868 -0
  5. package/SECURITY.md +110 -0
  6. package/dist/account-AVFLEM5D.js +90 -0
  7. package/dist/account-AVFLEM5D.js.map +1 -0
  8. package/dist/auth-GUJCVKTD.js +239 -0
  9. package/dist/auth-GUJCVKTD.js.map +1 -0
  10. package/dist/chunk-BN2CUM42.js +9 -0
  11. package/dist/chunk-BN2CUM42.js.map +1 -0
  12. package/dist/chunk-BRK7KJ4O.js +154 -0
  13. package/dist/chunk-BRK7KJ4O.js.map +1 -0
  14. package/dist/chunk-KMBMQIZ7.js +393 -0
  15. package/dist/chunk-KMBMQIZ7.js.map +1 -0
  16. package/dist/chunk-LBIRQHX5.js +133 -0
  17. package/dist/chunk-LBIRQHX5.js.map +1 -0
  18. package/dist/chunk-MIXOZU2S.js +366 -0
  19. package/dist/chunk-MIXOZU2S.js.map +1 -0
  20. package/dist/chunk-QJMF73M5.js +129 -0
  21. package/dist/chunk-QJMF73M5.js.map +1 -0
  22. package/dist/chunk-UZNSYATZ.js +680 -0
  23. package/dist/chunk-UZNSYATZ.js.map +1 -0
  24. package/dist/chunk-VIADBYFY.js +94 -0
  25. package/dist/chunk-VIADBYFY.js.map +1 -0
  26. package/dist/chunk-YHCG2SUC.js +159 -0
  27. package/dist/chunk-YHCG2SUC.js.map +1 -0
  28. package/dist/chunk-YJX3JJ4M.js +174 -0
  29. package/dist/chunk-YJX3JJ4M.js.map +1 -0
  30. package/dist/client-IOM55ZCS.js +14 -0
  31. package/dist/client-IOM55ZCS.js.map +1 -0
  32. package/dist/completion-ZZGX5BQC.js +100 -0
  33. package/dist/completion-ZZGX5BQC.js.map +1 -0
  34. package/dist/config-XJL5TSYK.js +690 -0
  35. package/dist/config-XJL5TSYK.js.map +1 -0
  36. package/dist/config-store-3ZSYGXMQ.js +44 -0
  37. package/dist/config-store-3ZSYGXMQ.js.map +1 -0
  38. package/dist/docs-MDKKSJDC.js +102 -0
  39. package/dist/docs-MDKKSJDC.js.map +1 -0
  40. package/dist/eoa-IQ72EIHR.js +551 -0
  41. package/dist/eoa-IQ72EIHR.js.map +1 -0
  42. package/dist/errors-WMZIEGQI.js +18 -0
  43. package/dist/errors-WMZIEGQI.js.map +1 -0
  44. package/dist/explain-H4EH3KH3.js +165 -0
  45. package/dist/explain-H4EH3KH3.js.map +1 -0
  46. package/dist/global-options-XOLJUPTT.js +18 -0
  47. package/dist/global-options-XOLJUPTT.js.map +1 -0
  48. package/dist/health-VZEIII74.js +98 -0
  49. package/dist/health-VZEIII74.js.map +1 -0
  50. package/dist/help-footer-GTANVDNP.js +43 -0
  51. package/dist/help-footer-GTANVDNP.js.map +1 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +251 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/intro-PQQTYWR7.js +41 -0
  56. package/dist/intro-PQQTYWR7.js.map +1 -0
  57. package/dist/markets-C37JZDPE.js +295 -0
  58. package/dist/markets-C37JZDPE.js.map +1 -0
  59. package/dist/output-VCBZ3FM7.js +22 -0
  60. package/dist/output-VCBZ3FM7.js.map +1 -0
  61. package/dist/portfolio-2AEPIJIG.js +115 -0
  62. package/dist/portfolio-2AEPIJIG.js.map +1 -0
  63. package/dist/protocol-XEQXF2GW.js +1572 -0
  64. package/dist/protocol-XEQXF2GW.js.map +1 -0
  65. package/dist/quote-I4DVJ7ZB.js +144 -0
  66. package/dist/quote-I4DVJ7ZB.js.map +1 -0
  67. package/dist/schema-PIFQ65TS.js +410 -0
  68. package/dist/schema-PIFQ65TS.js.map +1 -0
  69. package/dist/setup-USZ6IODD.js +260 -0
  70. package/dist/setup-USZ6IODD.js.map +1 -0
  71. package/dist/stdin-YW2CEQXU.js +28 -0
  72. package/dist/stdin-YW2CEQXU.js.map +1 -0
  73. package/dist/trace-IZBYTUFO.js +103 -0
  74. package/dist/trace-IZBYTUFO.js.map +1 -0
  75. package/dist/trade-IIZSEXEI.js +586 -0
  76. package/dist/trade-IIZSEXEI.js.map +1 -0
  77. package/dist/version-JDK3PEP5.js +117 -0
  78. package/dist/version-JDK3PEP5.js.map +1 -0
  79. package/dist/version-check-TDCION37.js +138 -0
  80. package/dist/version-check-TDCION37.js.map +1 -0
  81. package/dist/webhooks-PTVRKICZ.js +680 -0
  82. package/dist/webhooks-PTVRKICZ.js.map +1 -0
  83. package/dist/with-retry-4FIZG3A7.js +223 -0
  84. package/dist/with-retry-4FIZG3A7.js.map +1 -0
  85. package/package.json +99 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/protocol/index.ts","../src/commands/protocol/allowance.ts","../src/utils/direct-client.ts","../src/commands/protocol/balance.ts","../src/commands/protocol/decode-revert.ts","../src/commands/protocol/fees.ts","../src/commands/protocol/market.ts","../src/commands/protocol/position.ts","../src/commands/protocol/quote.ts","../src/commands/protocol/smart-account.ts","../src/commands/protocol/token-id.ts","../src/commands/protocol/trade.ts","../src/utils/userop-json.ts","../src/commands/protocol/userop.ts","../src/commands/protocol/watch.ts"],"sourcesContent":["/**\n * `kash protocol …` — self-orchestrated direct-to-chain operations.\n *\n * Wraps `@kashdao/protocol-sdk`. Every command in this namespace\n * reads from the chain via the consumer's RPC and, for write paths,\n * signs UserOps locally with the configured signer. Zero Kash backend\n * dependency.\n *\n * Both this self-orchestrated mode and the default Kash-orchestrated\n * mode (`kash markets`, `kash trade`, …) are fully non-custodial —\n * user funds always live in Privy-managed MPC smart accounts the user\n * controls; Kash never holds keys on either path. The split is about\n * who builds and submits the UserOp, not who has custody.\n *\n * Required profile fields for any subcommand:\n *\n * - `rpcUrl` — consumer-owned RPC endpoint\n * - `smartAccount` — ERC-4337 account whose funds are used\n * - `defaultChainId`— chain to run on (8453 mainnet, 84532 sepolia)\n *\n * Read-only subcommands (`balance`, `market`, `quote`) use a no-op\n * signer and don't require `signerKeyRef`; write subcommands do.\n */\n\nimport { Command } from 'commander';\n\nimport { allowanceCommand } from './allowance.js';\nimport { balanceCommand } from './balance.js';\nimport { decodeRevertCommand } from './decode-revert.js';\nimport { feesCommand } from './fees.js';\nimport { marketCommand } from './market.js';\nimport { positionCommand } from './position.js';\nimport { quoteCommand } from './quote.js';\nimport { smartAccountCommand } from './smart-account.js';\nimport { tokenIdCommand } from './token-id.js';\nimport { tradeCommand } from './trade.js';\nimport { useropCommand } from './userop.js';\nimport { watchCommand } from './watch.js';\n\nexport const protocolCommand = new Command('protocol')\n .description(\n 'Self-orchestrated direct-to-chain operations (uses @kashdao/protocol-sdk). Like the default Kash-orchestrated mode, this path is non-custodial — the difference is who builds and submits trades.'\n )\n .addCommand(balanceCommand)\n .addCommand(marketCommand)\n .addCommand(quoteCommand)\n .addCommand(positionCommand)\n .addCommand(allowanceCommand)\n .addCommand(smartAccountCommand)\n .addCommand(feesCommand)\n .addCommand(tokenIdCommand)\n .addCommand(decodeRevertCommand)\n .addCommand(tradeCommand)\n .addCommand(useropCommand)\n .addCommand(watchCommand);\n","/**\n * `kash protocol allowance <spender> [account]` — read the on-chain\n * USDC allowance from `account` to `spender`. Used to skip `approve`\n * calls when an existing allowance is already sufficient (the\n * conventional first-trade pattern).\n *\n * Defaults `account` to the active profile's `smartAccount`.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress, formatUsdcAtomic } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport { validateAddress, validateAddressOptional } from '../../utils/trade-input.js';\n\nexport const allowanceCommand = new Command('allowance')\n .description('Read the on-chain USDC allowance from `account` to `spender`.')\n .argument('<spender>', 'spender contract address (e.g. a market) — 0x-prefixed')\n .argument('[account]', \"owner address (default: profile's smartAccount)\")\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol allowance 0xMarket...\n $ kash protocol allowance 0xMarket... 0xOwner...\n $ kash protocol allowance 0xMarket... --json --quiet | jq -r '.allowanceAtomic'\n\nNotes:\n - The allowance is returned in USDC atomic units (6 decimals). A\n value larger than the trade's atomic-USDC input means \\`approve\\`\n can be skipped on the next trade.\n`\n )\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\n try {\n const resolved = await buildDirectClient({ globals });\n const owner = accountAddress ?? resolved.smartAccount;\n const allowance = await resolved.client.account.usdcAllowance(owner, spenderAddress);\n\n const payload = {\n owner,\n spender: spenderAddress,\n chainId: resolved.chainId,\n allowanceAtomic: allowance.toString(),\n };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Owner ')} ${formatAddress(owner, 10, 8)}`);\n print(` ${style.dim('Spender ')} ${formatAddress(spenderAddress, 10, 8)}`);\n print(\n ` ${style.dim('Allowance')} ${formatUsdcAtomic(allowance.toString())} ${style.dim(`(${allowance.toString()} atomic)`)}`\n );\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n","/**\n * Build a `@kashdao/protocol-sdk` `SmartAccountClient` from the active\n * profile's direct-mode config.\n *\n * **Lazy-loaded.** This module dynamically imports\n * `@kashdao/protocol-sdk` (and viem) inside `buildDirectClient` so\n * the Kash-orchestrated code paths (markets / trade / portfolio /\n * webhooks / health) keep their fast cold start. Touching this\n * module at the module-top level — even in a `type` import — would\n * pull viem into every `kash --version` invocation.\n *\n * The CLI exposes the protocol-sdk through a single namespace\n * (`kash protocol …`); every command in that namespace calls\n * `buildDirectClient` to get a configured client and routes through\n * it. Read-only commands (`balance`, `market`, `quote`) use a\n * `noopSigner` that throws if a write path tries to sign — a\n * structural guarantee that read commands cannot accidentally\n * authorise spend.\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\n// Type-only imports — TypeScript erases these at compile time, so\n// the protocol-sdk's runtime (and viem) is NOT pulled in via these\n// lines. The actual import happens lazily inside `buildDirectClient`\n// and `loadSigner` via dynamic `import()`.\nimport type { GlobalOptions } from './global-options.js';\nimport type {\n CustomChain,\n SmartAccountClient,\n SmartAccountClientConfigInput,\n SmartAccountSignerAdapter,\n} from '@kashdao/protocol-sdk';\n\n/**\n * Build a configured `DirectClient`. Caller passes the global\n * options so `--profile` / `--config` selection works uniformly with\n * the Kash-orchestrated path.\n *\n * `requireSigner: false` (default) constructs a no-op signer that\n * throws if anything actually tries to sign — fine for read-only\n * commands. Pass `true` for write-path commands (`build`, `submit`,\n * `simulate-write`).\n */\nexport async function buildDirectClient(opts: {\n readonly globals?: GlobalOptions;\n readonly requireSigner?: boolean;\n}): Promise<{\n readonly client: SmartAccountClient;\n readonly chainId: number;\n readonly smartAccount: `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 // Foundational fields — required for *any* direct-mode command.\n const rpc = globals?.baseUrl ?? config.rpcUrl;\n if (!rpc) {\n throw missingDirectConfig('rpcUrl', '--rpc-url or `kash config set rpcUrl <url>`');\n }\n if (!config.smartAccount) {\n throw missingDirectConfig(\n 'smartAccount',\n '`kash config set smartAccount 0x…` (the ERC-4337 account address whose funds you trade with)'\n );\n }\n\n // Lazy-load — the dynamic import is the cold-start firewall.\n const { createSmartAccountClient } = await import('@kashdao/protocol-sdk');\n\n const signer = opts.requireSigner ? await loadSigner(config.signerKeyRef) : noopSigner();\n\n const bundlerConfig = resolveBundlerConfig(config);\n\n // If the profile has `customChain` configured, build the SDK\n // CustomChain (viem chain + protocol addresses + optional SA factory\n // config) so we work against chains outside the static registry —\n // local Anvil, forks, sidechains. SA mode requires\n // `customChain.smartAccount.{factory,implementation,entryPoint}`\n // when running on Anvil because anvil_setCode can't copy immutable\n // variables (the canonical permissionless.js SimpleAccount factory\n // relies on immutable EntryPoint binding) — see protocol-sdk's\n // TROUBLESHOOTING.md § AA23.\n const customChain = await maybeBuildCustomChain(config, rpc);\n if (customChain !== undefined && customChain.smartAccount === undefined) {\n throw missingDirectConfig(\n 'customChain.smartAccount',\n 'all three: `kash config set customChain.smartAccount.factoryAddress 0x…`, `customChain.smartAccount.implementationAddress 0x…`, `customChain.smartAccount.entryPointAddress 0x…` (SA mode requires the local SimpleAccount factory + EntryPoint addresses on a custom chain — Anvil deploys these to addresses that differ from the canonical permissionless.js defaults)'\n );\n }\n\n const client = createSmartAccountClient({\n chainId: config.defaultChainId,\n rpc,\n signer,\n ...(bundlerConfig === undefined ? {} : { bundler: bundlerConfig }),\n ...(customChain === undefined ? {} : { customChain }),\n });\n\n return {\n client,\n chainId: config.defaultChainId,\n smartAccount: config.smartAccount as `0x${string}`,\n };\n}\n\n/**\n * Read-only signer for commands that don't need to sign anything\n * (`kash protocol balance/market/quote`). The DirectClient\n * constructor requires a signer, but read paths never call\n * `signUserOpHash` — if something does, this implementation throws\n * with a clear \"this is a CLI bug\" message so the failure surfaces\n * during testing rather than silently producing a bad signature.\n */\nfunction noopSigner(): SmartAccountSignerAdapter {\n return {\n ownerAddress: '0x0000000000000000000000000000000000000000',\n async signUserOpHash() {\n throw new CliError('CLI bug: read-only direct-mode command attempted to sign a UserOp.', {\n code: 'UNEXPECTED',\n suggestion:\n 'File an issue at https://github.com/KashDAO/cli/issues — this should not happen.',\n });\n },\n };\n}\n\n/**\n * Load a signer from the configured `signerKeyRef`. Supports two\n * sources today, both delegated to `loadRawPrivateKey` for parity\n * with EOA-mode:\n *\n * - `file:<path>` — read the key from disk. POSIX file mode is\n * checked after a successful load; if the file\n * is readable by group or other, the CLI emits\n * a `chmod 600` warning (load is NOT refused —\n * advisory, like ssh and aws-cli).\n * - `env:<NAME>` — read the key from the named env var.\n *\n * Both return a `viem` `LocalAccount` wrapped via\n * `viemAccountSigner` from the protocol-sdk.\n */\nasync function loadSigner(ref: string | undefined): Promise<SmartAccountSignerAdapter> {\n const rawKey = await loadRawPrivateKey(ref);\n // Lazy-load viem and the signer adapter together — both pulled by\n // the same dynamic import boundary.\n const [{ privateKeyToAccount }, { viemAccountSigner }] = await Promise.all([\n import('viem/accounts'),\n import('@kashdao/protocol-sdk'),\n ]);\n return viemAccountSigner(privateKeyToAccount(rawKey));\n}\n\n/**\n * Translate the CLI's profile-level bundler config into the\n * protocol-sdk's `bundler` field. The protocol-sdk's structured\n * bundler config requires `url` for every preset (the URL for\n * `flashbots`/`pimlico`/`alchemy` is the provider's own RPC, not\n * the chain RPC). The CLI surfaces this constraint as a\n * configuration error rather than silently defaulting.\n */\nfunction resolveBundlerConfig(\n config: Awaited<ReturnType<typeof readConfig>>\n): SmartAccountClientConfigInput['bundler'] | undefined {\n if (config.bundlerProvider === undefined && config.bundlerUrl === undefined) {\n return undefined; // Use the protocol-sdk's default (Flashbots Protect).\n }\n if (config.bundlerProvider === undefined) {\n // URL only — treat as a generic bundler (string shorthand).\n return config.bundlerUrl;\n }\n // Provider preset — `url` is required by the protocol-sdk schema.\n if (config.bundlerUrl === undefined) {\n throw new CliError(\n `Direct-mode config: bundlerProvider=\"${config.bundlerProvider}\" requires a bundlerUrl.`,\n {\n code: 'DIRECT_CONFIG_MISSING',\n suggestion:\n '`kash config set bundlerUrl <provider-rpc-url>` (e.g. https://api.pimlico.io/v2/8453/rpc?apikey=…)',\n }\n );\n }\n return {\n provider: config.bundlerProvider,\n url: config.bundlerUrl,\n };\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 missingDirectConfig(\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 missingDirectConfig(field: string, hint: string): CliError {\n return new CliError(`Direct-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","/**\n * `kash protocol balance [account]` — read on-chain balances for a\n * smart account.\n *\n * Direct mode, read-only. Uses the protocol-sdk's `account.usdcBalance`\n * + `account.gasBalance`. Defaults to the active profile's\n * `smartAccount` when no argument is given so most operators run a\n * bare `kash protocol balance` for their own account.\n *\n * Output (JSON shape pinned via `OnChainBalanceSchema`):\n *\n * ```jsonc\n * {\n * \"account\": \"0x...\",\n * \"chainId\": 8453,\n * \"usdcAtomic\": \"12345000000\",\n * \"gasWei\": \"12300000000000000\"\n * }\n * ```\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress, formatBigDecimal, formatUsdcAtomic } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport { validateAddressOptional } from '../../utils/trade-input.js';\n\nexport const balanceCommand = new Command('balance')\n .description(\"Read on-chain USDC + gas balance for a smart account (defaults to the profile's).\")\n .argument('[account]', \"smart-account address (defaults to the active profile's smartAccount)\")\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol balance\n $ kash protocol balance 0xabc...\n $ kash protocol balance --json --quiet | jq '.usdcAtomic'\n\nDirect-mode requires rpcUrl + smartAccount + signerKeyRef configured\non the active profile (signer is loaded but never invoked for reads).\n`\n )\n .action(async (account: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const accountOverride = validateAddressOptional(account, 'account');\n\n let resolved;\n try {\n resolved = await buildDirectClient({ globals });\n } catch (cause) {\n throw toCliError(cause);\n }\n const target = accountOverride ?? resolved.smartAccount;\n\n let usdcAtomic: bigint;\n let gasWei: bigint;\n try {\n [usdcAtomic, gasWei] = await Promise.all([\n resolved.client.account.usdcBalance(target),\n resolved.client.account.gasBalance(target),\n ]);\n } catch (cause) {\n throw toCliError(cause);\n }\n\n const payload = {\n account: target,\n chainId: resolved.chainId,\n usdcAtomic: usdcAtomic.toString(),\n gasWei: gasWei.toString(),\n };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\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(usdcAtomic.toString())}`);\n print(\n ` ${style.dim('ETH (gas) ')} ${formatBigDecimal(gasWei, { baseDecimals: 18, displayDecimals: 6 })} ETH`\n );\n });\n","/**\n * `kash protocol decode-revert <0x…>` — decode raw revert data\n * emitted by the Market contract or EntryPoint into a human-readable\n * `(name, args)` pair.\n *\n * Pure offline operation: matches the first 4 bytes of revert data\n * against the custom errors in the vendored ABIs (Market first,\n * EntryPoint as fallback). No RPC required.\n *\n * Useful when debugging stuck UserOps: `getUserOperationReceipt`\n * returns hex revert data; pipe it into this command to identify\n * which custom error was thrown.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\n\nconst HEX_DATA_RE = /^0x[0-9a-fA-F]+$/;\n\nexport const decodeRevertCommand = new Command('decode-revert')\n .description('Decode raw revert data into (name, args) using the Market + EntryPoint ABIs.')\n .argument('<data>', 'raw revert data (0x-prefixed hex)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol decode-revert 0x4e487b710000000000000000000000000000000000000000000000000000000000000011\n $ kash protocol decode-revert 0x... --json --quiet | jq -r '.name'\n\nNotes:\n - Returns \\`null\\` if the selector doesn't match any known error\n (the data may be raw \\`Error(string)\\` or vendor-specific).\n - The \\`args\\` array stringifies bigint values to preserve precision.\n`\n )\n .action(async (data: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n\n if (!HEX_DATA_RE.test(data) || data.length < 10) {\n throw new CliValidationError(\n '<data> must be 0x-prefixed hex with at least a 4-byte selector.',\n `Got \"${data}\".`,\n 'data'\n );\n }\n\n try {\n // Lazy-load protocol-sdk so this offline helper doesn't pull\n // viem on every CLI invocation.\n const { decodeMarketRevert } = await import('@kashdao/protocol-sdk');\n const decoded = decodeMarketRevert(data as `0x${string}`);\n\n // Stringify bigint args defensively — JSON.stringify chokes on\n // them and consumers can re-parse the strings if they need\n // precision.\n const args = decoded?.args.map((a) => (typeof a === 'bigint' ? a.toString() : a)) ?? null;\n\n const payload = decoded === null ? null : { name: decoded.name, args };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n if (decoded === null) {\n print('');\n print(` ${style.dim('No match — selector not in Market or EntryPoint ABIs.')}`);\n print(` ${style.dim('Data: ')}${data.slice(0, 10)}${data.length > 10 ? '…' : ''}`);\n return;\n }\n\n print('');\n print(` ${style.dim('Error ')} ${style.bold(decoded.name)}`);\n if (args && args.length > 0) {\n print(` ${style.dim('Args ')}`);\n for (const [i, arg] of args.entries()) {\n print(` [${String(i)}] ${String(arg)}`);\n }\n } else {\n print(` ${style.dim('Args ')} (none)`);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n","/**\n * `kash protocol fees` — EIP-1559 fee estimation for the configured\n * chain. Wraps `client.bundler.estimateFees(options)` from the\n * protocol-sdk.\n *\n * Useful for direct-mode operators tuning their submit strategy:\n * compare what the SDK would suggest under different multipliers,\n * sample sizes, or percentile windows. The estimate is read-only and\n * uses `eth_feeHistory` against the configured RPC.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatGwei } from '../../utils/formatting.js';\nimport {\n parseOptionalPositiveFloat,\n parseOptionalPositiveInt,\n readGlobals,\n} from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\n\ntype FeesOptions = {\n blocks?: string;\n percentile?: string;\n baseMultiplier?: string;\n priorityFloorGwei?: string;\n};\n\nexport const feesCommand = new Command('fees')\n .description('EIP-1559 fee estimate for the configured chain (uses eth_feeHistory).')\n .option('--blocks <n>', 'number of recent blocks to sample (default 4)')\n .option(\n '--percentile <n>',\n 'priority-fee percentile to take from each sampled block (1-99, default 50)'\n )\n .option(\n '--base-multiplier <n>',\n 'multiplier applied to predicted next-block base fee (default 2.0; raise for congested chains)'\n )\n .option('--priority-floor-gwei <n>', 'floor for maxPriorityFeePerGas in gwei (default 1)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol fees\n $ kash protocol fees --base-multiplier 3 --json --quiet | jq -r '.maxFeePerGas'\n $ kash protocol fees --blocks 16 --percentile 75 # smoother, more conservative\n`\n )\n .action(async (options: FeesOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n\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(\n '--percentile must be between 1 and 99.',\n undefined,\n 'percentile'\n );\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 buildDirectClient({ globals });\n const estimate = await resolved.client.bundler.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\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Chain ')} ${String(resolved.chainId)}`);\n print(\n ` ${style.dim('maxFee ')} ${formatGwei(estimate.maxFeePerGas)} gwei ${style.dim(`(${estimate.maxFeePerGas.toString()} wei)`)}`\n );\n print(\n ` ${style.dim('maxPrio ')} ${formatGwei(estimate.maxPriorityFeePerGas)} gwei ${style.dim(`(${estimate.maxPriorityFeePerGas.toString()} wei)`)}`\n );\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\n// `formatGwei` lives in `utils/formatting.ts` — single source of\n// truth for the wei-to-gwei display format shared with `kash eoa fees`\n// and the balance commands.\n","/**\n * `kash protocol market <market-address>` — read on-chain market state.\n *\n * Direct mode, read-only. Uses the protocol-sdk's `markets.state`\n * which returns the aggregated reserves, supplies, weights, and\n * derived per-outcome probabilities.\n *\n * The Kash-orchestrated equivalent is `kash markets get <uuid>`. The two are\n * deliberately separate commands because the inputs differ (UUID vs\n * 0x address) and the outputs differ (API-projected `MarketResource`\n * vs on-chain `MarketState`). Operators using direct mode should\n * never confuse on-chain state with the API's denormalised view.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress, formatWad } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport { validateAddress } from '../../utils/trade-input.js';\n\nexport const 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 .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol market 0xabc...\n $ kash protocol market 0xabc... --json --quiet | jq '.outcomes'\n`\n )\n .action(async (address: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n\n validateAddress(address, 'address');\n\n let resolved;\n let state;\n try {\n resolved = await buildDirectClient({ globals });\n state = await resolved.client.markets.state(address as `0x${string}`);\n } catch (cause) {\n throw toCliError(cause);\n }\n\n // Convert bigints to strings on the JSON path so consumers can\n // round-trip through `JSON.stringify` losslessly.\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\n if (globals.json) {\n printJson(payload);\n return;\n }\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(\n ` [${String(outcome.index)}] p=${pct}% outstanding=${formatWad(outcome.outstandingTokensWad)} weight=${formatWad(outcome.weightWad)}`\n );\n }\n });\n","/**\n * `kash protocol position <market-address> [account]` — read on-chain\n * outcome-token holdings (ERC-1155) for a single market.\n *\n * Direct mode, read-only. Uses the protocol-sdk's\n * `client.account.position(account, market)` which fans out a\n * `balanceOfBatch` against `OutcomeTokens1155`. Defaults `account` to\n * the active profile's `smartAccount`.\n *\n * Distinct from `kash portfolio positions` — that hits the public API\n * (Kash-orchestrated). This is on-chain truth, useful for direct-mode operators\n * verifying their balances independently.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress, formatWad } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport { validateAddress, validateAddressOptional } from '../../utils/trade-input.js';\n\nexport const 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(\n '[account]',\n \"EOA or smart-account address whose holdings to read (default: profile's smartAccount)\"\n )\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol position 0xMarket...\n $ kash protocol position 0xMarket... 0xOther...\n $ kash protocol position 0xMarket... --json --quiet | jq '.holdings[].balanceWad'\n`\n )\n .action(async (market: string, account: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n\n const marketAddr = validateAddress(market, 'market');\n const accountAddr = validateAddressOptional(account, 'account');\n\n let resolved;\n let position;\n try {\n resolved = await buildDirectClient({ globals });\n const target = accountAddr ?? resolved.smartAccount;\n position = await resolved.client.account.position(target, marketAddr);\n\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\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Account ')} ${formatAddress(target, 10, 8)}`);\n print(` ${style.dim('Market ')} ${formatAddress(position.marketAddress, 10, 8)}`);\n print(` ${style.dim('Outcomes ')} ${String(position.numOutcomes)}`);\n print('');\n for (const h of position.holdings) {\n const balanceLabel = formatWad(h.balanceWad);\n print(\n ` [${String(h.outcomeIndex)}] balance=${balanceLabel} ${style.dim(`(${h.balanceWad.toString()} WAD)`)}`\n );\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n","/**\n * `kash protocol quote <market-address>` — on-chain price quote.\n *\n * Direct mode, read-only. Calls `markets.quote` on the AMM contract.\n * The Kash-orchestrated equivalent is `kash quote buy/sell` which hits the\n * API; this version reads directly from chain via the configured RPC.\n *\n * Input units mirror the protocol-sdk's contract: `--amount` is\n * USDC (decimal, e.g. \"10\") on BUY, outcome tokens (decimal, e.g.\n * \"1.5\") on SELL. The CLI converts to atomic-6 / WAD-18 before\n * calling the SDK.\n *\n * Output:\n *\n * ```jsonc\n * {\n * \"side\": \"BUY\",\n * \"outcomeIndex\": 0,\n * \"amountIn\": \"10000000\", // atomic-6 USDC\n * \"amountOut\": \"16234567890123456\", // WAD-18 outcome tokens\n * \"reserveAfterWad\": \"...\",\n * \"pricesAfterWad\": [\"...\", \"...\"]\n * }\n * ```\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress, formatUsdcAtomic, formatWad } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport {\n decimalToAtomicUsdc,\n decimalToAtomicWad,\n parseOutcomeIndex,\n parseUppercaseSide,\n validateAddress,\n} from '../../utils/trade-input.js';\n\ntype QuoteOptions = {\n side: string;\n outcome: string;\n amount: string;\n};\n\nexport const quoteCommand = new Command('quote')\n .description('On-chain price quote for buying or selling an outcome.')\n .argument('<address>', 'market contract address (0x-prefixed)')\n .requiredOption('-s, --side <buy|sell>', 'trade side: buy or sell')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption(\n '-a, --amount <decimal>',\n 'amount: USDC decimal for buy (e.g. \"10\"), outcome-token decimal for sell (e.g. \"1.5\")'\n )\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol quote 0xabc... --side buy --outcome 0 --amount 10\n $ kash protocol quote 0xabc... --side sell --outcome 1 --tokens 1.5 --json\n`\n )\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, '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 let resolved;\n let quote;\n try {\n resolved = await buildDirectClient({ globals });\n quote = await resolved.client.markets.quote(marketAddress, {\n side,\n outcome,\n amount,\n });\n } catch (cause) {\n throw toCliError(cause);\n }\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\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Market ')} ${formatAddress(address, 10, 8)}`);\n print(` ${style.dim('Action ')} ${quote.side} outcome ${String(quote.outcomeIndex)}`);\n if (quote.side === 'BUY') {\n print(` ${style.dim('Spend ')} ${formatUsdcAtomic(quote.amountIn)}`);\n print(` ${style.dim('Tokens out')} ${formatWad(quote.amountOut)}`);\n } else {\n print(` ${style.dim('Tokens in ')} ${formatWad(quote.amountIn)}`);\n print(` ${style.dim('USDC out ')} ${formatUsdcAtomic(quote.amountOut)}`);\n }\n print(\n ` ${style.dim('Probs after')} [${quote.pricesAfterWad\n .map((p) => `${((Number(p) / 1e18) * 100).toFixed(2)}%`)\n .join(', ')}]`\n );\n });\n","/**\n * `kash protocol smart-account` — derive smart-account address +\n * check deployment status without sending a UserOp.\n *\n * Two read-only operations:\n *\n * - `compute --owner 0x… [--salt n]` — derive the deterministic\n * SimpleAccountFactory address for an EOA owner. Same address\n * whether deployed or not.\n * - `is-deployed [address]` — check whether a smart account has\n * bytecode at its address. A `false` result is normal for a\n * never-traded SA (the first UserOp deploys it via factory data).\n *\n * Wraps `client.account.computeAddress` and `client.account.isDeployed`\n * from `@kashdao/protocol-sdk`. Read-only — uses the existing\n * `noopSigner` plumbing.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress } from '../../utils/formatting.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\nimport { validateAddress, validateAddressOptional } from '../../utils/trade-input.js';\n\ntype ComputeOptions = {\n owner: string;\n salt?: string;\n};\n\nconst computeCommand = new Command('compute')\n .description('Derive the deterministic smart-account address for an EOA owner.')\n .requiredOption('-o, --owner <address>', 'EOA owner address (0x-prefixed)')\n .option('-s, --salt <n>', 'optional salt as a non-negative integer (default 0)', '0')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol smart-account compute --owner 0xEoa...\n $ kash protocol smart-account compute --owner 0xEoa... --salt 1\n $ kash protocol smart-account compute --owner 0xEoa... --json --quiet | jq -r '.address'\n`\n )\n .action(async (options: ComputeOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const ownerAddress = validateAddress(options.owner, 'owner');\n\n let salt: bigint | undefined;\n if (options.salt !== undefined) {\n let parsed: bigint;\n try {\n parsed = BigInt(options.salt);\n } catch {\n throw new CliValidationError(\n '--salt must be a non-negative integer (decimal or 0x-hex).',\n `Got \"${options.salt}\".`,\n 'salt'\n );\n }\n if (parsed < 0n) {\n throw new CliValidationError(\n '--salt must be non-negative.',\n `Got \"${options.salt}\".`,\n 'salt'\n );\n }\n salt = parsed === 0n ? undefined : parsed;\n }\n\n try {\n const resolved = await buildDirectClient({ globals });\n const address = await resolved.client.account.computeAddress(ownerAddress, salt);\n\n const payload = {\n owner: ownerAddress,\n salt: (salt ?? 0n).toString(),\n chainId: resolved.chainId,\n address,\n };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Owner ')} ${formatAddress(ownerAddress, 10, 8)}`);\n print(` ${style.dim('Salt ')} ${(salt ?? 0n).toString()}`);\n print(` ${style.dim('Address')} ${address}`);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst isDeployedCommand = new Command('is-deployed')\n .description('Check whether a smart account has bytecode (i.e. has been deployed on-chain).')\n .argument('[address]', \"smart account address (default: profile's smartAccount)\")\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol smart-account is-deployed\n $ kash protocol smart-account is-deployed 0xSa...\n $ kash protocol smart-account is-deployed --json --quiet | jq -r '.deployed'\n`\n )\n .action(async (address: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n const addressOverride = validateAddressOptional(address, 'address');\n\n try {\n const resolved = await buildDirectClient({ globals });\n const target = addressOverride ?? resolved.smartAccount;\n const deployed = await resolved.client.account.isDeployed(target);\n\n const payload = {\n address: target,\n chainId: resolved.chainId,\n deployed,\n };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Address ')} ${formatAddress(target, 10, 8)}`);\n print(\n ` ${style.dim('Deployed')} ${deployed ? style.success('yes') : style.dim('no — first UserOp will deploy')}`\n );\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nexport const smartAccountCommand = new Command('smart-account')\n .description('Smart-account address derivation and deployment-status checks.')\n .addCommand(computeCommand)\n .addCommand(isDeployedCommand);\n","/**\n * `kash protocol token-id --market-id <bigint> --outcome <n>` —\n * compute the ERC-1155 token id for a `(marketId, outcomeIndex)`\n * pair. Pure offline computation; no RPC required.\n *\n * Wraps `tokenIdFor` from `@kashdao/protocol-sdk`. The `marketId`\n * argument is the on-chain numeric id (read from `IMarket.marketId()`)\n * — NOT the market's contract address.\n */\n\nimport { Command } from 'commander';\n\nimport { CliValidationError, toCliError } from '../../errors.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { print, printJson, style } from '../../utils/output.js';\n\ntype TokenIdOptions = {\n marketId: string;\n outcome: string;\n};\n\nexport const tokenIdCommand = new Command('token-id')\n .description(\n 'Compute the ERC-1155 token id for a (marketId, outcomeIndex) pair (offline; no RPC).'\n )\n .requiredOption(\n '-m, --market-id <bigint>',\n 'on-chain numeric market id (decimal or 0x-prefixed hex)'\n )\n .requiredOption('-o, --outcome <index>', 'outcome index (0-255)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol token-id --market-id 42 --outcome 0\n $ kash protocol token-id --market-id 0x2a --outcome 1 --json --quiet | jq -r '.tokenId'\n\nNotes:\n - The numeric \\`marketId\\` is the on-chain id read from\n \\`IMarket(<addr>).marketId()\\`. It's NOT the same as the market\n contract address.\n - The token id encoding is \\`(marketId << 8) | outcomeIndex\\`,\n matching the on-chain \\`OutcomeTokens1155\\` contract.\n`\n )\n .action(async (options: TokenIdOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n\n let marketId: bigint;\n try {\n marketId = BigInt(options.marketId);\n } catch {\n throw new CliValidationError(\n '--market-id must be a non-negative integer (decimal or 0x-hex).',\n `Got \"${options.marketId}\".`,\n 'market-id'\n );\n }\n if (marketId < 0n) {\n throw new CliValidationError(\n '--market-id must be non-negative.',\n `Got \"${options.marketId}\".`,\n 'market-id'\n );\n }\n\n const outcomeIndex = Number.parseInt(options.outcome, 10);\n if (!Number.isFinite(outcomeIndex) || outcomeIndex < 0 || outcomeIndex > 255) {\n throw new CliValidationError(\n '--outcome must be an integer between 0 and 255.',\n `Got \"${options.outcome}\".`,\n 'outcome'\n );\n }\n\n try {\n // Lazy-import the protocol-sdk so this small offline helper\n // doesn't pull viem unnecessarily for the rest of the CLI.\n const { tokenIdFor } = await import('@kashdao/protocol-sdk');\n const tokenId = tokenIdFor(marketId, outcomeIndex);\n\n const payload = {\n marketId: marketId.toString(),\n outcomeIndex,\n tokenId: tokenId.toString(),\n tokenIdHex: `0x${tokenId.toString(16)}`,\n };\n\n if (globals.json) {\n printJson(payload);\n return;\n }\n\n print('');\n print(` ${style.dim('Market id ')} ${marketId.toString()}`);\n print(` ${style.dim('Outcome ')} ${String(outcomeIndex)}`);\n print(` ${style.dim('Token id ')} ${tokenId.toString()}`);\n print(` ${style.dim(' (hex) ')} 0x${tokenId.toString(16)}`);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n","/**\n * `kash protocol trade buy|sell|close|approve` — one-shot direct-mode\n * trade execution. Wraps `client.trades.send.{buy,sell,closePosition,approve}`\n * which prepares → simulates → signs → submits → (optionally) waits\n * for inclusion.\n *\n * **Real-money paths.** These commands sign and submit transactions\n * with the configured `signerKeyRef` against the configured\n * `bundlerUrl`/`bundlerProvider`. Use `--dry-run` to preview without\n * sending. Use `--no-wait` for fire-and-forget (returns userOpHash\n * immediately).\n *\n * **Safety:**\n * - The SDK's `prepare*` step always runs simulation (`eth_call`\n * preflight) before signing — pass `--no-simulate` to skip if\n * you've already validated and want the round-trip back.\n * - On simulation revert, throws `KashSimulationRevertedError`\n * before the consumer pays signer-infra round-trips.\n * - The signer's owner address is recovered from the signed hash\n * and compared to `signer.ownerAddress`; mismatches throw\n * `KashSignerError(STALE_USEROP_HASH)`.\n */\n\nimport { Command } from 'commander';\nimport ora from 'ora';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress } from '../../utils/formatting.js';\nimport { parsePositiveInt, readGlobals } from '../../utils/global-options.js';\nimport { isQuiet, 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 validateAddress,\n} from '../../utils/trade-input.js';\nimport { serializeUserOp } from '../../utils/userop-json.js';\n\ntype SharedOptions = {\n outcome?: string;\n slippageBps?: string;\n deadlineSec?: string;\n dryRun?: boolean;\n // Commander stores `--no-simulate` as `{ simulate: false }` — the\n // default for a `--no-X` boolean is `true`, so the explicit `false`\n // means the user passed the negative flag.\n simulate?: boolean;\n wait?: boolean;\n waitTimeoutMs?: string;\n waitIntervalMs?: string;\n};\n\ntype BuyOptions = SharedOptions & { amount: string };\ntype SellOptions = SharedOptions & { tokens: string };\ntype CloseOptions = SharedOptions;\ntype ApproveOptions = {\n amount?: string;\n // Commander stores `--no-X` as `{ x: false }`. See SharedOptions.\n wait?: boolean;\n waitTimeoutMs?: string;\n waitIntervalMs?: string;\n dryRun?: boolean;\n simulate?: boolean;\n};\n\nconst buyCommand = new Command('buy')\n .description('One-shot BUY: prepare → simulate → sign → submit (and wait by default).')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-a, --amount <usdc>', 'USDC to spend (decimal — e.g. \"10\" or \"12.50\")')\n .option('--slippage-bps <n>', 'slippage tolerance in basis points (default 50 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit; print the UserOp')\n .option('--no-simulate', 'skip the eth_call preflight (faster, riskier)')\n .option('--no-wait', 'fire-and-forget: return userOpHash without waiting for inclusion')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .option('--wait-interval-ms <n>', 'receipt poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol trade buy 0xMarket... -o 0 -a 10\n $ kash protocol trade buy 0xMarket... -o 0 -a 10 --slippage-bps 100 # 1% slippage\n $ kash protocol trade buy 0xMarket... -o 0 -a 10 --dry-run --json\n $ kash protocol trade buy 0xMarket... -o 0 -a 10 --no-wait --json --quiet\n`\n )\n .action(async (market: string, options: BuyOptions, cmd: Command) => {\n await runTrade('buy', market, options, cmd);\n });\n\nconst sellCommand = new Command('sell')\n .description('One-shot SELL: prepare → simulate → sign → submit (and wait by default).')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-t, --tokens <amount>', 'outcome tokens to sell (decimal — WAD precision)')\n .option('--slippage-bps <n>', 'slippage tolerance in basis points (default 50 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit; print the UserOp')\n .option('--no-simulate', 'skip the eth_call preflight (faster, riskier)')\n .option('--no-wait', 'fire-and-forget: return userOpHash without waiting for inclusion')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .option('--wait-interval-ms <n>', 'receipt poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol trade sell 0xMarket... -o 0 -t 1.5\n $ kash protocol trade sell 0xMarket... -o 1 -t 0.5 --json --quiet\n`\n )\n .action(async (market: string, options: SellOptions, cmd: Command) => {\n await runTrade('sell', market, options, cmd);\n });\n\nconst closeCommand = new Command('close')\n .description('Sell the entire SA balance for an outcome (one-shot prepare → submit).')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .option('--slippage-bps <n>', 'slippage tolerance in basis points (default 50 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit; print the UserOp')\n .option('--no-simulate', 'skip the eth_call preflight (faster, riskier)')\n .option('--no-wait', 'fire-and-forget: return userOpHash without waiting for inclusion')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .option('--wait-interval-ms <n>', 'receipt poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol trade close 0xMarket... -o 0\n $ kash protocol trade close 0xMarket... -o 1 --slippage-bps 200 --json\n`\n )\n .action(async (market: string, options: CloseOptions, cmd: Command) => {\n await runTrade('close', market, options, cmd);\n });\n\nconst approveCommand = new Command('approve')\n .description('USDC approval — required once before the first BUY.')\n .argument('<spender>', 'spender contract address (typically a Market) — 0x-prefixed')\n .option(\n '-a, --amount <usdc>',\n 'atomic-USDC amount to approve (decimal); default is unlimited (MAX_UINT256)'\n )\n .option('--dry-run', 'prepare + simulate but DO NOT sign or submit; print the UserOp')\n .option('--no-simulate', 'skip the eth_call preflight (faster, riskier)')\n .option('--no-wait', 'fire-and-forget: return userOpHash without waiting for inclusion')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .option('--wait-interval-ms <n>', 'receipt poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol trade approve 0xMarket... # unlimited approval\n $ kash protocol trade approve 0xMarket... --amount 100 # cap at 100 USDC\n $ kash protocol trade approve 0xMarket... --dry-run --json # preview only\n`\n )\n .action(async (spender: string, options: ApproveOptions, cmd: Command) => {\n await runApprove(spender, options, cmd);\n });\n\nexport const tradeCommand = new Command('trade')\n .description('Direct-mode trade execution (UserOp signed locally, submitted via bundler).')\n .addCommand(buyCommand)\n .addCommand(sellCommand)\n .addCommand(closeCommand)\n .addCommand(approveCommand);\n\n// ---------------------------------------------------------------------------\n// Shared runners\n// ---------------------------------------------------------------------------\n\ntype Side = TradeOpSide;\n\nasync function runTrade(\n side: Side,\n market: string,\n options: BuyOptions | SellOptions | CloseOptions,\n cmd: Command\n): Promise<void> {\n const globals = readGlobals(cmd);\n const marketAddress = validateAddress(market, 'market');\n\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 const waitIntervalMs = options.waitIntervalMs\n ? parsePositiveInt(options.waitIntervalMs, 'wait-interval-ms')\n : undefined;\n\n // Side-specific amount parsing.\n let amountUsdc: bigint | undefined;\n let amountTokens: bigint | undefined;\n if (side === 'buy') {\n const buyOpts = options as BuyOptions;\n amountUsdc = decimalToAtomicUsdc(buyOpts.amount, 'amount');\n } else if (side === 'sell') {\n const sellOpts = options as SellOptions;\n amountTokens = decimalToAtomicWad(sellOpts.tokens, 'tokens');\n }\n\n try {\n const resolved = await buildDirectClient({ globals, requireSigner: true });\n\n // --dry-run path: prepare only, emit the populated UserOp + hash.\n // Doesn't sign or submit. Bypasses the wait/submit pipeline.\n if (options.dryRun === true) {\n const built = await prepareForSide(resolved.client, side, {\n market: marketAddress,\n smartAccount: resolved.smartAccount,\n outcome,\n slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n ...(amountUsdc === undefined ? {} : { amountUsdc }),\n ...(amountTokens === undefined ? {} : { amountTokens }),\n simulate: options.simulate !== false,\n });\n emitDryRun(built, side, market, globals.json);\n return;\n }\n\n const sendOptions = {\n simulate: options.simulate !== false,\n wait: options.wait !== false,\n ...(waitTimeoutMs === undefined ? {} : { waitTimeoutMs }),\n ...(waitIntervalMs === undefined ? {} : { waitIntervalMs }),\n };\n\n const spinner =\n !globals.json && !isQuiet()\n ? ora({\n text: `Preparing ${side} on ${formatAddress(market, 8, 6)}…`,\n stream: process.stderr,\n }).start()\n : undefined;\n\n let result;\n try {\n if (side === 'buy') {\n result = await resolved.client.trades.send.buy(\n marketAddress,\n {\n account: resolved.smartAccount,\n outcome,\n amountUsdc: amountUsdc!,\n maxSlippageBps: slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n },\n sendOptions\n );\n } else if (side === 'sell') {\n result = await resolved.client.trades.send.sell(\n marketAddress,\n {\n account: resolved.smartAccount,\n outcome,\n amountTokens: amountTokens!,\n maxSlippageBps: slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n },\n sendOptions\n );\n } else {\n result = await resolved.client.trades.send.closePosition(\n marketAddress,\n {\n account: resolved.smartAccount,\n outcome,\n maxSlippageBps: slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n },\n sendOptions\n );\n }\n } catch (cause) {\n spinner?.fail(`${side} failed.`);\n // Partial-completion guard. If the SDK's submit step succeeded\n // but the wait step timed out, the cause is a KashBundlerError\n // with `code: 'BUNDLER_RECEIPT_TIMEOUT'` whose `context.userOpHash`\n // carries the hash the bundler will eventually land. Surface\n // that hash so the operator can resume via\n // `kash protocol userop wait <hash>` rather than paying for\n // another sign/submit cycle. The discriminator is narrow on\n // purpose — KashSignerError ALSO carries `context.userOpHash`,\n // and a remote-signer failure would be actively misleading if\n // it was reported as \"submit succeeded, wait timed out\". See\n // `extractPartialUserOpHash` for the discrimination details.\n const partialHash = extractPartialUserOpHash(cause);\n if (partialHash !== undefined) {\n if (globals.json) {\n printJson({ userOpHash: partialHash, waited: false, partial: true });\n } else {\n log.warn(\n `Submit succeeded but wait timed out. UserOp is on the bundler queue — resume with: kash protocol userop wait ${partialHash}`\n );\n }\n }\n throw cause;\n }\n spinner?.succeed(`${side} submitted.`);\n emitSendResult(result, side, market, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n}\n\nasync function runApprove(spender: string, options: ApproveOptions, cmd: Command): Promise<void> {\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 const waitIntervalMs = options.waitIntervalMs\n ? parsePositiveInt(options.waitIntervalMs, 'wait-interval-ms')\n : undefined;\n\n try {\n const resolved = await buildDirectClient({ globals, requireSigner: true });\n const params = {\n account: resolved.smartAccount,\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(built, 'approve', spender, globals.json);\n return;\n }\n\n const sendOptions = {\n simulate: options.simulate !== false,\n wait: options.wait !== false,\n ...(waitTimeoutMs === undefined ? {} : { waitTimeoutMs }),\n ...(waitIntervalMs === undefined ? {} : { waitIntervalMs }),\n };\n\n const spinner =\n !globals.json && !isQuiet()\n ? ora({\n text: `Approving ${formatAddress(spender, 8, 6)}…`,\n stream: process.stderr,\n }).start()\n : undefined;\n\n let result;\n try {\n result = await resolved.client.trades.send.approve(params, sendOptions);\n } catch (cause) {\n spinner?.fail('approve failed.');\n // Symmetric partial-completion guard. Approves cost gas; if\n // submit succeeded but wait timed out, surface `userOpHash`\n // so the operator can resume via `kash protocol userop wait\n // <hash>` rather than paying for a duplicate approve. See\n // `extractPartialUserOpHash` for the discrimination rule.\n const partialHash = extractPartialUserOpHash(cause);\n if (partialHash !== undefined) {\n if (globals.json) {\n printJson({ userOpHash: partialHash, waited: false, partial: true });\n } else {\n log.warn(\n `Submit succeeded but wait timed out. The approve UserOp is on the bundler queue — resume with: kash protocol userop wait ${partialHash}`\n );\n }\n }\n throw cause;\n }\n spinner?.succeed('approve submitted.');\n emitSendResult(result, 'approve', spender, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n}\n\n// ---------------------------------------------------------------------------\n// SDK call adapters\n// ---------------------------------------------------------------------------\n\n/**\n * Route prepare to the right SDK method by side. We pass the\n * intersection-typed params and let TypeScript narrow.\n */\nasync function prepareForSide(\n client: Awaited<ReturnType<typeof buildDirectClient>>['client'],\n side: Side,\n args: {\n market: `0x${string}`;\n /** SA address whose `execute()` will run the trade. Mapped to `account` on the SDK shape. */\n smartAccount: `0x${string}`;\n outcome: number;\n slippageBps: number;\n deadline?: bigint;\n amountUsdc?: bigint;\n amountTokens?: bigint;\n simulate: boolean;\n }\n): Promise<Awaited<ReturnType<typeof client.trades.prepareBuy>>> {\n const opts = { simulate: args.simulate };\n // The protocol-sdk's BuildBuy/Sell/ClosePositionParams use\n // `account` (the address that pays USDC and receives outcome\n // tokens). In SA mode, the operator-facing concept is \"the smart\n // account\" — we keep `smartAccount` as the local name and map at\n // the boundary so the rest of the file reads naturally.\n const baseParams = {\n account: args.smartAccount,\n outcome: args.outcome,\n maxSlippageBps: args.slippageBps,\n ...(args.deadline === undefined ? {} : { deadline: args.deadline }),\n };\n if (side === 'buy') {\n return await client.trades.prepareBuy(\n args.market,\n { ...baseParams, amountUsdc: args.amountUsdc! },\n opts\n );\n }\n if (side === 'sell') {\n return await client.trades.prepareSell(\n args.market,\n { ...baseParams, amountTokens: args.amountTokens! },\n opts\n );\n }\n return await client.trades.prepareClosePosition(args.market, baseParams, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Output emitters\n// ---------------------------------------------------------------------------\n\ntype BuiltLike = Awaited<\n ReturnType<Awaited<ReturnType<typeof buildDirectClient>>['client']['trades']['prepareBuy']>\n>;\n\nfunction emitDryRun(built: BuiltLike, side: Side | 'approve', target: string, json: boolean): void {\n // Pre-convert bigints to decimal strings via the shared encoder.\n // `printJson`'s `jsonReplacer` would coerce these on the JSON branch\n // anyway, but the human branch below also reads `userOp.sender` and\n // `userOp.nonce` for the dry-run summary, so we need the converted\n // shape *before* we know which branch we're on. Don't add a third\n // bigint encoder here — `utils/userop-json.ts` is the canonical one.\n const userOp = serializeUserOp(built.userOp);\n if (json) {\n printJson({\n side,\n target,\n userOp,\n userOpHash: built.userOpHash,\n typedData: built.typedData,\n dryRun: true,\n });\n return;\n }\n print('');\n print(` ${style.bold('Dry run')} — UserOp prepared but NOT signed/submitted.`);\n print(` ${style.dim('Side ')} ${side}`);\n print(` ${style.dim('Target ')} ${formatAddress(target, 10, 8)}`);\n const senderRaw = userOp['sender'];\n const sender = typeof senderRaw === 'string' ? senderRaw : '';\n print(` ${style.dim('Sender ')} ${formatAddress(sender, 10, 8)}`);\n print(` ${style.dim('Nonce ')} ${String(userOp['nonce'])}`);\n print(` ${style.dim('Hash ')} ${built.userOpHash}`);\n print('');\n print(style.dim('Re-run without --dry-run to sign and submit.'));\n}\n\ntype SendResultLike =\n | { userOpHash: `0x${string}` }\n | {\n userOpHash: `0x${string}`;\n transactionHash: `0x${string}`;\n blockNumber: bigint;\n success: boolean;\n // SDK type is `gasUsed` (see protocol-sdk's SendResultWaited).\n // The earlier alias `actualGasUsed` here was a copy of the\n // bundler-receipt field name, but the SDK normalises that into\n // `gasUsed: BigInt(receipt.actualGasUsed)` before returning.\n gasUsed: bigint;\n };\n\nfunction emitSendResult(\n result: SendResultLike,\n side: Side | 'approve',\n target: string,\n json: boolean\n): void {\n const waited = 'transactionHash' in result;\n const payload = waited\n ? {\n side,\n target,\n userOpHash: result.userOpHash,\n transactionHash: result.transactionHash,\n blockNumber: result.blockNumber.toString(),\n success: result.success,\n actualGasUsed: result.gasUsed.toString(),\n }\n : {\n side,\n target,\n userOpHash: result.userOpHash,\n waited: false,\n };\n if (json) {\n printJson(payload);\n return;\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('UserOp ')} ${result.userOpHash}`);\n print(` ${style.dim('Tx ')} ${result.transactionHash}`);\n print(` ${style.dim('Block ')} ${result.blockNumber.toString()}`);\n print(` ${style.dim('Gas used ')} ${result.gasUsed.toString()}`);\n } else {\n log.success(`${side} submitted (fire-and-forget).`);\n print(` ${style.dim('UserOp ')} ${result.userOpHash}`);\n log.info(`Use \\`kash protocol userop wait ${result.userOpHash}\\` to poll for inclusion.`);\n }\n}\n\n/**\n * SA-mode wrapper around the canonical `extractPartialHash` factory\n * (`utils/trade-input.ts`). Pinned to the bundler-timeout code so\n * pre-submit failures (`KashSignerError SIGNER_SIGN_FAILED` carries\n * `context.userOpHash` too) don't masquerade as partial completions.\n *\n * SDK throw site: `protocol-sdk/src/smart-account/bundler/generic.ts:337-341`.\n * Counter-case: `protocol-sdk/src/smart-account/trades/send.ts:222-226`.\n */\nfunction extractPartialUserOpHash(cause: unknown): `0x${string}` | undefined {\n return extractPartialHash(cause, {\n code: 'BUNDLER_RECEIPT_TIMEOUT',\n contextKey: 'userOpHash',\n });\n}\n\n// All input parsers live in `utils/trade-input.ts` — single source of\n// truth so SA-mode (`kash protocol trade`), userop-build, and EOA-mode\n// (`kash eoa trade`) behaviour can never drift on real-money paths.\n//\n// The UserOp bigint→string encoder lives in `utils/userop-json.ts`;\n// the same encoder is used by `userop build / sign / submit`, so a\n// `--print-userop` payload round-trips through the offline signer\n// pipeline byte-for-byte.\n","/**\n * JSON (de)serialisation helpers for ERC-4337 v0.7 UserOps.\n *\n * Two consumers share this module:\n *\n * - `kash protocol trade` (SA mode) emits the prepared UserOp on the\n * `--print-userop` path so an external signer can consume it.\n * - `kash protocol userop build / sign / submit / wait` round-trips\n * UserOps through disk and stdin via the same JSON shape.\n *\n * Both entered the codebase with their own local copy of the bigint→\n * string encoder, which is a real-money divergence risk: a UserOp\n * round-tripped through `trade --print-userop | userop sign --in -`\n * is the textbook \"operator builds + offline signs\" flow, and any\n * field that one side stringifies but the other does not would silently\n * change the call's gas semantics.\n *\n * The encoder is the load-bearing primitive; the decoder lives in\n * `userop.ts` next to the `UnsignedUserOp` field-shape declarations\n * that drive its bigint-field whitelist.\n */\n\n/**\n * Convert a UserOp's bigint fields (`nonce`, `callGasLimit`, gas\n * limits, fees, etc.) to decimal strings so the envelope round-trips\n * through `JSON.stringify`. Non-bigint fields pass through untouched.\n *\n * The shape is the inverse of `userop.ts:deserializeUserOp` — keep\n * the two in lockstep when adding new bigint fields to the SDK's\n * UnsignedUserOp.\n */\nexport function serializeUserOp(userOp: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(userOp)) {\n out[k] = typeof v === 'bigint' ? v.toString() : v;\n }\n return out;\n}\n","/**\n * `kash protocol userop {build,simulate,submit,hash,receipt,wait}` —\n * granular UserOp lifecycle for direct-mode cold-storage flows.\n *\n * Pairs with `kash protocol trade` (the all-in-one path). Use this\n * namespace when you need to:\n * - Build a UserOp on machine A (no signer; `noopSigner` plumbing).\n * - Move the UserOp to machine B (signer-only).\n * - Submit from machine C against the bundler.\n *\n * **File format.** Each command that takes/emits a UserOp uses the\n * canonical JSON shape (bigints serialized as decimal strings).\n * Reading from stdin is supported (`-` argument or no argument);\n * writing goes to stdout (or `--out <path>`).\n *\n * **`build`** uses the SDK's `prepare*` under the hood (build + gas\n * estimation + fees + hash recompute) — the resulting UserOp is fully\n * populated and ready to sign. This matches the cold-storage flow\n * users expect: build once, sign offline, submit later.\n */\n\nimport { readFile, writeFile } from 'node:fs/promises';\n\nimport { Command } from 'commander';\n\nimport { CliError, CliValidationError, toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { formatAddress } from '../../utils/formatting.js';\nimport { parsePositiveInt, readGlobals } from '../../utils/global-options.js';\nimport { log, print, printJson, style } from '../../utils/output.js';\nimport {\n DEFAULT_SLIPPAGE_BPS,\n HEX_HASH_REGEX,\n MAX_UINT256,\n decimalToAtomicUsdc,\n decimalToAtomicWad,\n parseDeadlineSec,\n parseOutcomeIndex,\n parseSlippageBps,\n validateAddress,\n} from '../../utils/trade-input.js';\nimport { serializeUserOp } from '../../utils/userop-json.js';\n\n// ---------------------------------------------------------------------------\n// `userop build buy|sell|close|approve`\n// ---------------------------------------------------------------------------\n\ntype BuildSharedOptions = {\n outcome?: string;\n slippageBps?: string;\n deadlineSec?: string;\n out?: string;\n // Commander stores `--no-simulate` as `{ simulate: false }`.\n simulate?: boolean;\n};\n\nconst buildBuyCommand = new Command('buy')\n .description('Build a fully-populated unsigned BUY UserOp ready for offline signing.')\n .argument('<market>', 'market contract address (0x-prefixed)')\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 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--out <path>', 'write the UserOp envelope to a file (default stdout)')\n .option('--no-simulate', 'skip eth_call preflight in `prepare`')\n .action(\n async (market: string, options: BuildSharedOptions & { amount: string }, cmd: Command) => {\n await runBuild('buy', market, options, cmd);\n }\n );\n\nconst buildSellCommand = new Command('sell')\n .description('Build a fully-populated unsigned SELL UserOp ready for offline signing.')\n .argument('<market>', 'market contract address (0x-prefixed)')\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 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--out <path>', 'write the UserOp envelope to a file (default stdout)')\n .option('--no-simulate', 'skip eth_call preflight in `prepare`')\n .action(\n async (market: string, options: BuildSharedOptions & { tokens: string }, cmd: Command) => {\n await runBuild('sell', market, options, cmd);\n }\n );\n\nconst buildCloseCommand = new Command('close')\n .description('Build a fully-populated unsigned UserOp that closes a position (full balance).')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .option('--slippage-bps <n>', 'slippage tolerance in bps (default 50 = 0.5%)')\n .option('--deadline-sec <n>', 'unix-seconds deadline (default now + 5min)')\n .option('--out <path>', 'write the UserOp envelope to a file (default stdout)')\n .option('--no-simulate', 'skip eth_call preflight in `prepare`')\n .action(async (market: string, options: BuildSharedOptions, cmd: Command) => {\n await runBuild('close', market, options, cmd);\n });\n\nconst buildApproveCommand = new Command('approve')\n .description('Build a fully-populated unsigned approve UserOp ready for offline signing.')\n .argument('<spender>', 'spender contract address (typically a Market) — 0x-prefixed')\n .option('-a, --amount <usdc>', 'atomic-USDC amount (decimal); default unlimited (MAX_UINT256)')\n .option('--out <path>', 'write the UserOp envelope to a file (default stdout)')\n .option('--no-simulate', 'skip eth_call preflight in `prepare`')\n .action(\n async (\n spender: string,\n options: { amount?: string; out?: string; simulate?: boolean },\n cmd: Command\n ) => {\n await runBuildApprove(spender, options, cmd);\n }\n );\n\nconst buildCommand = new Command('build')\n .description('Build (prepare) a fully-populated unsigned UserOp ready for offline signing.')\n .addCommand(buildBuyCommand)\n .addCommand(buildSellCommand)\n .addCommand(buildCloseCommand)\n .addCommand(buildApproveCommand);\n\ntype BuildSide = 'buy' | 'sell' | 'close';\n\nasync function runBuild(\n side: BuildSide,\n market: string,\n options: BuildSharedOptions & { 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\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 // `requireSigner: false` because build doesn't need to sign —\n // the noopSigner suffices. The cold-storage flow signs externally.\n const resolved = await buildDirectClient({ globals });\n // The protocol-sdk migrated `smartAccount` → `account` on its\n // BuildBuyParams / BuildSellParams / BuildClosePositionParams\n // shapes. The field still resolves to the same address (the SA\n // we configured); only the parameter name changed. EOA mode also\n // uses `account` (with a different invariant — owner must equal\n // signer.ownerAddress); SA mode is \"the SA whose execute() runs.\"\n const baseParams = {\n account: resolved.smartAccount,\n outcome,\n maxSlippageBps: slippageBps,\n ...(deadline === undefined ? {} : { deadline }),\n };\n const opts = { simulate: options.simulate !== false };\n\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\n await emitBuildResult(built, side, market, options.out, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n}\n\nasync function runBuildApprove(\n spender: string,\n options: { amount?: string; out?: string; simulate?: boolean },\n cmd: Command\n): Promise<void> {\n const globals = readGlobals(cmd);\n const spenderAddress = validateAddress(spender, 'spender');\n const amount = options.amount ? decimalToAtomicUsdc(options.amount, 'amount') : MAX_UINT256;\n\n try {\n const resolved = await buildDirectClient({ globals });\n const built = await resolved.client.trades.prepareApprove(\n {\n account: resolved.smartAccount,\n spender: spenderAddress,\n amount,\n },\n { simulate: options.simulate !== false }\n );\n await emitBuildResult(built, 'approve', spender, options.out, globals.json);\n } catch (cause) {\n throw toCliError(cause);\n }\n}\n\n// ---------------------------------------------------------------------------\n// `userop simulate`\n// ---------------------------------------------------------------------------\n\nconst simulateCommand = new Command('simulate')\n .description('Simulate (eth_call) an UnsignedUserOp from a file or stdin.')\n .argument('[file]', 'path to a UserOp JSON file (omit or pass \"-\" for stdin)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol userop build buy 0xMarket... -o 0 -a 10 --out trade.json\n $ kash protocol userop simulate trade.json\n $ cat trade.json | kash protocol userop simulate\n`\n )\n .action(async (file: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n try {\n const userOp = await readUnsignedUserOp(file);\n const resolved = await buildDirectClient({ globals });\n const result = await resolved.client.trades.simulate(userOp);\n\n if (globals.json) {\n printJson(serializeSimulationResult(result));\n return;\n }\n print('');\n if (result.willSucceed) {\n log.success('Simulation: would succeed.');\n if (result.gasEstimate !== undefined) {\n print(` ${style.dim('Gas estimate ')} ${result.gasEstimate.toString()}`);\n }\n } else {\n log.error('Simulation: would revert.');\n print(` ${style.dim('Reason ')} ${result.revertReason}`);\n if (result.decodedError) {\n print(` ${style.dim('Custom err')} ${result.decodedError.name}`);\n }\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\n// ---------------------------------------------------------------------------\n// `userop submit`\n// ---------------------------------------------------------------------------\n\ntype SubmitOptions = {\n skipStalenessCheck?: boolean;\n wait?: boolean;\n waitTimeoutMs?: string;\n waitIntervalMs?: string;\n};\n\nconst submitCommand = new Command('submit')\n .description('Submit a SignedUserOp from a file or stdin to the configured bundler.')\n .argument('[file]', 'path to a SignedUserOp JSON file (omit or pass \"-\" for stdin)')\n .option('--skip-staleness-check', 'bypass the EIP-191 staleness check (for typed-data signers)')\n .option('--wait', 'wait for receipt after submitting')\n .option('--wait-timeout-ms <n>', 'cap on the receipt wait (default 60000)')\n .option('--wait-interval-ms <n>', 'receipt poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol userop submit signed.json --json\n $ cat signed.json | kash protocol userop submit --wait\n`\n )\n .action(async (file: string | undefined, options: SubmitOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const waitTimeoutMs = options.waitTimeoutMs\n ? parsePositiveInt(options.waitTimeoutMs, 'wait-timeout-ms')\n : undefined;\n const waitIntervalMs = options.waitIntervalMs\n ? parsePositiveInt(options.waitIntervalMs, 'wait-interval-ms')\n : undefined;\n\n try {\n const signed = await readSignedUserOp(file);\n const resolved = await buildDirectClient({ globals });\n const result = await resolved.client.trades.submit(signed, {\n skipStalenessCheck: options.skipStalenessCheck === true,\n });\n\n if (options.wait !== true) {\n if (globals.json) {\n printJson({ userOpHash: result.userOpHash, waited: false });\n return;\n }\n log.success('UserOp submitted.');\n print(` ${style.dim('Hash')} ${result.userOpHash}`);\n log.info(`Use \\`kash protocol userop wait ${result.userOpHash}\\` to poll for inclusion.`);\n return;\n }\n\n const waitOpts = {\n ...(waitTimeoutMs === undefined ? {} : { timeoutMs: waitTimeoutMs }),\n ...(waitIntervalMs === undefined ? {} : { intervalMs: waitIntervalMs }),\n };\n\n // Partial-completion guard. The submit() above succeeded — the\n // UserOp is on the bundler's queue and will eventually land\n // even if our local wait times out. Surface `userOpHash` on\n // BOTH stderr and (for --json) the error envelope before\n // rethrowing, so the operator can resume via\n // `kash protocol userop wait <hash>` instead of paying for\n // another sign/submit cycle. The hash MUST persist before the\n // receipt wait so we never lose track of an in-flight UserOp.\n let receipt: Awaited<ReturnType<typeof resolved.client.bundler.waitForReceipt>>;\n try {\n receipt = await resolved.client.bundler.waitForReceipt(result.userOpHash, waitOpts);\n } catch (waitCause) {\n if (globals.json) {\n // Emit the hash on stdout as a structured partial-success\n // record before letting toCliError build the error envelope.\n // Two NDJSON lines are easier for agents to parse than a\n // merged error+hash blob.\n printJson({ userOpHash: result.userOpHash, waited: false, partial: true });\n } else {\n log.warn(\n `Submit succeeded but wait failed. UserOp is on the bundler queue — resume with: kash protocol userop wait ${result.userOpHash}`\n );\n }\n throw toCliError(waitCause);\n }\n\n if (globals.json) {\n printJson(serializeReceipt(receipt));\n return;\n }\n emitReceiptHuman(receipt);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\n// ---------------------------------------------------------------------------\n// `userop hash`\n// ---------------------------------------------------------------------------\n\nconst hashCommand = new Command('hash')\n .description('Recompute the canonical EIP-4337 v0.7 hash for a UnsignedUserOp.')\n .argument('[file]', 'path to a UserOp JSON file (omit or pass \"-\" for stdin)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol userop hash trade.json\n $ cat trade.json | kash protocol userop hash --json --quiet | jq -r '.userOpHash'\n\nNotes:\n - The hash baked into a freshly-built UserOp goes stale after gas\n fields are populated. Always recompute via this command (or\n \\`hashOf\\` in the SDK) before signing.\n`\n )\n .action(async (file: string | undefined, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n try {\n const userOp = await readUnsignedUserOp(file);\n const resolved = await buildDirectClient({ globals });\n const userOpHash = resolved.client.trades.hashOf(userOp);\n\n if (globals.json) {\n printJson({ userOpHash });\n return;\n }\n print(userOpHash);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\n// ---------------------------------------------------------------------------\n// `userop receipt` / `userop wait`\n// ---------------------------------------------------------------------------\n\nconst receiptCommand = new Command('receipt')\n .description('Fetch the bundler receipt for a UserOp hash (null if not yet included).')\n .argument('<hash>', 'UserOp hash (0x-prefixed, 32 bytes)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol userop receipt 0xabc...\n $ kash protocol userop receipt 0xabc... --json --quiet | jq -r '.success'\n`\n )\n .action(async (hash: string, _opts, cmd: Command) => {\n const globals = readGlobals(cmd);\n if (!HEX_HASH_REGEX.test(hash)) {\n throw new CliValidationError(\n '<hash> must be a 0x-prefixed 32-byte hex hash.',\n `Got \"${hash}\".`,\n 'hash'\n );\n }\n try {\n const resolved = await buildDirectClient({ globals });\n const receipt = await resolved.client.bundler.getReceipt(hash as `0x${string}`);\n\n if (globals.json) {\n printJson(receipt === null ? null : serializeReceipt(receipt));\n return;\n }\n if (receipt === null) {\n log.info('Not yet included (receipt is null).');\n return;\n }\n emitReceiptHuman(receipt);\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\nconst waitCommand = new Command('wait')\n .description('Wait for a UserOp to be included; polls with exponential backoff.')\n .argument('<hash>', 'UserOp hash (0x-prefixed, 32 bytes)')\n .option(\n '--wait-timeout-ms, --timeout-ms <n>',\n 'total time budget across polls (default 60000) — distinct from the global --timeout-ms (per-HTTP-request)'\n )\n .option('--interval-ms <n>', 'poll interval (default 1500)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol userop wait 0xabc...\n $ kash protocol userop wait 0xabc... --wait-timeout-ms 300000 # 5min budget\n`\n )\n .action(\n async (hash: string, options: { timeoutMs?: string; intervalMs?: string }, cmd: Command) => {\n const globals = readGlobals(cmd);\n if (!HEX_HASH_REGEX.test(hash)) {\n throw new CliValidationError(\n '<hash> must be a 0x-prefixed 32-byte hex hash.',\n `Got \"${hash}\".`,\n 'hash'\n );\n }\n const timeoutMs = options.timeoutMs\n ? parsePositiveInt(options.timeoutMs, 'timeout-ms')\n : undefined;\n const intervalMs = options.intervalMs\n ? parsePositiveInt(options.intervalMs, 'interval-ms')\n : undefined;\n\n try {\n const resolved = await buildDirectClient({ globals });\n const waitOpts = {\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n ...(intervalMs === undefined ? {} : { intervalMs }),\n };\n const receipt = await resolved.client.bundler.waitForReceipt(\n hash as `0x${string}`,\n waitOpts\n );\n if (globals.json) {\n printJson(serializeReceipt(receipt));\n return;\n }\n emitReceiptHuman(receipt);\n } catch (cause) {\n throw toCliError(cause);\n }\n }\n );\n\n// ---------------------------------------------------------------------------\n// Top-level userop namespace\n// ---------------------------------------------------------------------------\n\nexport const useropCommand = new Command('userop')\n .description('Granular UserOp lifecycle: build, simulate, submit, hash, receipt, wait.')\n .addCommand(buildCommand)\n .addCommand(simulateCommand)\n .addCommand(submitCommand)\n .addCommand(hashCommand)\n .addCommand(receiptCommand)\n .addCommand(waitCommand);\n\n// ---------------------------------------------------------------------------\n// File IO + serialization\n// ---------------------------------------------------------------------------\n\ntype UnsignedUserOp = Awaited<\n ReturnType<Awaited<ReturnType<typeof buildDirectClient>>['client']['trades']['prepareBuy']>\n>['userOp'];\n\ntype SignedUserOp = UnsignedUserOp & { signature: `0x${string}` };\n\nasync function emitBuildResult(\n built: { userOp: UnsignedUserOp; userOpHash: `0x${string}`; typedData: unknown },\n side: BuildSide | 'approve',\n target: string,\n outPath: string | undefined,\n json: boolean\n): Promise<void> {\n const payload = {\n side,\n target,\n userOp: serializeUserOp(built.userOp),\n userOpHash: built.userOpHash,\n typedData: built.typedData,\n };\n const serialized = JSON.stringify(payload, null, 2);\n\n if (outPath) {\n try {\n await writeFile(outPath, `${serialized}\\n`, { encoding: 'utf8', mode: 0o600 });\n } catch (cause) {\n throw new CliError(`Failed to write ${outPath}.`, {\n code: 'CONFIGURATION',\n recoverable: true,\n suggestion: 'Verify the path is writable and the parent directory exists.',\n cause,\n });\n }\n if (!json) {\n log.success(`Wrote ${outPath} (mode 0600).`);\n print(` ${style.dim('Side ')} ${side}`);\n print(` ${style.dim('Target')} ${formatAddress(target, 10, 8)}`);\n print(` ${style.dim('Hash ')} ${built.userOpHash}`);\n }\n return;\n }\n\n if (json) {\n printJson(payload);\n return;\n }\n // Human-mode without --out: emit a compact line + the JSON payload to\n // stderr-vs-stdout split. Keep stdout pure-JSON so it can pipe.\n log.success(`Built ${side} UserOp.`);\n log.detail('Hash', built.userOpHash);\n print(serialized);\n}\n\n/** Read a UserOp envelope (from `userop build`) and unpack the inner UserOp. */\nasync function readUnsignedUserOp(file: string | undefined): Promise<UnsignedUserOp> {\n const raw = await readSource(file);\n const parsed = parseEnvelope(raw);\n return deserializeUserOp(parsed.userOp) as UnsignedUserOp;\n}\n\n/**\n * Canonical 65-byte ECDSA signature shape: `0x` + 130 hex chars.\n * Some signers (Ledger, certain managed-signer / HSM flows) emit a\n * longer ERC-1271 / aggregate-style signature, so we accept any\n * 0x-prefixed hex string of even length ≥ 130 — but reject the empty\n * `0x` and sub-65-byte truncations early so the bundler doesn't have\n * to.\n */\nconst SIGNED_USEROP_SIG_REGEX = /^0x([0-9a-fA-F]{2})+$/;\n\n/** Read a signed UserOp; the signature must already be set. */\nasync function readSignedUserOp(file: string | undefined): Promise<SignedUserOp> {\n const raw = await readSource(file);\n const parsed = parseEnvelope(raw);\n const userOp = deserializeUserOp(parsed.userOp) as UnsignedUserOp;\n const signature = (userOp as unknown as { signature?: unknown }).signature;\n if (typeof signature !== 'string' || signature === '0x') {\n throw new CliValidationError(\n 'UserOp envelope is missing a non-empty `signature` field.',\n 'Sign the userOp externally and write the resulting signature into the `userOp.signature` field.'\n );\n }\n // Shape check first (catches typos, accidental truncation, base64\n // signatures that snuck in). Length check second (must be at least\n // a 65-byte ECDSA signature; longer signatures are accepted to\n // support ERC-1271 / aggregate signers).\n if (!SIGNED_USEROP_SIG_REGEX.test(signature)) {\n throw new CliValidationError(\n 'UserOp `signature` must be a 0x-prefixed hex string with even-length payload.',\n `Got ${String(signature.length)} characters. Expected at least 132 (0x + 130 hex chars for a 65-byte ECDSA signature).`\n );\n }\n if (signature.length < 132) {\n throw new CliValidationError(\n 'UserOp `signature` is too short to be a valid ECDSA signature.',\n `Got ${String(signature.length)} hex chars; canonical ECDSA signatures are 132 (0x + 130). Did the signer truncate output?`\n );\n }\n return userOp as SignedUserOp;\n}\n\nasync function readSource(file: string | undefined): Promise<string> {\n if (file !== undefined && file !== '-') {\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 // Stdin.\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n if (typeof chunk === 'string') chunks.push(Buffer.from(chunk));\n else if (chunk instanceof Buffer) chunks.push(chunk);\n else chunks.push(Buffer.from(chunk as Uint8Array));\n }\n if (chunks.length === 0) {\n throw new CliValidationError(\n 'No input received on stdin.',\n 'Pass a file path or pipe a UserOp JSON envelope into stdin.'\n );\n }\n // Strip a leading UTF-8 BOM. Required for files exported from\n // Notepad / VSCode-with-utf8bom — JSON.parse chokes on the leading\n // U+FEFF byte otherwise.\n const { stripBom } = await import('../../utils/stdin.js');\n return stripBom(Buffer.concat(chunks).toString('utf8'));\n}\n\nfunction parseEnvelope(raw: string): { userOp: Record<string, unknown> } {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new CliValidationError(\n 'Input is not valid JSON.',\n 'Expected the JSON output of `kash protocol userop build`.'\n );\n }\n if (\n typeof parsed !== 'object' ||\n parsed === null ||\n typeof (parsed as { userOp?: unknown }).userOp !== 'object' ||\n (parsed as { userOp?: unknown }).userOp === null\n ) {\n throw new CliValidationError(\n 'Input does not contain a `userOp` object.',\n 'The envelope must look like { userOp: {...}, userOpHash: \"0x…\", typedData: {...} }.'\n );\n }\n return parsed as { userOp: Record<string, unknown> };\n}\n\n/** Reverse of `serializeUserOp`. Bigint-shaped fields are decoded back. */\nfunction deserializeUserOp(input: Record<string, unknown>): Record<string, unknown> {\n // The bigint-typed fields per UnsignedUserOp's declaration.\n const BIGINT_FIELDS = new Set([\n 'nonce',\n 'callGasLimit',\n 'verificationGasLimit',\n 'preVerificationGas',\n 'maxFeePerGas',\n 'maxPriorityFeePerGas',\n 'paymasterVerificationGasLimit',\n 'paymasterPostOpGasLimit',\n ]);\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(input)) {\n if (BIGINT_FIELDS.has(k) && typeof v === 'string') {\n try {\n out[k] = BigInt(v);\n } catch {\n throw new CliValidationError(\n `UserOp field \"${k}\" is not a valid bigint string.`,\n `Got ${typeof v === 'string' ? `\"${v}\"` : String(v)}.`\n );\n }\n } else {\n out[k] = v;\n }\n }\n return out;\n}\n\ntype UserOpReceipt = {\n userOpHash: `0x${string}`;\n sender: `0x${string}`;\n nonce: `0x${string}`;\n success: boolean;\n actualGasCost: `0x${string}`;\n actualGasUsed: `0x${string}`;\n receipt: {\n transactionHash: `0x${string}`;\n blockNumber: `0x${string}`;\n status: `0x${string}`;\n };\n};\n\nfunction serializeReceipt(receipt: UserOpReceipt): Record<string, unknown> {\n return {\n userOpHash: receipt.userOpHash,\n sender: receipt.sender,\n nonce: receipt.nonce,\n success: receipt.success,\n actualGasCost: receipt.actualGasCost,\n actualGasUsed: receipt.actualGasUsed,\n receipt: {\n transactionHash: receipt.receipt.transactionHash,\n blockNumber: receipt.receipt.blockNumber,\n status: receipt.receipt.status,\n },\n };\n}\n\nfunction emitReceiptHuman(receipt: UserOpReceipt): void {\n print('');\n if (receipt.success) {\n log.success('UserOp included successfully.');\n } else {\n log.error('UserOp included but reverted on-chain.');\n }\n print(` ${style.dim('UserOp ')} ${receipt.userOpHash}`);\n print(` ${style.dim('Tx ')} ${receipt.receipt.transactionHash}`);\n print(` ${style.dim('Block ')} ${receipt.receipt.blockNumber}`);\n print(` ${style.dim('Gas ')} ${receipt.actualGasUsed}`);\n}\n\ntype SimulationResultLike =\n | { willSucceed: true; gasEstimate?: bigint }\n | {\n willSucceed: false;\n revertReason: string;\n decodedError: { name: string; args: readonly unknown[] } | undefined;\n };\n\nfunction serializeSimulationResult(result: SimulationResultLike): Record<string, unknown> {\n if (result.willSucceed) {\n return {\n willSucceed: true,\n ...(result.gasEstimate === undefined ? {} : { gasEstimate: result.gasEstimate.toString() }),\n };\n }\n return {\n willSucceed: false,\n revertReason: result.revertReason,\n ...(result.decodedError === undefined\n ? {}\n : {\n decodedError: {\n name: result.decodedError.name,\n args: result.decodedError.args.map((a) => (typeof a === 'bigint' ? a.toString() : a)),\n },\n }),\n };\n}\n\n// All input parsers (parseOutcomeIndex, parseSlippageBps,\n// parseDeadlineSec, decimalToAtomicUsdc, decimalToAtomicWad,\n// validateAddress) live in `utils/trade-input.ts`. Single source of\n// truth — userop / trade / eoa modes share the exact same validation\n// behaviour, keeping real-money paths in lockstep.\n","/**\n * `kash protocol watch <market>` — long-running subscription to\n * on-chain trade events for a market.\n *\n * Streams every `TRADE`, `RESOLVED`, and `FROZEN` event the SDK\n * decodes, one NDJSON record per line on stdout. Designed for piping\n * into `jq`, `awk`, or downstream collectors. SIGINT / Ctrl-C\n * terminates cleanly via `subscription.unsubscribe()`.\n *\n * **Best-effort delivery.** viem's `watchContractEvent` reconnects on\n * RPC drops but does NOT replay missed events. For gap-free coverage,\n * pair with `kash markets predictions` (the public-API trade feed)\n * which IS gap-free since it sources from our indexer.\n *\n * **Termination:**\n * - `--max-events <n>` exits cleanly after N events.\n * - `--timeout-ms <ms>` exits after a wall-clock budget.\n * - SIGINT / Ctrl-C unsubscribes and exits 0.\n *\n * **Output:**\n * - JSON mode (`--json`) emits NDJSON: each event = one line.\n * - Human mode prints a compact `[timestamp] TYPE side outcome amounts...` line.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildDirectClient } from '../../utils/direct-client.js';\nimport { parsePositiveInt, readGlobals } from '../../utils/global-options.js';\nimport { log, print, style, writeNdjson } from '../../utils/output.js';\nimport { validateAddress } from '../../utils/trade-input.js';\n\ntype WatchOptions = {\n maxEvents?: string;\n timeoutMs?: string;\n};\n\nexport const watchCommand = new Command('watch')\n .description('Subscribe to on-chain trade events for a market (NDJSON stream).')\n .argument('<market>', 'market contract address (0x-prefixed)')\n .option('--max-events <n>', 'exit cleanly after observing N events')\n .option('--timeout-ms <n>', 'exit cleanly after this wall-clock budget (ms)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash protocol watch 0xMarket... --json\n $ kash protocol watch 0xMarket... --json --quiet | jq -r '.transactionHash'\n $ kash protocol watch 0xMarket... --max-events 100 --json\n\nNotes:\n - Best-effort: on RPC reconnect, missed events are NOT replayed. For\n gap-free history, use \\`kash markets predictions <id>\\` (indexer-backed).\n - Press Ctrl-C to terminate cleanly. The subscription unsubscribes\n before the process exits.\n`\n )\n .action(async (market: string, options: WatchOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n\n const marketAddress = validateAddress(market, 'market');\n\n const maxEvents = options.maxEvents\n ? parsePositiveInt(options.maxEvents, 'max-events')\n : undefined;\n const timeoutMs = options.timeoutMs\n ? parsePositiveInt(options.timeoutMs, 'timeout-ms')\n : undefined;\n\n try {\n const resolved = await buildDirectClient({ globals });\n\n // **Lifecycle.** `markets.watch` returns a `subscription` that\n // holds an open RPC connection. We need to keep the process\n // alive until one of three signals fires (SIGINT / max-events /\n // timeout-ms), then tear down cleanly. We model the wait as a\n // Deferred so the await is reachable / collectable instead of\n // a never-resolving promise that leaks on any future post-\n // processing wrap.\n let resolveDone: ((reason: string) => void) | undefined;\n let count = 0;\n const done = new Promise<string>((resolve) => {\n resolveDone = resolve;\n });\n\n // Holder pattern so `teardown` (defined now) can reference the\n // subscription that `markets.watch` returns shortly. Today the\n // SDK's watch is async-only, but if a future implementation\n // synchronously fired `onEvent` during subscribe (or threw\n // before returning), referencing the binding directly would\n // throw. The `subscriptionHolder.current` indirection keeps the\n // closure stable and lets ESLint's `prefer-const` pass.\n const subscriptionHolder: {\n current: ReturnType<typeof resolved.client.markets.watch> | undefined;\n } = { current: undefined };\n let teardownTriggered = false;\n const teardown = (reason: string): void => {\n if (teardownTriggered) return;\n teardownTriggered = true;\n try {\n subscriptionHolder.current?.unsubscribe();\n } catch {\n // ignore — best-effort cleanup\n }\n resolveDone?.(reason);\n };\n\n subscriptionHolder.current = resolved.client.markets.watch(marketAddress, {\n onEvent: (event) => {\n if (globals.json) {\n // `writeNdjson`'s jsonReplacer is the single source of\n // truth for bigint→decimal-string encoding (incl. inside\n // arrays — `JSON.stringify` walks recursively). No\n // pre-conversion needed here.\n writeNdjson(event);\n } else {\n print(formatEventHuman(event));\n }\n count += 1;\n if (maxEvents !== undefined && count >= maxEvents) {\n teardown(`reached --max-events ${String(maxEvents)}`);\n }\n },\n onReconnect: () => {\n if (!globals.json) {\n log.warn('Watcher reconnecting — missed events will NOT be replayed.');\n }\n },\n onError: (err) => {\n // Non-fatal — viem will retry. Surface it on stderr in human mode.\n if (!globals.json) {\n log.warn(`Watcher error: ${err.message}`);\n }\n },\n });\n\n // SIGINT / SIGTERM tear down rather than process.exit so any\n // post-processing (rare today, but the seam matters) can run.\n const onSigint = (): void => teardown('SIGINT');\n const onSigterm = (): void => teardown('SIGTERM');\n process.on('SIGINT', onSigint);\n process.on('SIGTERM', onSigterm);\n\n // Wall-clock budget. `.unref()` so a quick exit (max-events\n // before the timer fires) doesn't keep the event loop alive.\n const timeoutHandle =\n timeoutMs !== undefined\n ? setTimeout(() => teardown(`reached --timeout-ms ${String(timeoutMs)}`), timeoutMs)\n : undefined;\n timeoutHandle?.unref();\n\n // Print a human-mode header so the user sees something while\n // waiting for the first event. JSON mode stays silent on stderr\n // so the pipe is pure NDJSON.\n if (!globals.json) {\n log.info(`Watching market ${marketAddress}…`);\n log.detail('Stop', 'Ctrl-C');\n if (maxEvents !== undefined) log.detail('Max events', String(maxEvents));\n if (timeoutMs !== undefined) log.detail('Timeout (ms)', String(timeoutMs));\n }\n\n const reason = await done;\n // Clean up signal handlers + timer so a wrapping caller doesn't\n // leak them.\n process.off('SIGINT', onSigint);\n process.off('SIGTERM', onSigterm);\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);\n\n if (!globals.json) {\n log.info(`Watcher stopped (${reason}).`);\n }\n } catch (cause) {\n throw toCliError(cause);\n }\n });\n\n// ---------------------------------------------------------------------------\n// Event serialization\n// ---------------------------------------------------------------------------\n\nexport type WatchEventLike =\n | {\n type: 'TRADE';\n side: 'buy' | 'sell';\n outcome: number;\n receiver: `0x${string}`;\n assetsUsdc: bigint;\n tokensWad: bigint;\n reserveAfterWad: bigint;\n supplyAfterWad: readonly bigint[];\n blockNumber: bigint;\n transactionHash: `0x${string}`;\n logIndex: number;\n }\n | {\n type: 'RESOLVED';\n winningOutcome: number;\n evidenceHash: `0x${string}`;\n blockNumber: bigint;\n transactionHash: `0x${string}`;\n logIndex: number;\n }\n | {\n type: 'FROZEN';\n observedAt: bigint;\n blockNumber: bigint;\n transactionHash: `0x${string}`;\n logIndex: number;\n };\n\nexport function formatEventHuman(event: WatchEventLike): string {\n const time = new Date().toISOString().slice(11, 19); // HH:MM:SS\n if (event.type === 'TRADE') {\n return `${style.dim(time)} ${style.bold('TRADE')} side=${event.side} out=${String(event.outcome)} usdc=${event.assetsUsdc.toString()} tokens=${event.tokensWad.toString()} tx=${event.transactionHash.slice(0, 10)}…`;\n }\n if (event.type === 'RESOLVED') {\n return `${style.dim(time)} ${style.bold('RESOLVED')} winner=${String(event.winningOutcome)} tx=${event.transactionHash.slice(0, 10)}…`;\n }\n return `${style.dim(time)} ${style.bold('FROZEN')} observedAt=${event.observedAt.toString()} tx=${event.transactionHash.slice(0, 10)}…`;\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","reason","Command"]}
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ colorStatus,
4
+ formatUsdcAtomic,
5
+ formatWad,
6
+ shortId
7
+ } from "./chunk-BRK7KJ4O.js";
8
+ import {
9
+ buildClient
10
+ } from "./chunk-QJMF73M5.js";
11
+ import "./chunk-KMBMQIZ7.js";
12
+ import {
13
+ decimalToAtomicUsdc,
14
+ decimalToAtomicWad,
15
+ parseOutcomeIndex
16
+ } from "./chunk-YHCG2SUC.js";
17
+ import "./chunk-BN2CUM42.js";
18
+ import {
19
+ readGlobals
20
+ } from "./chunk-LBIRQHX5.js";
21
+ import {
22
+ log,
23
+ print,
24
+ printJson,
25
+ style
26
+ } from "./chunk-VIADBYFY.js";
27
+ import "./chunk-MIXOZU2S.js";
28
+ import {
29
+ toCliError
30
+ } from "./chunk-UZNSYATZ.js";
31
+
32
+ // src/commands/quote/index.ts
33
+ import { Command as Command3 } from "commander";
34
+
35
+ // src/commands/quote/buy.ts
36
+ import { Command } from "commander";
37
+
38
+ // src/commands/quote/shared.ts
39
+ function renderQuote(quote) {
40
+ print("");
41
+ print(
42
+ ` ${style.dim("Market ")} ${shortId(quote.market.id)} (${colorStatus(quote.market.status ?? "UNKNOWN")})`
43
+ );
44
+ print(
45
+ ` ${style.dim("Outcome ")} ${String(quote.outcomeIndex)}: ${quote.market.outcomes[quote.outcomeIndex]?.label ?? "(unknown)"}`
46
+ );
47
+ print(` ${style.dim("Action ")} ${quote.action}`);
48
+ if (quote.action === "buy") {
49
+ print(` ${style.dim("Spend ")} ${formatUsdcAtomic(quote.amountIn)}`);
50
+ print(` ${style.dim("Tokens out")} ${formatWad(quote.tokensOut)}`);
51
+ } else {
52
+ print(` ${style.dim("Tokens in ")} ${formatWad(quote.tokensIn)}`);
53
+ print(` ${style.dim("Receive ")} ${formatUsdcAtomic(quote.usdcOut)}`);
54
+ print(` ${style.dim("Gross ")} ${formatWad(quote.grossRelease)} (before fees)`);
55
+ }
56
+ print(` ${style.dim("Eff. price")} ${quote.effectivePrice.toFixed(6)} USDC/token`);
57
+ if (quote.impliedProbability !== null) {
58
+ print(` ${style.dim("Implied p ")} ${(quote.impliedProbability * 100).toFixed(2)}%`);
59
+ }
60
+ if (quote.action === "buy") {
61
+ log.info(
62
+ `To execute: kash trade buy ${quote.market.id} --outcome ${String(quote.outcomeIndex)} --amount <usdc>`
63
+ );
64
+ } else {
65
+ log.info(
66
+ `To execute: kash trade sell ${quote.market.id} --outcome ${String(quote.outcomeIndex)} --amount <usdc> (USDC target, not tokens-in)`
67
+ );
68
+ }
69
+ }
70
+ function usdcDecimalToAtomic(decimal, name) {
71
+ return decimalToAtomicUsdc(decimal, name).toString();
72
+ }
73
+ function tokenDecimalToWad(decimal, name) {
74
+ return decimalToAtomicWad(decimal, name).toString();
75
+ }
76
+
77
+ // src/commands/quote/buy.ts
78
+ var buyQuoteCommand = new Command("buy").description("Quote a buy of USDC into an outcome.").argument("<marketId>", "market UUID").requiredOption("-o, --outcome <index>", "outcome index (0-based)").requiredOption("-a, --amount <usdc>", 'USDC to spend (decimal, e.g. "10" or "12.50")').addHelpText(
79
+ "after",
80
+ `
81
+ Examples:
82
+ $ kash quote buy 9f0b... --outcome 0 --amount 10
83
+ $ kash quote buy 9f0b... --outcome 1 --amount 100 --json --quiet | jq -r '.tokensOut'
84
+ `
85
+ ).action(async (marketId, options, cmd) => {
86
+ const globals = readGlobals(cmd);
87
+ const outcomeIndex = parseOutcomeIndex(options.outcome);
88
+ const amountUsdcAtomic = usdcDecimalToAtomic(options.amount, "amount");
89
+ let quote;
90
+ try {
91
+ const { client } = await buildClient({ requireAuth: true, globals });
92
+ quote = await client.quotes.buy({ marketId, outcomeIndex, amountUsdcAtomic });
93
+ } catch (cause) {
94
+ throw toCliError(cause);
95
+ }
96
+ if (globals.json) {
97
+ printJson(quote);
98
+ return;
99
+ }
100
+ renderQuote(quote);
101
+ });
102
+
103
+ // src/commands/quote/sell.ts
104
+ import { Command as Command2 } from "commander";
105
+ var sellQuoteCommand = new Command2("sell").description("Quote a sell of outcome tokens back into USDC.").argument("<marketId>", "market UUID").requiredOption("-o, --outcome <index>", "outcome index (0-based)").requiredOption(
106
+ "-t, --tokens <amount>",
107
+ 'outcome tokens to surrender (decimal, e.g. "1.5") \u2014 quote-side input shape'
108
+ ).addHelpText(
109
+ "after",
110
+ `
111
+ Examples:
112
+ $ kash quote sell 9f0b... --outcome 0 --tokens 1
113
+ $ kash quote sell 9f0b... --outcome 1 --tokens 0.5 --json --quiet | jq -r '.usdcOut'
114
+
115
+ Notes:
116
+ This is a quote on a tokens-in figure. To EXECUTE a sell, run
117
+ \`kash trade sell\` \u2014 that command takes \`--amount <usdc>\` (the target
118
+ USDC out, not tokens-in). The unit shift is intentional: the public
119
+ API exposes USDC as the canonical user-facing amount.
120
+ `
121
+ ).action(async (marketId, options, cmd) => {
122
+ const globals = readGlobals(cmd);
123
+ const outcomeIndex = parseOutcomeIndex(options.outcome);
124
+ const tokensInWad = tokenDecimalToWad(options.tokens, "tokens");
125
+ let quote;
126
+ try {
127
+ const { client } = await buildClient({ requireAuth: true, globals });
128
+ quote = await client.quotes.sell({ marketId, outcomeIndex, tokensInWad });
129
+ } catch (cause) {
130
+ throw toCliError(cause);
131
+ }
132
+ if (globals.json) {
133
+ printJson(quote);
134
+ return;
135
+ }
136
+ renderQuote(quote);
137
+ });
138
+
139
+ // src/commands/quote/index.ts
140
+ var quoteCommand = new Command3("quote").description("Get on-chain AMM price quotes (requires `markets:quote` scope).").addCommand(buyQuoteCommand).addCommand(sellQuoteCommand);
141
+ export {
142
+ quoteCommand
143
+ };
144
+ //# sourceMappingURL=quote-I4DVJ7ZB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/quote/index.ts","../src/commands/quote/buy.ts","../src/commands/quote/shared.ts","../src/commands/quote/sell.ts"],"sourcesContent":["/**\n * `kash quote` — on-chain AMM price quotes.\n *\n * Wraps the SDK's `quotes` sub-client. Requires API key with the\n * `markets:quote` scope (granted by default on every tier; split from\n * `markets:read` because quotes are RPC-heavy and customers may want\n * to throttle quote traffic independently). Both subcommands accept\n * human decimals (USDC for buys, outcome tokens for sells) and\n * convert to the SDK's atomic-6 / WAD-18 wire format.\n */\n\nimport { Command } from 'commander';\n\nimport { buyQuoteCommand } from './buy.js';\nimport { sellQuoteCommand } from './sell.js';\n\nexport const quoteCommand = new Command('quote')\n .description('Get on-chain AMM price quotes (requires `markets:quote` scope).')\n .addCommand(buyQuoteCommand)\n .addCommand(sellQuoteCommand);\n","/**\n * `kash quote buy <marketId>` — price quote for buying outcome tokens.\n *\n * Requires API key with `markets:quote` scope (granted by default on every\n * tier; split from `markets:read` because quotes are RPC-heavy). The SDK's\n * `quotes.buy` returns the AMM's `quoteBuyExactAssetsIn` view: how many\n * outcome tokens you get for the given USDC, plus implied probability and\n * effective price.\n *\n * `--amount` is human USDC decimal (e.g. \"10\" for 10 USDC, \"0.50\"\n * for 50 cents). The CLI converts to atomic-6 before calling the SDK.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildClient } from '../../utils/client.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { printJson } from '../../utils/output.js';\nimport { parseOutcomeIndex } from '../../utils/trade-input.js';\n\nimport { renderQuote, usdcDecimalToAtomic } from './shared.js';\n\ntype BuyQuoteOptions = {\n outcome: string;\n amount: string;\n};\n\nexport const buyQuoteCommand = new Command('buy')\n .description('Quote a buy of USDC into an outcome.')\n .argument('<marketId>', 'market UUID')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption('-a, --amount <usdc>', 'USDC to spend (decimal, e.g. \"10\" or \"12.50\")')\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash quote buy 9f0b... --outcome 0 --amount 10\n $ kash quote buy 9f0b... --outcome 1 --amount 100 --json --quiet | jq -r '.tokensOut'\n`\n )\n .action(async (marketId: string, options: BuyQuoteOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const outcomeIndex = parseOutcomeIndex(options.outcome);\n const amountUsdcAtomic = usdcDecimalToAtomic(options.amount, 'amount');\n\n let quote;\n try {\n const { client } = await buildClient({ requireAuth: true, globals });\n quote = await client.quotes.buy({ marketId, outcomeIndex, amountUsdcAtomic });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson(quote);\n return;\n }\n renderQuote(quote);\n });\n","/**\n * Shared rendering for `kash quote buy/sell` output.\n *\n * The buy and sell endpoints differ in input units (USDC atomic-6\n * vs. WAD-18) but share the same output shape: a flat `Quote` with\n * the embedded market summary. Centralising the render avoids\n * drift between the two commands.\n */\n\nimport { colorStatus, formatUsdcAtomic, formatWad, shortId } from '../../utils/formatting.js';\nimport { log, print, style } from '../../utils/output.js';\nimport { decimalToAtomicUsdc, decimalToAtomicWad } from '../../utils/trade-input.js';\n\nimport type { Quote, QuoteBuyDetail, QuoteSellDetail } from '@kashdao/sdk';\n\n/** Render either a buy or a sell quote in human mode. */\nexport function renderQuote(quote: Quote & (QuoteBuyDetail | QuoteSellDetail)): void {\n print('');\n print(\n ` ${style.dim('Market ')} ${shortId(quote.market.id)} (${colorStatus(quote.market.status ?? 'UNKNOWN')})`\n );\n print(\n ` ${style.dim('Outcome ')} ${String(quote.outcomeIndex)}: ${quote.market.outcomes[quote.outcomeIndex]?.label ?? '(unknown)'}`\n );\n print(` ${style.dim('Action ')} ${quote.action}`);\n if (quote.action === 'buy') {\n print(` ${style.dim('Spend ')} ${formatUsdcAtomic(quote.amountIn)}`);\n print(` ${style.dim('Tokens out')} ${formatWad(quote.tokensOut)}`);\n } else {\n print(` ${style.dim('Tokens in ')} ${formatWad(quote.tokensIn)}`);\n print(` ${style.dim('Receive ')} ${formatUsdcAtomic(quote.usdcOut)}`);\n print(` ${style.dim('Gross ')} ${formatWad(quote.grossRelease)} (before fees)`);\n }\n print(` ${style.dim('Eff. price')} ${quote.effectivePrice.toFixed(6)} USDC/token`);\n if (quote.impliedProbability !== null) {\n print(` ${style.dim('Implied p ')} ${(quote.impliedProbability * 100).toFixed(2)}%`);\n }\n\n // Cross-link to the natural next command. A quote is a planning step;\n // the operator's next call is almost always to actually execute the\n // trade. Surface the exact command so they don't bounce through\n // `--help`. Note the unit shift on `sell`: quote takes `--tokens`,\n // trade takes `--amount` in USDC (the documented API contract).\n if (quote.action === 'buy') {\n log.info(\n `To execute: kash trade buy ${quote.market.id} --outcome ${String(quote.outcomeIndex)} --amount <usdc>`\n );\n } else {\n log.info(\n `To execute: kash trade sell ${quote.market.id} --outcome ${String(quote.outcomeIndex)} --amount <usdc> (USDC target, not tokens-in)`\n );\n }\n}\n\n/**\n * Convert a human USDC decimal string (\"10\", \"12.50\", \"0.000001\") to\n * the atomic-6 integer string the SDK expects.\n *\n * Thin string-typed wrapper around the canonical\n * `decimalToAtomicUsdc` (which returns bigint). The SDK accepts the\n * decimal-string shape over the wire, so we stringify here once\n * rather than coupling every call site to bigint→string conversion.\n */\nexport function usdcDecimalToAtomic(decimal: string, name: string): string {\n return decimalToAtomicUsdc(decimal, name).toString();\n}\n\n/**\n * Convert a human token decimal string (\"1\", \"1.5\", \"0.0001\") to the\n * WAD-18 integer string the SDK expects. String-typed wrapper around\n * the canonical `decimalToAtomicWad`.\n */\nexport function tokenDecimalToWad(decimal: string, name: string): string {\n return decimalToAtomicWad(decimal, name).toString();\n}\n","/**\n * `kash quote sell <marketId>` — price quote for selling outcome tokens.\n *\n * Requires API key with `markets:quote` scope (granted by default on every\n * tier; split from `markets:read` because quotes are RPC-heavy). The SDK's\n * `quotes.sell` returns the AMM's `quoteSellExactTokensIn` view: how much\n * USDC the trader receives (after fees) for surrendering the given tokens.\n *\n * `--tokens` is human-decimal token quantity (e.g. \"1.5\" for one and a\n * half outcome tokens). The CLI converts to WAD-18 before calling the\n * SDK.\n */\n\nimport { Command } from 'commander';\n\nimport { toCliError } from '../../errors.js';\nimport { buildClient } from '../../utils/client.js';\nimport { readGlobals } from '../../utils/global-options.js';\nimport { printJson } from '../../utils/output.js';\nimport { parseOutcomeIndex } from '../../utils/trade-input.js';\n\nimport { renderQuote, tokenDecimalToWad } from './shared.js';\n\ntype SellQuoteOptions = {\n outcome: string;\n tokens: string;\n};\n\nexport const sellQuoteCommand = new Command('sell')\n .description('Quote a sell of outcome tokens back into USDC.')\n .argument('<marketId>', 'market UUID')\n .requiredOption('-o, --outcome <index>', 'outcome index (0-based)')\n .requiredOption(\n '-t, --tokens <amount>',\n 'outcome tokens to surrender (decimal, e.g. \"1.5\") — quote-side input shape'\n )\n .addHelpText(\n 'after',\n `\nExamples:\n $ kash quote sell 9f0b... --outcome 0 --tokens 1\n $ kash quote sell 9f0b... --outcome 1 --tokens 0.5 --json --quiet | jq -r '.usdcOut'\n\nNotes:\n This is a quote on a tokens-in figure. To EXECUTE a sell, run\n \\`kash trade sell\\` — that command takes \\`--amount <usdc>\\` (the target\n USDC out, not tokens-in). The unit shift is intentional: the public\n API exposes USDC as the canonical user-facing amount.\n`\n )\n .action(async (marketId: string, options: SellQuoteOptions, cmd: Command) => {\n const globals = readGlobals(cmd);\n const outcomeIndex = parseOutcomeIndex(options.outcome);\n const tokensInWad = tokenDecimalToWad(options.tokens, 'tokens');\n\n let quote;\n try {\n const { client } = await buildClient({ requireAuth: true, globals });\n quote = await client.quotes.sell({ marketId, outcomeIndex, tokensInWad });\n } catch (cause) {\n throw toCliError(cause);\n }\n\n if (globals.json) {\n printJson(quote);\n return;\n }\n renderQuote(quote);\n });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,SAAS,WAAAA,gBAAe;;;ACExB,SAAS,eAAe;;;ACGjB,SAAS,YAAY,OAAyD;AACnF,QAAM,EAAE;AACR;AAAA,IACE,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,QAAQ,MAAM,OAAO,EAAE,CAAC,KAAK,YAAY,MAAM,OAAO,UAAU,SAAS,CAAC;AAAA,EAC5G;AACA;AAAA,IACE,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,OAAO,MAAM,YAAY,CAAC,KAAK,MAAM,OAAO,SAAS,MAAM,YAAY,GAAG,SAAS,WAAW;AAAA,EAChI;AACA,QAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,MAAM,MAAM,EAAE;AACpD,MAAI,MAAM,WAAW,OAAO;AAC1B,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,iBAAiB,MAAM,QAAQ,CAAC,EAAE;AACxE,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,UAAU,MAAM,SAAS,CAAC,EAAE;AAAA,EACpE,OAAO;AACL,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,UAAU,MAAM,QAAQ,CAAC,EAAE;AACjE,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,iBAAiB,MAAM,OAAO,CAAC,EAAE;AACvE,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,UAAU,MAAM,YAAY,CAAC,gBAAgB;AAAA,EACrF;AACA,QAAM,KAAK,MAAM,IAAI,YAAY,CAAC,IAAI,MAAM,eAAe,QAAQ,CAAC,CAAC,aAAa;AAClF,MAAI,MAAM,uBAAuB,MAAM;AACrC,UAAM,KAAK,MAAM,IAAI,YAAY,CAAC,KAAK,MAAM,qBAAqB,KAAK,QAAQ,CAAC,CAAC,GAAG;AAAA,EACtF;AAOA,MAAI,MAAM,WAAW,OAAO;AAC1B,QAAI;AAAA,MACF,8BAA8B,MAAM,OAAO,EAAE,cAAc,OAAO,MAAM,YAAY,CAAC;AAAA,IACvF;AAAA,EACF,OAAO;AACL,QAAI;AAAA,MACF,+BAA+B,MAAM,OAAO,EAAE,cAAc,OAAO,MAAM,YAAY,CAAC;AAAA,IACxF;AAAA,EACF;AACF;AAWO,SAAS,oBAAoB,SAAiB,MAAsB;AACzE,SAAO,oBAAoB,SAAS,IAAI,EAAE,SAAS;AACrD;AAOO,SAAS,kBAAkB,SAAiB,MAAsB;AACvE,SAAO,mBAAmB,SAAS,IAAI,EAAE,SAAS;AACpD;;;AD9CO,IAAM,kBAAkB,IAAI,QAAQ,KAAK,EAC7C,YAAY,sCAAsC,EAClD,SAAS,cAAc,aAAa,EACpC,eAAe,yBAAyB,yBAAyB,EACjE,eAAe,uBAAuB,+CAA+C,EACrF;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAKF,EACC,OAAO,OAAO,UAAkB,SAA0B,QAAiB;AAC1E,QAAM,UAAU,YAAY,GAAG;AAC/B,QAAM,eAAe,kBAAkB,QAAQ,OAAO;AACtD,QAAM,mBAAmB,oBAAoB,QAAQ,QAAQ,QAAQ;AAErE,MAAI;AACJ,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,YAAY,EAAE,aAAa,MAAM,QAAQ,CAAC;AACnE,YAAQ,MAAM,OAAO,OAAO,IAAI,EAAE,UAAU,cAAc,iBAAiB,CAAC;AAAA,EAC9E,SAAS,OAAO;AACd,UAAM,WAAW,KAAK;AAAA,EACxB;AAEA,MAAI,QAAQ,MAAM;AAChB,cAAU,KAAK;AACf;AAAA,EACF;AACA,cAAY,KAAK;AACnB,CAAC;;;AE9CH,SAAS,WAAAC,gBAAe;AAejB,IAAM,mBAAmB,IAAIC,SAAQ,MAAM,EAC/C,YAAY,gDAAgD,EAC5D,SAAS,cAAc,aAAa,EACpC,eAAe,yBAAyB,yBAAyB,EACjE;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWF,EACC,OAAO,OAAO,UAAkB,SAA2B,QAAiB;AAC3E,QAAM,UAAU,YAAY,GAAG;AAC/B,QAAM,eAAe,kBAAkB,QAAQ,OAAO;AACtD,QAAM,cAAc,kBAAkB,QAAQ,QAAQ,QAAQ;AAE9D,MAAI;AACJ,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,YAAY,EAAE,aAAa,MAAM,QAAQ,CAAC;AACnE,YAAQ,MAAM,OAAO,OAAO,KAAK,EAAE,UAAU,cAAc,YAAY,CAAC;AAAA,EAC1E,SAAS,OAAO;AACd,UAAM,WAAW,KAAK;AAAA,EACxB;AAEA,MAAI,QAAQ,MAAM;AAChB,cAAU,KAAK;AACf;AAAA,EACF;AACA,cAAY,KAAK;AACnB,CAAC;;;AHpDI,IAAM,eAAe,IAAIC,SAAQ,OAAO,EAC5C,YAAY,iEAAiE,EAC7E,WAAW,eAAe,EAC1B,WAAW,gBAAgB;","names":["Command","Command","Command","Command"]}