@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 CHANGED
@@ -8219,6 +8219,150 @@ function registerFarm(parent, getOpts, makeExecutor2) {
8219
8219
  });
8220
8220
  }
8221
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
+
8222
8366
  // src/cli.ts
8223
8367
  var _require = createRequire(import.meta.url);
8224
8368
  var _pkg = _require("../package.json");
@@ -8270,6 +8414,7 @@ registerSwap(program, getOutputMode, makeExecutor);
8270
8414
  registerBridge(program, getOutputMode);
8271
8415
  registerNft(program, getOutputMode);
8272
8416
  registerFarm(program, getOutputMode, makeExecutor);
8417
+ registerSetup(program);
8273
8418
  program.command("agent").description("Agent mode: read JSON commands from stdin (for AI agents)").action(async () => {
8274
8419
  const executor = makeExecutor();
8275
8420
  process.stderr.write("Agent mode: reading JSON commands from stdin...\n");