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.
- package/.mcp.example.json +8 -0
- package/FUTURE.md +37 -0
- package/LICENSE +21 -0
- package/PLAN.md +132 -0
- package/README.md +126 -0
- package/dist/artifacts.d.ts +69 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +181 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/bootstrap.d.ts +12 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +83 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/config.js.map +1 -0
- package/dist/hardhat.d.ts +26 -0
- package/dist/hardhat.d.ts.map +1 -0
- package/dist/hardhat.js +87 -0
- package/dist/hardhat.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/decoders.d.ts +51 -0
- package/dist/lib/decoders.d.ts.map +1 -0
- package/dist/lib/decoders.js +122 -0
- package/dist/lib/decoders.js.map +1 -0
- package/dist/lib/govAddresses.d.ts +35 -0
- package/dist/lib/govAddresses.d.ts.map +1 -0
- package/dist/lib/govAddresses.js +51 -0
- package/dist/lib/govAddresses.js.map +1 -0
- package/dist/lib/selectors.d.ts +31 -0
- package/dist/lib/selectors.d.ts.map +1 -0
- package/dist/lib/selectors.js +110 -0
- package/dist/lib/selectors.js.map +1 -0
- package/dist/rpc.d.ts +14 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +23 -0
- package/dist/rpc.js.map +1 -0
- package/dist/tools/build.d.ts +21 -0
- package/dist/tools/build.d.ts.map +1 -0
- package/dist/tools/build.js +281 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/context.d.ts +16 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +2 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/gov.d.ts +4 -0
- package/dist/tools/gov.d.ts.map +1 -0
- package/dist/tools/gov.js +302 -0
- package/dist/tools/gov.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +21 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspect.d.ts +4 -0
- package/dist/tools/introspect.d.ts.map +1 -0
- package/dist/tools/introspect.js +312 -0
- package/dist/tools/introspect.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir, platform } from "node:os";
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
const REPO_URL = "https://github.com/dexe-network/DeXe-Protocol.git";
|
|
6
|
+
const CACHE_DIR_NAME = "dexe-mcp";
|
|
7
|
+
const CHECKOUT_DIR = "DeXe-Protocol";
|
|
8
|
+
/**
|
|
9
|
+
* Returns the platform-appropriate cache directory for dexe-mcp.
|
|
10
|
+
*
|
|
11
|
+
* - Windows: %LOCALAPPDATA%/dexe-mcp
|
|
12
|
+
* - macOS: ~/Library/Caches/dexe-mcp
|
|
13
|
+
* - Linux: ~/.cache/dexe-mcp (XDG_CACHE_HOME if set)
|
|
14
|
+
*/
|
|
15
|
+
function getCacheDir() {
|
|
16
|
+
const os = platform();
|
|
17
|
+
if (os === "win32") {
|
|
18
|
+
const base = process.env.LOCALAPPDATA || join(homedir(), "AppData", "Local");
|
|
19
|
+
return join(base, CACHE_DIR_NAME);
|
|
20
|
+
}
|
|
21
|
+
if (os === "darwin") {
|
|
22
|
+
return join(homedir(), "Library", "Caches", CACHE_DIR_NAME);
|
|
23
|
+
}
|
|
24
|
+
// Linux / others — respect XDG_CACHE_HOME
|
|
25
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
26
|
+
return join(base, CACHE_DIR_NAME);
|
|
27
|
+
}
|
|
28
|
+
function log(msg) {
|
|
29
|
+
process.stderr.write(`[dexe-mcp] ${msg}\n`);
|
|
30
|
+
}
|
|
31
|
+
function runSync(cmd, cwd) {
|
|
32
|
+
execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Ensures a DeXe-Protocol checkout is available, returning its absolute path.
|
|
36
|
+
*
|
|
37
|
+
* Priority:
|
|
38
|
+
* 1. `DEXE_PROTOCOL_PATH` env var (power-user override)
|
|
39
|
+
* 2. Auto-managed clone in the platform cache directory
|
|
40
|
+
*
|
|
41
|
+
* On first run the clone + npm install may take a few minutes.
|
|
42
|
+
* Progress is logged to stderr (stdout is the MCP protocol channel).
|
|
43
|
+
*/
|
|
44
|
+
export async function ensureProtocolCheckout() {
|
|
45
|
+
// ---- explicit override ----
|
|
46
|
+
const explicit = process.env.DEXE_PROTOCOL_PATH?.trim();
|
|
47
|
+
if (explicit)
|
|
48
|
+
return explicit;
|
|
49
|
+
// ---- auto-managed clone ----
|
|
50
|
+
const cacheDir = getCacheDir();
|
|
51
|
+
const protocolPath = join(cacheDir, CHECKOUT_DIR);
|
|
52
|
+
if (!existsSync(cacheDir)) {
|
|
53
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
const gitDir = join(protocolPath, ".git");
|
|
56
|
+
if (!existsSync(gitDir)) {
|
|
57
|
+
log(`Cloning DeXe-Protocol (shallow, ~200 MB) into ${protocolPath} …`);
|
|
58
|
+
log("This only happens once. Subsequent launches will be instant.");
|
|
59
|
+
try {
|
|
60
|
+
runSync(`git clone --depth 1 ${REPO_URL} "${CHECKOUT_DIR}"`, cacheDir);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
64
|
+
throw new Error(`Failed to clone DeXe-Protocol. Make sure git is installed and you have internet access.\n${msg}`);
|
|
65
|
+
}
|
|
66
|
+
log("Clone complete.");
|
|
67
|
+
}
|
|
68
|
+
// Ensure npm dependencies are installed
|
|
69
|
+
const nodeModules = join(protocolPath, "node_modules");
|
|
70
|
+
if (!existsSync(nodeModules)) {
|
|
71
|
+
log("Installing DeXe-Protocol npm dependencies (first run only) …");
|
|
72
|
+
try {
|
|
73
|
+
runSync("npm install", protocolPath);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
77
|
+
throw new Error(`npm install failed in DeXe-Protocol checkout.\n${msg}`);
|
|
78
|
+
}
|
|
79
|
+
log("Dependencies installed.");
|
|
80
|
+
}
|
|
81
|
+
return protocolPath;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface DexeConfig {
|
|
2
|
+
/** Absolute, normalized path to the DeXe-Protocol checkout. */
|
|
3
|
+
protocolPath: string;
|
|
4
|
+
/** Optional JSON-RPC endpoint for on-chain gov tools. */
|
|
5
|
+
rpcUrl?: string;
|
|
6
|
+
/** Optional fork block pin (Phase B). */
|
|
7
|
+
forkBlock?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validates environment and returns a frozen config.
|
|
11
|
+
*
|
|
12
|
+
* If `DEXE_PROTOCOL_PATH` is set, uses it directly (power-user override).
|
|
13
|
+
* Otherwise, auto-clones DeXe-Protocol into a platform cache directory.
|
|
14
|
+
*
|
|
15
|
+
* Exported primarily for the MCP entrypoint; tests can construct their own
|
|
16
|
+
* config objects directly.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadConfig(): Promise<DexeConfig>;
|
|
19
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CA4BtD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { resolve, join } from "node:path";
|
|
3
|
+
import { ensureProtocolCheckout } from "./bootstrap.js";
|
|
4
|
+
/**
|
|
5
|
+
* Validates environment and returns a frozen config.
|
|
6
|
+
*
|
|
7
|
+
* If `DEXE_PROTOCOL_PATH` is set, uses it directly (power-user override).
|
|
8
|
+
* Otherwise, auto-clones DeXe-Protocol into a platform cache directory.
|
|
9
|
+
*
|
|
10
|
+
* Exported primarily for the MCP entrypoint; tests can construct their own
|
|
11
|
+
* config objects directly.
|
|
12
|
+
*/
|
|
13
|
+
export async function loadConfig() {
|
|
14
|
+
const raw = await ensureProtocolCheckout();
|
|
15
|
+
const protocolPath = resolve(raw);
|
|
16
|
+
if (!existsSync(protocolPath) || !statSync(protocolPath).isDirectory()) {
|
|
17
|
+
fatal(`DeXe-Protocol path does not exist or is not a directory: ${protocolPath}`);
|
|
18
|
+
}
|
|
19
|
+
const hardhatConfig = join(protocolPath, "hardhat.config.js");
|
|
20
|
+
const hardhatConfigTs = join(protocolPath, "hardhat.config.ts");
|
|
21
|
+
if (!existsSync(hardhatConfig) && !existsSync(hardhatConfigTs)) {
|
|
22
|
+
fatal(`DeXe-Protocol path is not a Hardhat project — no hardhat.config.{js,ts} found at ${protocolPath}`);
|
|
23
|
+
}
|
|
24
|
+
const rpcUrl = process.env.DEXE_RPC_URL?.trim() || undefined;
|
|
25
|
+
let forkBlock;
|
|
26
|
+
if (process.env.DEXE_FORK_BLOCK) {
|
|
27
|
+
const n = Number(process.env.DEXE_FORK_BLOCK);
|
|
28
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
29
|
+
fatal(`DEXE_FORK_BLOCK must be a non-negative integer, got: ${process.env.DEXE_FORK_BLOCK}`);
|
|
30
|
+
}
|
|
31
|
+
forkBlock = n;
|
|
32
|
+
}
|
|
33
|
+
return Object.freeze({ protocolPath, rpcUrl, forkBlock });
|
|
34
|
+
}
|
|
35
|
+
function fatal(msg) {
|
|
36
|
+
// stderr only — stdout is the MCP protocol channel.
|
|
37
|
+
process.stderr.write(`[dexe-mcp] fatal: ${msg}\n`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAWxD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,GAAG,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACvE,KAAK,CAAC,4DAA4D,YAAY,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/D,KAAK,CACH,oFAAoF,YAAY,EAAE,CACnG,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAE7D,IAAI,SAA6B,CAAC;IAClC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,wDAAwD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,oDAAoD;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DexeConfig } from "./config.js";
|
|
2
|
+
/** Result of a shelled-out hardhat/npm invocation. */
|
|
3
|
+
export interface RunResult {
|
|
4
|
+
exitCode: number;
|
|
5
|
+
/** Full captured stdout (uncapped — tools surface `stdoutTail` publicly). */
|
|
6
|
+
stdout: string;
|
|
7
|
+
stderr: string;
|
|
8
|
+
/** Last ~200 lines of stdout, joined with newlines. */
|
|
9
|
+
stdoutTail: string;
|
|
10
|
+
/** Last ~100 lines of stderr, joined with newlines. */
|
|
11
|
+
stderrTail: string;
|
|
12
|
+
/** Absolute path to a tmp file holding the full stdout+stderr log. */
|
|
13
|
+
logFile: string;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
timedOut: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class HardhatRunner {
|
|
18
|
+
private readonly config;
|
|
19
|
+
constructor(config: DexeConfig);
|
|
20
|
+
/** Run `npm run <script>` in the protocol directory. */
|
|
21
|
+
runNpmScript(script: string, extraArgs?: string[]): Promise<RunResult>;
|
|
22
|
+
/** Run `npx hardhat <subcommand> <args...>` in the protocol directory. */
|
|
23
|
+
runHardhat(subcommand: string, args?: string[]): Promise<RunResult>;
|
|
24
|
+
private run;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=hardhat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardhat.d.ts","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,sDAAsD;AACtD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiBD,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAE/C,wDAAwD;IACxD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAQ1E,0EAA0E;IAC1E,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAIvE,OAAO,CAAC,GAAG;CAuDZ"}
|
package/dist/hardhat.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import pLimit from "p-limit";
|
|
3
|
+
import { writeFileSync, mkdtempSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
const HARDHAT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
7
|
+
const STDOUT_TAIL_LINES = 200;
|
|
8
|
+
const STDERR_TAIL_LINES = 100;
|
|
9
|
+
// One hardhat invocation at a time per process. Hardhat doesn't parallelize well
|
|
10
|
+
// across invocations against the same project, and solidity-coverage definitely
|
|
11
|
+
// doesn't.
|
|
12
|
+
const limit = pLimit(1);
|
|
13
|
+
let tmpRoot = null;
|
|
14
|
+
function getTmpRoot() {
|
|
15
|
+
if (!tmpRoot)
|
|
16
|
+
tmpRoot = mkdtempSync(join(tmpdir(), "dexe-mcp-"));
|
|
17
|
+
return tmpRoot;
|
|
18
|
+
}
|
|
19
|
+
export class HardhatRunner {
|
|
20
|
+
config;
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
}
|
|
24
|
+
/** Run `npm run <script>` in the protocol directory. */
|
|
25
|
+
runNpmScript(script, extraArgs = []) {
|
|
26
|
+
const args = ["run", script];
|
|
27
|
+
if (extraArgs.length > 0) {
|
|
28
|
+
args.push("--", ...extraArgs);
|
|
29
|
+
}
|
|
30
|
+
return this.run("npm", args, `npm-run-${script}`);
|
|
31
|
+
}
|
|
32
|
+
/** Run `npx hardhat <subcommand> <args...>` in the protocol directory. */
|
|
33
|
+
runHardhat(subcommand, args = []) {
|
|
34
|
+
return this.run("npx", ["hardhat", subcommand, ...args], `hardhat-${subcommand}`);
|
|
35
|
+
}
|
|
36
|
+
run(command, args, label) {
|
|
37
|
+
return limit(async () => {
|
|
38
|
+
const started = Date.now();
|
|
39
|
+
let timedOut = false;
|
|
40
|
+
const subprocess = execa(command, args, {
|
|
41
|
+
cwd: this.config.protocolPath,
|
|
42
|
+
timeout: HARDHAT_TIMEOUT_MS,
|
|
43
|
+
reject: false,
|
|
44
|
+
all: true,
|
|
45
|
+
env: { ...process.env, FORCE_COLOR: "0", CI: "1" },
|
|
46
|
+
});
|
|
47
|
+
// Best-effort: mirror child stderr to ours in near-real-time so the
|
|
48
|
+
// user sees progress in the MCP's stderr logs. The return value still
|
|
49
|
+
// captures everything.
|
|
50
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
51
|
+
process.stderr.write(chunk);
|
|
52
|
+
});
|
|
53
|
+
const result = await subprocess;
|
|
54
|
+
const durationMs = Date.now() - started;
|
|
55
|
+
const stdout = result.stdout ?? "";
|
|
56
|
+
const stderr = result.stderr ?? "";
|
|
57
|
+
if (result.timedOut)
|
|
58
|
+
timedOut = true;
|
|
59
|
+
const logFile = join(getTmpRoot(), `${label}-${started}.log`);
|
|
60
|
+
try {
|
|
61
|
+
writeFileSync(logFile, `$ ${command} ${args.join(" ")}\n(cwd: ${this.config.protocolPath})\n\n--- stdout ---\n${stdout}\n\n--- stderr ---\n${stderr}\n`);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// tmp write failure shouldn't fail the tool; the caller still gets tails.
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
exitCode: typeof result.exitCode === "number" ? result.exitCode : -1,
|
|
68
|
+
stdout,
|
|
69
|
+
stderr,
|
|
70
|
+
stdoutTail: tailLines(stdout, STDOUT_TAIL_LINES),
|
|
71
|
+
stderrTail: tailLines(stderr, STDERR_TAIL_LINES),
|
|
72
|
+
logFile,
|
|
73
|
+
durationMs,
|
|
74
|
+
timedOut,
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function tailLines(text, n) {
|
|
80
|
+
if (!text)
|
|
81
|
+
return "";
|
|
82
|
+
const lines = text.split(/\r?\n/);
|
|
83
|
+
if (lines.length <= n)
|
|
84
|
+
return lines.join("\n");
|
|
85
|
+
return lines.slice(-n).join("\n");
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=hardhat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardhat.js","sourceRoot":"","sources":["../src/hardhat.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
import { registerAll } from "./tools/index.js";
|
|
6
|
+
async function main() {
|
|
7
|
+
const config = await loadConfig();
|
|
8
|
+
const server = new McpServer({ name: "dexe-mcp", version: "0.1.0" }, {
|
|
9
|
+
instructions: "Tools for the DeXe Protocol governance-DAO codebase. Before calling any dexe_get_* / dexe_list_contracts / dexe_find_selector tool, ensure artifacts exist by calling dexe_compile once per session. dexe_decode_proposal and dexe_read_gov_state require DEXE_RPC_URL to be set.",
|
|
10
|
+
});
|
|
11
|
+
registerAll(server, config);
|
|
12
|
+
const transport = new StdioServerTransport();
|
|
13
|
+
await server.connect(transport);
|
|
14
|
+
// Log-only, not protocol. stdout is the MCP channel.
|
|
15
|
+
process.stderr.write(`[dexe-mcp] connected on stdio. DEXE_PROTOCOL_PATH=${config.protocolPath}${config.rpcUrl ? " (rpc enabled)" : ""}\n`);
|
|
16
|
+
}
|
|
17
|
+
main().catch((err) => {
|
|
18
|
+
const msg = err instanceof Error ? err.stack || err.message : String(err);
|
|
19
|
+
process.stderr.write(`[dexe-mcp] unhandled error:\n${msg}\n`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,EACtC;QACE,YAAY,EACV,mRAAmR;KACtR,CACF,CAAC;IAEF,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,qDAAqD;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qDAAqD,MAAM,CAAC,YAAY,GACtE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EACrC,IAAI,CACL,CAAC;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,GAAG,IAAI,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Artifacts } from "../artifacts.js";
|
|
2
|
+
import type { SelectorIndex } from "./selectors.js";
|
|
3
|
+
export interface DecodedCall {
|
|
4
|
+
/** Which contract's ABI produced this decode. May be `null` if we used a bare selector match. */
|
|
5
|
+
contract: string | null;
|
|
6
|
+
sourceName: string | null;
|
|
7
|
+
signature: string;
|
|
8
|
+
selector: string;
|
|
9
|
+
/** Arguments as a plain object keyed by parameter name (falls back to positional `arg_0` keys). */
|
|
10
|
+
args: Record<string, unknown>;
|
|
11
|
+
/** Raw positional args — useful for agents that want the tuple directly. */
|
|
12
|
+
argsArray: unknown[];
|
|
13
|
+
}
|
|
14
|
+
export interface DecodedProposalAction {
|
|
15
|
+
side: "for" | "against";
|
|
16
|
+
executor: string;
|
|
17
|
+
value: string;
|
|
18
|
+
data: string;
|
|
19
|
+
/** Decoded call against the executor's ABI. `null` if we couldn't match. */
|
|
20
|
+
decoded: DecodedCall | null;
|
|
21
|
+
}
|
|
22
|
+
export declare class CalldataDecoder {
|
|
23
|
+
private readonly artifacts;
|
|
24
|
+
private readonly selectors;
|
|
25
|
+
constructor(artifacts: Artifacts, selectors: SelectorIndex);
|
|
26
|
+
/**
|
|
27
|
+
* Decode raw calldata. If `contractName` is given, only that contract's ABI
|
|
28
|
+
* is tried. Otherwise every artifact whose selector matches is tried in
|
|
29
|
+
* turn; the first successful parse wins (with alternatives in `.alternatives`).
|
|
30
|
+
*/
|
|
31
|
+
decodeCalldata(data: string, contractName?: string): {
|
|
32
|
+
primary: DecodedCall | null;
|
|
33
|
+
alternatives: DecodedCall[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Given a ProposalAction tuple, find the executor contract and decode `data`
|
|
37
|
+
* against its ABI. Strategy: try to find an artifact whose runtime bytecode
|
|
38
|
+
* is "close enough" via name fallback — but in practice we can't easily
|
|
39
|
+
* reverse-lookup an address to a contract type off-chain without an on-chain
|
|
40
|
+
* probe. So instead we rely on the selector index: decode purely by selector
|
|
41
|
+
* match across all loaded ABIs, which works for the DeXe proposal executors
|
|
42
|
+
* because each one has distinct signatures.
|
|
43
|
+
*/
|
|
44
|
+
decodeProposalAction(action: {
|
|
45
|
+
executor: string;
|
|
46
|
+
value: bigint;
|
|
47
|
+
data: string;
|
|
48
|
+
side: "for" | "against";
|
|
49
|
+
}): DecodedProposalAction;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=decoders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoders.d.ts","sourceRoot":"","sources":["../../src/lib/decoders.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,iGAAiG;IACjG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,mGAAmG;IACnG,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,4EAA4E;IAC5E,SAAS,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAED,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,aAAa;IAG3C;;;;OAIG;IACH,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,GACpB;QAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,WAAW,EAAE,CAAA;KAAE;IA4C/D;;;;;;;;OAQG;IACH,oBAAoB,CAAC,MAAM,EAAE;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;KACzB,GAAG,qBAAqB;CAU1B"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Interface } from "ethers";
|
|
2
|
+
export class CalldataDecoder {
|
|
3
|
+
artifacts;
|
|
4
|
+
selectors;
|
|
5
|
+
constructor(artifacts, selectors) {
|
|
6
|
+
this.artifacts = artifacts;
|
|
7
|
+
this.selectors = selectors;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Decode raw calldata. If `contractName` is given, only that contract's ABI
|
|
11
|
+
* is tried. Otherwise every artifact whose selector matches is tried in
|
|
12
|
+
* turn; the first successful parse wins (with alternatives in `.alternatives`).
|
|
13
|
+
*/
|
|
14
|
+
decodeCalldata(data, contractName) {
|
|
15
|
+
if (!data || data.length < 10 || !data.startsWith("0x")) {
|
|
16
|
+
return { primary: null, alternatives: [] };
|
|
17
|
+
}
|
|
18
|
+
const selector = data.slice(0, 10).toLowerCase();
|
|
19
|
+
if (contractName) {
|
|
20
|
+
const record = this.artifacts.get(contractName)[0];
|
|
21
|
+
if (!record)
|
|
22
|
+
return { primary: null, alternatives: [] };
|
|
23
|
+
const hit = tryDecodeWith(record.abi, data);
|
|
24
|
+
if (hit) {
|
|
25
|
+
return {
|
|
26
|
+
primary: {
|
|
27
|
+
contract: record.contractName,
|
|
28
|
+
sourceName: record.sourceName,
|
|
29
|
+
...hit,
|
|
30
|
+
},
|
|
31
|
+
alternatives: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return { primary: null, alternatives: [] };
|
|
35
|
+
}
|
|
36
|
+
const candidates = this.selectors.find(selector).filter((h) => h.kind === "function");
|
|
37
|
+
const decoded = [];
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
for (const cand of candidates) {
|
|
40
|
+
if (seen.has(cand.contract))
|
|
41
|
+
continue;
|
|
42
|
+
seen.add(cand.contract);
|
|
43
|
+
const records = this.artifacts.get(cand.contract);
|
|
44
|
+
for (const r of records) {
|
|
45
|
+
const hit = tryDecodeWith(r.abi, data);
|
|
46
|
+
if (hit) {
|
|
47
|
+
decoded.push({ contract: r.contractName, sourceName: r.sourceName, ...hit });
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (decoded.length === 0) {
|
|
53
|
+
return { primary: null, alternatives: [] };
|
|
54
|
+
}
|
|
55
|
+
return { primary: decoded[0], alternatives: decoded.slice(1) };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Given a ProposalAction tuple, find the executor contract and decode `data`
|
|
59
|
+
* against its ABI. Strategy: try to find an artifact whose runtime bytecode
|
|
60
|
+
* is "close enough" via name fallback — but in practice we can't easily
|
|
61
|
+
* reverse-lookup an address to a contract type off-chain without an on-chain
|
|
62
|
+
* probe. So instead we rely on the selector index: decode purely by selector
|
|
63
|
+
* match across all loaded ABIs, which works for the DeXe proposal executors
|
|
64
|
+
* because each one has distinct signatures.
|
|
65
|
+
*/
|
|
66
|
+
decodeProposalAction(action) {
|
|
67
|
+
const result = this.decodeCalldata(action.data);
|
|
68
|
+
return {
|
|
69
|
+
side: action.side,
|
|
70
|
+
executor: action.executor,
|
|
71
|
+
value: action.value.toString(),
|
|
72
|
+
data: action.data,
|
|
73
|
+
decoded: result.primary,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function tryDecodeWith(abi, data) {
|
|
78
|
+
let iface;
|
|
79
|
+
try {
|
|
80
|
+
iface = new Interface(abi);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const parsed = iface.parseTransaction({ data });
|
|
87
|
+
if (!parsed)
|
|
88
|
+
return null;
|
|
89
|
+
return {
|
|
90
|
+
signature: parsed.fragment.format("sighash"),
|
|
91
|
+
selector: parsed.selector,
|
|
92
|
+
args: resultToObject(parsed.args, parsed.fragment.inputs.map((i) => i.name)),
|
|
93
|
+
argsArray: [...parsed.args].map(normalize),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function resultToObject(result, names) {
|
|
101
|
+
const out = {};
|
|
102
|
+
for (let i = 0; i < result.length; i++) {
|
|
103
|
+
const key = names[i] && names[i] !== "" ? names[i] : `arg_${i}`;
|
|
104
|
+
out[key] = normalize(result[i]);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
function normalize(v) {
|
|
109
|
+
if (typeof v === "bigint")
|
|
110
|
+
return v.toString();
|
|
111
|
+
if (Array.isArray(v))
|
|
112
|
+
return v.map(normalize);
|
|
113
|
+
if (v && typeof v === "object") {
|
|
114
|
+
// ethers Result is an array-like with named keys; treat as array for JSON safety.
|
|
115
|
+
const asResult = v;
|
|
116
|
+
if (typeof asResult.toArray === "function") {
|
|
117
|
+
return asResult.toArray().map(normalize);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return v;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=decoders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoders.js","sourceRoot":"","sources":["../../src/lib/decoders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,QAAQ,CAAC;AAyBhD,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,SAAoB,EACpB,SAAwB;QADxB,cAAS,GAAT,SAAS,CAAW;QACpB,cAAS,GAAT,SAAS,CAAe;IACxC,CAAC;IAEJ;;;;OAIG;IACH,cAAc,CACZ,IAAY,EACZ,YAAqB;QAErB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAEjD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC5C,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO;oBACL,OAAO,EAAE;wBACP,QAAQ,EAAE,MAAM,CAAC,YAAY;wBAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,GAAG,GAAG;qBACP;oBACD,YAAY,EAAE,EAAE;iBACjB,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACtF,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACtC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACvC,IAAI,GAAG,EAAE,CAAC;oBACR,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;oBAC7E,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,CAAC;IAED;;;;;;;;OAQG;IACH,oBAAoB,CAAC,MAKpB;QACC,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC9B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC;IACJ,CAAC;CACF;AAED,SAAS,aAAa,CAAC,GAAuB,EAAE,IAAY;IAC1D,IAAI,KAAgB,CAAC;IACrB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,SAAS,CAAC,GAAkD,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YAC5C,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5E,SAAS,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;SAC3C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,KAAwB;IAC9D,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,CAAU;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC/B,kFAAkF;QAClF,MAAM,QAAQ,GAAG,CAAW,CAAC;QAC7B,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YAC3C,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Provider } from "ethers";
|
|
2
|
+
import type { Artifacts } from "../artifacts.js";
|
|
3
|
+
/**
|
|
4
|
+
* Core helper contracts for a single GovPool instance, as returned by
|
|
5
|
+
* `GovPool.getHelperContracts()` on-chain.
|
|
6
|
+
*
|
|
7
|
+
* Note: proposal executors (DistributionProposal, StakingProposal,
|
|
8
|
+
* TokenSaleProposal) are NOT helpers of a pool — they're per-proposal targets
|
|
9
|
+
* referenced by the `executor` field on each ProposalAction. Discover them
|
|
10
|
+
* from the action itself, not from here.
|
|
11
|
+
*/
|
|
12
|
+
export interface GovHelpers {
|
|
13
|
+
settings: string;
|
|
14
|
+
userKeeper: string;
|
|
15
|
+
validators: string;
|
|
16
|
+
poolRegistry: string;
|
|
17
|
+
votePower: string;
|
|
18
|
+
}
|
|
19
|
+
/** Secondary NFT contracts exposed by `GovPool.getNftContracts()`. */
|
|
20
|
+
export interface GovNftContracts {
|
|
21
|
+
nftMultiplier: string;
|
|
22
|
+
expertNft: string;
|
|
23
|
+
dexeExpertNft: string;
|
|
24
|
+
babt: string;
|
|
25
|
+
}
|
|
26
|
+
export declare class GovAddressResolver {
|
|
27
|
+
private readonly artifacts;
|
|
28
|
+
private helperCache;
|
|
29
|
+
private nftCache;
|
|
30
|
+
constructor(artifacts: Artifacts);
|
|
31
|
+
resolveHelpers(govPool: string, provider: Provider): Promise<GovHelpers>;
|
|
32
|
+
resolveNftContracts(govPool: string, provider: Provider): Promise<GovNftContracts>;
|
|
33
|
+
private loadGovPoolAbi;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=govAddresses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"govAddresses.d.ts","sourceRoot":"","sources":["../../src/lib/govAddresses.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAUD,qBAAa,kBAAkB;IAIjB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAHtC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,QAAQ,CAAsC;gBAEzB,SAAS,EAAE,SAAS;IAE3C,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAexE,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;IAexF,OAAO,CAAC,cAAc;CASvB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Contract } from "ethers";
|
|
2
|
+
// Hand-written fragment so this module doesn't require GovPool artifacts to be
|
|
3
|
+
// compiled. If you later want to swap in the real ABI, `artifacts.getOne("GovPool").abi`
|
|
4
|
+
// works the same.
|
|
5
|
+
const HELPER_ABI = [
|
|
6
|
+
"function getHelperContracts() view returns (address settings, address userKeeper, address validators, address poolRegistry, address votePower)",
|
|
7
|
+
"function getNftContracts() view returns (address nftMultiplier, address expertNft, address dexeExpertNft, address babt)",
|
|
8
|
+
];
|
|
9
|
+
export class GovAddressResolver {
|
|
10
|
+
artifacts;
|
|
11
|
+
helperCache = new Map();
|
|
12
|
+
nftCache = new Map();
|
|
13
|
+
constructor(artifacts) {
|
|
14
|
+
this.artifacts = artifacts;
|
|
15
|
+
}
|
|
16
|
+
async resolveHelpers(govPool, provider) {
|
|
17
|
+
const key = govPool.toLowerCase();
|
|
18
|
+
const cached = this.helperCache.get(key);
|
|
19
|
+
if (cached)
|
|
20
|
+
return cached;
|
|
21
|
+
const abi = this.loadGovPoolAbi() ?? HELPER_ABI;
|
|
22
|
+
const pool = new Contract(govPool, abi, provider);
|
|
23
|
+
const [settings, userKeeper, validators, poolRegistry, votePower] = await pool.getFunction("getHelperContracts")();
|
|
24
|
+
const helpers = { settings, userKeeper, validators, poolRegistry, votePower };
|
|
25
|
+
this.helperCache.set(key, helpers);
|
|
26
|
+
return helpers;
|
|
27
|
+
}
|
|
28
|
+
async resolveNftContracts(govPool, provider) {
|
|
29
|
+
const key = govPool.toLowerCase();
|
|
30
|
+
const cached = this.nftCache.get(key);
|
|
31
|
+
if (cached)
|
|
32
|
+
return cached;
|
|
33
|
+
const abi = this.loadGovPoolAbi() ?? HELPER_ABI;
|
|
34
|
+
const pool = new Contract(govPool, abi, provider);
|
|
35
|
+
const [nftMultiplier, expertNft, dexeExpertNft, babt] = await pool.getFunction("getNftContracts")();
|
|
36
|
+
const result = { nftMultiplier, expertNft, dexeExpertNft, babt };
|
|
37
|
+
this.nftCache.set(key, result);
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
loadGovPoolAbi() {
|
|
41
|
+
try {
|
|
42
|
+
this.artifacts.requireArtifactsExist();
|
|
43
|
+
const records = this.artifacts.get("GovPool");
|
|
44
|
+
return records[0]?.abi ?? null;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=govAddresses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"govAddresses.js","sourceRoot":"","sources":["../../src/lib/govAddresses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAoC,MAAM,QAAQ,CAAC;AA4BpE,+EAA+E;AAC/E,yFAAyF;AACzF,kBAAkB;AAClB,MAAM,UAAU,GAAG;IACjB,gJAAgJ;IAChJ,yHAAyH;CAC1H,CAAC;AAEF,MAAM,OAAO,kBAAkB;IAIA;IAHrB,WAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtD,YAA6B,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAErD,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,QAAkB;QACtD,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,IAAK,UAA2B,CAAC;QAClE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC,GAAG,MAAM,IAAI,CAAC,WAAW,CACxF,oBAAoB,CACrB,EAAE,CAAC;QACJ,MAAM,OAAO,GAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;QAC1F,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,OAAe,EAAE,QAAkB;QAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,IAAK,UAA2B,CAAC;QAClE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,WAAW,CAC5E,iBAAiB,CAClB,EAAE,CAAC;QACJ,MAAM,MAAM,GAAoB,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QAClF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9C,OAAQ,OAAO,CAAC,CAAC,CAAC,EAAE,GAAgC,IAAI,IAAI,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Artifacts } from "../artifacts.js";
|
|
2
|
+
export type SelectorKind = "function" | "event" | "error";
|
|
3
|
+
export interface SelectorHit {
|
|
4
|
+
contract: string;
|
|
5
|
+
sourceName: string;
|
|
6
|
+
signature: string;
|
|
7
|
+
selector: string;
|
|
8
|
+
kind: SelectorKind;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Lazy, memoized selector index over all loaded contract artifacts.
|
|
12
|
+
* Built on first query; invalidated when the underlying artifact cache is.
|
|
13
|
+
* Supports collisions — the same 4-byte selector can appear in multiple contracts.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SelectorIndex {
|
|
16
|
+
private readonly artifacts;
|
|
17
|
+
private built;
|
|
18
|
+
private byFunctionSelector;
|
|
19
|
+
private byEventTopic;
|
|
20
|
+
private byErrorSelector;
|
|
21
|
+
private lastCacheStamp;
|
|
22
|
+
constructor(artifacts: Artifacts);
|
|
23
|
+
/** Build the index (idempotent). Called automatically by find/forContract. */
|
|
24
|
+
private ensureBuilt;
|
|
25
|
+
private indexContract;
|
|
26
|
+
/** Look up a selector or event topic. Accepts function selector (4B), error selector (4B), or event topic (32B). */
|
|
27
|
+
find(selector: string): SelectorHit[];
|
|
28
|
+
/** All selectors exposed by a single contract. */
|
|
29
|
+
forContract(contractName: string): SelectorHit[];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=selectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/lib/selectors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,aAAa;IAOZ,OAAO,CAAC,QAAQ,CAAC,SAAS;IANtC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,cAAc,CAAiB;gBAEV,SAAS,EAAE,SAAS;IAEjD,8EAA8E;IAC9E,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,aAAa;IA0CrB,oHAAoH;IACpH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAUrC,kDAAkD;IAClD,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,EAAE;CAcjD"}
|