@rubanrubi/hardhat-dashboard 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/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +10 -0
- package/dist/plugin.js +123 -0
- package/dist/plugin.js.map +1 -0
- package/dist/server/artifacts.d.ts +10 -0
- package/dist/server/artifacts.js +191 -0
- package/dist/server/artifacts.js.map +1 -0
- package/dist/server/proxy.d.ts +15 -0
- package/dist/server/proxy.js +306 -0
- package/dist/server/proxy.js.map +1 -0
- package/dist/server/queue.d.ts +50 -0
- package/dist/server/queue.js +179 -0
- package/dist/server/queue.js.map +1 -0
- package/dist/types/config.d.ts +21 -0
- package/dist/types/config.js +14 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/rpc.d.ts +113 -0
- package/dist/types/rpc.js +10 -0
- package/dist/types/rpc.js.map +1 -0
- package/dist/ui/app.js +25008 -0
- package/dist/ui/app.js.map +7 -0
- package/dist/ui/index.html +13 -0
- package/dist/ui/styles.css +371 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
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/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# @rubanrubi/hardhat-dashboard
|
|
2
|
+
|
|
3
|
+
A Hardhat plugin that provides a **secure, browser-based dashboard** for reviewing and signing transactions during smart contract development. It eliminates the need to store private keys or mnemonics in `hardhat.config.ts` — all signing is delegated to MetaMask or a connected hardware wallet (Ledger/Trezor).
|
|
4
|
+
|
|
5
|
+
> **Think of it as Truffle Dashboard, but for Hardhat.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🔐 **No private keys on disk** — signing happens entirely in your browser wallet
|
|
12
|
+
- 🖥️ **Local dashboard UI** — review every transaction before it hits the chain
|
|
13
|
+
- ⚡ **Auto-decode transactions** — contract ABIs are synced after `hardhat compile` for human-readable call details
|
|
14
|
+
- 🔌 **Drop-in integration** — just add `--network dashboard` to any Hardhat command
|
|
15
|
+
- 📋 **Session history** — track confirmed, rejected, and failed transactions
|
|
16
|
+
- 🔒 **Localhost only** — the server binds to `127.0.0.1`; no network exposure
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install --save-dev @rubanrubi/hardhat-dashboard
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🚀 Quick Start
|
|
29
|
+
|
|
30
|
+
### 1. Register the plugin
|
|
31
|
+
|
|
32
|
+
Add the import to your `hardhat.config.ts`:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import "@rubanrubi/hardhat-dashboard";
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or in JavaScript (`hardhat.config.js`):
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
require("@rubanrubi/hardhat-dashboard");
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 2. Start the dashboard
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx hardhat dashboard
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This starts a local server at `http://localhost:24012` and opens it in your browser automatically. Connect your MetaMask wallet to the page.
|
|
51
|
+
|
|
52
|
+
### 3. Run any Hardhat command with `--network dashboard`
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Compile first (ABIs are synced to the dashboard for tx decoding)
|
|
56
|
+
npx hardhat compile
|
|
57
|
+
|
|
58
|
+
# Deploy via the dashboard
|
|
59
|
+
npx hardhat run scripts/deploy.ts --network dashboard
|
|
60
|
+
|
|
61
|
+
# Or run any script/task
|
|
62
|
+
npx hardhat run scripts/interact.ts --network dashboard
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Each transaction appears in the browser UI. Review the decoded contract call details and click **Confirm** to sign via MetaMask, or **Reject** to cancel.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ⚙️ Configuration
|
|
70
|
+
|
|
71
|
+
You can customize the plugin in your `hardhat.config.ts`:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { defineConfig } from "hardhat/config";
|
|
75
|
+
import "@rubanrubi/hardhat-dashboard";
|
|
76
|
+
|
|
77
|
+
export default defineConfig({
|
|
78
|
+
solidity: "0.8.24",
|
|
79
|
+
|
|
80
|
+
dashboardPlugin: {
|
|
81
|
+
port: 24012, // Port for the dashboard server (default: 24012)
|
|
82
|
+
networkName: "dashboard", // Name of the auto-registered network (default: "dashboard")
|
|
83
|
+
autoOpen: true, // Open browser automatically on start (default: true)
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### CLI Options
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Override port from the command line
|
|
92
|
+
npx hardhat dashboard --port 3000
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 🏗️ How It Works
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
┌───────────────────┐ JSON-RPC ┌─────────────────────┐
|
|
101
|
+
│ │ ──────────────────▶ │ │
|
|
102
|
+
│ Hardhat CLI │ │ Dashboard Server │
|
|
103
|
+
│ (your scripts) │ ◀────────────────── │ (localhost:24012) │
|
|
104
|
+
│ │ Response │ │
|
|
105
|
+
└───────────────────┘ └─────────┬───────────┘
|
|
106
|
+
│ WebSocket
|
|
107
|
+
▼
|
|
108
|
+
┌─────────────────────┐
|
|
109
|
+
│ │
|
|
110
|
+
│ Browser Dashboard │
|
|
111
|
+
│ (React UI) │
|
|
112
|
+
│ │
|
|
113
|
+
│ ┌───────────────┐ │
|
|
114
|
+
│ │ MetaMask / │ │
|
|
115
|
+
│ │ Ledger / │ │
|
|
116
|
+
│ │ Trezor │ │
|
|
117
|
+
│ └───────────────┘ │
|
|
118
|
+
└─────────────────────┘
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
1. **Hardhat** sends JSON-RPC requests to the local dashboard server
|
|
122
|
+
2. **Read-only calls** (`eth_call`, `eth_getBalance`, etc.) are forwarded automatically
|
|
123
|
+
3. **Signing requests** (`eth_sendTransaction`, `personal_sign`, etc.) are queued and displayed in the browser UI
|
|
124
|
+
4. **You** review the decoded transaction and click Confirm or Reject
|
|
125
|
+
5. **MetaMask** signs the transaction — the private key never leaves the wallet
|
|
126
|
+
6. The signed response is relayed back to Hardhat
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🔑 Security
|
|
131
|
+
|
|
132
|
+
- Private keys are **never** stored, logged, or transmitted by the plugin
|
|
133
|
+
- The dashboard server binds to `127.0.0.1` only — it is **not** accessible over the network
|
|
134
|
+
- The `/rpc` endpoint rejects requests not originating from localhost
|
|
135
|
+
- All signing is handled natively by MetaMask or your hardware wallet
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 📋 Requirements
|
|
140
|
+
|
|
141
|
+
| Requirement | Version |
|
|
142
|
+
|---|---|
|
|
143
|
+
| **Node.js** | ≥ 18.x |
|
|
144
|
+
| **Hardhat** | ≥ 2.22.0 |
|
|
145
|
+
| **Browser** | Chrome or Edge with MetaMask |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 🛠️ Development
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Clone the repository
|
|
153
|
+
git clone https://github.com/ruban/hardhat-dashboard.git
|
|
154
|
+
cd hardhat-dashboard
|
|
155
|
+
|
|
156
|
+
# Install dependencies
|
|
157
|
+
npm install
|
|
158
|
+
|
|
159
|
+
# Build the project
|
|
160
|
+
npm run build
|
|
161
|
+
|
|
162
|
+
# Run the dashboard UI locally (no Hardhat needed)
|
|
163
|
+
npm run dev
|
|
164
|
+
|
|
165
|
+
# Run tests
|
|
166
|
+
npm test
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 📄 License
|
|
172
|
+
|
|
173
|
+
MIT — see [LICENSE](./LICENSE) for details.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.default = void 0;
|
|
21
|
+
require("./plugin");
|
|
22
|
+
var plugin_1 = require("./plugin");
|
|
23
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(plugin_1).default; } });
|
|
24
|
+
__exportStar(require("./plugin"), exports);
|
|
25
|
+
__exportStar(require("./server/artifacts"), exports);
|
|
26
|
+
__exportStar(require("./server/proxy"), exports);
|
|
27
|
+
__exportStar(require("./server/queue"), exports);
|
|
28
|
+
__exportStar(require("./types/config"), exports);
|
|
29
|
+
__exportStar(require("./types/rpc"), exports);
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,oBAAkB;AAElB,mCAAmC;AAA1B,kHAAA,OAAO,OAAA;AAChB,2CAAyB;AACzB,qDAAmC;AACnC,iDAA+B;AAC/B,iDAA+B;AAC/B,iDAA+B;AAC/B,8CAA4B"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HardhatRuntimeEnvironment } from 'hardhat/types';
|
|
2
|
+
import { type DashboardServerHandle } from './server/proxy';
|
|
3
|
+
import { type ResolvedDashboardPluginConfig } from './types/config';
|
|
4
|
+
export declare function startDashboardServer(config: ResolvedDashboardPluginConfig): Promise<DashboardServerHandle>;
|
|
5
|
+
export declare function relayCompiledArtifacts(hre: HardhatRuntimeEnvironment, config?: ResolvedDashboardPluginConfig): Promise<void>;
|
|
6
|
+
declare const dashboardPlugin: {
|
|
7
|
+
startDashboardServer: typeof startDashboardServer;
|
|
8
|
+
relayCompiledArtifacts: typeof relayCompiledArtifacts;
|
|
9
|
+
};
|
|
10
|
+
export default dashboardPlugin;
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startDashboardServer = startDashboardServer;
|
|
7
|
+
exports.relayCompiledArtifacts = relayCompiledArtifacts;
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const config_1 = require("hardhat/config");
|
|
11
|
+
const task_names_1 = require("hardhat/builtin-tasks/task-names");
|
|
12
|
+
const open_1 = __importDefault(require("open"));
|
|
13
|
+
const artifacts_1 = require("./server/artifacts");
|
|
14
|
+
const proxy_1 = require("./server/proxy");
|
|
15
|
+
const config_2 = require("./types/config");
|
|
16
|
+
let activeServer;
|
|
17
|
+
function getDashboardOrigin(port) {
|
|
18
|
+
return `http://127.0.0.1:${port}`;
|
|
19
|
+
}
|
|
20
|
+
function getDashboardRpcUrl(port) {
|
|
21
|
+
return `${getDashboardOrigin(port)}/rpc`;
|
|
22
|
+
}
|
|
23
|
+
function applyDashboardNetwork(networks, config) {
|
|
24
|
+
const networkName = config.networkName || config_2.DEFAULT_DASHBOARD_NETWORK;
|
|
25
|
+
const existing = networks[networkName];
|
|
26
|
+
if (!existing) {
|
|
27
|
+
networks[networkName] = {
|
|
28
|
+
url: getDashboardRpcUrl(config.port),
|
|
29
|
+
timeout: 0,
|
|
30
|
+
};
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (existing.url === undefined) {
|
|
34
|
+
existing.url = getDashboardRpcUrl(config.port);
|
|
35
|
+
}
|
|
36
|
+
if (existing.timeout === undefined) {
|
|
37
|
+
existing.timeout = 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function resolveTaskConfig(baseConfig, overrides) {
|
|
41
|
+
return (0, config_2.resolveDashboardPluginConfig)({
|
|
42
|
+
port: overrides?.port ?? baseConfig.port,
|
|
43
|
+
networkName: overrides?.networkName ?? baseConfig.networkName,
|
|
44
|
+
autoOpen: overrides?.autoOpen ?? baseConfig.autoOpen,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function ensureServer(config) {
|
|
48
|
+
if (activeServer && activeServer.config.port === config.port) {
|
|
49
|
+
return activeServer.server;
|
|
50
|
+
}
|
|
51
|
+
if (activeServer) {
|
|
52
|
+
await activeServer.server.stop();
|
|
53
|
+
}
|
|
54
|
+
const server = (0, proxy_1.createDashboardServer)({
|
|
55
|
+
port: config.port,
|
|
56
|
+
host: '127.0.0.1',
|
|
57
|
+
uiDir: node_path_1.default.resolve(__dirname, 'ui'),
|
|
58
|
+
});
|
|
59
|
+
await server.start();
|
|
60
|
+
activeServer = { config, server };
|
|
61
|
+
return server;
|
|
62
|
+
}
|
|
63
|
+
async function waitForShutdown(server) {
|
|
64
|
+
await new Promise((resolve) => {
|
|
65
|
+
let closing = false;
|
|
66
|
+
const shutdown = () => {
|
|
67
|
+
if (closing) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
closing = true;
|
|
71
|
+
process.off('SIGINT', shutdown);
|
|
72
|
+
process.off('SIGTERM', shutdown);
|
|
73
|
+
void server.stop().finally(resolve);
|
|
74
|
+
};
|
|
75
|
+
process.on('SIGINT', shutdown);
|
|
76
|
+
process.on('SIGTERM', shutdown);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function relayArtifactsFromHre(hre, config) {
|
|
80
|
+
const artifacts = await (0, artifacts_1.collectArtifactsFromDirectory)(hre.config.paths.artifacts);
|
|
81
|
+
await (0, artifacts_1.postArtifactsToDashboard)(getDashboardOrigin(config.port), artifacts);
|
|
82
|
+
}
|
|
83
|
+
(0, config_1.extendConfig)((config, userConfig) => {
|
|
84
|
+
const resolved = (0, config_2.resolveDashboardPluginConfig)(userConfig.dashboardPlugin);
|
|
85
|
+
config.dashboardPlugin = resolved;
|
|
86
|
+
applyDashboardNetwork(config.networks, resolved);
|
|
87
|
+
});
|
|
88
|
+
(0, config_1.task)('dashboard', 'Start the local browser dashboard for transaction approval')
|
|
89
|
+
.addOptionalParam('port', 'Override the dashboard port', undefined, config_1.types.int)
|
|
90
|
+
.setAction(async ({ port }, hre) => {
|
|
91
|
+
const config = resolveTaskConfig(hre.config.dashboardPlugin, { port });
|
|
92
|
+
const server = await ensureServer(config);
|
|
93
|
+
// eslint-disable-next-line no-console
|
|
94
|
+
console.log(chalk_1.default.green(`Dashboard network: ${chalk_1.default.bold(config.networkName)}`));
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
console.log(chalk_1.default.green(`RPC endpoint: ${chalk_1.default.bold(server.getRpcUrl())}`));
|
|
97
|
+
// eslint-disable-next-line no-console
|
|
98
|
+
console.log(chalk_1.default.green(`Open this page in MetaMask-enabled Chrome/Edge: ${chalk_1.default.bold(server.getOrigin())}`));
|
|
99
|
+
if (config.autoOpen) {
|
|
100
|
+
await (0, open_1.default)(server.getOrigin());
|
|
101
|
+
}
|
|
102
|
+
await waitForShutdown(server);
|
|
103
|
+
activeServer = undefined;
|
|
104
|
+
});
|
|
105
|
+
(0, config_1.subtask)(task_names_1.TASK_COMPILE).setAction(async (taskArgs, hre, runSuper) => {
|
|
106
|
+
const result = await runSuper(taskArgs);
|
|
107
|
+
void relayArtifactsFromHre(hre, hre.config.dashboardPlugin).catch(() => {
|
|
108
|
+
// The artifact relay is best-effort; compilation should still succeed when the dashboard isn't running.
|
|
109
|
+
});
|
|
110
|
+
return result;
|
|
111
|
+
});
|
|
112
|
+
async function startDashboardServer(config) {
|
|
113
|
+
return ensureServer(config);
|
|
114
|
+
}
|
|
115
|
+
async function relayCompiledArtifacts(hre, config = hre.config.dashboardPlugin) {
|
|
116
|
+
await relayArtifactsFromHre(hre, config);
|
|
117
|
+
}
|
|
118
|
+
const dashboardPlugin = {
|
|
119
|
+
startDashboardServer,
|
|
120
|
+
relayCompiledArtifacts,
|
|
121
|
+
};
|
|
122
|
+
exports.default = dashboardPlugin;
|
|
123
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ArtifactPayload, DecodedContractCall, JsonRpcRequest, PendingRpcRequest } from '../types/rpc';
|
|
2
|
+
export declare class ArtifactRegistry {
|
|
3
|
+
private readonly selectors;
|
|
4
|
+
upsertArtifacts(artifacts: ArtifactPayload[]): void;
|
|
5
|
+
decodeRequest(request: JsonRpcRequest | PendingRpcRequest): DecodedContractCall | undefined;
|
|
6
|
+
decodeCalldata(calldata: string): DecodedContractCall;
|
|
7
|
+
private getSelector;
|
|
8
|
+
}
|
|
9
|
+
export declare function collectArtifactsFromDirectory(directory: string): Promise<ArtifactPayload[]>;
|
|
10
|
+
export declare function postArtifactsToDashboard(serverOrigin: string, artifacts: ArtifactPayload[], timeoutMs?: number): Promise<boolean>;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ArtifactRegistry = void 0;
|
|
7
|
+
exports.collectArtifactsFromDirectory = collectArtifactsFromDirectory;
|
|
8
|
+
exports.postArtifactsToDashboard = postArtifactsToDashboard;
|
|
9
|
+
const promises_1 = require("node:fs/promises");
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const ethers_1 = require("ethers");
|
|
12
|
+
function formatDecodedValue(value) {
|
|
13
|
+
if (typeof value === 'bigint') {
|
|
14
|
+
return value.toString();
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === 'string') {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === 'number' || typeof value === 'boolean' || value === null || value === undefined) {
|
|
20
|
+
return String(value);
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
return `[${value.map((entry) => formatDecodedValue(entry)).join(', ')}]`;
|
|
24
|
+
}
|
|
25
|
+
if (typeof value === 'object') {
|
|
26
|
+
const objectValue = value;
|
|
27
|
+
return JSON.stringify(Object.fromEntries(Object.entries(objectValue).map(([key, nestedValue]) => [key, formatDecodedValue(nestedValue)])));
|
|
28
|
+
}
|
|
29
|
+
return String(value);
|
|
30
|
+
}
|
|
31
|
+
function getTransactionObject(params) {
|
|
32
|
+
if (Array.isArray(params) && params.length > 0) {
|
|
33
|
+
const [first] = params;
|
|
34
|
+
if (first && typeof first === 'object') {
|
|
35
|
+
return first;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (params && typeof params === 'object' && !Array.isArray(params)) {
|
|
39
|
+
return params;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
class ArtifactRegistry {
|
|
44
|
+
selectors = new Map();
|
|
45
|
+
upsertArtifacts(artifacts) {
|
|
46
|
+
for (const artifact of artifacts) {
|
|
47
|
+
if (!artifact.abi.length) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const iface = new ethers_1.Interface(artifact.abi);
|
|
51
|
+
for (const fragment of iface.fragments) {
|
|
52
|
+
if (fragment.type !== 'function') {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const functionFragment = fragment;
|
|
56
|
+
const selector = this.getSelector(iface, functionFragment);
|
|
57
|
+
const existing = this.selectors.get(selector) ?? [];
|
|
58
|
+
existing.push({ artifact, iface, fragment: functionFragment });
|
|
59
|
+
this.selectors.set(selector, existing);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
decodeRequest(request) {
|
|
64
|
+
if (request.method !== 'eth_sendTransaction') {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const transaction = getTransactionObject(request.params);
|
|
68
|
+
const calldata = transaction?.data;
|
|
69
|
+
if (typeof calldata !== 'string') {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return this.decodeCalldata(calldata);
|
|
73
|
+
}
|
|
74
|
+
decodeCalldata(calldata) {
|
|
75
|
+
if (!calldata.startsWith('0x') || calldata.length < 10) {
|
|
76
|
+
return {
|
|
77
|
+
matched: false,
|
|
78
|
+
args: [],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const selector = calldata.slice(0, 10).toLowerCase();
|
|
82
|
+
const entries = this.selectors.get(selector);
|
|
83
|
+
if (!entries?.length) {
|
|
84
|
+
return {
|
|
85
|
+
matched: false,
|
|
86
|
+
selector,
|
|
87
|
+
args: [],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
try {
|
|
92
|
+
const decoded = entry.iface.decodeFunctionData(entry.fragment, calldata);
|
|
93
|
+
return {
|
|
94
|
+
matched: true,
|
|
95
|
+
selector,
|
|
96
|
+
contractName: entry.artifact.contractName,
|
|
97
|
+
functionName: entry.fragment.name,
|
|
98
|
+
signature: entry.fragment.format(),
|
|
99
|
+
args: Array.from(decoded).map((value) => formatDecodedValue(value)),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
matched: false,
|
|
108
|
+
selector,
|
|
109
|
+
args: [],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
getSelector(iface, fragment) {
|
|
113
|
+
const fragmentWithSelector = fragment;
|
|
114
|
+
if (typeof fragmentWithSelector.selector === 'string') {
|
|
115
|
+
return fragmentWithSelector.selector.toLowerCase();
|
|
116
|
+
}
|
|
117
|
+
const ifaceWithSighash = iface;
|
|
118
|
+
if (typeof ifaceWithSighash.getSighash === 'function') {
|
|
119
|
+
return ifaceWithSighash.getSighash(fragment).toLowerCase();
|
|
120
|
+
}
|
|
121
|
+
const resolved = iface.getFunction(fragment.format());
|
|
122
|
+
if (!resolved) {
|
|
123
|
+
throw new Error(`Unable to resolve function fragment for ${fragment.format()}.`);
|
|
124
|
+
}
|
|
125
|
+
const resolvedWithSelector = resolved;
|
|
126
|
+
if (typeof resolvedWithSelector.selector !== 'string') {
|
|
127
|
+
throw new Error(`Unable to derive selector for ${fragment.format()}.`);
|
|
128
|
+
}
|
|
129
|
+
return resolvedWithSelector.selector.toLowerCase();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.ArtifactRegistry = ArtifactRegistry;
|
|
133
|
+
async function collectJsonFiles(directory) {
|
|
134
|
+
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
135
|
+
const files = [];
|
|
136
|
+
for (const entry of entries) {
|
|
137
|
+
const fullPath = node_path_1.default.join(directory, entry.name);
|
|
138
|
+
if (entry.isDirectory()) {
|
|
139
|
+
files.push(...(await collectJsonFiles(fullPath)));
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (entry.isFile() && entry.name.endsWith('.json') && !entry.name.endsWith('.dbg.json')) {
|
|
143
|
+
files.push(fullPath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return files;
|
|
147
|
+
}
|
|
148
|
+
async function collectArtifactsFromDirectory(directory) {
|
|
149
|
+
const files = await collectJsonFiles(directory);
|
|
150
|
+
const artifacts = [];
|
|
151
|
+
for (const file of files) {
|
|
152
|
+
const contents = await (0, promises_1.readFile)(file, 'utf8');
|
|
153
|
+
const parsed = JSON.parse(contents);
|
|
154
|
+
if (!parsed.contractName || !Array.isArray(parsed.abi)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
artifacts.push({
|
|
158
|
+
contractName: parsed.contractName,
|
|
159
|
+
sourceName: parsed.sourceName,
|
|
160
|
+
abi: parsed.abi,
|
|
161
|
+
bytecode: parsed.bytecode,
|
|
162
|
+
deployedBytecode: parsed.deployedBytecode,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return artifacts;
|
|
166
|
+
}
|
|
167
|
+
async function postArtifactsToDashboard(serverOrigin, artifacts, timeoutMs = 1_500) {
|
|
168
|
+
if (!artifacts.length) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
const controller = new AbortController();
|
|
172
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
173
|
+
try {
|
|
174
|
+
const response = await fetch(`${serverOrigin.replace(/\/$/, '')}/artifacts`, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: {
|
|
177
|
+
'content-type': 'application/json',
|
|
178
|
+
},
|
|
179
|
+
body: JSON.stringify({ artifacts }),
|
|
180
|
+
signal: controller.signal,
|
|
181
|
+
});
|
|
182
|
+
return response.ok;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
clearTimeout(timeout);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/server/artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ArtifactPayload } from '../types/rpc';
|
|
2
|
+
export interface DashboardServerOptions {
|
|
3
|
+
port: number;
|
|
4
|
+
host?: string;
|
|
5
|
+
uiDir?: string;
|
|
6
|
+
requestTimeoutMs?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface DashboardServerHandle {
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
stop(): Promise<void>;
|
|
11
|
+
getOrigin(): string;
|
|
12
|
+
getRpcUrl(): string;
|
|
13
|
+
pushArtifacts(artifacts: ArtifactPayload[]): void;
|
|
14
|
+
}
|
|
15
|
+
export declare function createDashboardServer(options: DashboardServerOptions): DashboardServerHandle;
|