dexe-mcp 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 (62) hide show
  1. package/.mcp.example.json +8 -0
  2. package/FUTURE.md +37 -0
  3. package/LICENSE +21 -0
  4. package/PLAN.md +132 -0
  5. package/README.md +126 -0
  6. package/dist/artifacts.d.ts +69 -0
  7. package/dist/artifacts.d.ts.map +1 -0
  8. package/dist/artifacts.js +181 -0
  9. package/dist/artifacts.js.map +1 -0
  10. package/dist/bootstrap.d.ts +12 -0
  11. package/dist/bootstrap.d.ts.map +1 -0
  12. package/dist/bootstrap.js +83 -0
  13. package/dist/bootstrap.js.map +1 -0
  14. package/dist/config.d.ts +19 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +40 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/hardhat.d.ts +26 -0
  19. package/dist/hardhat.d.ts.map +1 -0
  20. package/dist/hardhat.js +87 -0
  21. package/dist/hardhat.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +22 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/lib/decoders.d.ts +51 -0
  27. package/dist/lib/decoders.d.ts.map +1 -0
  28. package/dist/lib/decoders.js +122 -0
  29. package/dist/lib/decoders.js.map +1 -0
  30. package/dist/lib/govAddresses.d.ts +35 -0
  31. package/dist/lib/govAddresses.d.ts.map +1 -0
  32. package/dist/lib/govAddresses.js +51 -0
  33. package/dist/lib/govAddresses.js.map +1 -0
  34. package/dist/lib/selectors.d.ts +31 -0
  35. package/dist/lib/selectors.d.ts.map +1 -0
  36. package/dist/lib/selectors.js +110 -0
  37. package/dist/lib/selectors.js.map +1 -0
  38. package/dist/rpc.d.ts +14 -0
  39. package/dist/rpc.d.ts.map +1 -0
  40. package/dist/rpc.js +23 -0
  41. package/dist/rpc.js.map +1 -0
  42. package/dist/tools/build.d.ts +21 -0
  43. package/dist/tools/build.d.ts.map +1 -0
  44. package/dist/tools/build.js +281 -0
  45. package/dist/tools/build.js.map +1 -0
  46. package/dist/tools/context.d.ts +16 -0
  47. package/dist/tools/context.d.ts.map +1 -0
  48. package/dist/tools/context.js +2 -0
  49. package/dist/tools/context.js.map +1 -0
  50. package/dist/tools/gov.d.ts +4 -0
  51. package/dist/tools/gov.d.ts.map +1 -0
  52. package/dist/tools/gov.js +302 -0
  53. package/dist/tools/gov.js.map +1 -0
  54. package/dist/tools/index.d.ts +9 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +21 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/introspect.d.ts +4 -0
  59. package/dist/tools/introspect.d.ts.map +1 -0
  60. package/dist/tools/introspect.js +312 -0
  61. package/dist/tools/introspect.js.map +1 -0
  62. package/package.json +69 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "dexe": {
4
+ "command": "npx",
5
+ "args": ["-y", "dexe-mcp"]
6
+ }
7
+ }
8
+ }
package/FUTURE.md ADDED
@@ -0,0 +1,37 @@
1
+ # Future work
2
+
3
+ Tracking features deliberately deferred out of the Phase A / B roadmap.
4
+
5
+ ## `dexe_get_storage_layout` (dropped from v1)
6
+
7
+ The current `DeXe-Protocol/hardhat.config.js` does not include `storageLayout` in `outputSelection`, so build-info files don't contain the data this tool would read.
8
+
9
+ **To enable:** add `storageLayout` to `outputSelection` in DeXe-Protocol's hardhat config:
10
+
11
+ ```js
12
+ solidity: {
13
+ compilers: [{
14
+ version: "0.8.20",
15
+ settings: {
16
+ outputSelection: {
17
+ "*": {
18
+ "*": ["storageLayout", /* ...existing */]
19
+ }
20
+ }
21
+ }
22
+ }]
23
+ }
24
+ ```
25
+
26
+ Then the tool becomes a short handler reading `output.contracts[file][name].storageLayout` from the matching build-info JSON.
27
+
28
+ ## `dexe_simulate_vote` (Phase B)
29
+
30
+ Needs a managed `hardhat node --fork $DEXE_RPC_URL` child process owned by the MCP. See `src/fork.ts` (not yet created) per the execution plan at `C:\Users\edwar\.claude\plans\kind-rolling-pelican.md`.
31
+
32
+ ## Other ideas surfaced during design
33
+
34
+ - **TypeChain integration** — the protocol already emits ethers-v5 TypeChain bindings. We intentionally parse ABI JSON directly (dexe-mcp uses ethers v6). Revisit if/when DeXe-Protocol moves to ethers v6.
35
+ - **Custom `hardhat-migrate` wrappers** — out of scope per user decision (deployment tooling excluded).
36
+ - **Gas reporter parsing** — the `hardhat-gas-reporter` plugin is already wired in the protocol; `dexe_test` could optionally parse its output for per-function gas numbers.
37
+ - **Foundry fallback** — the repo is pure Hardhat today. Skip unless a Foundry config is added upstream.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Edward Arinin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/PLAN.md ADDED
@@ -0,0 +1,132 @@
1
+ # Plan: `dexe-mcp` — MCP Server for DeXe Protocol Dev Tooling
2
+
3
+ ## Context
4
+
5
+ DeXe Protocol (`D:\dev\DeXe-Protocol`) is a governance DAO protocol: 129 Solidity contracts (OpenZeppelin v4.9.2, Solidity 0.8.20, Hardhat 2.20.1), organized around `GovPool`, `GovSettings`, `GovUserKeeper`, `GovValidators`, proposal contracts (`DistributionProposal`, `StakingProposal`, `TokenSaleProposal`), voting-power libs (`LinearPower`, `PolynomialPower`), and a `ContractsRegistry` service locator.
6
+
7
+ Day-to-day dev work on this repo currently means jumping between `npm run compile`, `hardhat test --grep`, reading TypeChain output, and hand-decoding proposal calldata against ABIs. We want an MCP server Claude Code can drive directly so an agent can compile, introspect contracts, and answer governance-domain questions (decode a proposal, read on-chain gov state, simulate a vote on a fork) without the human babysitting each shell command.
8
+
9
+ **Decisions already made (from user):**
10
+ - TypeScript / Node, `@modelcontextprotocol/sdk` v1.x, stdio transport
11
+ - Separate repo (`dexe-mcp`) — not nested inside DeXe-Protocol
12
+ - Scope: **build/test**, **contract introspection**, **governance domain**. Explicitly **out of scope**: deployment/migration tooling
13
+ - Consumer: Claude Code (stdio)
14
+
15
+ The server points at a DeXe-Protocol checkout via `DEXE_PROTOCOL_PATH`; it reads Hardhat artifacts off disk and shells out to `npm run <script>` in that directory. On-chain / fork interactions go through an injected RPC URL.
16
+
17
+ ## Repository Layout
18
+
19
+ ```
20
+ dexe-mcp/
21
+ ├── package.json # "bin": { "dexe-mcp": "dist/index.js" }
22
+ ├── tsconfig.json
23
+ ├── README.md # how to wire into Claude Code .mcp.json
24
+ ├── .mcp.example.json # copy-paste snippet for users
25
+ ├── src/
26
+ │ ├── index.ts # McpServer + StdioServerTransport entrypoint
27
+ │ ├── config.ts # env: DEXE_PROTOCOL_PATH, RPC_URL, FORK_BLOCK
28
+ │ ├── artifacts.ts # load hardhat artifacts + build-info + storage layout
29
+ │ ├── hardhat.ts # spawn `npm run …` in DEXE_PROTOCOL_PATH, stream + cap output
30
+ │ ├── rpc.ts # ethers v6 Provider factory
31
+ │ ├── fork.ts # on-demand `hardhat node --fork` child process mgmt
32
+ │ ├── lib/
33
+ │ │ ├── selectors.ts # 4byte index built from all compiled ABIs
34
+ │ │ ├── decoders.ts # proposal-executor decoders (Distribution/Staking/TokenSale)
35
+ │ │ └── govAddresses.ts # resolve GovPool ecosystem via ContractsRegistry
36
+ │ └── tools/
37
+ │ ├── index.ts # registerAll(server)
38
+ │ ├── build.ts # compile / test / coverage / lint
39
+ │ ├── introspect.ts # abi / selectors / storage / natspec / source
40
+ │ └── gov.ts # decode_calldata / decode_proposal / read_gov_state / simulate_vote
41
+ └── test/
42
+ └── tools.test.ts # vitest; uses a tiny fixture hardhat project
43
+ ```
44
+
45
+ ## Dependencies
46
+
47
+ - `@modelcontextprotocol/sdk` (v1.x) — `McpServer`, `StdioServerTransport`, `registerTool`
48
+ - `zod` — input/output schemas (Standard Schema, per current MCP SDK docs)
49
+ - `ethers` v6 — ABI parsing, `Interface.parseTransaction`, providers, impersonation
50
+ - `execa` — child_process wrapper for hardhat shell-outs (timeout + stdout capping)
51
+ - `p-limit` — guard concurrent hardhat invocations
52
+ - Dev: `typescript`, `tsx`, `vitest`, `@types/node`
53
+
54
+ ## Tool Catalog
55
+
56
+ All tools use `registerTool(name, {title, description, inputSchema, outputSchema}, handler)` with Zod schemas and return both `content` (text) and `structuredContent` (machine-readable).
57
+
58
+ ### Build / test (wraps `npm run …` in `DEXE_PROTOCOL_PATH`)
59
+
60
+ | Tool | Input | Behavior |
61
+ |---|---|---|
62
+ | `dexe_compile` | `{ force?: boolean }` | Runs `npm run compile`. Parses solc errors/warnings; returns counts + first N diagnostics with file/line. |
63
+ | `dexe_test` | `{ grep?: string, file?: string, bail?: boolean }` | Runs `npx hardhat test` (with `--grep` / file arg). Parses mocha output; returns pass/fail counts and up to 20 failures with stack traces. |
64
+ | `dexe_coverage` | `{ grep?: string }` | Runs `npm run coverage`. Returns per-contract line/branch % summary parsed from `coverage/coverage-summary.json`. |
65
+ | `dexe_lint` | `{ fix?: boolean }` | Runs `npm run lint-fix` (or dry-run). Returns changed-file list. |
66
+
67
+ All build/test tools cap stdout at ~200 lines and write full logs to a tmp file, surfacing the path in `structuredContent.logFile`.
68
+
69
+ ### Contract introspection (reads artifacts, no network)
70
+
71
+ `artifacts.ts` loads `${DEXE_PROTOCOL_PATH}/artifacts/contracts/**/*.json` and the matching `build-info/*.json` for storage layout + metadata.
72
+
73
+ | Tool | Input | Behavior |
74
+ |---|---|---|
75
+ | `dexe_list_contracts` | `{ filter?: string, kind?: "contract"\|"interface"\|"library" }` | Enumerates compiled contracts, returning `{name, path, kind}`. |
76
+ | `dexe_get_abi` | `{ contract: string }` | Returns ABI JSON for named contract. |
77
+ | `dexe_get_selectors` | `{ contract: string }` | Returns list of `{signature, selector, type: "function"\|"event"\|"error"}` using `ethers.Interface.getFunction().selector`. |
78
+ | `dexe_find_selector` | `{ selector: "0xXXXXXXXX" }` | Reverse-lookup against the prebuilt index in `lib/selectors.ts`; returns all matching signatures + contracts. |
79
+ | `dexe_get_storage_layout` | `{ contract: string }` | Extracts storage layout from build-info `output.contracts[file][name].storageLayout`. |
80
+ | `dexe_get_natspec` | `{ contract: string, member?: string }` | Returns `devdoc`/`userdoc` from artifact metadata, optionally scoped to one function. |
81
+ | `dexe_get_source` | `{ contract: string, symbol?: string }` | Returns source path; if `symbol`, returns a slice around its definition using AST from build-info. |
82
+
83
+ ### Governance domain (the reason this MCP exists)
84
+
85
+ | Tool | Input | Behavior |
86
+ |---|---|---|
87
+ | `dexe_decode_calldata` | `{ data: "0x...", contract?: string }` | Tries to decode calldata. Without `contract`, iterates all loaded ABIs by selector match. Returns decoded function + args (recursively decoding nested proposal executor calldata for `GovPool.createProposal` / `execute`). |
88
+ | `dexe_decode_proposal` | `{ govPool: address, proposalId: number }` | Calls `GovPool.getProposals` via RPC, decodes every action's `data` against the matching executor (`DistributionProposal`, `TokenSaleProposal`, `StakingProposal`, or generic) using `lib/decoders.ts`. |
89
+ | `dexe_read_gov_state` | `{ govPool: address, fields?: string[] }` | Aggregate read: `GovSettings` params, `GovUserKeeper` totals, `GovValidators` set, active proposal count. Resolved via `ContractsRegistry` (`lib/govAddresses.ts`). |
90
+ | `dexe_simulate_vote` | `{ govPool: address, proposalId: number, voter: address, voteAmount: string, support: boolean }` | Starts/reuses a `hardhat node --fork $RPC_URL` child (managed by `fork.ts`), impersonates `voter`, calls `GovPool.vote`, returns the new proposal state + gas used. Fork is torn down on server shutdown. |
91
+ | `dexe_list_gov_contract_types` | `{}` | Static catalog: names, roles, ABI pointers for the governance subsystem. Cheap orientation tool for agents new to the repo. |
92
+
93
+ ## Key Implementation Notes
94
+
95
+ - **Single source of truth for artifacts.** `artifacts.ts` memoizes a `Map<contractName, {abi, bytecode, buildInfoPath}>` built once per `DEXE_PROTOCOL_PATH` mtime. Invalidated after `dexe_compile` completes.
96
+ - **Selector index.** Built lazily on first introspection call by walking the artifact map and calling `new ethers.Interface(abi)` on each. Stored as `Map<selector, Array<{contract, signature}>>` — supports collisions.
97
+ - **Proposal decoding is the crown jewel.** `lib/decoders.ts` must handle `GovPool`'s `ProposalAction[]` shape (`executor`, `value`, `data`), dispatching by `executor` address class to the proposal-specific ABIs. Fall back to generic ABI decode when executor is unknown. Unit-test this against real calldata captured from mainnet proposals.
98
+ - **Fork lifecycle.** `fork.ts` owns at most one `hardhat node` child process. Tools that need fork state (`simulate_vote`) start it lazily; `server.onclose` kills it. No persistent state between tool calls beyond the running fork.
99
+ - **Shell-out safety.** All child_process calls use `execa` with `cwd: DEXE_PROTOCOL_PATH`, fixed arg arrays (no shell interpolation), 10-minute timeout, and `maxBuffer` protection.
100
+ - **Config.** `config.ts` reads `DEXE_PROTOCOL_PATH` (required), `DEXE_RPC_URL` (optional; needed for gov state / simulate), `DEXE_FORK_BLOCK` (optional). Fails fast on startup with a clear error if `DEXE_PROTOCOL_PATH` is missing or not a Hardhat project (no `hardhat.config.js`).
101
+ - **Logging.** Per MCP convention, **all logs to stderr** (stdout is the protocol channel). Use `console.error` or a thin `pino` stderr stream.
102
+
103
+ ## Verification
104
+
105
+ 1. **Unit tests** (`vitest`): each tool handler tested against a tiny fixture Hardhat project committed under `test/fixtures/`. Covers ABI loading, selector index, calldata decoding (including nested proposal executors), stdout parsing for compile/test.
106
+ 2. **Smoke against the real repo.** With `DEXE_PROTOCOL_PATH=D:\dev\DeXe-Protocol` set, run the server under the official MCP Inspector: `npx @modelcontextprotocol/inspector node dist/index.js`. Manually exercise:
107
+ - `dexe_compile` → expect clean build
108
+ - `dexe_test { grep: "GovPool" }` → expect real pass/fail summary
109
+ - `dexe_list_contracts { filter: "Gov" }` → expect `GovPool`, `GovSettings`, etc.
110
+ - `dexe_get_abi { contract: "GovPool" }`
111
+ - `dexe_find_selector { selector: "<known GovPool selector>" }`
112
+ - `dexe_decode_calldata` against a captured real-world proposal createProposal calldata
113
+ 3. **End-to-end in Claude Code.** Add to `.mcp.json`:
114
+ ```json
115
+ {
116
+ "mcpServers": {
117
+ "dexe": {
118
+ "command": "node",
119
+ "args": ["D:/dev/dexe-mcp/dist/index.js"],
120
+ "env": { "DEXE_PROTOCOL_PATH": "D:/dev/DeXe-Protocol" }
121
+ }
122
+ }
123
+ }
124
+ ```
125
+ Restart Claude Code, confirm tools appear, ask it "compile the protocol and summarize any warnings" and "decode proposal 42 on GovPool 0x…".
126
+ 4. **Fork simulation test** (optional, needs RPC): set `DEXE_RPC_URL` to an Ethereum archive node, run `dexe_simulate_vote` against a real active proposal, verify no orphaned `hardhat node` processes after server shutdown.
127
+
128
+ ## Out of Scope (explicit, per user)
129
+
130
+ - Deployment / migration tooling (`hardhat-migrate` wrappers, network configs under `deploy/config/configs/`, verification) — deliberately excluded.
131
+ - TypeChain codegen orchestration, Go bindings, markup doc generation.
132
+ - Remote / HTTP transport, auth, multi-tenant hosting.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # dexe-mcp
2
+
3
+ ![npm](https://img.shields.io/npm/v/dexe-mcp.svg)
4
+
5
+ MCP server for Claude Code / Antigravity that wraps the [DeXe Protocol](https://github.com/dexe-network/DeXe-Protocol) Hardhat codebase with build/test, contract introspection, and governance-domain tools.
6
+
7
+ ## Prerequisites
8
+
9
+ - **Node.js >= 20**
10
+ - **Git** (the server auto-clones DeXe-Protocol on first run)
11
+
12
+ ## Quick start
13
+
14
+ Add this to your project's `.mcp.json` (or your MCP client config):
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "dexe": {
20
+ "command": "npx",
21
+ "args": ["-y", "dexe-mcp"]
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ Restart your MCP client. On first launch, `dexe-mcp` will automatically:
28
+
29
+ 1. Clone `dexe-network/DeXe-Protocol` to a local cache directory (~200 MB, shallow clone)
30
+ 2. Run `npm install` in the checkout
31
+
32
+ Subsequent launches are instant. No manual setup needed.
33
+
34
+ ### Advanced: custom checkout path
35
+
36
+ If you already have a DeXe-Protocol checkout or want to control its location:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "dexe": {
42
+ "command": "npx",
43
+ "args": ["-y", "dexe-mcp"],
44
+ "env": {
45
+ "DEXE_PROTOCOL_PATH": "/absolute/path/to/your/DeXe-Protocol"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## First run
53
+
54
+ Before introspection tools work, run `dexe_compile` once per session to populate `DeXe-Protocol/artifacts/`. You will get a clear "artifacts not found" error otherwise.
55
+
56
+ ## Tool catalog
57
+
58
+ ### Build / test
59
+
60
+ | Tool | Description |
61
+ |------|-------------|
62
+ | `dexe_compile` | Compile all contracts via Hardhat |
63
+ | `dexe_test` | Run the test suite (optional grep filter) |
64
+ | `dexe_coverage` | Run tests with solidity-coverage |
65
+ | `dexe_lint` | Lint Solidity sources with solhint |
66
+
67
+ ### Contract introspection
68
+
69
+ | Tool | Description |
70
+ |------|-------------|
71
+ | `dexe_list_contracts` | List all compiled contracts (filter by name/kind) |
72
+ | `dexe_get_abi` | Get the full ABI for a contract |
73
+ | `dexe_get_selectors` | List function selectors for a contract |
74
+ | `dexe_find_selector` | Reverse-lookup: selector hex to function signature |
75
+ | `dexe_get_natspec` | Read NatSpec documentation for a contract |
76
+ | `dexe_get_source` | Read Solidity source code for a contract |
77
+
78
+ ### Governance domain
79
+
80
+ | Tool | Description |
81
+ |------|-------------|
82
+ | `dexe_decode_calldata` | Decode arbitrary calldata against contract ABI |
83
+ | `dexe_decode_proposal` | Fetch and decode a full on-chain proposal |
84
+ | `dexe_read_gov_state` | Read governance pool state from chain |
85
+ | `dexe_list_gov_contract_types` | List known governance contract type names |
86
+
87
+ ## Environment variables
88
+
89
+ | Variable | Required | Purpose |
90
+ |----------|----------|---------|
91
+ | `DEXE_PROTOCOL_PATH` | no | Override the auto-managed DeXe-Protocol checkout path |
92
+ | `DEXE_RPC_URL` | no | JSON-RPC endpoint for `dexe_decode_proposal` and `dexe_read_gov_state` |
93
+ | `DEXE_FORK_BLOCK` | no | Pin the fork to a specific block (Phase B) |
94
+
95
+ ## Troubleshooting
96
+
97
+ ### "Hardhat artifacts not found — run dexe_compile first"
98
+
99
+ Introspection tools require compiled artifacts. Run `dexe_compile` once after the initial setup to populate them.
100
+
101
+ ### "Failed to clone DeXe-Protocol"
102
+
103
+ Make sure `git` is installed and available on your PATH, and that you have internet access. The server clones from `https://github.com/dexe-network/DeXe-Protocol.git`.
104
+
105
+ ### "DEXE_RPC_URL is not set"
106
+
107
+ The governance tools `dexe_decode_proposal` and `dexe_read_gov_state` require an Ethereum JSON-RPC endpoint. Add `DEXE_RPC_URL` to your MCP env config.
108
+
109
+ ## Contributing
110
+
111
+ ```bash
112
+ git clone https://github.com/edward-arinin-web-dev/dexe-mcp.git
113
+ cd dexe-mcp
114
+ npm install
115
+ npm run build
116
+ npm run typecheck
117
+ npm run dev # watch mode
118
+ ```
119
+
120
+ ## Roadmap
121
+
122
+ Phase B (`dexe_simulate_vote` + Hardhat fork management) is planned for v0.2.0. See [FUTURE.md](./FUTURE.md) for all deferred features.
123
+
124
+ ## License
125
+
126
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,69 @@
1
+ import type { DexeConfig } from "./config.js";
2
+ /**
3
+ * Minimal artifact record loaded from a Hardhat artifact JSON.
4
+ *
5
+ * We intentionally don't pull the full Hardhat Artifact type off the bundle —
6
+ * keeps the dependency footprint small and works across Hardhat versions.
7
+ */
8
+ export interface ArtifactRecord {
9
+ contractName: string;
10
+ sourceName: string;
11
+ abi: readonly unknown[];
12
+ bytecode: string;
13
+ deployedBytecode: string;
14
+ /** Absolute path to the artifact JSON on disk. */
15
+ artifactPath: string;
16
+ /** Inferred kind. "library" detection is best-effort; interfaces are reliable (bytecode === "0x"). */
17
+ kind: "contract" | "interface" | "library";
18
+ }
19
+ /** Structured error thrown when introspection tools run before `dexe_compile`. */
20
+ export declare class ArtifactsMissingError extends Error {
21
+ readonly artifactsDir: string;
22
+ constructor(artifactsDir: string);
23
+ }
24
+ export declare class Artifacts {
25
+ private readonly config;
26
+ private cache;
27
+ constructor(config: DexeConfig);
28
+ /** Directory holding contract artifacts (not build-info). */
29
+ get contractsDir(): string;
30
+ /** Directory holding build-info JSON (used for natspec + AST). */
31
+ get buildInfoDir(): string;
32
+ /**
33
+ * Throws `ArtifactsMissingError` if `artifacts/contracts/` does not exist.
34
+ * Introspection tools call this before touching the cache.
35
+ */
36
+ requireArtifactsExist(): void;
37
+ /** Discard the in-memory index — called after `dexe_compile` succeeds. */
38
+ invalidate(): void;
39
+ /** Load (and memoize) all contract artifacts on disk. */
40
+ private load;
41
+ /** Enumerate all loaded artifacts, with optional filters. */
42
+ list(opts?: {
43
+ filter?: string;
44
+ kind?: ArtifactRecord["kind"];
45
+ }): ArtifactRecord[];
46
+ /**
47
+ * Look up an artifact by contract name. Returns the first match; if there
48
+ * are collisions (same contract name under different source paths), returns
49
+ * all of them so callers can disambiguate.
50
+ */
51
+ get(contractName: string): ArtifactRecord[];
52
+ /** Convenience: get exactly one artifact or throw. */
53
+ getOne(contractName: string): ArtifactRecord;
54
+ private readonly buildInfoCache;
55
+ /**
56
+ * Load the build-info file that holds the compiler output for a given
57
+ * artifact. Hardhat writes one build-info per compile per solc invocation;
58
+ * the artifact's `.dbg.json` points at the right one.
59
+ */
60
+ loadBuildInfoFor(record: ArtifactRecord): BuildInfoContract | null;
61
+ private loadBuildInfoFile;
62
+ }
63
+ export interface BuildInfoContract {
64
+ abi?: unknown[];
65
+ metadata?: string;
66
+ devdoc?: unknown;
67
+ userdoc?: unknown;
68
+ }
69
+ //# sourceMappingURL=artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,SAAS,OAAO,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,sGAAsG;IACtG,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;CAC5C;AAED,kFAAkF;AAClF,qBAAa,qBAAsB,SAAQ,KAAK;aAClB,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAMjD;AAQD,qBAAa,SAAS;IAGR,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,KAAK,CAA4B;gBAEZ,MAAM,EAAE,UAAU;IAE/C,6DAA6D;IAC7D,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,kEAAkE;IAClE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;OAGG;IACH,qBAAqB,IAAI,IAAI;IAM7B,0EAA0E;IAC1E,UAAU,IAAI,IAAI;IAKlB,yDAAyD;IACzD,OAAO,CAAC,IAAI;IAmDZ,6DAA6D;IAC7D,IAAI,CAAC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;KAAO,GAAG,cAAc,EAAE;IAUrF;;;;OAIG;IACH,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,EAAE;IAI3C,sDAAsD;IACtD,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc;IAmB5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoC;IAEnE;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB,GAAG,IAAI;IAiBlE,OAAO,CAAC,iBAAiB;CAmB1B;AAWD,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,181 @@
1
+ import { readdirSync, readFileSync, statSync, existsSync } from "node:fs";
2
+ import { join, sep, posix } from "node:path";
3
+ /** Structured error thrown when introspection tools run before `dexe_compile`. */
4
+ export class ArtifactsMissingError extends Error {
5
+ artifactsDir;
6
+ constructor(artifactsDir) {
7
+ super(`Hardhat artifacts not found at ${artifactsDir}. Run dexe_compile first to populate them.`);
8
+ this.artifactsDir = artifactsDir;
9
+ this.name = "ArtifactsMissingError";
10
+ }
11
+ }
12
+ export class Artifacts {
13
+ config;
14
+ cache = null;
15
+ constructor(config) {
16
+ this.config = config;
17
+ }
18
+ /** Directory holding contract artifacts (not build-info). */
19
+ get contractsDir() {
20
+ return join(this.config.protocolPath, "artifacts", "contracts");
21
+ }
22
+ /** Directory holding build-info JSON (used for natspec + AST). */
23
+ get buildInfoDir() {
24
+ return join(this.config.protocolPath, "artifacts", "build-info");
25
+ }
26
+ /**
27
+ * Throws `ArtifactsMissingError` if `artifacts/contracts/` does not exist.
28
+ * Introspection tools call this before touching the cache.
29
+ */
30
+ requireArtifactsExist() {
31
+ if (!existsSync(this.contractsDir)) {
32
+ throw new ArtifactsMissingError(this.contractsDir);
33
+ }
34
+ }
35
+ /** Discard the in-memory index — called after `dexe_compile` succeeds. */
36
+ invalidate() {
37
+ this.cache = null;
38
+ this.buildInfoCache.clear();
39
+ }
40
+ /** Load (and memoize) all contract artifacts on disk. */
41
+ load() {
42
+ this.requireArtifactsExist();
43
+ const st = statSync(this.contractsDir);
44
+ if (this.cache && this.cache.mtimeMs === st.mtimeMs) {
45
+ return this.cache;
46
+ }
47
+ const all = [];
48
+ const byName = new Map();
49
+ for (const file of walk(this.contractsDir)) {
50
+ if (!file.endsWith(".json"))
51
+ continue;
52
+ if (file.endsWith(".dbg.json"))
53
+ continue;
54
+ let parsed;
55
+ try {
56
+ parsed = JSON.parse(readFileSync(file, "utf8"));
57
+ }
58
+ catch {
59
+ continue; // skip malformed JSON
60
+ }
61
+ if (!parsed.contractName || !parsed.sourceName || !Array.isArray(parsed.abi))
62
+ continue;
63
+ const bytecode = parsed.bytecode ?? "0x";
64
+ const record = {
65
+ contractName: parsed.contractName,
66
+ sourceName: parsed.sourceName,
67
+ abi: parsed.abi,
68
+ bytecode,
69
+ deployedBytecode: parsed.deployedBytecode ?? "0x",
70
+ artifactPath: file,
71
+ kind: inferKind(parsed.sourceName, bytecode),
72
+ };
73
+ all.push(record);
74
+ const list = byName.get(record.contractName);
75
+ if (list)
76
+ list.push(record);
77
+ else
78
+ byName.set(record.contractName, [record]);
79
+ }
80
+ this.cache = { mtimeMs: st.mtimeMs, all, byContractName: byName };
81
+ return this.cache;
82
+ }
83
+ /** Enumerate all loaded artifacts, with optional filters. */
84
+ list(opts = {}) {
85
+ const { all } = this.load();
86
+ const f = opts.filter?.toLowerCase();
87
+ return all.filter((r) => {
88
+ if (opts.kind && r.kind !== opts.kind)
89
+ return false;
90
+ if (f && !r.contractName.toLowerCase().includes(f))
91
+ return false;
92
+ return true;
93
+ });
94
+ }
95
+ /**
96
+ * Look up an artifact by contract name. Returns the first match; if there
97
+ * are collisions (same contract name under different source paths), returns
98
+ * all of them so callers can disambiguate.
99
+ */
100
+ get(contractName) {
101
+ return this.load().byContractName.get(contractName) ?? [];
102
+ }
103
+ /** Convenience: get exactly one artifact or throw. */
104
+ getOne(contractName) {
105
+ const list = this.get(contractName);
106
+ if (list.length === 0) {
107
+ throw new Error(`Unknown contract: ${contractName}. Call dexe_list_contracts to see what's available.`);
108
+ }
109
+ if (list.length > 1) {
110
+ const paths = list.map((r) => r.sourceName).join(", ");
111
+ throw new Error(`Ambiguous contract name: ${contractName} exists in multiple sources (${paths}). ` +
112
+ `Pass a fully-qualified name like "${list[0].sourceName}:${contractName}" (not yet supported — open an issue).`);
113
+ }
114
+ return list[0];
115
+ }
116
+ // ---------- build-info ----------
117
+ buildInfoCache = new Map();
118
+ /**
119
+ * Load the build-info file that holds the compiler output for a given
120
+ * artifact. Hardhat writes one build-info per compile per solc invocation;
121
+ * the artifact's `.dbg.json` points at the right one.
122
+ */
123
+ loadBuildInfoFor(record) {
124
+ const dbgPath = record.artifactPath.replace(/\.json$/, ".dbg.json");
125
+ if (!existsSync(dbgPath))
126
+ return null;
127
+ let dbg;
128
+ try {
129
+ dbg = JSON.parse(readFileSync(dbgPath, "utf8"));
130
+ }
131
+ catch {
132
+ return null;
133
+ }
134
+ if (!dbg.buildInfo)
135
+ return null;
136
+ // dbg.buildInfo is a relative path from the .dbg.json's directory.
137
+ const biPath = join(dbgPath, "..", dbg.buildInfo);
138
+ return this.loadBuildInfoFile(biPath, record.sourceName, record.contractName);
139
+ }
140
+ loadBuildInfoFile(absPath, sourceName, contractName) {
141
+ let file = this.buildInfoCache.get(absPath);
142
+ if (!file) {
143
+ if (!existsSync(absPath))
144
+ return null;
145
+ try {
146
+ file = JSON.parse(readFileSync(absPath, "utf8"));
147
+ }
148
+ catch {
149
+ return null;
150
+ }
151
+ this.buildInfoCache.set(absPath, file);
152
+ }
153
+ const src = file.output?.contracts?.[sourceName];
154
+ if (!src)
155
+ return null;
156
+ return src[contractName] ?? null;
157
+ }
158
+ }
159
+ // ---------- helpers ----------
160
+ function* walk(dir) {
161
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
162
+ const full = join(dir, entry.name);
163
+ if (entry.isDirectory()) {
164
+ yield* walk(full);
165
+ }
166
+ else if (entry.isFile()) {
167
+ yield full;
168
+ }
169
+ }
170
+ }
171
+ function inferKind(sourceName, bytecode) {
172
+ // Reliable: interfaces have no deployable bytecode.
173
+ if (bytecode === "0x" || bytecode === "")
174
+ return "interface";
175
+ // Best-effort heuristic for libraries. True library detection needs AST.
176
+ const normalized = sourceName.split(sep).join(posix.sep);
177
+ if (/\/libs?\//i.test(normalized))
178
+ return "library";
179
+ return "contract";
180
+ }
181
+ //# sourceMappingURL=artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Ensures a DeXe-Protocol checkout is available, returning its absolute path.
3
+ *
4
+ * Priority:
5
+ * 1. `DEXE_PROTOCOL_PATH` env var (power-user override)
6
+ * 2. Auto-managed clone in the platform cache directory
7
+ *
8
+ * On first run the clone + npm install may take a few minutes.
9
+ * Progress is logged to stderr (stdout is the MCP protocol channel).
10
+ */
11
+ export declare function ensureProtocolCheckout(): Promise<string>;
12
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAgD9D"}