dexe-mcp 0.7.1 → 0.8.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 (59) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +20 -2
  3. package/dist/cli/doctor.d.ts +11 -0
  4. package/dist/cli/doctor.d.ts.map +1 -0
  5. package/dist/cli/doctor.js +44 -0
  6. package/dist/cli/doctor.js.map +1 -0
  7. package/dist/cli/init.d.ts +2 -0
  8. package/dist/cli/init.d.ts.map +1 -0
  9. package/dist/cli/init.js +306 -0
  10. package/dist/cli/init.js.map +1 -0
  11. package/dist/diag/checks.d.ts +25 -0
  12. package/dist/diag/checks.d.ts.map +1 -0
  13. package/dist/diag/checks.js +387 -0
  14. package/dist/diag/checks.js.map +1 -0
  15. package/dist/env/loader.d.ts +43 -0
  16. package/dist/env/loader.d.ts.map +1 -0
  17. package/dist/env/loader.js +121 -0
  18. package/dist/env/loader.js.map +1 -0
  19. package/dist/env/parse.d.ts +23 -0
  20. package/dist/env/parse.d.ts.map +1 -0
  21. package/dist/env/parse.js +41 -0
  22. package/dist/env/parse.js.map +1 -0
  23. package/dist/env/schema.d.ts +257 -0
  24. package/dist/env/schema.d.ts.map +1 -0
  25. package/dist/env/schema.js +240 -0
  26. package/dist/env/schema.js.map +1 -0
  27. package/dist/governor/adapter.d.ts +1 -1
  28. package/dist/governor/adapter.d.ts.map +1 -1
  29. package/dist/governor/adapter.js +2 -1
  30. package/dist/governor/adapter.js.map +1 -1
  31. package/dist/governor/tools/extras.js +14 -3
  32. package/dist/governor/tools/extras.js.map +1 -1
  33. package/dist/index.js +31 -11
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/requireEnv.d.ts +30 -0
  36. package/dist/lib/requireEnv.d.ts.map +1 -0
  37. package/dist/lib/requireEnv.js +48 -0
  38. package/dist/lib/requireEnv.js.map +1 -0
  39. package/dist/lib/signer.d.ts +8 -0
  40. package/dist/lib/signer.d.ts.map +1 -1
  41. package/dist/lib/signer.js +18 -0
  42. package/dist/lib/signer.js.map +1 -1
  43. package/dist/rpc.d.ts +8 -0
  44. package/dist/rpc.d.ts.map +1 -1
  45. package/dist/rpc.js +18 -0
  46. package/dist/rpc.js.map +1 -1
  47. package/dist/tools/doctor.d.ts +11 -0
  48. package/dist/tools/doctor.d.ts.map +1 -0
  49. package/dist/tools/doctor.js +75 -0
  50. package/dist/tools/doctor.js.map +1 -0
  51. package/dist/tools/index.d.ts.map +1 -1
  52. package/dist/tools/index.js +3 -0
  53. package/dist/tools/index.js.map +1 -1
  54. package/dist/tools/read.js +40 -10
  55. package/dist/tools/read.js.map +1 -1
  56. package/dist/tools/txSend.d.ts.map +1 -1
  57. package/dist/tools/txSend.js +18 -1
  58. package/dist/tools/txSend.js.map +1 -1
  59. package/package.json +5 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,111 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 — 2026-05-30
4
+
5
+ ### Env onboarding overhaul
6
+
7
+ This release exists to make first-run setup fail-safe for new users
8
+ (human or AI assistant). Previously, when an env var was missing or
9
+ typoed, tools threw raw stacks and the assistant had no way to discover
10
+ which file to edit, which key was missing, or whether `.claude.json` was
11
+ shadowing `.env`. Now there is one diagnostic, one wizard, one skill,
12
+ and one schema that drives every check.
13
+
14
+ **Upgrade:** zero env changes required, no breaking renames or removals.
15
+ See [`docs/MIGRATION.md`](docs/MIGRATION.md) for the 0.7.x → 0.8.0
16
+ guide and the documented behavior change in `dexe_read_*` /
17
+ `dexe_tx_send` error responses.
18
+
19
+ ### Added
20
+
21
+ - **`dexe_doctor` tool + CLI.** New diagnostic that walks every
22
+ recognized `DEXE_*` env var, runs reachability checks (RPC
23
+ `eth_chainId` per chain, Pinata `testAuthentication`, IPFS gateway DNS
24
+ lookup, subgraph `{__typename}` introspection, backend HEAD), and
25
+ reports pass/warn/fail per check with paste-ready remediation hints.
26
+ Network checks have a 3s hard timeout that downgrades to `warn` so
27
+ offline laptops don't see all-red. Also runnable as
28
+ `npx dexe-mcp doctor` (exit 0/1/2). See [`docs/DOCTOR.md`](docs/DOCTOR.md).
29
+ - **`npx dexe-mcp init` wizard.** Interactive onboarding via native
30
+ `node:readline/promises`. Asks four questions (network, Pinata JWT,
31
+ Graph API key, signer mode), writes `.env` at the repo root (merge or
32
+ overwrite), and prints a `~/.claude.json` snippet for copy-paste.
33
+ Validates the Pinata JWT against the live endpoint before writing.
34
+ Defaults the signer mode to readonly; warns explicitly and double-confirms
35
+ before storing a private key in plaintext. Never auto-edits
36
+ `.claude.json`. No new dependencies.
37
+ - **Schema-driven env handling.** `src/env/schema.ts` (`ENV_SPEC`,
38
+ `ENV_REGISTRY`) is now the canonical registry for every recognized
39
+ `DEXE_*` var (category, doc, zod schema, enabled flows, secret flag).
40
+ Consumed by the new parser, doctor, fail-soft guards, and the
41
+ `/dexe-setup` skill. Drift guarded by `tests/env/schema.test.ts`
42
+ against `.env.example`.
43
+ - **Startup self-diagnostic banner.** `src/env/loader.ts` reads `.env`
44
+ raw bytes before `process.loadEnvFile()` and emits stderr warnings
45
+ for: UTF-8 BOM, missing trailing newline, spaces around `=`, unknown
46
+ `DEXE_*` keys, and host-env shadowing of `.env` values. Surfaces
47
+ silent parse traps that previously made "I edited .env and nothing
48
+ changed" hard to diagnose.
49
+ - **Fail-soft guard helpers.** New `src/lib/requireEnv.ts` (`requireEnv`,
50
+ `hintFor`) generalizes the existing `requirePinata` pattern from
51
+ `src/tools/ipfs.ts`. Added `SignerManager.trySigner` and
52
+ `RpcProvider.tryProvider` siblings that return `{error, remediation}`
53
+ instead of throwing — keeps the throwing variants for backward
54
+ compatibility.
55
+ - **`/dexe-setup` skill** at `.claude/skills/dexe-setup/SKILL.md`. Calls
56
+ `dexe_doctor`, parses the report, asks the user only for missing
57
+ values, edits `.env` (never `.claude.json`), and tells the user to
58
+ restart Claude Code. Caps at 3 doctor → fix → restart iterations.
59
+ Hard rule: refuse to write `DEXE_PRIVATE_KEY` without explicit user
60
+ opt-in; suggest WalletConnect first.
61
+ - **`docs/SETUP.md` + `docs/DOCTOR.md` + `docs/MIGRATION.md`.**
62
+ Consolidated quickstart with three setup paths, the full check
63
+ reference, and the per-version migration notes.
64
+ - **"For AI assistants" block in `CLAUDE.md`.** Tells future Claude:
65
+ call `dexe_doctor` first; edit `.env` not `.claude.json`; restart is
66
+ required after env changes; the `/dexe-setup` skill exists; point
67
+ upgrading users at `docs/MIGRATION.md`.
68
+
69
+ ### Changed
70
+
71
+ - **`src/tools/read.ts` and `src/tools/txSend.ts` hot handlers** migrated
72
+ to the soft `tryProvider`/`trySigner` variants. Missing RPC or
73
+ `DEXE_PRIVATE_KEY` now surfaces as a structured MCP error with fix
74
+ instructions instead of a thrown stack. Other call sites of
75
+ `requireProvider`/`requireSigner` keep their throwing behavior — they
76
+ are migrated incrementally in 0.8.1.
77
+ - **`src/index.ts`** now dispatches `dexe-mcp doctor` and `dexe-mcp init`
78
+ to their respective CLI entry points before opening the MCP stdio
79
+ transport. No-arg invocation still starts the server as before. The
80
+ env loader runs BEFORE the subcommand dispatch so the CLI sees the
81
+ same env as the MCP server.
82
+ - **`docs/TOOLS.md`** bumped to 153 tools / 19 groups (added the
83
+ Diagnostics group containing `dexe_doctor`).
84
+ - **`README.md` Quickstart** now leads with the wizard path
85
+ (`init` + `doctor`) above the manual install instructions.
86
+
87
+ ### Notes
88
+
89
+ - No removed APIs. `requireSigner`/`requireProvider` keep throwing so
90
+ every existing call site (~17 outside read.ts and txSend.ts)
91
+ continues to work; the migration is incremental.
92
+ - No new runtime dependencies. The wizard and doctor use only
93
+ `node:readline/promises`, `node:dns/promises`, and native `fetch`.
94
+
95
+ ## 0.7.2 — 2026-05-27
96
+
97
+ ### Fixed
98
+
99
+ - **`dexe_gov_has_voted` reverted on every Bravo DAO (Uniswap, Compound).** Classic
100
+ `GovernorBravoDelegate` does not expose `hasVoted(uint256, address)` — it exposes
101
+ `getReceipt(proposalId, voter)` returning `Receipt{hasVoted, support, votes}`. The
102
+ Bravo read ABI wrongly listed `hasVoted` and the tool called it unconditionally, so
103
+ the call failed with `CALL_EXCEPTION`. The tool now family-branches: OZ reads
104
+ `hasVoted`, Bravo reads `getReceipt(...).hasVoted`, and the response reports the
105
+ `method` used. OZ (Optimism) was unaffected. Found via live verification of the
106
+ governor adapter against mainnet/OP RPCs; verified live post-fix (Compound 374,
107
+ Uniswap 75, Optimism).
108
+
3
109
  ## 0.7.1 — 2026-05-26
4
110
 
5
111
  ### Fixed
package/README.md CHANGED
@@ -40,7 +40,7 @@ That era is ending.
40
40
 
41
41
  LLMs can now reason about voting power, weigh proposals against a mandate, draft calldata, simulate execution, and ask your wallet to sign — **continuously, across every DAO you care about, all at once.** What was a UI is becoming a conversation. What was a treasurer's spreadsheet is becoming an always-on agent.
42
42
 
43
- **`dexe-mcp` is the substrate that makes it real for the DeXe stack — and now for external OpenZeppelin Governor DAOs as well.** One MCP server. 152 typed tools across 19 groups. Every flow the DeXe frontend exposes — plus a generic `dexe_gov_*` surface targeting Uniswap, Compound, and Optimism.
43
+ **`dexe-mcp` is the substrate that makes it real for the DeXe stack — and now for external OpenZeppelin Governor DAOs as well.** One MCP server. 153 typed tools across 19 groups. Every flow the DeXe frontend exposes — plus a generic `dexe_gov_*` surface targeting Uniswap, Compound, and Optimism.
44
44
 
45
45
  | | What you get |
46
46
  |-----|------|
@@ -87,6 +87,24 @@ The next generation of DAOs will be **operated by language, not by clicks.**
87
87
 
88
88
  ## Quickstart
89
89
 
90
+ **Fastest path — wizard + diagnostic:**
91
+
92
+ ```bash
93
+ npm install -g dexe-mcp
94
+ npx dexe-mcp init # interactive setup (network, Pinata, signer mode)
95
+ npx dexe-mcp doctor # verify (RPC + Pinata + IPFS gateway + subgraph)
96
+ ```
97
+
98
+ The wizard writes `.env` at the repo root and prints a `~/.claude.json`
99
+ snippet to paste. Then `doctor` walks every recognized `DEXE_*` var and
100
+ returns a pass/warn/fail report with paste-ready remediation hints. See
101
+ [`docs/SETUP.md`](./docs/SETUP.md) for the full runbook,
102
+ [`docs/DOCTOR.md`](./docs/DOCTOR.md) for the check reference, and
103
+ [`docs/MIGRATION.md`](./docs/MIGRATION.md) if you are upgrading from
104
+ 0.7.x.
105
+
106
+ **Manual path:**
107
+
90
108
  **1.** Install:
91
109
 
92
110
  ```bash
@@ -211,7 +229,7 @@ Full docs in [`docs/`](https://github.com/edward-arinin-web-dev/dexe-mcp/tree/ma
211
229
  | **WalletConnect** | 3 | `dexe_wc_status` (resolved config + live session state), `dexe_wc_connect` (start a session, returns a pairing URI to scan as a QR), `dexe_wc_disconnect` (tear down). Broadcast convenience without a hot key — every tx is signed and broadcast on the operator's phone, the key never enters the MCP. See [`docs/WALLETCONNECT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/WALLETCONNECT.md). |
212
230
  | **Simulator** | 3 | `eth_call`-based preflight with decoded revert reasons — `_sim_calldata`, `_sim_proposal`, `_sim_buy`. Catch reverts before you pay gas. See [`docs/SIMULATOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SIMULATOR.md). |
213
231
  | **Multi-DAO inbox + forecast** | 2 | `dexe_user_inbox` aggregates pending items (unvoted proposals, claimable rewards, locked deposits) across N DAOs. `_proposal_forecast` predicts pass rate with quorum projection + risk flags. See [`docs/INBOX.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/INBOX.md). |
214
- | **External Governor DAOs** | 18 | `dexe_gov_*` — read, build, simulate, and decode against OpenZeppelin Governor + Compound Bravo DAOs. Tier-1: Uniswap, Compound, Optimism. Config-only addition for new DAOs. Family-aware (OZ vs Bravo) propose / castVote / queue / execute / cancel / delegate. Eth-call dry-run + vote-impact projection. hasVoted + state + hashProposal + decode + descriptionHash utilities. Tally state-enum parity harness. See [`docs/GOVERNOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/GOVERNOR.md). |
232
+ | **External Governor DAOs** | 18 | `dexe_gov_*` — read, build, simulate, and decode against OpenZeppelin Governor + Compound Bravo DAOs. Tier-1: Uniswap, Compound, Optimism. Config-only addition for new DAOs. Family-aware (OZ vs Bravo) propose / castVote / queue / execute / cancel / delegate. Eth-call dry-run + vote-impact projection. vote-receipt check (family-aware) + state + hashProposal + decode + descriptionHash utilities. Tally state-enum parity harness. See [`docs/GOVERNOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/GOVERNOR.md). |
215
233
 
216
234
  ---
217
235
 
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CLI entrypoint: `npx dexe-mcp doctor`. Runs the same check suite as the
3
+ * MCP tool, prints a flat colorless table to stdout, exits with:
4
+ * - 0 when every check passes
5
+ * - 1 when there are warnings but no failures
6
+ * - 2 when at least one check fails
7
+ *
8
+ * Designed for both human terminal use and CI pipelines.
9
+ */
10
+ export declare function run(): Promise<void>;
11
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAiCzC"}
@@ -0,0 +1,44 @@
1
+ import { loadConfig } from "../config.js";
2
+ import { runAllChecks } from "../diag/checks.js";
3
+ /**
4
+ * CLI entrypoint: `npx dexe-mcp doctor`. Runs the same check suite as the
5
+ * MCP tool, prints a flat colorless table to stdout, exits with:
6
+ * - 0 when every check passes
7
+ * - 1 when there are warnings but no failures
8
+ * - 2 when at least one check fails
9
+ *
10
+ * Designed for both human terminal use and CI pipelines.
11
+ */
12
+ export async function run() {
13
+ const config = await loadConfig().catch(err => {
14
+ process.stderr.write(`[dexe-mcp doctor] config load failed: ${err instanceof Error ? err.message : String(err)}\n`);
15
+ process.exit(2);
16
+ });
17
+ if (!config) {
18
+ process.exit(2);
19
+ }
20
+ const checks = await runAllChecks({ config });
21
+ let pass = 0;
22
+ let warn = 0;
23
+ let fail = 0;
24
+ for (const c of checks) {
25
+ if (c.status === "pass")
26
+ pass++;
27
+ else if (c.status === "warn")
28
+ warn++;
29
+ else
30
+ fail++;
31
+ }
32
+ for (const c of checks) {
33
+ const tag = c.status === "pass" ? " OK " : c.status === "warn" ? "WARN" : "FAIL";
34
+ process.stdout.write(`[${tag}] ${c.id.padEnd(36)} ${c.message}\n`);
35
+ if (c.remediation) {
36
+ for (const line of c.remediation.split("\n")) {
37
+ process.stdout.write(` -> ${line}\n`);
38
+ }
39
+ }
40
+ }
41
+ process.stdout.write(`\nsummary: ${pass} pass / ${warn} warn / ${fail} fail\n`);
42
+ process.exit(fail > 0 ? 2 : warn > 0 ? 1 : 0);
43
+ }
44
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yCAAyC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC9F,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,IAAI,EAAE,CAAC;aAC3B,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,IAAI,EAAE,CAAC;;YAChC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAClB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,WAAW,IAAI,WAAW,IAAI,SAAS,CAAC,CAAC;IAChF,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function run(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAsBA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CA8KzC"}
@@ -0,0 +1,306 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { stdin as input, stdout as output } from "node:process";
3
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { resolve, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ /**
7
+ * `npx dexe-mcp init` — zero-config onboarding wizard.
8
+ *
9
+ * Walks the user through a minimal `.env` (network, RPCs, Pinata, subgraph
10
+ * key, signer mode), validates the Pinata JWT against the live endpoint
11
+ * before writing, and prints a paste-ready `.claude.json` snippet. Never
12
+ * auto-edits the user's MCP host config — that is too risky to do
13
+ * automatically (other servers, other env keys, comments to preserve).
14
+ *
15
+ * Uses only the Node 20 standard library (`node:readline/promises`,
16
+ * `node:fs`, native `fetch`) — no new dependency.
17
+ */
18
+ const TESTNET_DEFAULT_RPC = "https://data-seed-prebsc-1-s1.bnbchain.org:8545";
19
+ const MAINNET_DEFAULT_RPC = "https://bsc-dataseed.bnbchain.org";
20
+ export async function run() {
21
+ if (!input.isTTY) {
22
+ process.stderr.write("[dexe-mcp init] stdin is not a TTY. Pipe-driven init is not supported (too risky for secrets). " +
23
+ "Fill in .env manually instead — see .env.example.\n");
24
+ process.exit(2);
25
+ }
26
+ const rl = createInterface({ input, output });
27
+ try {
28
+ output.write(line("dexe-mcp init — onboarding wizard"));
29
+ output.write(line("─".repeat(64)));
30
+ output.write(line("Builds a minimal .env. Answers are stored in plaintext;"));
31
+ output.write(line("use WalletConnect or readonly mode if that worries you."));
32
+ output.write("\n");
33
+ // ---- Network selection ----------------------------------------------
34
+ const network = await pickOne(rl, "Which network(s)?", [
35
+ ["t", "testnet — BSC chain 97 (free faucet BNB, recommended for first run)"],
36
+ ["m", "mainnet — BSC chain 56 (real funds)"],
37
+ ["b", "both"],
38
+ ], "t");
39
+ let rpcTestnet;
40
+ let rpcMainnet;
41
+ if (network === "t" || network === "b") {
42
+ rpcTestnet = (await ask(rl, "Testnet RPC URL", TESTNET_DEFAULT_RPC)).trim();
43
+ }
44
+ if (network === "m" || network === "b") {
45
+ rpcMainnet = (await ask(rl, "Mainnet RPC URL", MAINNET_DEFAULT_RPC)).trim();
46
+ }
47
+ const defaultChainId = network === "m" ? "56" : "97";
48
+ // ---- Pinata JWT (optional) -----------------------------------------
49
+ output.write(line("Pinata JWT enables IPFS uploads (proposal metadata, DAO avatars)."));
50
+ output.write(line("Reads work without it via a public gateway. Press Enter to skip."));
51
+ const pinataJwt = (await ask(rl, "Pinata JWT", "")).trim();
52
+ if (pinataJwt) {
53
+ const ok = await validatePinataJwt(pinataJwt);
54
+ if (!ok) {
55
+ const proceed = await yn(rl, "Pinata says that JWT is invalid (or the network is unreachable). Save anyway?", false);
56
+ if (!proceed) {
57
+ output.write(line("Aborted — re-run init when you have a valid JWT."));
58
+ process.exit(2);
59
+ }
60
+ }
61
+ else {
62
+ output.write(line(" → Pinata JWT validated."));
63
+ }
64
+ }
65
+ const ipfsGateway = pinataJwt
66
+ ? (await ask(rl, "IPFS gateway URL", "https://gateway.pinata.cloud")).trim()
67
+ : "";
68
+ // ---- Subgraph (optional) -------------------------------------------
69
+ output.write(line("Subgraph reads need a Graph API key (free at thegraph.com)."));
70
+ const graphKey = (await ask(rl, "Graph API key (blank to skip subgraph reads)", "")).trim();
71
+ // ---- Signer mode ---------------------------------------------------
72
+ output.write(line(""));
73
+ output.write(line("Signer mode:"));
74
+ output.write(line(" readonly — no broadcast; tools return unsigned calldata (safest)"));
75
+ output.write(line(" walletconnect — broadcast via phone wallet; key never enters this process"));
76
+ output.write(line(" privkey — hot key in .env; convenient for CI and bots, NOT recommended"));
77
+ const signerMode = await pickOne(rl, "Pick a signer mode", [
78
+ ["r", "readonly (recommended)"],
79
+ ["w", "walletconnect"],
80
+ ["p", "privkey (warning: plaintext in .env)"],
81
+ ], "r");
82
+ let privateKey;
83
+ let wcProjectId;
84
+ if (signerMode === "p") {
85
+ output.write(line(""));
86
+ output.write(line("⚠ Plaintext private keys in .env are a security risk."));
87
+ output.write(line(" Anyone who reads the file can drain that wallet."));
88
+ output.write(line(" Prefer WalletConnect (re-run init and pick `w`) when possible."));
89
+ const confirm = await yn(rl, "Continue with privkey mode?", false);
90
+ if (!confirm) {
91
+ output.write(line("Aborted — re-run init and pick readonly or walletconnect."));
92
+ process.exit(2);
93
+ }
94
+ const pk = (await ask(rl, "Private key (0x… 64 hex)", "")).trim();
95
+ if (!/^0x[0-9a-fA-F]{64}$/.test(pk)) {
96
+ output.write(line("That does not look like a 64-hex key — aborting."));
97
+ process.exit(2);
98
+ }
99
+ const addr = await deriveAddress(pk);
100
+ output.write(line(` → Derived address: ${addr}`));
101
+ const ok = await yn(rl, "Is that the wallet you intended?", true);
102
+ if (!ok) {
103
+ output.write(line("Aborted — re-run init."));
104
+ process.exit(2);
105
+ }
106
+ privateKey = pk;
107
+ }
108
+ else if (signerMode === "w") {
109
+ wcProjectId = (await ask(rl, "WalletConnect project id (cloud.reown.com)", "")).trim();
110
+ }
111
+ // ---- Build the env block + write .env ------------------------------
112
+ const updates = {};
113
+ if (rpcTestnet)
114
+ updates.DEXE_RPC_URL_TESTNET = rpcTestnet;
115
+ if (rpcMainnet)
116
+ updates.DEXE_RPC_URL_MAINNET = rpcMainnet;
117
+ updates.DEXE_DEFAULT_CHAIN_ID = defaultChainId;
118
+ if (pinataJwt)
119
+ updates.DEXE_PINATA_JWT = pinataJwt;
120
+ if (ipfsGateway)
121
+ updates.DEXE_IPFS_GATEWAY = ipfsGateway;
122
+ if (graphKey)
123
+ updates.DEXE_GRAPH_API_KEY = graphKey;
124
+ if (privateKey)
125
+ updates.DEXE_PRIVATE_KEY = privateKey;
126
+ if (wcProjectId)
127
+ updates.DEXE_WALLETCONNECT_PROJECT_ID = wcProjectId;
128
+ const repoRoot = findRepoRoot();
129
+ const envPath = resolve(repoRoot, ".env");
130
+ // Read the file once up-front (or treat ENOENT as "no existing .env") so
131
+ // the later write isn't a check-then-act TOCTOU: every decision below
132
+ // operates on this captured snapshot, not on a re-stat of the path.
133
+ let existingEnv = null;
134
+ try {
135
+ existingEnv = readFileSync(envPath, "utf8");
136
+ }
137
+ catch (err) {
138
+ if (err.code !== "ENOENT")
139
+ throw err;
140
+ }
141
+ let action = "write";
142
+ if (existingEnv !== null) {
143
+ const choice = await pickOne(rl, `Existing .env at ${envPath}. Overwrite or merge?`, [
144
+ ["m", "merge — replace known keys, keep everything else (recommended)"],
145
+ ["o", "overwrite — wipe and start fresh"],
146
+ ["a", "abort — keep .env unchanged, exit"],
147
+ ], "m");
148
+ if (choice === "a") {
149
+ output.write(line("Aborted — .env unchanged."));
150
+ process.exit(0);
151
+ }
152
+ action = choice === "o" ? "write" : "merge";
153
+ }
154
+ const content = action === "write" || existingEnv === null
155
+ ? renderFreshEnv(updates)
156
+ : mergeEnv(existingEnv, updates);
157
+ writeFileSync(envPath, content, "utf8");
158
+ output.write(line(`✔ Wrote ${envPath} (${Object.keys(updates).length} key${Object.keys(updates).length === 1 ? "" : "s"} set).`));
159
+ output.write(line(""));
160
+ // ---- Print .claude.json snippet ------------------------------------
161
+ output.write(line("Paste this into your ~/.claude.json under `mcpServers`:"));
162
+ output.write(line(""));
163
+ output.write(jsonSnippet(repoRoot));
164
+ output.write(line(""));
165
+ output.write(line(`Next: run \`npx dexe-mcp doctor\` to verify, then restart Claude Code.`));
166
+ }
167
+ finally {
168
+ rl.close();
169
+ }
170
+ }
171
+ // ─── prompt helpers ──────────────────────────────────────────────────────
172
+ async function ask(rl, prompt, fallback) {
173
+ const suffix = fallback ? ` [${fallback}]` : "";
174
+ const a = await rl.question(`${prompt}${suffix}: `);
175
+ return a.length === 0 ? fallback : a;
176
+ }
177
+ async function yn(rl, prompt, defaultYes) {
178
+ const suffix = defaultYes ? "[Y/n]" : "[y/N]";
179
+ const a = (await rl.question(`${prompt} ${suffix}: `)).trim().toLowerCase();
180
+ if (!a)
181
+ return defaultYes;
182
+ return a === "y" || a === "yes";
183
+ }
184
+ async function pickOne(rl, prompt, options, defaultKey) {
185
+ output.write(line(prompt));
186
+ for (const [key, label] of options) {
187
+ const tag = key === defaultKey ? `[${key}*]` : `[${key} ]`;
188
+ output.write(line(` ${tag} ${label}`));
189
+ }
190
+ const valid = new Set(options.map(o => o[0]));
191
+ // eslint-disable-next-line no-constant-condition
192
+ while (true) {
193
+ const a = (await rl.question(`Choice (default ${defaultKey}): `)).trim().toLowerCase();
194
+ if (!a)
195
+ return defaultKey;
196
+ if (valid.has(a))
197
+ return a;
198
+ output.write(line(` → please answer one of ${[...valid].join(" / ")}`));
199
+ }
200
+ }
201
+ // ─── env file rendering ──────────────────────────────────────────────────
202
+ function renderFreshEnv(updates) {
203
+ const lines = [
204
+ "# dexe-mcp — generated by `npx dexe-mcp init`",
205
+ "# Loaded via process.loadEnvFile() at MCP startup.",
206
+ "# Run `npx dexe-mcp doctor` after any edit to verify.",
207
+ "",
208
+ ];
209
+ for (const [k, v] of Object.entries(updates)) {
210
+ lines.push(`${k}=${v}`);
211
+ }
212
+ return lines.join("\n") + "\n";
213
+ }
214
+ /**
215
+ * Merge new values into an existing .env in place: known keys are replaced,
216
+ * unknown keys + comments + blank lines preserved verbatim. Detects CRLF vs
217
+ * LF and matches the file's existing line endings.
218
+ */
219
+ function mergeEnv(existing, updates) {
220
+ const eol = /\r\n/.test(existing) ? "\r\n" : "\n";
221
+ const lines = existing.split(/\r?\n/);
222
+ const seen = new Set();
223
+ const out = [];
224
+ for (const line_ of lines) {
225
+ const m = /^(\s*)([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line_);
226
+ if (m && Object.prototype.hasOwnProperty.call(updates, m[2])) {
227
+ const key = m[2];
228
+ out.push(`${m[1] ?? ""}${key}=${updates[key]}`);
229
+ seen.add(key);
230
+ continue;
231
+ }
232
+ out.push(line_);
233
+ }
234
+ // Append any keys that did not already exist.
235
+ const appended = [];
236
+ for (const [k, v] of Object.entries(updates)) {
237
+ if (seen.has(k))
238
+ continue;
239
+ appended.push(`${k}=${v}`);
240
+ }
241
+ if (appended.length > 0) {
242
+ if (out.length > 0 && out[out.length - 1] !== "")
243
+ out.push("");
244
+ out.push("# added by `npx dexe-mcp init`");
245
+ out.push(...appended);
246
+ }
247
+ // Ensure trailing newline (Node's loadEnvFile drops the last line otherwise).
248
+ if (out.length > 0 && out[out.length - 1] !== "")
249
+ out.push("");
250
+ return out.join(eol);
251
+ }
252
+ // ─── Pinata + ethers helpers ─────────────────────────────────────────────
253
+ async function validatePinataJwt(jwt) {
254
+ try {
255
+ const ctrl = new AbortController();
256
+ const timer = setTimeout(() => ctrl.abort(), 5000);
257
+ const r = await fetch("https://api.pinata.cloud/data/testAuthentication", {
258
+ method: "GET",
259
+ headers: { Authorization: `Bearer ${jwt}` },
260
+ signal: ctrl.signal,
261
+ });
262
+ clearTimeout(timer);
263
+ return r.status >= 200 && r.status < 300;
264
+ }
265
+ catch {
266
+ return false;
267
+ }
268
+ }
269
+ async function deriveAddress(pk) {
270
+ const { Wallet } = await import("ethers");
271
+ return new Wallet(pk).address;
272
+ }
273
+ // ─── path + snippet helpers ──────────────────────────────────────────────
274
+ function findRepoRoot() {
275
+ // `dist/index.js` → `..` is repo root. Walk up if running from src/cli/.
276
+ const here = dirname(fileURLToPath(import.meta.url));
277
+ // Two known layouts: dist/cli/init.js → up 2; dist/index.js's import → up 1 from dist.
278
+ // Easiest: walk up until we find package.json.
279
+ let cur = here;
280
+ for (let i = 0; i < 6; i++) {
281
+ if (existsSync(resolve(cur, "package.json")))
282
+ return cur;
283
+ cur = resolve(cur, "..");
284
+ }
285
+ return process.cwd();
286
+ }
287
+ function jsonSnippet(repoRoot) {
288
+ const distPath = resolve(repoRoot, "dist", "index.js");
289
+ // Use JSON.stringify to handle Windows backslashes cleanly.
290
+ const safe = JSON.stringify(distPath);
291
+ return [
292
+ "{",
293
+ ` "mcpServers": {`,
294
+ ` "dexe": {`,
295
+ ` "command": "node",`,
296
+ ` "args": [${safe}]`,
297
+ ` }`,
298
+ ` }`,
299
+ `}`,
300
+ "",
301
+ ].join("\n");
302
+ }
303
+ function line(s) {
304
+ return s + "\n";
305
+ }
306
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type EnvCategory } from "../env/schema.js";
2
+ import type { DexeConfig } from "../config.js";
3
+ export type CheckStatus = "pass" | "warn" | "fail";
4
+ export type CheckCategory = EnvCategory | "network" | "process";
5
+ export interface CheckResult {
6
+ id: string;
7
+ category: CheckCategory;
8
+ status: CheckStatus;
9
+ message: string;
10
+ remediation?: string;
11
+ }
12
+ export interface RunCheckOpts {
13
+ /** When omitted, checks that depend on resolved config are skipped. */
14
+ config?: DexeConfig;
15
+ /** Per-network-check timeout. Defaults to 3000ms. */
16
+ timeoutMs?: number;
17
+ }
18
+ /**
19
+ * Run every diagnostic check in parallel, gather results.
20
+ *
21
+ * Network checks have a hard timeout that downgrades to `warn`, never `fail` —
22
+ * an offline laptop or VPN flake should not make the doctor scream red.
23
+ */
24
+ export declare function runAllChecks(opts?: RunCheckOpts): Promise<CheckResult[]>;
25
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/diag/checks.ts"],"names":[],"mappings":"AACA,OAAO,EAA4C,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAqBlF"}