tenjin-cli 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (133) hide show
  1. package/NOTICE.md +33 -0
  2. package/README.md +167 -16
  3. package/dist/{_esm-ZH2J4QEH.js → _esm-C5CRWCYU.js} +2 -2
  4. package/dist/_esm-FEASBWRP.js +881 -0
  5. package/dist/buy-EE6SEXP6.js +1598 -0
  6. package/dist/buy-EE6SEXP6.js.map +1 -0
  7. package/dist/candidate-ERMSYYQZ.js +127 -0
  8. package/dist/candidate-ERMSYYQZ.js.map +1 -0
  9. package/dist/{ccip-UCLT5VOW.js → ccip-NQXCEK2U.js} +6 -5
  10. package/dist/ccip-XR5NE5QK.js +19 -0
  11. package/dist/chunk-2I4QTOLB.js +11 -0
  12. package/dist/chunk-2I4QTOLB.js.map +1 -0
  13. package/dist/chunk-3OV7E5G5.js +18 -0
  14. package/dist/chunk-3OV7E5G5.js.map +1 -0
  15. package/dist/chunk-4ONXEEQL.js +152 -0
  16. package/dist/chunk-4ONXEEQL.js.map +1 -0
  17. package/dist/chunk-5CLSD5YN.js +209 -0
  18. package/dist/chunk-5CLSD5YN.js.map +1 -0
  19. package/dist/chunk-662MSGZB.js +286 -0
  20. package/dist/chunk-662MSGZB.js.map +1 -0
  21. package/dist/chunk-7KUW4MJD.js +59 -0
  22. package/dist/chunk-7KUW4MJD.js.map +1 -0
  23. package/dist/{doctor-3QBYN46N.js → chunk-AWPAWHNX.js} +88 -93
  24. package/dist/chunk-AWPAWHNX.js.map +1 -0
  25. package/dist/chunk-CYOF7ROH.js +70 -0
  26. package/dist/chunk-CYOF7ROH.js.map +1 -0
  27. package/dist/chunk-DXTQ3CSI.js +171 -0
  28. package/dist/chunk-DXTQ3CSI.js.map +1 -0
  29. package/dist/{chunk-EZROUI5U.js → chunk-ESPNTPQ2.js} +80 -8
  30. package/dist/chunk-ESPNTPQ2.js.map +1 -0
  31. package/dist/chunk-FJPLRISB.js +79 -0
  32. package/dist/chunk-FJPLRISB.js.map +1 -0
  33. package/dist/chunk-GO75V3NZ.js +160 -0
  34. package/dist/chunk-GO75V3NZ.js.map +1 -0
  35. package/dist/chunk-HIVZG55D.js +204 -0
  36. package/dist/chunk-HIVZG55D.js.map +1 -0
  37. package/dist/chunk-HSDCI7OV.js +7806 -0
  38. package/dist/chunk-HSDCI7OV.js.map +1 -0
  39. package/dist/chunk-JPHG2JW3.js +96 -0
  40. package/dist/chunk-JPHG2JW3.js.map +1 -0
  41. package/dist/{chunk-ZPZFPVDN.js → chunk-MUBUQVC3.js} +1 -1
  42. package/dist/chunk-MUBUQVC3.js.map +1 -0
  43. package/dist/{chunk-T4LKNY7T.js → chunk-NCE5NSN6.js} +166 -11
  44. package/dist/chunk-NCE5NSN6.js.map +1 -0
  45. package/dist/{chunk-YG2DO46P.js → chunk-OYMYCW7J.js} +18 -3
  46. package/dist/{chunk-YG2DO46P.js.map → chunk-OYMYCW7J.js.map} +1 -1
  47. package/dist/{chunk-Q53IYV2G.js → chunk-QVX5MWJZ.js} +20 -17
  48. package/dist/{chunk-Q53IYV2G.js.map → chunk-QVX5MWJZ.js.map} +1 -1
  49. package/dist/{chunk-CUWUHTIL.js → chunk-RBJPAZFI.js} +16 -202
  50. package/dist/chunk-RBJPAZFI.js.map +1 -0
  51. package/dist/chunk-RRN3YTK7.js +6199 -0
  52. package/dist/chunk-RRN3YTK7.js.map +1 -0
  53. package/dist/chunk-RY4XKNV3.js +140 -0
  54. package/dist/chunk-RY4XKNV3.js.map +1 -0
  55. package/dist/chunk-S3IGX57D.js +14682 -0
  56. package/dist/chunk-S3IGX57D.js.map +1 -0
  57. package/dist/chunk-TLCMMYLY.js +126 -0
  58. package/dist/chunk-TLCMMYLY.js.map +1 -0
  59. package/dist/{chunk-IPOWB3G3.js → chunk-UGX7YPX2.js} +3314 -306
  60. package/dist/chunk-UGX7YPX2.js.map +1 -0
  61. package/dist/chunk-UO22YNY4.js +69 -0
  62. package/dist/chunk-UO22YNY4.js.map +1 -0
  63. package/dist/{config-CEFTL5ZL.js → chunk-XHC6FCGZ.js} +115 -18
  64. package/dist/chunk-XHC6FCGZ.js.map +1 -0
  65. package/dist/chunk-XJIW7USF.js +217 -0
  66. package/dist/chunk-XJIW7USF.js.map +1 -0
  67. package/dist/{chunk-BRJHUQSY.js → chunk-YALGASEU.js} +1548 -1452
  68. package/dist/chunk-YALGASEU.js.map +1 -0
  69. package/dist/{chunk-DXPYFVKG.js → chunk-YN5SHIXQ.js} +6 -6
  70. package/dist/chunk-YN5SHIXQ.js.map +1 -0
  71. package/dist/chunk-Z52RA3NC.js +137 -0
  72. package/dist/chunk-Z52RA3NC.js.map +1 -0
  73. package/dist/{chunk-EXBMF5X7.js → chunk-Z6MFJV5Z.js} +151 -19
  74. package/dist/chunk-Z6MFJV5Z.js.map +1 -0
  75. package/dist/chunk-ZABPQJ3M.js +83 -0
  76. package/dist/chunk-ZABPQJ3M.js.map +1 -0
  77. package/dist/{chunk-LPRVHM7P.js → chunk-ZMHYXMO6.js} +1655 -114
  78. package/dist/chunk-ZMHYXMO6.js.map +1 -0
  79. package/dist/{chunk-3IMLRUZE.js → chunk-ZXTAQYNA.js} +6 -2
  80. package/dist/{cli-WA65NP4Y.js → cli-SBXI5AMS.js} +177 -177
  81. package/dist/cli-SBXI5AMS.js.map +1 -0
  82. package/dist/config-VELDKLHY.js +21 -0
  83. package/dist/doctor-T3KWNNP2.js +20 -0
  84. package/dist/doctor-T3KWNNP2.js.map +1 -0
  85. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js +18 -0
  86. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js.map +1 -0
  87. package/dist/index.js +1 -1
  88. package/dist/inspect-LMKOXE4Y.js +96 -0
  89. package/dist/inspect-LMKOXE4Y.js.map +1 -0
  90. package/dist/install-LEX3ENQ6.js +387 -0
  91. package/dist/install-LEX3ENQ6.js.map +1 -0
  92. package/dist/lookup-ZPN2Q67N.js +129 -0
  93. package/dist/lookup-ZPN2Q67N.js.map +1 -0
  94. package/dist/{mine.wasm-GQECMSGN.js → mine.wasm-6PIT3DK6.js} +2 -2
  95. package/dist/outcome-N7TAK6WR.js +66 -0
  96. package/dist/outcome-N7TAK6WR.js.map +1 -0
  97. package/dist/publish-BKBQQAW4.js +1478 -0
  98. package/dist/publish-BKBQQAW4.js.map +1 -0
  99. package/dist/{secp256k1-BEZS642W.js → secp256k1-N3ZHU7LB.js} +5 -4
  100. package/dist/secp256k1-N3ZHU7LB.js.map +1 -0
  101. package/dist/usdc-JIAJW4SV.js +22 -0
  102. package/dist/usdc-JIAJW4SV.js.map +1 -0
  103. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js +14 -0
  104. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js.map +1 -0
  105. package/dist/{wallet-XD576HF3.js → wallet-CWEMYVIH.js} +28 -22
  106. package/dist/{wallet-XD576HF3.js.map → wallet-CWEMYVIH.js.map} +1 -1
  107. package/dist/wallet-PA54CRBL.js +30 -0
  108. package/dist/wallet-PA54CRBL.js.map +1 -0
  109. package/package.json +19 -16
  110. package/skills/tenjin/SKILL.md +199 -0
  111. package/skills/tenjin-publish/SKILL.md +111 -0
  112. package/skills/tenjin-search/SKILL.md +133 -0
  113. package/dist/chunk-BRJHUQSY.js.map +0 -1
  114. package/dist/chunk-CUWUHTIL.js.map +0 -1
  115. package/dist/chunk-DXPYFVKG.js.map +0 -1
  116. package/dist/chunk-EXBMF5X7.js.map +0 -1
  117. package/dist/chunk-EZROUI5U.js.map +0 -1
  118. package/dist/chunk-IPOWB3G3.js.map +0 -1
  119. package/dist/chunk-LPRVHM7P.js.map +0 -1
  120. package/dist/chunk-T4LKNY7T.js.map +0 -1
  121. package/dist/chunk-ZPZFPVDN.js.map +0 -1
  122. package/dist/cli-WA65NP4Y.js.map +0 -1
  123. package/dist/config-CEFTL5ZL.js.map +0 -1
  124. package/dist/doctor-3QBYN46N.js.map +0 -1
  125. package/dist/usdc-44R6XZF2.js +0 -18
  126. package/dist/wallet-ELBTBMXO.js +0 -20
  127. /package/dist/{_esm-ZH2J4QEH.js.map → _esm-C5CRWCYU.js.map} +0 -0
  128. /package/dist/{ccip-UCLT5VOW.js.map → _esm-FEASBWRP.js.map} +0 -0
  129. /package/dist/{chunk-3IMLRUZE.js.map → ccip-NQXCEK2U.js.map} +0 -0
  130. /package/dist/{secp256k1-BEZS642W.js.map → ccip-XR5NE5QK.js.map} +0 -0
  131. /package/dist/{usdc-44R6XZF2.js.map → chunk-ZXTAQYNA.js.map} +0 -0
  132. /package/dist/{wallet-ELBTBMXO.js.map → config-VELDKLHY.js.map} +0 -0
  133. /package/dist/{mine.wasm-GQECMSGN.js.map → mine.wasm-6PIT3DK6.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/doctor.ts","../src/lib/http.ts"],"sourcesContent":["import { styleText } from 'node:util';\nimport { Stream } from 'node:stream';\nimport { CliError } from '../lib/errors';\nimport { fetchJson } from '../lib/http';\nimport { loadRawConfig, resolveSettings } from '../lib/config';\nimport { configPath } from '../lib/paths';\nimport { toMoney } from '../lib/money';\nimport { walletFileExists } from '../lib/wallet/store';\nimport type { PartialConfig } from '../lib/config';\nimport type { ErrorCode } from '../schemas';\nimport type { Io } from '../lib/output';\nimport type { WalletDescription, WalletProvider } from '../lib/wallet';\nimport type { CommandContext, CommandResult } from '../context';\n\n/**\n * One environment/reachability check. The doctor agent builds the check list\n * against this shape without changing it: `required` drives the exit code (exit\n * 0 iff every required check is ok), `status` drives the TTY rendering, and a\n * `fix` is mandatory on every failure (spec 10). Warn-level checks never fail\n * the command.\n */\nexport interface CheckResult {\n name: string;\n status: 'ok' | 'warn' | 'fail';\n required: boolean;\n detail: string;\n fix?: string;\n}\n\n/**\n * A CheckResult plus the error code to raise if it is a *required* failure. Only\n * required checks carry a `failCode`; the outcome step raises the first one, so\n * the failure envelope's `error.code` names what actually broke (api-contract\n * unreachable vs malformed differ) while still carrying the whole check list.\n */\ninterface BuiltCheck {\n result: CheckResult;\n failCode?: ErrorCode;\n}\n\nexport interface DoctorDeps {\n /** Environment for wallet-key detection and settings precedence. */\n env?: NodeJS.ProcessEnv;\n /** Injected fetch for the reachability checks; tests pass a canned stub. */\n fetchImpl?: typeof fetch;\n /** Inject the active wallet provider. When set, NO local fs/env is consulted —\n * the provider owns its own describe() and diagnostics(), so a remote provider's\n * checks can't be contaminated by a stale local wallet file. */\n provider?: WalletProvider;\n}\n\nexport async function runDoctor(\n ctx: CommandContext,\n deps: DoctorDeps = {},\n): Promise<CommandResult> {\n const env = deps.env ?? process.env;\n const { config, check: configCheck } = await loadConfigForDoctor(ctx.dataDir);\n const settings = resolveSettings({ config, flags: { baseUrl: ctx.flags.baseUrl }, env });\n const baseUrl = settings.baseUrl.value;\n\n const built: BuiltCheck[] = [\n checkNode(),\n configCheck,\n await checkApiContract(baseUrl, ctx.flags.timeout, deps.fetchImpl),\n await checkReadPath(baseUrl, ctx.flags.timeout, deps.fetchImpl),\n ];\n\n // The wallet/custody/balance checks all come from the ACTIVE provider: it owns\n // describe() and diagnostics(), so doctor never runs its own fs/env probe.\n for (const result of await checkWallet(ctx, deps, env, settings.rpcUrl.value)) {\n built.push({ result });\n }\n\n const checks = built.map((b) => b.result);\n const firstFail = built.find((b) => b.result.required && b.result.status === 'fail');\n if (firstFail !== undefined) {\n const r = firstFail.result;\n throw new CliError(firstFail.failCode ?? 'INTERNAL', r.detail, {\n ...(r.fix !== undefined ? { fix: r.fix } : {}),\n details: { checks },\n });\n }\n\n return { data: { status: 'pass', checks }, humanLines: renderHuman(ctx.io, checks) };\n}\n\nfunction checkNode(): BuiltCheck {\n const version = process.versions.node;\n const major = Number.parseInt(version.split('.')[0] ?? '0', 10);\n if (major >= 22) {\n return { result: { name: 'node', status: 'ok', required: true, detail: `Node ${version}` } };\n }\n return {\n result: {\n name: 'node',\n status: 'fail',\n required: true,\n detail: `Node ${version} is unsupported (need >= 22)`,\n fix: 'Install Node 22 or newer',\n },\n failCode: 'NODE_UNSUPPORTED',\n };\n}\n\n/**\n * loadRawConfig throws CONFIG_INVALID on a bad file (which we convert into a\n * failing check) but the config value is also needed for baseUrl/rpcUrl\n * resolution; an invalid file falls back to {} so the reachability checks still\n * run and appear in the list, and config is reported as the first required fail.\n */\nasync function loadConfigForDoctor(\n dataDir: string,\n): Promise<{ config: PartialConfig; check: BuiltCheck }> {\n try {\n const config = await loadRawConfig(dataDir);\n const detail =\n Object.keys(config).length === 0\n ? 'No config file; using defaults'\n : `Config at ${configPath(dataDir)} is valid`;\n return { config, check: { result: { name: 'config', status: 'ok', required: true, detail } } };\n } catch (err) {\n if (err instanceof CliError && err.code === 'CONFIG_INVALID') {\n return {\n config: {},\n check: {\n result: {\n name: 'config',\n status: 'fail',\n required: true,\n detail: err.message,\n ...(err.fix !== undefined ? { fix: err.fix } : {}),\n },\n failCode: 'CONFIG_INVALID',\n },\n };\n }\n throw err;\n }\n}\n\nasync function checkApiContract(\n baseUrl: string,\n timeoutMs: number,\n fetchImpl?: typeof fetch,\n): Promise<BuiltCheck> {\n const url = `${trimSlash(baseUrl)}/openapi.json`;\n const res = await fetchJson(url, { timeoutMs, fetchImpl });\n if (!res.ok) {\n const malformed = res.kind === 'invalid-json';\n return {\n result: {\n name: 'api-contract',\n status: 'fail',\n required: true,\n detail: malformed\n ? `OpenAPI document at ${url} was not valid JSON`\n : `Could not reach the Tenjin API at ${url}: ${res.message}`,\n fix: malformed\n ? 'Point --base-url at a Tenjin API (expected an OpenAPI document).'\n : 'Check your network connection and --base-url.',\n },\n failCode: malformed ? 'CONTRACT_MISMATCH' : 'API_UNREACHABLE',\n };\n }\n const version = infoVersion(res.json);\n if (version === undefined) {\n return {\n result: {\n name: 'api-contract',\n status: 'fail',\n required: true,\n detail: `OpenAPI document at ${url} is missing a string info.version`,\n fix: 'Point --base-url at a Tenjin API (expected an OpenAPI document).',\n },\n failCode: 'CONTRACT_MISMATCH',\n };\n }\n return {\n result: {\n name: 'api-contract',\n status: 'ok',\n required: true,\n detail: `Tenjin API ${version} at ${baseUrl}`,\n },\n };\n}\n\nasync function checkReadPath(\n baseUrl: string,\n timeoutMs: number,\n fetchImpl?: typeof fetch,\n): Promise<BuiltCheck> {\n // The shipped public read path. The A2 lookup-contract check is a B2 follow-up.\n // Probe the UNFILTERED listing: the server logs every nonblank first-page `q`\n // as agent search demand, so a `q` here would fabricate that demand into the\n // experiment this CLI exists to measure. Never add a `q` to this probe.\n const url = `${trimSlash(baseUrl)}/api/articles?limit=1`;\n const res = await fetchJson(url, { timeoutMs, fetchImpl });\n if (!res.ok) {\n return {\n result: {\n name: 'read-path',\n status: 'fail',\n required: true,\n detail: `Read path ${url} failed: ${res.message}`,\n fix: 'Check your network connection and --base-url.',\n },\n failCode: 'API_UNREACHABLE',\n };\n }\n const items = isRecord(res.json) ? res.json.items : undefined;\n if (!Array.isArray(items)) {\n return {\n result: {\n name: 'read-path',\n status: 'fail',\n required: true,\n detail: `Read path ${url} did not return an items array`,\n fix: 'Point --base-url at a Tenjin API.',\n },\n failCode: 'API_UNREACHABLE',\n };\n }\n return {\n result: { name: 'read-path', status: 'ok', required: true, detail: `Read path OK at ${url}` },\n };\n}\n\n/**\n * Diagnose the wallet the CLI would actually use, entirely through the ACTIVE\n * provider. An injected provider owns everything — no local file or env is touched.\n * With no injected provider we do ONE cheap fs/env probe purely to decide whether\n * any credential exists: none → emit the \"no wallet\" warn WITHOUT importing the\n * wallet lib (that import statically pulls viem, and a no-wallet run must not parse\n * it). Otherwise the provider describes itself (address + source), reports its own\n * custody warnings, and the balance probes describe()'s address. A custody problem\n * (bad key, provider refusal) is warn-level, never a hard fail.\n */\nasync function checkWallet(\n ctx: CommandContext,\n deps: DoctorDeps,\n env: NodeJS.ProcessEnv,\n rpcUrl: string,\n): Promise<CheckResult[]> {\n const provider = deps.provider ?? (await resolveLocalProviderOrNull(ctx, env));\n if (provider === null) return [noWalletCheck()];\n\n const { describeWallet } = await import('../lib/wallet');\n let desc: WalletDescription;\n try {\n desc = await describeWallet(provider);\n } catch (err) {\n if (err instanceof CliError && err.code === 'WALLET_MISSING') return [noWalletCheck()];\n return [walletWarn(err)];\n }\n\n const checks: CheckResult[] = [\n {\n name: 'wallet',\n status: 'ok',\n required: false,\n detail: `Wallet ${desc.address} (${desc.credentialSource})`,\n },\n ];\n // Custody warnings are the provider's own (perms, env-shadow for the local\n // provider; none for a remote one). Render each as a warn check; the fix text,\n // when there is one, is carried inline in the warning string.\n for (const warning of (await provider.diagnostics()).warnings) {\n checks.push({ name: 'wallet-custody', status: 'warn', required: false, detail: warning });\n }\n checks.push(await checkBalance(desc.address, rpcUrl));\n return checks;\n}\n\n/**\n * The active local provider, or null when no credential exists at all. The null\n * path never imports the wallet lib, keeping a no-wallet doctor run off viem.\n */\nasync function resolveLocalProviderOrNull(\n ctx: CommandContext,\n env: NodeJS.ProcessEnv,\n): Promise<WalletProvider | null> {\n const envKey = env.TENJIN_WALLET_KEY;\n const envKeySet = typeof envKey === 'string' && envKey.length > 0;\n if (!envKeySet && !(await walletFileExists(ctx.dataDir))) return null;\n const { resolveWalletProvider } = await import('../lib/wallet');\n return resolveWalletProvider(ctx);\n}\n\nfunction noWalletCheck(): CheckResult {\n return {\n name: 'wallet',\n status: 'warn',\n required: false,\n detail: 'No wallet; needed only for buy/publish',\n fix: 'tenjin wallet create',\n };\n}\n\nfunction walletWarn(err: unknown): CheckResult {\n return {\n name: 'wallet',\n status: 'warn',\n required: false,\n detail: err instanceof Error ? err.message : String(err),\n ...(err instanceof CliError && err.fix !== undefined ? { fix: err.fix } : {}),\n };\n}\n\n/**\n * Balance is best-effort: a zero balance is a fundable warning and an RPC flake\n * must never fail doctor. viem loads only here, via a lazy import, so a doctor\n * run without a wallet never parses the viem chunk.\n */\nasync function checkBalance(address: string, rpcUrl: string): Promise<CheckResult> {\n try {\n const { getUsdcBalance } = await import('../lib/usdc');\n const balance = await getUsdcBalance(address as `0x${string}`, rpcUrl);\n if (balance === 0n) {\n return {\n name: 'balance',\n status: 'warn',\n required: false,\n detail: 'Wallet USDC balance is 0',\n fix: 'Send USDC on Base. $5 covers ~50 typical resources.',\n };\n }\n const money = toMoney(balance.toString());\n return {\n name: 'balance',\n status: 'ok',\n required: false,\n detail: `Balance ${money.usd} USDC (${money.atomic} atomic)`,\n };\n } catch (err) {\n return {\n name: 'balance',\n status: 'warn',\n required: false,\n detail: `Could not read balance: ${err instanceof Error ? err.message : String(err)}`,\n fix: 'Check rpcUrl or retry; a balance read failure never fails doctor.',\n };\n }\n}\n\nfunction renderHuman(io: Io, checks: CheckResult[]): string[] {\n const nameWidth = Math.max(...checks.map((c) => c.name.length));\n const lines: string[] = [];\n for (const c of checks) {\n const icon =\n c.status === 'ok'\n ? paint(io, 'green', '✓')\n : c.status === 'warn'\n ? paint(io, 'yellow', '!')\n : paint(io, 'red', '✗');\n lines.push(`${icon} ${c.name.padEnd(nameWidth)} ${paint(io, 'dim', c.detail)}`);\n if (c.status !== 'ok' && c.fix !== undefined) {\n lines.push(` ${paint(io, 'dim', `fix: ${c.fix}`)}`);\n }\n }\n return lines;\n}\n\n/**\n * Color for stderr, honoring NO_COLOR and the target's color depth: styleText\n * takes the stderr stream when it is a genuine Stream (it throws on anything\n * else, so a test/redirected sink falls back to the default plain check).\n */\nfunction paint(io: Io, format: Parameters<typeof styleText>[0], text: string): string {\n if (io.stderr instanceof Stream) return styleText(format, text, { stream: io.stderr });\n return styleText(format, text);\n}\n\nfunction infoVersion(json: unknown): string | undefined {\n if (!isRecord(json)) return undefined;\n const info = json.info;\n if (!isRecord(info)) return undefined;\n return typeof info.version === 'string' ? info.version : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction trimSlash(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n","import { CliError } from './errors';\n\n/**\n * The single JSON client the whole CLI grows on: `doctor` uses it in B1, `lookup`\n * reuses it in B2. It never throws on a transport/protocol failure — it returns a\n * discriminated result so callers decide how each failure class maps to a check\n * or an error. `fetchImpl` is injectable so tests never touch the network.\n */\nexport interface FetchJsonOptions {\n /** Abort the request after this many milliseconds. */\n timeoutMs: number;\n /** Override global fetch (tests inject a stub returning canned Responses). */\n fetchImpl?: typeof fetch;\n}\n\n/** A successful 2xx whose body parsed as JSON. */\nexport interface FetchJsonSuccess {\n ok: true;\n status: number;\n json: unknown;\n /** The server's `x-request-id`, when it sent one — useful in error reports. */\n requestId?: string;\n}\n\n/**\n * A failed request, tagged by class so the caller maps it deliberately:\n * `network`/`timeout` (never reached the server or no answer), `http` (a non-2xx\n * status), `invalid-json` (2xx but the body was not JSON).\n */\nexport interface FetchJsonFailure {\n ok: false;\n kind: 'network' | 'timeout' | 'http' | 'invalid-json';\n status?: number;\n requestId?: string;\n message: string;\n}\n\nexport type FetchJsonResult = FetchJsonSuccess | FetchJsonFailure;\n\nexport async function fetchJson(url: string, opts: FetchJsonOptions): Promise<FetchJsonResult> {\n const doFetch = opts.fetchImpl ?? fetch;\n const controller = new AbortController();\n let timedOut = false;\n // The timer stays armed until the body is fully consumed (cleared in the outer\n // finally), so a server that sends headers then stalls the body still trips the\n // deadline instead of hanging forever on res.json().\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, opts.timeoutMs);\n\n try {\n let res: Response;\n try {\n res = await doFetch(url, { signal: controller.signal });\n } catch (err) {\n // A timeout is a network failure the AbortController induced; distinguish it\n // from an organic one so the caller can say \"timed out\" rather than a raw\n // AbortError message.\n return timedOut\n ? timeoutFailure(url, opts.timeoutMs)\n : { ok: false, kind: 'network', message: `Request to ${url} failed: ${errorMessage(err)}` };\n }\n\n const requestId = res.headers.get('x-request-id') ?? undefined;\n\n if (!res.ok) {\n return {\n ok: false,\n kind: 'http',\n status: res.status,\n ...(requestId !== undefined ? { requestId } : {}),\n message: `Request to ${url} failed with status ${res.status}`,\n };\n }\n\n let json: unknown;\n try {\n json = await res.json();\n } catch (err) {\n // The body read can fail three ways. A timeout wins first: the abort fires\n // synchronously with `timedOut`, so any abort-induced rejection here is our\n // deadline. Otherwise a SyntaxError is a genuine parse failure (invalid\n // JSON); anything else is a transport failure mid-body (network).\n if (timedOut) return timeoutFailure(url, opts.timeoutMs);\n if (err instanceof SyntaxError) {\n return {\n ok: false,\n kind: 'invalid-json',\n status: res.status,\n ...(requestId !== undefined ? { requestId } : {}),\n message: `Response from ${url} was not valid JSON`,\n };\n }\n return {\n ok: false,\n kind: 'network',\n status: res.status,\n ...(requestId !== undefined ? { requestId } : {}),\n message: `Request to ${url} failed while reading the response body: ${errorMessage(err)}`,\n };\n }\n\n return {\n ok: true,\n status: res.status,\n json,\n ...(requestId !== undefined ? { requestId } : {}),\n };\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction timeoutFailure(url: string, timeoutMs: number): FetchJsonFailure {\n return {\n ok: false,\n kind: 'timeout',\n message: `Request to ${url} timed out after ${timeoutMs}ms`,\n };\n}\n\nexport interface FailureToCliErrorOptions {\n fix?: string;\n details?: unknown;\n}\n\n/**\n * Normalize a fetch failure into the CLI error contract: network/timeout are a\n * NETWORK_ERROR, an `http` status (server reachable but errored — commonly 5xx)\n * is API_UNREACHABLE, and a 2xx that failed to parse when JSON was required is a\n * CONTRACT_MISMATCH. Callers that need a check-specific code (doctor) build their\n * own CliError; this is the default B2's passthrough leans on.\n */\nexport function fetchFailureToCliError(\n failure: FetchJsonFailure,\n opts: FailureToCliErrorOptions = {},\n): CliError {\n const code =\n failure.kind === 'network' || failure.kind === 'timeout'\n ? 'NETWORK_ERROR'\n : failure.kind === 'invalid-json'\n ? 'CONTRACT_MISMATCH'\n : 'API_UNREACHABLE';\n return new CliError(code, failure.message, {\n ...(opts.fix !== undefined ? { fix: opts.fix } : {}),\n ...(opts.details !== undefined ? { details: opts.details } : {}),\n });\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n"],"mappings":"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","names":[]}
@@ -1,18 +0,0 @@
1
- import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
- import {
3
- USDC_ADDRESS,
4
- USDC_DECIMALS,
5
- getUsdcBalance
6
- } from "./chunk-IPOWB3G3.js";
7
- import "./chunk-T4LKNY7T.js";
8
- import "./chunk-Q53IYV2G.js";
9
- import "./chunk-LPRVHM7P.js";
10
- import "./chunk-BRJHUQSY.js";
11
- import "./chunk-CUWUHTIL.js";
12
- import "./chunk-3IMLRUZE.js";
13
- export {
14
- USDC_ADDRESS,
15
- USDC_DECIMALS,
16
- getUsdcBalance
17
- };
18
- //# sourceMappingURL=usdc-44R6XZF2.js.map
@@ -1,20 +0,0 @@
1
- import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
- import {
3
- createLocalWallet,
4
- describeWallet,
5
- resolveWalletProvider
6
- } from "./chunk-EXBMF5X7.js";
7
- import "./chunk-T4LKNY7T.js";
8
- import "./chunk-Q53IYV2G.js";
9
- import "./chunk-BRJHUQSY.js";
10
- import "./chunk-CUWUHTIL.js";
11
- import "./chunk-DXPYFVKG.js";
12
- import "./chunk-ZPZFPVDN.js";
13
- import "./chunk-YG2DO46P.js";
14
- import "./chunk-3IMLRUZE.js";
15
- export {
16
- createLocalWallet,
17
- describeWallet,
18
- resolveWalletProvider
19
- };
20
- //# sourceMappingURL=wallet-ELBTBMXO.js.map