@hypurrquant/defi-cli 0.2.2 → 0.2.4
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/dist/index.js +149 -1
- package/dist/index.js.map +1 -1
- package/dist/main.js +189 -29
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import { createRequire } from "module";
|
|
5
6
|
|
|
6
7
|
// src/executor.ts
|
|
7
8
|
import { createPublicClient as createPublicClient2, createWalletClient, http as http2 } from "viem";
|
|
@@ -8218,7 +8219,153 @@ function registerFarm(parent, getOpts, makeExecutor2) {
|
|
|
8218
8219
|
});
|
|
8219
8220
|
}
|
|
8220
8221
|
|
|
8222
|
+
// src/commands/setup.ts
|
|
8223
|
+
import pc2 from "picocolors";
|
|
8224
|
+
import { createInterface } from "readline";
|
|
8225
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
8226
|
+
import { resolve as resolve3 } from "path";
|
|
8227
|
+
var DEFI_DIR = resolve3(process.env.HOME || "~", ".defi");
|
|
8228
|
+
var ENV_FILE = resolve3(DEFI_DIR, ".env");
|
|
8229
|
+
function ensureDefiDir() {
|
|
8230
|
+
if (!existsSync3(DEFI_DIR)) mkdirSync2(DEFI_DIR, { recursive: true, mode: 448 });
|
|
8231
|
+
}
|
|
8232
|
+
function loadEnvFile() {
|
|
8233
|
+
if (!existsSync3(ENV_FILE)) return {};
|
|
8234
|
+
const lines = readFileSync3(ENV_FILE, "utf-8").split("\n");
|
|
8235
|
+
const env = {};
|
|
8236
|
+
for (const line of lines) {
|
|
8237
|
+
const trimmed = line.trim();
|
|
8238
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
8239
|
+
const eqIdx = trimmed.indexOf("=");
|
|
8240
|
+
if (eqIdx > 0) {
|
|
8241
|
+
env[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
|
|
8242
|
+
}
|
|
8243
|
+
}
|
|
8244
|
+
return env;
|
|
8245
|
+
}
|
|
8246
|
+
function writeEnvFile(env) {
|
|
8247
|
+
ensureDefiDir();
|
|
8248
|
+
const lines = [
|
|
8249
|
+
"# defi-cli configuration",
|
|
8250
|
+
"# Generated by 'defi setup' \u2014 edit freely",
|
|
8251
|
+
""
|
|
8252
|
+
];
|
|
8253
|
+
for (const [key, value] of Object.entries(env)) {
|
|
8254
|
+
lines.push(`${key}=${value}`);
|
|
8255
|
+
}
|
|
8256
|
+
lines.push("");
|
|
8257
|
+
writeFileSync2(ENV_FILE, lines.join("\n"), { mode: 384 });
|
|
8258
|
+
}
|
|
8259
|
+
function ask(rl, question) {
|
|
8260
|
+
return new Promise((res) => rl.question(question, (answer) => res(answer.trim())));
|
|
8261
|
+
}
|
|
8262
|
+
function isValidAddress(s) {
|
|
8263
|
+
return /^0x[0-9a-fA-F]{40}$/.test(s);
|
|
8264
|
+
}
|
|
8265
|
+
function isValidPrivateKey(s) {
|
|
8266
|
+
return /^0x[0-9a-fA-F]{64}$/.test(s);
|
|
8267
|
+
}
|
|
8268
|
+
async function deriveAddress(privateKey) {
|
|
8269
|
+
try {
|
|
8270
|
+
const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
|
|
8271
|
+
const account = privateKeyToAccount3(privateKey);
|
|
8272
|
+
return account.address;
|
|
8273
|
+
} catch {
|
|
8274
|
+
return null;
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
8277
|
+
function registerSetup(program2) {
|
|
8278
|
+
program2.command("setup").alias("init").description("Interactive setup wizard \u2014 configure wallet & RPC URLs").action(async () => {
|
|
8279
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
8280
|
+
try {
|
|
8281
|
+
console.log(pc2.cyan(pc2.bold("\n defi-cli Setup Wizard\n")));
|
|
8282
|
+
const existing = loadEnvFile();
|
|
8283
|
+
if (Object.keys(existing).length > 0) {
|
|
8284
|
+
console.log(pc2.white(" Current configuration:"));
|
|
8285
|
+
for (const [key, value] of Object.entries(existing)) {
|
|
8286
|
+
const masked = key.toLowerCase().includes("key") ? value.slice(0, 6) + "..." + value.slice(-4) : value;
|
|
8287
|
+
console.log(` ${pc2.cyan(key.padEnd(24))} ${pc2.gray(masked)}`);
|
|
8288
|
+
}
|
|
8289
|
+
console.log();
|
|
8290
|
+
const overwrite = await ask(rl, " Overwrite existing config? (y/N): ");
|
|
8291
|
+
if (overwrite.toLowerCase() !== "y" && overwrite.toLowerCase() !== "yes") {
|
|
8292
|
+
console.log(pc2.gray("\n Keeping existing configuration.\n"));
|
|
8293
|
+
rl.close();
|
|
8294
|
+
return;
|
|
8295
|
+
}
|
|
8296
|
+
console.log();
|
|
8297
|
+
}
|
|
8298
|
+
const newEnv = {};
|
|
8299
|
+
console.log(pc2.cyan(pc2.bold(" Wallet")));
|
|
8300
|
+
const privateKey = await ask(rl, " Private key (optional, for --broadcast, 0x...): ");
|
|
8301
|
+
if (privateKey) {
|
|
8302
|
+
const normalized = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
|
|
8303
|
+
if (!isValidPrivateKey(normalized)) {
|
|
8304
|
+
console.log(pc2.red(" Invalid private key (must be 0x + 64 hex chars). Skipped."));
|
|
8305
|
+
} else {
|
|
8306
|
+
newEnv.DEFI_PRIVATE_KEY = normalized;
|
|
8307
|
+
const derived = await deriveAddress(normalized);
|
|
8308
|
+
if (derived) {
|
|
8309
|
+
newEnv.DEFI_WALLET_ADDRESS = derived;
|
|
8310
|
+
console.log(` ${pc2.green("OK")} derived address: ${pc2.gray(derived)}`);
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
}
|
|
8314
|
+
if (!newEnv.DEFI_WALLET_ADDRESS) {
|
|
8315
|
+
const address = await ask(rl, " Wallet address (0x...): ");
|
|
8316
|
+
if (address) {
|
|
8317
|
+
if (!isValidAddress(address)) {
|
|
8318
|
+
console.log(pc2.yellow(" Invalid address format. Skipping."));
|
|
8319
|
+
} else {
|
|
8320
|
+
newEnv.DEFI_WALLET_ADDRESS = address;
|
|
8321
|
+
console.log(` ${pc2.green("OK")} ${pc2.gray(address)}`);
|
|
8322
|
+
}
|
|
8323
|
+
}
|
|
8324
|
+
}
|
|
8325
|
+
console.log(pc2.cyan(pc2.bold("\n RPC URLs")) + pc2.gray(" (press Enter to use public defaults)"));
|
|
8326
|
+
const hyperevmRpc = await ask(rl, " HyperEVM RPC URL: ");
|
|
8327
|
+
if (hyperevmRpc) {
|
|
8328
|
+
newEnv.HYPEREVM_RPC_URL = hyperevmRpc;
|
|
8329
|
+
console.log(` ${pc2.green("OK")} HyperEVM RPC set`);
|
|
8330
|
+
}
|
|
8331
|
+
const mantleRpc = await ask(rl, " Mantle RPC URL: ");
|
|
8332
|
+
if (mantleRpc) {
|
|
8333
|
+
newEnv.MANTLE_RPC_URL = mantleRpc;
|
|
8334
|
+
console.log(` ${pc2.green("OK")} Mantle RPC set`);
|
|
8335
|
+
}
|
|
8336
|
+
const finalEnv = { ...existing, ...newEnv };
|
|
8337
|
+
writeEnvFile(finalEnv);
|
|
8338
|
+
console.log(pc2.cyan(pc2.bold("\n Setup Complete!\n")));
|
|
8339
|
+
console.log(` Config: ${pc2.gray(ENV_FILE)}`);
|
|
8340
|
+
if (finalEnv.DEFI_WALLET_ADDRESS) {
|
|
8341
|
+
console.log(` Wallet: ${pc2.gray(finalEnv.DEFI_WALLET_ADDRESS)}`);
|
|
8342
|
+
}
|
|
8343
|
+
if (finalEnv.DEFI_PRIVATE_KEY) {
|
|
8344
|
+
console.log(` Key: ${pc2.green("configured")}`);
|
|
8345
|
+
}
|
|
8346
|
+
if (finalEnv.HYPEREVM_RPC_URL) {
|
|
8347
|
+
console.log(` HyperEVM RPC: ${pc2.gray(finalEnv.HYPEREVM_RPC_URL)}`);
|
|
8348
|
+
}
|
|
8349
|
+
if (finalEnv.MANTLE_RPC_URL) {
|
|
8350
|
+
console.log(` Mantle RPC: ${pc2.gray(finalEnv.MANTLE_RPC_URL)}`);
|
|
8351
|
+
}
|
|
8352
|
+
console.log(pc2.bold(pc2.white("\n Next steps:")));
|
|
8353
|
+
console.log(` ${pc2.green("defi portfolio")} view balances & positions`);
|
|
8354
|
+
console.log(` ${pc2.green("defi scan")} scan for exploits`);
|
|
8355
|
+
console.log(` ${pc2.green("defi dex quote")} get a swap quote`);
|
|
8356
|
+
console.log(` ${pc2.green("defi --help")} browse all commands
|
|
8357
|
+
`);
|
|
8358
|
+
rl.close();
|
|
8359
|
+
} catch (err) {
|
|
8360
|
+
rl.close();
|
|
8361
|
+
throw err;
|
|
8362
|
+
}
|
|
8363
|
+
});
|
|
8364
|
+
}
|
|
8365
|
+
|
|
8221
8366
|
// src/cli.ts
|
|
8367
|
+
var _require = createRequire(import.meta.url);
|
|
8368
|
+
var _pkg = _require("../package.json");
|
|
8222
8369
|
var BANNER = `
|
|
8223
8370
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557
|
|
8224
8371
|
\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
@@ -8232,7 +8379,7 @@ var BANNER = `
|
|
|
8232
8379
|
Scan exploits, swap tokens, bridge assets, track whales,
|
|
8233
8380
|
compare yields \u2014 all from your terminal.
|
|
8234
8381
|
`;
|
|
8235
|
-
var program = new Command().name("defi").description("DeFi CLI \u2014 Multi-chain DeFi toolkit").version(
|
|
8382
|
+
var program = new Command().name("defi").description("DeFi CLI \u2014 Multi-chain DeFi toolkit").version(_pkg.version).addHelpText("before", BANNER).option("--json", "Output as JSON").option("--ndjson", "Output as newline-delimited JSON").option("--fields <fields>", "Select specific output fields (comma-separated)").option("--chain <chain>", "Target chain", "hyperevm").option("--dry-run", "Dry-run mode (default, no broadcast)", true).option("--broadcast", "Actually broadcast the transaction");
|
|
8236
8383
|
function getOutputMode() {
|
|
8237
8384
|
const opts = program.opts();
|
|
8238
8385
|
return parseOutputMode(opts);
|
|
@@ -8267,6 +8414,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8267
8414
|
registerBridge(program, getOutputMode);
|
|
8268
8415
|
registerNft(program, getOutputMode);
|
|
8269
8416
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
8417
|
+
registerSetup(program);
|
|
8270
8418
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8271
8419
|
const executor = makeExecutor();
|
|
8272
8420
|
process.stderr.write("Agent mode: reading JSON commands from stdin...\n");
|