@byreal-io/byreal-cli-realclaw 0.3.9 → 0.3.10

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.cjs +136 -17
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -85,6 +85,7 @@ All commands support `-o json` for structured output.
85
85
  | `wallet balance` | Query wallet balance |
86
86
  | `jup swap` | Swap tokens via Jupiter aggregator |
87
87
  | `jup price` | Get token price from Jupiter |
88
+ | `kamino reserves` | Show Kamino Lend APY for SOL/USDC/USDT (or a specific token) |
88
89
  | `kamino deposit` | Deposit tokens into Kamino Lend |
89
90
  | `kamino withdraw` | Withdraw tokens from Kamino Lend |
90
91
  | `kamino status` | View Kamino lending positions and yield |
package/dist/index.cjs CHANGED
@@ -3033,7 +3033,7 @@ var INJECTED_VERSION, VERSION, CLI_NAME, NPM_PACKAGE, API_BASE_URL, API_ENDPOINT
3033
3033
  var init_constants = __esm({
3034
3034
  "src/core/constants.ts"() {
3035
3035
  "use strict";
3036
- INJECTED_VERSION = true ? "0.3.9" : void 0;
3036
+ INJECTED_VERSION = true ? "0.3.10" : void 0;
3037
3037
  VERSION = INJECTED_VERSION ?? process.env.npm_package_version ?? "0.0.0";
3038
3038
  CLI_NAME = "byreal-cli";
3039
3039
  NPM_PACKAGE = "@byreal-io/byreal-cli-realclaw";
@@ -84350,6 +84350,7 @@ byreal-cli catalog show dex.pool.list
84350
84350
  | update.install | Install latest CLI version |
84351
84351
  | defi.jup.swap | Swap tokens via Jupiter aggregator |
84352
84352
  | defi.jup.price | Get token prices from Jupiter |
84353
+ | defi.kamino.reserves | Show Kamino Lend APY for SOL/USDC/USDT (or a specific --token) |
84353
84354
  | defi.kamino.deposit | Deposit to Kamino Lend |
84354
84355
  | defi.kamino.withdraw | Withdraw from Kamino Lend |
84355
84356
  | defi.kamino.status | View Kamino positions and APY |
@@ -84424,6 +84425,8 @@ Present on-chain data first, then external context, then synthesize how external
84424
84425
  | Jupiter swap preview | \`byreal-cli jup swap --input-mint <mint> --output-mint <mint> --amount <amt> --dry-run --wallet-address <addr>\` |
84425
84426
  | Jupiter swap execute | \`byreal-cli jup swap --input-mint <mint> --output-mint <mint> --amount <amt> --wallet-address <addr>\` |
84426
84427
  | Jupiter token price | \`byreal-cli jup price --mint <mint>\` |
84428
+ | Kamino APY (SOL/USDC/USDT) | \`byreal-cli kamino reserves\` |
84429
+ | Kamino APY (specific token) | \`byreal-cli kamino reserves --token <symbol|mint>\` |
84427
84430
  | Kamino deposit | \`byreal-cli kamino deposit --amount <amt> --wallet-address <addr>\` |
84428
84431
  | Kamino withdraw | \`byreal-cli kamino withdraw --amount <amt> --wallet-address <addr>\` |
84429
84432
  | Kamino status | \`byreal-cli kamino status --wallet-address <addr>\` |
@@ -84556,9 +84559,10 @@ When user wants to swap tokens via Jupiter (not the built-in Byreal swap):
84556
84559
  ## Workflow: Idle Yield with Kamino
84557
84560
 
84558
84561
  When user wants to earn yield on idle tokens (e.g. USDC):
84559
- 1. **Check status**: \`byreal-cli kamino status --wallet-address <addr>\` \u2014 view current positions and APY
84560
- 2. **Deposit**: \`byreal-cli kamino deposit --amount <amt> --wallet-address <addr>\` \u2014 deposit USDC (default) or specify \`--mint <mint>\` for other tokens
84561
- 3. **Withdraw**: \`byreal-cli kamino withdraw --amount <amt> --wallet-address <addr>\` \u2014 withdraw back to wallet
84562
+ 1. **Check APY**: \`byreal-cli kamino reserves\` \u2014 shows the supply/borrow APY for SOL, USDC, USDT. For any other token, pass \`--token <symbol|mint>\` (e.g. \`--token JitoSOL\`). This is an aid, not a browser \u2014 do not attempt to list every reserve.
84563
+ 2. **Check status**: \`byreal-cli kamino status --wallet-address <addr>\` \u2014 view current positions and APY
84564
+ 3. **Deposit**: \`byreal-cli kamino deposit --amount <amt> --wallet-address <addr>\` \u2014 deposit USDC (default) or specify \`--mint <mint>\` for other tokens
84565
+ 4. **Withdraw**: \`byreal-cli kamino withdraw --amount <amt> --wallet-address <addr>\` \u2014 withdraw back to wallet
84562
84566
 
84563
84567
  Default market: Kamino Main Market. Use \`--market <address>\` for a different market.
84564
84568
 
@@ -84999,23 +85003,43 @@ function sfToRaw(valueSf) {
84999
85003
  return "0";
85000
85004
  }
85001
85005
  }
85002
- async function getReserveMetrics(market) {
85006
+ function toReserveMetrics(r) {
85007
+ const totalSupplyUsd = parseFloat(r.totalSupplyUsd) || 0;
85008
+ const totalBorrowUsd = parseFloat(r.totalBorrowUsd) || 0;
85009
+ return {
85010
+ reserveAddress: r.reserve,
85011
+ mintAddress: r.liquidityTokenMint,
85012
+ symbol: r.liquidityToken,
85013
+ supplyApy: parseFloat(r.supplyApy) || 0,
85014
+ borrowApy: parseFloat(r.borrowApy) || 0,
85015
+ totalSupplyUsd,
85016
+ totalBorrowUsd,
85017
+ utilization: totalSupplyUsd > 0 ? totalBorrowUsd / totalSupplyUsd : 0,
85018
+ maxLtv: parseFloat(r.maxLtv) || 0
85019
+ };
85020
+ }
85021
+ async function getReservesMetrics(market) {
85003
85022
  try {
85004
85023
  const response = await fetch(`${KAMINO_API}/kamino-market/${market}/reserves/metrics`);
85005
- if (!response.ok) return {};
85006
- const data = await response.json();
85007
- const result = {};
85008
- for (const r of data) {
85009
- result[r.reserve] = {
85010
- supplyApy: parseFloat(r.supplyApy) || 0,
85011
- borrowApy: parseFloat(r.borrowApy) || 0
85012
- };
85024
+ if (!response.ok) {
85025
+ const text = await response.text();
85026
+ return err(apiError(`Kamino reserves metrics failed: ${text}`, response.status));
85013
85027
  }
85014
- return result;
85015
- } catch {
85016
- return {};
85028
+ const data = await response.json();
85029
+ return ok(data.map(toReserveMetrics));
85030
+ } catch (error) {
85031
+ return err(networkError(`Kamino reserves metrics: ${error.message}`));
85017
85032
  }
85018
85033
  }
85034
+ async function getReserveApyMap(market) {
85035
+ const result = await getReservesMetrics(market);
85036
+ if (!result.ok) return {};
85037
+ const map = {};
85038
+ for (const r of result.value) {
85039
+ map[r.reserveAddress] = { supplyApy: r.supplyApy, borrowApy: r.borrowApy };
85040
+ }
85041
+ return map;
85042
+ }
85019
85043
  async function getExchangeRate(market, reserve) {
85020
85044
  try {
85021
85045
  const now = /* @__PURE__ */ new Date();
@@ -85054,7 +85078,7 @@ async function enrichObligations(rawObligations, market) {
85054
85078
  }
85055
85079
  const [priceResult, reserveMetrics, ...exchangeRateResults] = await Promise.all([
85056
85080
  mintsToPrice.size > 0 ? getPrice([...mintsToPrice]) : Promise.resolve({ ok: false, error: null }),
85057
- getReserveMetrics(market),
85081
+ getReserveApyMap(market),
85058
85082
  ...[...activeReserves].map((r) => getExchangeRate(market, r).then((rate) => ({ reserve: r, rate })))
85059
85083
  ]);
85060
85084
  const prices = priceResult.ok ? priceResult.value : {};
@@ -85265,6 +85289,88 @@ Error: ${message}`));
85265
85289
  }
85266
85290
  });
85267
85291
  }
85292
+ var DEFAULT_RESERVE_SYMBOLS = ["SOL", "USDC", "USDT"];
85293
+ function formatUsdThousands(value) {
85294
+ return `$${value.toLocaleString("en-US", { maximumFractionDigits: 2 })}`;
85295
+ }
85296
+ function createKaminoReservesCommand() {
85297
+ return new Command("reserves").description("Show Kamino Lend supply/borrow APY for SOL, USDC, USDT (or a specific --token)").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).option("--token <symbolOrMint>", "Query a single token by symbol (e.g. JitoSOL) or mint address instead of the default set").action(async (options, cmdObj) => {
85298
+ const globalOptions = cmdObj.optsWithGlobals();
85299
+ const format = globalOptions.output;
85300
+ const startTime = Date.now();
85301
+ try {
85302
+ const result = await getReservesMetrics(options.market);
85303
+ if (!result.ok) {
85304
+ format === "json" ? outputErrorJson(result.error) : outputErrorTable(result.error);
85305
+ process.exit(1);
85306
+ }
85307
+ const all = result.value;
85308
+ let reserves;
85309
+ if (options.token) {
85310
+ const needle = String(options.token).trim();
85311
+ const bySymbol = all.filter((r) => r.symbol.toLowerCase() === needle.toLowerCase());
85312
+ const byMint = all.filter((r) => r.mintAddress === needle);
85313
+ reserves = bySymbol.length > 0 ? bySymbol : byMint;
85314
+ if (reserves.length === 0) {
85315
+ const msg = `Token "${needle}" not found in Kamino market ${options.market}. Pass a valid symbol (e.g. JitoSOL) or mint address.`;
85316
+ format === "json" ? outputErrorJson({ code: "NOT_FOUND", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
85317
+ Error: ${msg}`));
85318
+ process.exit(1);
85319
+ }
85320
+ } else {
85321
+ const order = new Map(DEFAULT_RESERVE_SYMBOLS.map((s, i) => [s, i]));
85322
+ reserves = all.filter((r) => order.has(r.symbol)).sort((a, b) => (order.get(a.symbol) ?? 0) - (order.get(b.symbol) ?? 0));
85323
+ }
85324
+ if (format === "json") {
85325
+ outputJson({
85326
+ market: options.market,
85327
+ query: options.token ?? "default",
85328
+ total: reserves.length,
85329
+ reserves
85330
+ }, startTime);
85331
+ return;
85332
+ }
85333
+ const table = new import_cli_table33.default({
85334
+ head: [
85335
+ source_default.cyan.bold("Token"),
85336
+ source_default.cyan.bold("Supply APY"),
85337
+ source_default.cyan.bold("Borrow APY"),
85338
+ source_default.cyan.bold("TVL (USD)"),
85339
+ source_default.cyan.bold("Borrowed (USD)"),
85340
+ source_default.cyan.bold("Utilization"),
85341
+ source_default.cyan.bold("Max LTV"),
85342
+ source_default.cyan.bold("Mint"),
85343
+ source_default.cyan.bold("Reserve")
85344
+ ],
85345
+ chars: TABLE_CHARS
85346
+ });
85347
+ for (const r of reserves) {
85348
+ table.push([
85349
+ r.symbol,
85350
+ `${(r.supplyApy * 100).toFixed(2)}%`,
85351
+ `${(r.borrowApy * 100).toFixed(2)}%`,
85352
+ formatUsdThousands(r.totalSupplyUsd),
85353
+ formatUsdThousands(r.totalBorrowUsd),
85354
+ `${(r.utilization * 100).toFixed(2)}%`,
85355
+ `${(r.maxLtv * 100).toFixed(0)}%`,
85356
+ r.mintAddress,
85357
+ r.reserveAddress
85358
+ ]);
85359
+ }
85360
+ console.log(source_default.cyan.bold("\n Kamino Lend Reserves"));
85361
+ console.log(source_default.gray(` Market: ${options.market}`));
85362
+ if (!options.token) {
85363
+ console.log(source_default.gray(` Showing default set: ${DEFAULT_RESERVE_SYMBOLS.join(", ")} (use --token <symbol|mint> for others)`));
85364
+ }
85365
+ console.log(table.toString());
85366
+ } catch (e) {
85367
+ const message = e.message || "Kamino reserves failed";
85368
+ format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
85369
+ Error: ${message}`));
85370
+ process.exit(1);
85371
+ }
85372
+ });
85373
+ }
85268
85374
  function createKaminoStatusCommand() {
85269
85375
  return new Command("status").description("View Kamino Lend positions and APY").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).action(async (options, cmdObj) => {
85270
85376
  const globalOptions = cmdObj.optsWithGlobals();
@@ -85367,6 +85473,18 @@ var capabilities2 = [
85367
85473
  params: [
85368
85474
  { name: "market", type: "string", required: false, description: "Kamino market address", default: "main market" }
85369
85475
  ]
85476
+ },
85477
+ {
85478
+ id: "defi.kamino.reserves",
85479
+ name: "Kamino Reserves",
85480
+ description: "Show Kamino Lend supply/borrow APY for SOL, USDC, USDT by default. Use --token <symbol|mint> to query a specific other token.",
85481
+ category: "query",
85482
+ auth_required: false,
85483
+ command: "byreal-cli kamino reserves",
85484
+ params: [
85485
+ { name: "market", type: "string", required: false, description: "Kamino market address", default: "main market" },
85486
+ { name: "token", type: "string", required: false, description: "Query a single token by symbol or mint address instead of the default SOL/USDC/USDT set" }
85487
+ ]
85370
85488
  }
85371
85489
  ];
85372
85490
  var kaminoPlugin = {
@@ -85374,6 +85492,7 @@ var kaminoPlugin = {
85374
85492
  name: "Kamino Lend",
85375
85493
  createCommand() {
85376
85494
  const cmd = new Command("kamino").description("Kamino Lend \u2014 deposit, withdraw, yield status");
85495
+ cmd.addCommand(createKaminoReservesCommand());
85377
85496
  cmd.addCommand(createKaminoDepositCommand());
85378
85497
  cmd.addCommand(createKaminoWithdrawCommand());
85379
85498
  cmd.addCommand(createKaminoStatusCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byreal-io/byreal-cli-realclaw",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "AI-native CLI for Byreal CLMM DEX on Solana",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",