@hypurrquant/defi-cli 1.0.3 → 1.0.5

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
@@ -227,7 +227,7 @@ var init_dist = __esm({
227
227
  aggregators;
228
228
  effectiveRpcUrl() {
229
229
  const chainEnv = this.name.toUpperCase().replace(/ /g, "_") + "_RPC_URL";
230
- return process.env[chainEnv] ?? process.env["HYPEREVM_RPC_URL"] ?? this.rpc_url;
230
+ return process.env[chainEnv] ?? this.rpc_url;
231
231
  }
232
232
  };
233
233
  ProtocolCategory = /* @__PURE__ */ ((ProtocolCategory2) => {
@@ -5617,6 +5617,9 @@ var init_dist2 = __esm({
5617
5617
  "function borrowRatePerBlock() external view returns (uint256)",
5618
5618
  "function totalSupply() external view returns (uint256)",
5619
5619
  "function totalBorrows() external view returns (uint256)",
5620
+ "function balanceOf(address account) external view returns (uint256)",
5621
+ "function exchangeRateStored() external view returns (uint256)",
5622
+ "function borrowBalanceStored(address account) external view returns (uint256)",
5620
5623
  "function mint(uint256 mintAmount) external returns (uint256)",
5621
5624
  "function redeem(uint256 redeemTokens) external returns (uint256)",
5622
5625
  "function borrow(uint256 borrowAmount) external returns (uint256)",
@@ -5759,10 +5762,41 @@ var init_dist2 = __esm({
5759
5762
  total_borrow: totalBorrows
5760
5763
  };
5761
5764
  }
5762
- async getUserPosition(_user) {
5763
- throw DefiError.unsupported(
5764
- `[${this.protocolName}] User position requires querying individual vToken balances`
5765
- );
5765
+ async getUserPosition(user) {
5766
+ if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
5767
+ const client = createPublicClient13({ transport: http13(this.rpcUrl) });
5768
+ const ERC20_ABI42 = parseAbi17([
5769
+ "function symbol() external view returns (string)"
5770
+ ]);
5771
+ const supplies = [];
5772
+ const borrows = [];
5773
+ await Promise.all(this.vTokenCandidates.map(async (vtoken) => {
5774
+ try {
5775
+ const [vtokenBal, rate, borrowed, underlying] = await Promise.all([
5776
+ client.readContract({ address: vtoken, abi: CTOKEN_ABI, functionName: "balanceOf", args: [user] }),
5777
+ client.readContract({ address: vtoken, abi: CTOKEN_ABI, functionName: "exchangeRateStored" }),
5778
+ client.readContract({ address: vtoken, abi: CTOKEN_ABI, functionName: "borrowBalanceStored", args: [user] }),
5779
+ client.readContract({ address: vtoken, abi: CTOKEN_ABI, functionName: "underlying" }).catch(() => null)
5780
+ ]);
5781
+ if (vtokenBal === 0n && borrowed === 0n) return;
5782
+ const assetAddr = underlying ?? vtoken;
5783
+ const symbol = await client.readContract({
5784
+ address: assetAddr,
5785
+ abi: ERC20_ABI42,
5786
+ functionName: "symbol"
5787
+ }).catch(() => "?");
5788
+ const supplyUnderlying = vtokenBal * rate / 10n ** 18n;
5789
+ if (supplyUnderlying > 0n) supplies.push({ asset: assetAddr, symbol, amount: supplyUnderlying });
5790
+ if (borrowed > 0n) borrows.push({ asset: assetAddr, symbol, amount: borrowed });
5791
+ } catch {
5792
+ }
5793
+ }));
5794
+ return {
5795
+ protocol: this.protocolName,
5796
+ user,
5797
+ supplies,
5798
+ borrows
5799
+ };
5766
5800
  }
5767
5801
  };
5768
5802
  COMET_ABI = parseAbi18([
@@ -5772,6 +5806,8 @@ var init_dist2 = __esm({
5772
5806
  "function getBorrowRate(uint256 utilization) external view returns (uint64)",
5773
5807
  "function totalSupply() external view returns (uint256)",
5774
5808
  "function totalBorrow() external view returns (uint256)",
5809
+ "function balanceOf(address account) external view returns (uint256)",
5810
+ "function borrowBalanceOf(address account) external view returns (uint256)",
5775
5811
  "function supply(address asset, uint256 amount) external",
5776
5812
  "function withdraw(address asset, uint256 amount) external"
5777
5813
  ]);
@@ -5902,10 +5938,30 @@ var init_dist2 = __esm({
5902
5938
  total_borrow: totalBorrow
5903
5939
  };
5904
5940
  }
5905
- async getUserPosition(_user) {
5906
- throw DefiError.unsupported(
5907
- `[${this.protocolName}] User position requires querying Comet balanceOf + borrowBalanceOf`
5908
- );
5941
+ async getUserPosition(user) {
5942
+ if (!this.rpcUrl) throw DefiError.rpcError("No RPC URL configured");
5943
+ const client = createPublicClient14({ transport: http14(this.rpcUrl) });
5944
+ const ERC20_ABI42 = parseAbi18([
5945
+ "function symbol() external view returns (string)"
5946
+ ]);
5947
+ const [supplyBal, borrowBal, baseToken] = await Promise.all([
5948
+ client.readContract({ address: this.comet, abi: COMET_ABI, functionName: "balanceOf", args: [user] }).catch(() => 0n),
5949
+ client.readContract({ address: this.comet, abi: COMET_ABI, functionName: "borrowBalanceOf", args: [user] }).catch(() => 0n),
5950
+ client.readContract({ address: this.comet, abi: COMET_ABI, functionName: "baseToken" })
5951
+ ]);
5952
+ const baseSymbol = await client.readContract({
5953
+ address: baseToken,
5954
+ abi: ERC20_ABI42,
5955
+ functionName: "symbol"
5956
+ }).catch(() => "?");
5957
+ const supplies = supplyBal > 0n ? [{ asset: baseToken, symbol: baseSymbol, amount: supplyBal }] : [];
5958
+ const borrows = borrowBal > 0n ? [{ asset: baseToken, symbol: baseSymbol, amount: borrowBal }] : [];
5959
+ return {
5960
+ protocol: this.protocolName,
5961
+ user,
5962
+ supplies,
5963
+ borrows
5964
+ };
5909
5965
  }
5910
5966
  };
5911
5967
  EULER_VAULT_ABI = parseAbi19([
@@ -7960,7 +8016,7 @@ function handleSchema(params) {
7960
8016
  from: { type: "string", required: true, description: "Input token symbol or address" },
7961
8017
  to: { type: "string", required: true, description: "Output token symbol or address" },
7962
8018
  amount: { type: "string", required: true, description: "Amount in wei" },
7963
- provider: { type: "string", required: false, default: "kyber", description: "Aggregator: kyber, openocean, liquid" },
8019
+ provider: { type: "string", required: false, default: "kyber", description: "Aggregator: kyber, openocean, liquid, lifi, relay" },
7964
8020
  slippage: { type: "string", required: false, default: "50", description: "Slippage in bps" }
7965
8021
  },
7966
8022
  cli: "defi --chain hyperevm swap --from USDC --to WHYPE --amount 1000000"
@@ -9818,11 +9874,12 @@ function registerYield(parent, getOpts, makeExecutor2) {
9818
9874
  if (opts.targetChain) {
9819
9875
  targetChainName = opts.targetChain.toLowerCase();
9820
9876
  } else {
9821
- process.stderr.write(`Scanning all chains for best ${asset} yield...
9877
+ const quiet = getOpts().json;
9878
+ if (!quiet) process.stderr.write(`Scanning all chains for best ${asset} yield...
9822
9879
  `);
9823
9880
  const t0 = Date.now();
9824
9881
  const allRates = await scanRatesForExecute(registry, asset);
9825
- process.stderr.write(`Scan done in ${Date.now() - t0}ms \u2014 ${allRates.length} rates found
9882
+ if (!quiet) process.stderr.write(`Scan done in ${Date.now() - t0}ms \u2014 ${allRates.length} rates found
9826
9883
  `);
9827
9884
  if (allRates.length === 0) {
9828
9885
  printOutput({ error: `No yield opportunities found for ${asset}` }, getOpts());
@@ -11509,15 +11566,19 @@ function registerSetup(program2) {
11509
11566
  }
11510
11567
  }
11511
11568
  console.log(pc2.cyan(pc2.bold("\n RPC URLs")) + pc2.gray(" (press Enter to use public defaults)"));
11512
- const hyperevmRpc = await ask(rl, " HyperEVM RPC URL: ");
11513
- if (hyperevmRpc) {
11514
- newEnv.HYPEREVM_RPC_URL = hyperevmRpc;
11515
- console.log(` ${pc2.green("OK")} HyperEVM RPC set`);
11516
- }
11517
- const mantleRpc = await ask(rl, " Mantle RPC URL: ");
11518
- if (mantleRpc) {
11519
- newEnv.MANTLE_RPC_URL = mantleRpc;
11520
- console.log(` ${pc2.green("OK")} Mantle RPC set`);
11569
+ const rpcPrompts = [
11570
+ { env: "HYPEREVM_RPC_URL", label: "HyperEVM" },
11571
+ { env: "MANTLE_RPC_URL", label: "Mantle" },
11572
+ { env: "BASE_RPC_URL", label: "Base" },
11573
+ { env: "BNB_RPC_URL", label: "BNB" },
11574
+ { env: "MONAD_RPC_URL", label: "Monad" }
11575
+ ];
11576
+ for (const { env, label } of rpcPrompts) {
11577
+ const value = await ask(rl, ` ${label} RPC URL: `);
11578
+ if (value) {
11579
+ newEnv[env] = value;
11580
+ console.log(` ${pc2.green("OK")} ${label} RPC set`);
11581
+ }
11521
11582
  }
11522
11583
  const finalEnv = { ...existing, ...newEnv };
11523
11584
  writeEnvFile(finalEnv);
@@ -11529,11 +11590,16 @@ function registerSetup(program2) {
11529
11590
  if (finalEnv.DEFI_PRIVATE_KEY) {
11530
11591
  console.log(` Key: ${pc2.green("configured")}`);
11531
11592
  }
11532
- if (finalEnv.HYPEREVM_RPC_URL) {
11533
- console.log(` HyperEVM RPC: ${pc2.gray(finalEnv.HYPEREVM_RPC_URL)}`);
11534
- }
11535
- if (finalEnv.MANTLE_RPC_URL) {
11536
- console.log(` Mantle RPC: ${pc2.gray(finalEnv.MANTLE_RPC_URL)}`);
11593
+ const rpcSummary = [
11594
+ ["HYPEREVM_RPC_URL", "HyperEVM RPC"],
11595
+ ["MANTLE_RPC_URL", "Mantle RPC "],
11596
+ ["BASE_RPC_URL", "Base RPC "],
11597
+ ["BNB_RPC_URL", "BNB RPC "],
11598
+ ["MONAD_RPC_URL", "Monad RPC "]
11599
+ ];
11600
+ for (const [k, label] of rpcSummary) {
11601
+ const v = finalEnv[k];
11602
+ if (v) console.log(` ${label}: ${pc2.gray(v)}`);
11537
11603
  }
11538
11604
  console.log(pc2.bold(pc2.white("\n Next steps:")));
11539
11605
  console.log(` ${pc2.green("defi portfolio")} view balances & positions`);
@@ -11746,7 +11812,9 @@ function buildBanner() {
11746
11812
  try {
11747
11813
  const reg = Registry.loadEmbedded();
11748
11814
  chainCount = reg.chains.size;
11749
- protocolCount = reg.protocols.length;
11815
+ protocolCount = reg.protocols.filter(
11816
+ (p) => p.verified !== false && p.is_active !== false
11817
+ ).length;
11750
11818
  } catch {
11751
11819
  }
11752
11820
  const stats = chainCount && protocolCount ? `${chainCount} chains \xB7 ${protocolCount} protocols \xB7 by HypurrQuant` : `by HypurrQuant`;