@hypurrquant/defi-cli 0.2.3 → 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 +145 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +179 -26
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/main.ts
|
|
4
|
+
import { config } from "dotenv";
|
|
5
|
+
import { resolve as resolve4 } from "path";
|
|
6
|
+
|
|
3
7
|
// src/cli.ts
|
|
4
8
|
import { Command } from "commander";
|
|
5
9
|
import { createRequire } from "module";
|
|
@@ -8223,6 +8227,150 @@ function registerFarm(parent, getOpts, makeExecutor2) {
|
|
|
8223
8227
|
});
|
|
8224
8228
|
}
|
|
8225
8229
|
|
|
8230
|
+
// src/commands/setup.ts
|
|
8231
|
+
import pc2 from "picocolors";
|
|
8232
|
+
import { createInterface } from "readline";
|
|
8233
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
8234
|
+
import { resolve as resolve3 } from "path";
|
|
8235
|
+
var DEFI_DIR = resolve3(process.env.HOME || "~", ".defi");
|
|
8236
|
+
var ENV_FILE = resolve3(DEFI_DIR, ".env");
|
|
8237
|
+
function ensureDefiDir() {
|
|
8238
|
+
if (!existsSync3(DEFI_DIR)) mkdirSync2(DEFI_DIR, { recursive: true, mode: 448 });
|
|
8239
|
+
}
|
|
8240
|
+
function loadEnvFile() {
|
|
8241
|
+
if (!existsSync3(ENV_FILE)) return {};
|
|
8242
|
+
const lines = readFileSync3(ENV_FILE, "utf-8").split("\n");
|
|
8243
|
+
const env = {};
|
|
8244
|
+
for (const line of lines) {
|
|
8245
|
+
const trimmed = line.trim();
|
|
8246
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
8247
|
+
const eqIdx = trimmed.indexOf("=");
|
|
8248
|
+
if (eqIdx > 0) {
|
|
8249
|
+
env[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
|
|
8250
|
+
}
|
|
8251
|
+
}
|
|
8252
|
+
return env;
|
|
8253
|
+
}
|
|
8254
|
+
function writeEnvFile(env) {
|
|
8255
|
+
ensureDefiDir();
|
|
8256
|
+
const lines = [
|
|
8257
|
+
"# defi-cli configuration",
|
|
8258
|
+
"# Generated by 'defi setup' \u2014 edit freely",
|
|
8259
|
+
""
|
|
8260
|
+
];
|
|
8261
|
+
for (const [key, value] of Object.entries(env)) {
|
|
8262
|
+
lines.push(`${key}=${value}`);
|
|
8263
|
+
}
|
|
8264
|
+
lines.push("");
|
|
8265
|
+
writeFileSync2(ENV_FILE, lines.join("\n"), { mode: 384 });
|
|
8266
|
+
}
|
|
8267
|
+
function ask(rl, question) {
|
|
8268
|
+
return new Promise((res) => rl.question(question, (answer) => res(answer.trim())));
|
|
8269
|
+
}
|
|
8270
|
+
function isValidAddress(s) {
|
|
8271
|
+
return /^0x[0-9a-fA-F]{40}$/.test(s);
|
|
8272
|
+
}
|
|
8273
|
+
function isValidPrivateKey(s) {
|
|
8274
|
+
return /^0x[0-9a-fA-F]{64}$/.test(s);
|
|
8275
|
+
}
|
|
8276
|
+
async function deriveAddress(privateKey) {
|
|
8277
|
+
try {
|
|
8278
|
+
const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
|
|
8279
|
+
const account = privateKeyToAccount3(privateKey);
|
|
8280
|
+
return account.address;
|
|
8281
|
+
} catch {
|
|
8282
|
+
return null;
|
|
8283
|
+
}
|
|
8284
|
+
}
|
|
8285
|
+
function registerSetup(program2) {
|
|
8286
|
+
program2.command("setup").alias("init").description("Interactive setup wizard \u2014 configure wallet & RPC URLs").action(async () => {
|
|
8287
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
8288
|
+
try {
|
|
8289
|
+
console.log(pc2.cyan(pc2.bold("\n defi-cli Setup Wizard\n")));
|
|
8290
|
+
const existing = loadEnvFile();
|
|
8291
|
+
if (Object.keys(existing).length > 0) {
|
|
8292
|
+
console.log(pc2.white(" Current configuration:"));
|
|
8293
|
+
for (const [key, value] of Object.entries(existing)) {
|
|
8294
|
+
const masked = key.toLowerCase().includes("key") ? value.slice(0, 6) + "..." + value.slice(-4) : value;
|
|
8295
|
+
console.log(` ${pc2.cyan(key.padEnd(24))} ${pc2.gray(masked)}`);
|
|
8296
|
+
}
|
|
8297
|
+
console.log();
|
|
8298
|
+
const overwrite = await ask(rl, " Overwrite existing config? (y/N): ");
|
|
8299
|
+
if (overwrite.toLowerCase() !== "y" && overwrite.toLowerCase() !== "yes") {
|
|
8300
|
+
console.log(pc2.gray("\n Keeping existing configuration.\n"));
|
|
8301
|
+
rl.close();
|
|
8302
|
+
return;
|
|
8303
|
+
}
|
|
8304
|
+
console.log();
|
|
8305
|
+
}
|
|
8306
|
+
const newEnv = {};
|
|
8307
|
+
console.log(pc2.cyan(pc2.bold(" Wallet")));
|
|
8308
|
+
const privateKey = await ask(rl, " Private key (optional, for --broadcast, 0x...): ");
|
|
8309
|
+
if (privateKey) {
|
|
8310
|
+
const normalized = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
|
|
8311
|
+
if (!isValidPrivateKey(normalized)) {
|
|
8312
|
+
console.log(pc2.red(" Invalid private key (must be 0x + 64 hex chars). Skipped."));
|
|
8313
|
+
} else {
|
|
8314
|
+
newEnv.DEFI_PRIVATE_KEY = normalized;
|
|
8315
|
+
const derived = await deriveAddress(normalized);
|
|
8316
|
+
if (derived) {
|
|
8317
|
+
newEnv.DEFI_WALLET_ADDRESS = derived;
|
|
8318
|
+
console.log(` ${pc2.green("OK")} derived address: ${pc2.gray(derived)}`);
|
|
8319
|
+
}
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
if (!newEnv.DEFI_WALLET_ADDRESS) {
|
|
8323
|
+
const address = await ask(rl, " Wallet address (0x...): ");
|
|
8324
|
+
if (address) {
|
|
8325
|
+
if (!isValidAddress(address)) {
|
|
8326
|
+
console.log(pc2.yellow(" Invalid address format. Skipping."));
|
|
8327
|
+
} else {
|
|
8328
|
+
newEnv.DEFI_WALLET_ADDRESS = address;
|
|
8329
|
+
console.log(` ${pc2.green("OK")} ${pc2.gray(address)}`);
|
|
8330
|
+
}
|
|
8331
|
+
}
|
|
8332
|
+
}
|
|
8333
|
+
console.log(pc2.cyan(pc2.bold("\n RPC URLs")) + pc2.gray(" (press Enter to use public defaults)"));
|
|
8334
|
+
const hyperevmRpc = await ask(rl, " HyperEVM RPC URL: ");
|
|
8335
|
+
if (hyperevmRpc) {
|
|
8336
|
+
newEnv.HYPEREVM_RPC_URL = hyperevmRpc;
|
|
8337
|
+
console.log(` ${pc2.green("OK")} HyperEVM RPC set`);
|
|
8338
|
+
}
|
|
8339
|
+
const mantleRpc = await ask(rl, " Mantle RPC URL: ");
|
|
8340
|
+
if (mantleRpc) {
|
|
8341
|
+
newEnv.MANTLE_RPC_URL = mantleRpc;
|
|
8342
|
+
console.log(` ${pc2.green("OK")} Mantle RPC set`);
|
|
8343
|
+
}
|
|
8344
|
+
const finalEnv = { ...existing, ...newEnv };
|
|
8345
|
+
writeEnvFile(finalEnv);
|
|
8346
|
+
console.log(pc2.cyan(pc2.bold("\n Setup Complete!\n")));
|
|
8347
|
+
console.log(` Config: ${pc2.gray(ENV_FILE)}`);
|
|
8348
|
+
if (finalEnv.DEFI_WALLET_ADDRESS) {
|
|
8349
|
+
console.log(` Wallet: ${pc2.gray(finalEnv.DEFI_WALLET_ADDRESS)}`);
|
|
8350
|
+
}
|
|
8351
|
+
if (finalEnv.DEFI_PRIVATE_KEY) {
|
|
8352
|
+
console.log(` Key: ${pc2.green("configured")}`);
|
|
8353
|
+
}
|
|
8354
|
+
if (finalEnv.HYPEREVM_RPC_URL) {
|
|
8355
|
+
console.log(` HyperEVM RPC: ${pc2.gray(finalEnv.HYPEREVM_RPC_URL)}`);
|
|
8356
|
+
}
|
|
8357
|
+
if (finalEnv.MANTLE_RPC_URL) {
|
|
8358
|
+
console.log(` Mantle RPC: ${pc2.gray(finalEnv.MANTLE_RPC_URL)}`);
|
|
8359
|
+
}
|
|
8360
|
+
console.log(pc2.bold(pc2.white("\n Next steps:")));
|
|
8361
|
+
console.log(` ${pc2.green("defi portfolio")} view balances & positions`);
|
|
8362
|
+
console.log(` ${pc2.green("defi scan")} scan for exploits`);
|
|
8363
|
+
console.log(` ${pc2.green("defi dex quote")} get a swap quote`);
|
|
8364
|
+
console.log(` ${pc2.green("defi --help")} browse all commands
|
|
8365
|
+
`);
|
|
8366
|
+
rl.close();
|
|
8367
|
+
} catch (err) {
|
|
8368
|
+
rl.close();
|
|
8369
|
+
throw err;
|
|
8370
|
+
}
|
|
8371
|
+
});
|
|
8372
|
+
}
|
|
8373
|
+
|
|
8226
8374
|
// src/cli.ts
|
|
8227
8375
|
var _require = createRequire(import.meta.url);
|
|
8228
8376
|
var _pkg = _require("../package.json");
|
|
@@ -8274,6 +8422,7 @@ registerSwap(program, getOutputMode, makeExecutor);
|
|
|
8274
8422
|
registerBridge(program, getOutputMode);
|
|
8275
8423
|
registerNft(program, getOutputMode);
|
|
8276
8424
|
registerFarm(program, getOutputMode, makeExecutor);
|
|
8425
|
+
registerSetup(program);
|
|
8277
8426
|
program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
|
|
8278
8427
|
const executor = makeExecutor();
|
|
8279
8428
|
process.stderr.write("Agent mode: reading JSON commands from stdin...\n");
|
|
@@ -8282,7 +8431,7 @@ program.command("agent").description("Agent mode: read JSON commands from stdin
|
|
|
8282
8431
|
});
|
|
8283
8432
|
|
|
8284
8433
|
// src/landing.ts
|
|
8285
|
-
import
|
|
8434
|
+
import pc3 from "picocolors";
|
|
8286
8435
|
import { encodeFunctionData as encodeFunctionData28, parseAbi as parseAbi31, formatUnits } from "viem";
|
|
8287
8436
|
var HYPEREVM_DISPLAY = ["HYPE", "WHYPE", "USDC", "USDT0", "USDe", "kHYPE", "wstHYPE"];
|
|
8288
8437
|
var MANTLE_DISPLAY = ["MNT", "WMNT", "USDC", "USDT", "WETH", "mETH"];
|
|
@@ -8376,20 +8525,20 @@ async function showLandingPage(isJson) {
|
|
|
8376
8525
|
const version = pkg.version;
|
|
8377
8526
|
if (!wallet) {
|
|
8378
8527
|
console.log("");
|
|
8379
|
-
console.log(
|
|
8528
|
+
console.log(pc3.bold(pc3.cyan(" DeFi CLI v" + version)));
|
|
8380
8529
|
console.log("");
|
|
8381
|
-
console.log(
|
|
8530
|
+
console.log(pc3.yellow(" Wallet not configured."));
|
|
8382
8531
|
console.log(" Set DEFI_WALLET_ADDRESS to see your balances:");
|
|
8383
8532
|
console.log("");
|
|
8384
|
-
console.log(
|
|
8533
|
+
console.log(pc3.dim(" export DEFI_WALLET_ADDRESS=0x..."));
|
|
8385
8534
|
console.log("");
|
|
8386
8535
|
console.log(" Commands:");
|
|
8387
|
-
console.log(
|
|
8388
|
-
console.log(
|
|
8389
|
-
console.log(
|
|
8390
|
-
console.log(
|
|
8391
|
-
console.log(
|
|
8392
|
-
console.log(
|
|
8536
|
+
console.log(pc3.dim(" defi status Protocol overview"));
|
|
8537
|
+
console.log(pc3.dim(" defi lending rates Compare lending APYs"));
|
|
8538
|
+
console.log(pc3.dim(" defi dex quote Get swap quotes"));
|
|
8539
|
+
console.log(pc3.dim(" defi portfolio View all positions"));
|
|
8540
|
+
console.log(pc3.dim(" defi scan Exploit detection"));
|
|
8541
|
+
console.log(pc3.dim(" defi --help Full command list"));
|
|
8393
8542
|
console.log("");
|
|
8394
8543
|
return;
|
|
8395
8544
|
}
|
|
@@ -8411,20 +8560,20 @@ async function showLandingPage(isJson) {
|
|
|
8411
8560
|
const divider = "\u2500".repeat(colWidth - 2);
|
|
8412
8561
|
console.log("");
|
|
8413
8562
|
console.log(
|
|
8414
|
-
|
|
8563
|
+
pc3.bold(pc3.cyan(" DeFi CLI v" + version)) + pc3.dim(" \u2014 ") + pc3.bold(heChain.name) + pc3.dim(" \xB7 ") + pc3.bold(mantleChain.name)
|
|
8415
8564
|
);
|
|
8416
8565
|
console.log("");
|
|
8417
|
-
console.log(" Wallet: " +
|
|
8566
|
+
console.log(" Wallet: " + pc3.yellow(shortenAddress(wallet)));
|
|
8418
8567
|
console.log("");
|
|
8419
8568
|
const heHeader = padRight(
|
|
8420
|
-
" " +
|
|
8569
|
+
" " + pc3.bold(heChain.name),
|
|
8421
8570
|
colWidth + 10
|
|
8422
8571
|
/* account for ANSI */
|
|
8423
8572
|
);
|
|
8424
|
-
const mantleHeader =
|
|
8573
|
+
const mantleHeader = pc3.bold(mantleChain.name);
|
|
8425
8574
|
console.log(heHeader + " " + mantleHeader);
|
|
8426
|
-
const heDivider = padRight(" " +
|
|
8427
|
-
const mantleDivider =
|
|
8575
|
+
const heDivider = padRight(" " + pc3.dim(divider), colWidth + 10);
|
|
8576
|
+
const mantleDivider = pc3.dim(divider);
|
|
8428
8577
|
console.log(heDivider + " " + mantleDivider);
|
|
8429
8578
|
const maxRows = Math.max(heBalances.length, mantleBalances.length);
|
|
8430
8579
|
for (let i = 0; i < maxRows; i++) {
|
|
@@ -8432,25 +8581,27 @@ async function showLandingPage(isJson) {
|
|
|
8432
8581
|
const mantleEntry = mantleBalances[i];
|
|
8433
8582
|
const heText = heEntry ? formatBalanceLine(heEntry.symbol, heEntry.balance) : "";
|
|
8434
8583
|
const mantleText = mantleEntry ? formatBalanceLine(mantleEntry.symbol, mantleEntry.balance) : "";
|
|
8435
|
-
const heColored = heEntry ? heEntry.balance === "0.00" || heEntry.balance === "?" ?
|
|
8436
|
-
const mantleColored = mantleEntry ? mantleEntry.balance === "0.00" || mantleEntry.balance === "?" ?
|
|
8584
|
+
const heColored = heEntry ? heEntry.balance === "0.00" || heEntry.balance === "?" ? pc3.dim(heText) : heText : "";
|
|
8585
|
+
const mantleColored = mantleEntry ? mantleEntry.balance === "0.00" || mantleEntry.balance === "?" ? pc3.dim(mantleText) : mantleText : "";
|
|
8437
8586
|
const visibleLen = heText.length;
|
|
8438
8587
|
const padNeeded = colWidth - visibleLen;
|
|
8439
8588
|
const paddedHe = heColored + (padNeeded > 0 ? " ".repeat(padNeeded) : "");
|
|
8440
8589
|
console.log(paddedHe + " " + mantleColored);
|
|
8441
8590
|
}
|
|
8442
8591
|
console.log("");
|
|
8443
|
-
console.log(" " +
|
|
8444
|
-
console.log(" " +
|
|
8445
|
-
console.log(" " +
|
|
8446
|
-
console.log(" " +
|
|
8447
|
-
console.log(" " +
|
|
8448
|
-
console.log(" " +
|
|
8449
|
-
console.log(" " +
|
|
8592
|
+
console.log(" " + pc3.bold("Commands:"));
|
|
8593
|
+
console.log(" " + pc3.cyan("defi status") + " Protocol overview");
|
|
8594
|
+
console.log(" " + pc3.cyan("defi lending rates") + " Compare lending APYs");
|
|
8595
|
+
console.log(" " + pc3.cyan("defi dex quote") + " Get swap quotes");
|
|
8596
|
+
console.log(" " + pc3.cyan("defi portfolio") + " View all positions");
|
|
8597
|
+
console.log(" " + pc3.cyan("defi scan") + " Exploit detection");
|
|
8598
|
+
console.log(" " + pc3.cyan("defi --help") + " Full command list");
|
|
8450
8599
|
console.log("");
|
|
8451
8600
|
}
|
|
8452
8601
|
|
|
8453
8602
|
// src/main.ts
|
|
8603
|
+
config({ path: resolve4(process.env.HOME || "~", ".defi", ".env"), quiet: true });
|
|
8604
|
+
config({ quiet: true });
|
|
8454
8605
|
async function main() {
|
|
8455
8606
|
try {
|
|
8456
8607
|
const rawArgs = process.argv.slice(2);
|
|
@@ -8479,7 +8630,9 @@ async function main() {
|
|
|
8479
8630
|
"bridge",
|
|
8480
8631
|
"nft",
|
|
8481
8632
|
"farm",
|
|
8482
|
-
"agent"
|
|
8633
|
+
"agent",
|
|
8634
|
+
"setup",
|
|
8635
|
+
"init"
|
|
8483
8636
|
]);
|
|
8484
8637
|
const hasSubcommand = rawArgs.some((a) => !a.startsWith("-") && knownSubcommands.has(a));
|
|
8485
8638
|
const isJson = rawArgs.includes("--json") || rawArgs.includes("--ndjson");
|