@canister-software/consensus-cli 0.1.0-beta.1
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/.consensus-config.json +8 -0
- package/README.md +67 -0
- package/bin/consensus.js +371 -0
- package/canister-software-consensus-cli-0.1.0-beta.1.tgz +0 -0
- package/package.json +39 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"wallet_name": "d9c3e80732b0fa01",
|
|
3
|
+
"account_address": "0xaADf599FBF8328dBF4E92917Fc0b186148641225",
|
|
4
|
+
"api_key": "1926af832206a9eecb406a071335e2a0056e43808e07111702c99b644a41e15a",
|
|
5
|
+
"x402_proxy_url": "http://localhost:3001",
|
|
6
|
+
"setup_date": "2025-08-03T20:48:50.182Z",
|
|
7
|
+
"version": "1.0.0"
|
|
8
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="../assets/setup.gif" alt="Consensus Client Setup Demo" width="800">
|
|
4
|
+
</p>
|
|
5
|
+
<h1 align="center">Consensus Client</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
CLI tool for setting up and managing access credentials for the Consensus protocol.<br>
|
|
9
|
+
Creates a wallet, registers it, and generates your local configuration.<br>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="#"><img alt="Version" src="https://img.shields.io/badge/version-alpha-orange"></a>
|
|
14
|
+
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-BUSL--1.1-blue"></a>
|
|
15
|
+
<a href="https://github.com/Demali-876/consensus/stargazers">
|
|
16
|
+
<img alt="GitHub stars" src="https://img.shields.io/github/stars/Demali-876/consensus?style=social">
|
|
17
|
+
</a>
|
|
18
|
+
<a href="#"><img alt="Status" src="https://img.shields.io/badge/status-experimental-yellow"></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
## Setup Guide
|
|
22
|
+
|
|
23
|
+
Install the Consensus client library:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install consensus
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The Consensus proxy uses Coinbase Developer Platform (CDP) to create and manage wallets. You'll need to provide CDP credentials in your project's root directory.
|
|
30
|
+
|
|
31
|
+
## Environment Variables
|
|
32
|
+
|
|
33
|
+
Create a `.env` file in the root of your project with the following required variables:
|
|
34
|
+
|
|
35
|
+
| Variable | Description |
|
|
36
|
+
|----------|-------------|
|
|
37
|
+
| <kbd>CDP_API_KEY_ID</kbd> | Your CDP API key ID |
|
|
38
|
+
| <kbd>CDP_API_KEY_SECRET`</kbd> | Your CDP API key secret |
|
|
39
|
+
| <kbd>CDP_WALLET_SECRET</kbd> | Your CDP wallet secret |
|
|
40
|
+
|
|
41
|
+
Get your CDP credentials at: [https://portal.cdp.coinbase.com/](https://portal.cdp.coinbase.com/)
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
These are the commands avaialable in the Consesnsus CLI:
|
|
46
|
+
|
|
47
|
+
| Command | Description |
|
|
48
|
+
|--- |--- |
|
|
49
|
+
| <kbd>setup</kbd> | Create new account and register with `x402-proxy` |
|
|
50
|
+
| <kbd>setup --force</kbd> | Force create new account (reset existing) |
|
|
51
|
+
| <kbd>help</kbd> | Show help message |
|
|
52
|
+
|
|
53
|
+
## Setup Process
|
|
54
|
+
|
|
55
|
+
When you run the setup command, the Consensus client SDK will:
|
|
56
|
+
|
|
57
|
+
1. **Create a wallet** using your CDP credentials
|
|
58
|
+
2. **Generate a configuration file** (`.consensus-config.json`) containing your credentials
|
|
59
|
+
3. **Export wallet authorization** to the x402 proxy for payment delegation
|
|
60
|
+
|
|
61
|
+
> [!CAUTION]
|
|
62
|
+
> **DO NOT EXPOSE** the `.consensus-config.json` file as it contains sensitive information.
|
|
63
|
+
> The client automatically adds this file to `.gitignore` to prevent accidental commits.
|
|
64
|
+
|
|
65
|
+
> [!WARNING]
|
|
66
|
+
> **DO NOT keep large amounts** in the proxy-delegated wallet - if the proxy is compromised, your delegation could be at risk.
|
|
67
|
+
> Only fund the wallet with amounts you're comfortable delegating for API payments.
|
package/bin/consensus.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import { CdpClient } from "@coinbase/cdp-sdk";
|
|
5
|
+
import { toAccount } from "viem/accounts";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import crypto from "crypto";
|
|
8
|
+
import inquirer from "inquirer";
|
|
9
|
+
import figlet from "figlet";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
import { readFile } from "fs/promises";
|
|
13
|
+
import path from "path";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = path.dirname(__filename);
|
|
18
|
+
|
|
19
|
+
async function showBanner() {
|
|
20
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = path.dirname(__filename);
|
|
22
|
+
|
|
23
|
+
const pkg = await readFile(path.join(__dirname, "../package.json"), "utf8");
|
|
24
|
+
const version = JSON.parse(pkg).version;
|
|
25
|
+
|
|
26
|
+
const ascii = figlet.textSync("CONSENSUS\nClient", {
|
|
27
|
+
font: "ANSI Shadow",
|
|
28
|
+
horizontalLayout: "default",
|
|
29
|
+
verticalLayout: "default",
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(chalk.black(ascii));
|
|
33
|
+
console.log(chalk.dim(`v${version}\n`));
|
|
34
|
+
|
|
35
|
+
console.log(
|
|
36
|
+
chalk.gray(
|
|
37
|
+
"• Stable IPs • HTTP Deduplication • Built for Blockchains \nPowered by x402 Payments\n"
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const spinner = ora("Launching Consensus Client...").start();
|
|
42
|
+
|
|
43
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
44
|
+
spinner.succeed("Client CLI READY");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class ConsensusSDK {
|
|
48
|
+
constructor() {
|
|
49
|
+
this.configPath = path.join(process.cwd(), ".consensus-config.json");
|
|
50
|
+
this.x402ProxyUrl = process.env.X402_PROXY_URL || "https://consensus.proxy.canister.software:3001";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
generateWalletName() {
|
|
54
|
+
return crypto.randomBytes(8).toString("hex");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
loadConfig() {
|
|
58
|
+
try {
|
|
59
|
+
if (fs.existsSync(this.configPath)) {
|
|
60
|
+
return JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(chalk.red("Error reading config:"), error.message);
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
saveConfig(config) {
|
|
69
|
+
try {
|
|
70
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
|
|
71
|
+
console.log(chalk.green("✓ Configuration saved"));
|
|
72
|
+
|
|
73
|
+
const rootDir = path.resolve(__dirname, "../../");
|
|
74
|
+
const gitignorePath = path.join(rootDir, ".gitignore");
|
|
75
|
+
const ignoreEntry = path.basename(this.configPath);
|
|
76
|
+
|
|
77
|
+
let gitignoreContents = "";
|
|
78
|
+
if (fs.existsSync(gitignorePath)) {
|
|
79
|
+
gitignoreContents = fs.readFileSync(gitignorePath, "utf8");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!gitignoreContents.split("\n").includes(ignoreEntry)) {
|
|
83
|
+
fs.appendFileSync(
|
|
84
|
+
gitignorePath,
|
|
85
|
+
`\n# Ignore consensus config\n${ignoreEntry}\n`
|
|
86
|
+
);
|
|
87
|
+
console.log(chalk.yellow(`⚠️ .config hidden from git`));
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw new Error(`Failed to save config: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
validateEnvironment() {
|
|
95
|
+
const requiredVars = [
|
|
96
|
+
"CDP_API_KEY_ID",
|
|
97
|
+
"CDP_API_KEY_SECRET",
|
|
98
|
+
"CDP_WALLET_SECRET",
|
|
99
|
+
];
|
|
100
|
+
const missing = requiredVars.filter((varName) => !process.env[varName]);
|
|
101
|
+
|
|
102
|
+
if (missing.length > 0) {
|
|
103
|
+
console.error(chalk.red("Missing required environment variables:"));
|
|
104
|
+
missing.forEach((varName) => console.error(chalk.red(` ${varName}`)));
|
|
105
|
+
console.log(chalk.yellow("\nCreate a .env file with:"));
|
|
106
|
+
console.log("CDP_API_KEY_ID=your-api-key-id");
|
|
107
|
+
console.log("CDP_API_KEY_SECRET=your-api-key-secret");
|
|
108
|
+
console.log("CDP_WALLET_SECRET=your-wallet-secret");
|
|
109
|
+
console.log("X402_PROXY_URL=https://consensus.proxy.canister.software:3001 # (optional)");
|
|
110
|
+
console.log(
|
|
111
|
+
chalk.blue("\nGet CDP credentials: https://portal.cdp.coinbase.com/")
|
|
112
|
+
);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async checkExistingSetup(forceFlag) {
|
|
119
|
+
const config = this.loadConfig();
|
|
120
|
+
|
|
121
|
+
if (config) {
|
|
122
|
+
console.log(chalk.yellow("⚠️ Existing Consensus setup found!"));
|
|
123
|
+
console.log(chalk.cyan("Account Name:"), config.wallet_name);
|
|
124
|
+
console.log(chalk.cyan("Account Address:"), config.account_address);
|
|
125
|
+
console.log(chalk.cyan("Setup Date:"), config.setup_date);
|
|
126
|
+
|
|
127
|
+
if (!forceFlag) {
|
|
128
|
+
const { action } = await inquirer.prompt([
|
|
129
|
+
{
|
|
130
|
+
type: "list",
|
|
131
|
+
name: "action",
|
|
132
|
+
message: "What would you like to do?",
|
|
133
|
+
choices: [
|
|
134
|
+
{ name: "Keep existing setup", value: "keep" },
|
|
135
|
+
{ name: "Create new setup (reset)", value: "reset" },
|
|
136
|
+
{ name: "Exit", value: "exit" },
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
if (action === "keep") {
|
|
142
|
+
console.log(chalk.green("Using existing setup"));
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (action === "exit") {
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
if (action === "reset") {
|
|
149
|
+
return this.confirmReset();
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
return this.confirmReset();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async confirmReset() {
|
|
160
|
+
console.log(
|
|
161
|
+
chalk.red(
|
|
162
|
+
"\n⚠️ WARNING: This will reset your account and create a new wallet."
|
|
163
|
+
)
|
|
164
|
+
);
|
|
165
|
+
console.log(
|
|
166
|
+
chalk.red("⚠️ Make sure to backup any funds from your current wallet!")
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const { confirmed } = await inquirer.prompt([
|
|
170
|
+
{
|
|
171
|
+
type: "confirm",
|
|
172
|
+
name: "confirmed",
|
|
173
|
+
message: "Are you sure you want to continue?",
|
|
174
|
+
default: false,
|
|
175
|
+
},
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
if (!confirmed) {
|
|
179
|
+
console.log(chalk.yellow("Setup cancelled"));
|
|
180
|
+
process.exit(0);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async createWallet() {
|
|
187
|
+
const spinner = ora("Creating CDP wallet...").start();
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const cdp = new CdpClient();
|
|
191
|
+
const walletName = this.generateWalletName();
|
|
192
|
+
|
|
193
|
+
const cdpAccount = await cdp.evm.createAccount({ name: walletName });
|
|
194
|
+
const account = toAccount(cdpAccount);
|
|
195
|
+
|
|
196
|
+
spinner.succeed("CDP wallet created");
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
wallet_name: walletName,
|
|
200
|
+
account_address: account.address,
|
|
201
|
+
cdpAccount: cdpAccount,
|
|
202
|
+
};
|
|
203
|
+
} catch (error) {
|
|
204
|
+
spinner.fail("Failed to create CDP wallet");
|
|
205
|
+
throw new Error(`Wallet creation failed: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async registerWithProxy(walletName, accountAddress, cdpAccount) {
|
|
210
|
+
const spinner = ora("Registering with x402 proxy...").start();
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const cdp = new CdpClient();
|
|
214
|
+
const privateKeyData = await cdp.evm.exportAccount({ name: walletName });
|
|
215
|
+
|
|
216
|
+
let privateKey;
|
|
217
|
+
if (typeof privateKeyData === "string") {
|
|
218
|
+
privateKey = privateKeyData.startsWith("0x")
|
|
219
|
+
? privateKeyData
|
|
220
|
+
: `0x${privateKeyData}`;
|
|
221
|
+
} else if (privateKeyData && privateKeyData.privateKey) {
|
|
222
|
+
privateKey = privateKeyData.privateKey.startsWith("0x")
|
|
223
|
+
? privateKeyData.privateKey
|
|
224
|
+
: `0x${privateKeyData.privateKey}`;
|
|
225
|
+
} else {
|
|
226
|
+
throw new Error("Unexpected private key format from CDP");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const response = await fetch(`${this.x402ProxyUrl}/register-wallet`, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
headers: {
|
|
232
|
+
"Content-Type": "application/json",
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify({
|
|
235
|
+
wallet_name: walletName,
|
|
236
|
+
account_address: accountAddress,
|
|
237
|
+
private_key: privateKey,
|
|
238
|
+
}),
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
const error = await response
|
|
243
|
+
.json()
|
|
244
|
+
.catch(() => ({ error: "Unknown error" }));
|
|
245
|
+
throw new Error(
|
|
246
|
+
error.error || `Registration failed: ${response.status}`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const data = await response.json();
|
|
251
|
+
spinner.succeed("Registered with x402 proxy");
|
|
252
|
+
|
|
253
|
+
return data.api_key;
|
|
254
|
+
} catch (error) {
|
|
255
|
+
spinner.fail("Failed to register with x402 proxy");
|
|
256
|
+
if (error.message.includes("ECONNREFUSED")) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
"Cannot connect to x402 proxy. Is it running on " +
|
|
259
|
+
this.x402ProxyUrl +
|
|
260
|
+
"?"
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
throw new Error(`Proxy registration failed: ${error.message}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async setup() {
|
|
268
|
+
try {
|
|
269
|
+
console.log(chalk.blue.bold("Consensus SDK Setup\n"));
|
|
270
|
+
|
|
271
|
+
if (!this.validateEnvironment()) {
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const forceFlag = process.argv.includes("--force");
|
|
276
|
+
const shouldSkip = await this.checkExistingSetup(forceFlag);
|
|
277
|
+
|
|
278
|
+
if (shouldSkip) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const { wallet_name, account_address, cdpAccount } =
|
|
283
|
+
await this.createWallet();
|
|
284
|
+
const api_key = await this.registerWithProxy(
|
|
285
|
+
wallet_name,
|
|
286
|
+
account_address,
|
|
287
|
+
cdpAccount
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const config = {
|
|
291
|
+
wallet_name,
|
|
292
|
+
account_address,
|
|
293
|
+
api_key,
|
|
294
|
+
x402_proxy_url: this.x402ProxyUrl,
|
|
295
|
+
setup_date: new Date().toISOString(),
|
|
296
|
+
version: "1.0.0",
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
this.saveConfig(config);
|
|
300
|
+
|
|
301
|
+
console.log(chalk.green.bold("\n✅ Setup Complete!\n"));
|
|
302
|
+
console.log(chalk.cyan("Wallet Name:"), wallet_name);
|
|
303
|
+
console.log(chalk.cyan("Account Address:"), account_address);
|
|
304
|
+
console.log(chalk.cyan("API Key:"), api_key);
|
|
305
|
+
console.log(chalk.cyan("x402 Proxy:"), this.x402ProxyUrl);
|
|
306
|
+
|
|
307
|
+
console.log(chalk.yellow("\n📋 Next Steps:"));
|
|
308
|
+
console.log("1. Fund your account with USDC on Base Sepolia");
|
|
309
|
+
console.log(` Address: ${account_address}`);
|
|
310
|
+
console.log("2. Get USDC: https://faucet.circle.com/");
|
|
311
|
+
console.log("3. Make API calls using your API key");
|
|
312
|
+
|
|
313
|
+
console.log(chalk.blue("\n🔧 Usage Example:"));
|
|
314
|
+
console.log(`curl -X POST ${this.x402ProxyUrl}/proxy \\`);
|
|
315
|
+
console.log(` -H "X-API-Key: ${api_key}" \\`);
|
|
316
|
+
console.log(' -H "Content-Type: application/json" \\');
|
|
317
|
+
console.log(
|
|
318
|
+
` -d '{"target_url": "https://api.example.com", "idempotency_key": "unique-key"}'`
|
|
319
|
+
);
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error(chalk.red("\n❌ Setup failed:"), error.message);
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
showHelp() {
|
|
327
|
+
console.log(chalk.blue.bold("Consensus SDK\n"));
|
|
328
|
+
console.log("Commands:");
|
|
329
|
+
console.log(" setup Create new account and register with proxy");
|
|
330
|
+
console.log(" setup --force Force create new account (reset existing)");
|
|
331
|
+
console.log(" help Show this help message");
|
|
332
|
+
console.log("\nEnvironment variables required:");
|
|
333
|
+
console.log(" CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET");
|
|
334
|
+
console.log(
|
|
335
|
+
" X402_PROXY_URL (optional, defaults to https://consensus.proxy.canister.software:3001/)"
|
|
336
|
+
);
|
|
337
|
+
console.log(
|
|
338
|
+
"\nAfter setup, use the API key from .consensus-config.json for requests"
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function main() {
|
|
344
|
+
await showBanner();
|
|
345
|
+
const sdk = new ConsensusSDK();
|
|
346
|
+
const command = process.argv[2];
|
|
347
|
+
|
|
348
|
+
switch (command) {
|
|
349
|
+
case "setup":
|
|
350
|
+
await sdk.setup();
|
|
351
|
+
break;
|
|
352
|
+
case "help":
|
|
353
|
+
case "--help":
|
|
354
|
+
case "-h":
|
|
355
|
+
sdk.showHelp();
|
|
356
|
+
break;
|
|
357
|
+
default:
|
|
358
|
+
if (!command) {
|
|
359
|
+
sdk.showHelp();
|
|
360
|
+
} else {
|
|
361
|
+
console.error(chalk.red(`Unknown command: ${command}`));
|
|
362
|
+
sdk.showHelp();
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
main().catch((error) => {
|
|
369
|
+
console.error(chalk.red("Error:"), error.message);
|
|
370
|
+
process.exit(1);
|
|
371
|
+
});
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@canister-software/consensus-cli",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "Consensus SDK for interacting with the Consensus protocol",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"consensus": "./bin/consensus.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"consensus": "node bin/consensus.js",
|
|
11
|
+
"setup": "node bin/consensus.js setup",
|
|
12
|
+
"reset": "node bin/consensus.js setup --force"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@coinbase/cdp-sdk": "^1.25.0",
|
|
16
|
+
"chalk": "^5.4.1",
|
|
17
|
+
"chalk-animation": "^2.0.3",
|
|
18
|
+
"dotenv": "^16.4.5",
|
|
19
|
+
"figlet": "^1.8.2",
|
|
20
|
+
"gradient-string": "^3.0.0",
|
|
21
|
+
"inquirer": "^9.2.15",
|
|
22
|
+
"ora": "^8.2.0",
|
|
23
|
+
"viem": "^2.31.7"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"consensus",
|
|
27
|
+
"api",
|
|
28
|
+
"deduplication",
|
|
29
|
+
"x402",
|
|
30
|
+
"payments",
|
|
31
|
+
"HTTPS",
|
|
32
|
+
"cli"
|
|
33
|
+
],
|
|
34
|
+
"author": "Demali Gregg",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
}
|
|
39
|
+
}
|