@t2000/cli 0.22.4 → 0.22.6

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
@@ -497,12 +497,73 @@ function registerDeposit(program2) {
497
497
  }
498
498
 
499
499
  // src/commands/history.ts
500
+ import pc4 from "picocolors";
500
501
  import { T2000 as T20006, truncateAddress as truncateAddress2 } from "@t2000/sdk";
502
+ var ACTION_LABELS = {
503
+ send: "\u2197 send",
504
+ lending: "\u{1F3E6} lend",
505
+ swap: "\u{1F504} swap",
506
+ "mpp payment": "\u{1F4B3} mpp",
507
+ transaction: "\u{1F4E6} tx"
508
+ };
509
+ function relativeTime(ts) {
510
+ const diff = Date.now() - ts;
511
+ const mins = Math.floor(diff / 6e4);
512
+ if (mins < 1) return "just now";
513
+ if (mins < 60) return `${mins}m ago`;
514
+ const hours = Math.floor(mins / 60);
515
+ if (hours < 24) return `${hours}h ago`;
516
+ const days = Math.floor(hours / 24);
517
+ if (days < 7) return `${days}d ago`;
518
+ return new Date(ts).toLocaleDateString();
519
+ }
520
+ function formatAmount(tx) {
521
+ if (!tx.amount) return "";
522
+ return pc4.bold(`${tx.amount.toFixed(tx.amount < 0.01 ? 4 : 2)} ${tx.asset ?? ""}`);
523
+ }
524
+ function printTxSummary(tx) {
525
+ const label = ACTION_LABELS[tx.action] ?? `\u{1F4E6} ${tx.action}`;
526
+ const time = tx.timestamp ? relativeTime(tx.timestamp) : "";
527
+ const amount = formatAmount(tx);
528
+ const recipient = tx.recipient ? pc4.dim(`\u2192 ${truncateAddress2(tx.recipient)}`) : "";
529
+ const link = pc4.dim(explorerUrl(tx.digest));
530
+ printLine(`${label} ${amount} ${recipient}`);
531
+ printLine(` ${pc4.dim(truncateAddress2(tx.digest))} ${pc4.dim(time)}`);
532
+ printLine(` ${link}`);
533
+ }
534
+ function printTxDetail(tx) {
535
+ printHeader("Transaction Detail");
536
+ const label = ACTION_LABELS[tx.action] ?? `\u{1F4E6} ${tx.action}`;
537
+ printKeyValue("Type", label);
538
+ printKeyValue("Digest", tx.digest);
539
+ if (tx.amount) printKeyValue("Amount", `${tx.amount.toFixed(tx.amount < 0.01 ? 6 : 4)} ${tx.asset ?? ""}`);
540
+ if (tx.recipient) printKeyValue("Recipient", tx.recipient);
541
+ if (tx.timestamp) {
542
+ printKeyValue("Time", `${new Date(tx.timestamp).toLocaleString()} (${relativeTime(tx.timestamp)})`);
543
+ }
544
+ if (tx.gasCost !== void 0) printKeyValue("Gas", `${tx.gasCost.toFixed(6)} SUI`);
545
+ printBlank();
546
+ printKeyValue("Explorer", explorerUrl(tx.digest));
547
+ printBlank();
548
+ }
501
549
  function registerHistory(program2) {
502
- program2.command("history").description("Show transaction history").option("--limit <n>", "Number of transactions", "20").option("--key <path>", "Key file path").action(async (opts) => {
550
+ program2.command("history").description("Show transaction history, or detail for a specific digest").argument("[digest]", "Transaction digest to view details").option("--limit <n>", "Number of transactions", "20").option("--key <path>", "Key file path").action(async (digest, opts) => {
503
551
  try {
504
552
  const pin = await resolvePin();
505
553
  const agent = await T20006.create({ pin, keyPath: opts.key });
554
+ if (digest) {
555
+ const tx = await agent.transactionDetail(digest);
556
+ if (!tx) {
557
+ handleError(new Error(`Transaction not found: ${digest}`));
558
+ return;
559
+ }
560
+ if (isJsonMode()) {
561
+ printJson(tx);
562
+ return;
563
+ }
564
+ printTxDetail(tx);
565
+ return;
566
+ }
506
567
  const txns = await agent.history({ limit: parseInt(opts.limit, 10) });
507
568
  if (isJsonMode()) {
508
569
  printJson(txns);
@@ -513,11 +574,12 @@ function registerHistory(program2) {
513
574
  printInfo("No transactions yet.");
514
575
  } else {
515
576
  for (const tx of txns) {
516
- const time = tx.timestamp ? new Date(tx.timestamp).toLocaleString() : "unknown";
517
- const gas = tx.gasMethod ? ` (${tx.gasMethod})` : "";
518
- printLine(`${truncateAddress2(tx.digest)} ${tx.action}${gas} ${time}`);
577
+ printTxSummary(tx);
578
+ printBlank();
519
579
  }
520
580
  }
581
+ printDivider();
582
+ printInfo(`${txns.length} transaction${txns.length === 1 ? "" : "s"} shown`);
521
583
  printBlank();
522
584
  } catch (error) {
523
585
  handleError(error);
@@ -629,7 +691,7 @@ function registerImport(program2) {
629
691
  }
630
692
 
631
693
  // src/commands/save.ts
632
- import pc4 from "picocolors";
694
+ import pc5 from "picocolors";
633
695
  import { T2000 as T20009, formatUsd as formatUsd3 } from "@t2000/sdk";
634
696
  function registerSave(program2) {
635
697
  const action = async (amountStr, opts) => {
@@ -651,16 +713,16 @@ function registerSave(program2) {
651
713
  }
652
714
  printBlank();
653
715
  if (gasManagerUsdc > 0) {
654
- printSuccess(`Gas manager: ${pc4.yellow(formatUsd3(gasManagerUsdc))} USDC \u2192 SUI`);
716
+ printSuccess(`Gas manager: ${pc5.yellow(formatUsd3(gasManagerUsdc))} USDC \u2192 SUI`);
655
717
  }
656
718
  const protocolName = opts.protocol ?? "best rate";
657
- printSuccess(`Saved ${pc4.yellow(formatUsd3(result.amount))} USDC to ${protocolName}`);
719
+ printSuccess(`Saved ${pc5.yellow(formatUsd3(result.amount))} USDC to ${protocolName}`);
658
720
  if (result.fee > 0) {
659
721
  const feeRate = (result.fee / result.amount * 100).toFixed(1);
660
- printSuccess(`Protocol fee: ${pc4.dim(`${formatUsd3(result.fee)} USDC (${feeRate}%)`)}`);
722
+ printSuccess(`Protocol fee: ${pc5.dim(`${formatUsd3(result.fee)} USDC (${feeRate}%)`)}`);
661
723
  }
662
- printSuccess(`Current APY: ${pc4.green(`${result.apy.toFixed(2)}%`)}`);
663
- printSuccess(`Savings balance: ${pc4.yellow(formatUsd3(result.savingsBalance))} USDC`);
724
+ printSuccess(`Current APY: ${pc5.green(`${result.apy.toFixed(2)}%`)}`);
725
+ printSuccess(`Savings balance: ${pc5.yellow(formatUsd3(result.savingsBalance))} USDC`);
664
726
  printKeyValue("Tx", explorerUrl(result.tx));
665
727
  printBlank();
666
728
  } catch (error) {
@@ -792,7 +854,7 @@ function registerHealth(program2) {
792
854
  }
793
855
 
794
856
  // src/commands/rates.ts
795
- import pc5 from "picocolors";
857
+ import pc6 from "picocolors";
796
858
  import { T2000 as T200014, SUPPORTED_ASSETS, INVESTMENT_ASSETS, STABLE_ASSETS } from "@t2000/sdk";
797
859
  var INVEST_ASSETS = Object.keys(INVESTMENT_ASSETS);
798
860
  function registerRates(program2) {
@@ -809,14 +871,14 @@ function registerRates(program2) {
809
871
  if (allRates.length > 0) {
810
872
  const best = allRates.reduce((a, b) => b.rates.saveApy > a.rates.saveApy ? b : a);
811
873
  const bestDisplay = SUPPORTED_ASSETS[best.asset]?.displayName ?? best.asset;
812
- printLine(pc5.bold(pc5.green(`Best yield: ${best.rates.saveApy.toFixed(2)}% APY`)) + pc5.dim(` (${bestDisplay} on ${best.protocol})`));
874
+ printLine(pc6.bold(pc6.green(`Best yield: ${best.rates.saveApy.toFixed(2)}% APY`)) + pc6.dim(` (${bestDisplay} on ${best.protocol})`));
813
875
  printBlank();
814
876
  }
815
877
  for (const asset of STABLE_ASSETS) {
816
878
  const assetRates = allRates.filter((r) => r.asset === asset);
817
879
  if (assetRates.length === 0) continue;
818
880
  const display = SUPPORTED_ASSETS[asset]?.displayName ?? asset;
819
- printLine(pc5.bold(display));
881
+ printLine(pc6.bold(display));
820
882
  printDivider();
821
883
  for (const entry of assetRates) {
822
884
  printKeyValue(entry.protocol, `Save ${entry.rates.saveApy.toFixed(2)}% Borrow ${entry.rates.borrowApy.toFixed(2)}%`);
@@ -825,7 +887,7 @@ function registerRates(program2) {
825
887
  }
826
888
  const investRates = allRates.filter((r) => INVEST_ASSETS.includes(r.asset));
827
889
  if (investRates.length > 0) {
828
- printLine(pc5.bold("Investment Assets"));
890
+ printLine(pc6.bold("Investment Assets"));
829
891
  printDivider();
830
892
  for (const asset of INVEST_ASSETS) {
831
893
  const assetRates = investRates.filter((r) => r.asset === asset);
@@ -848,7 +910,7 @@ function registerRates(program2) {
848
910
  }
849
911
 
850
912
  // src/commands/positions.ts
851
- import pc6 from "picocolors";
913
+ import pc7 from "picocolors";
852
914
  import { T2000 as T200015, formatUsd as formatUsd8, formatAssetAmount } from "@t2000/sdk";
853
915
  function registerPositions(program2) {
854
916
  program2.command("positions").description("Show savings & borrow positions across all protocols and assets").option("--key <path>", "Key file path").action(async (opts) => {
@@ -877,10 +939,10 @@ function registerPositions(program2) {
877
939
  const saves = result.positions.filter((p) => p.type === "save");
878
940
  const borrows = result.positions.filter((p) => p.type === "borrow");
879
941
  if (saves.length > 0) {
880
- printLine(pc6.bold("Savings"));
942
+ printLine(pc7.bold("Savings"));
881
943
  printDivider();
882
944
  for (const pos of saves) {
883
- const earning = rewardsByKey.has(`${pos.protocol}:${pos.asset}`) ? ` ${pc6.yellow("+rewards")}` : "";
945
+ const earning = rewardsByKey.has(`${pos.protocol}:${pos.asset}`) ? ` ${pc7.yellow("+rewards")}` : "";
884
946
  const usd = formatUsd8(pos.amountUsd ?? pos.amount);
885
947
  printKeyValue(pos.protocol, `${formatAssetAmount(pos.amount, pos.asset)} ${pos.asset} (${usd}) @ ${pos.apy.toFixed(2)}% APY${earning}`);
886
948
  }
@@ -889,12 +951,12 @@ function registerPositions(program2) {
889
951
  printKeyValue("Total", formatUsd8(totalSaved));
890
952
  }
891
953
  if (hasRewards) {
892
- printLine(` ${pc6.dim("Run claim-rewards to collect and convert to USDC")}`);
954
+ printLine(` ${pc7.dim("Run claim-rewards to collect and convert to USDC")}`);
893
955
  }
894
956
  printBlank();
895
957
  }
896
958
  if (borrows.length > 0) {
897
- printLine(pc6.bold("Borrows"));
959
+ printLine(pc7.bold("Borrows"));
898
960
  printDivider();
899
961
  for (const pos of borrows) {
900
962
  const usd = formatUsd8(pos.amountUsd ?? pos.amount);
@@ -914,7 +976,7 @@ function registerPositions(program2) {
914
976
  }
915
977
 
916
978
  // src/commands/earnings.ts
917
- import pc7 from "picocolors";
979
+ import pc8 from "picocolors";
918
980
  import { T2000 as T200016, formatUsd as formatUsd9, formatAssetAmount as formatAssetAmount2 } from "@t2000/sdk";
919
981
  function registerEarnings(program2) {
920
982
  program2.command("earnings").description("Show yield earned to date").option("--key <path>", "Key file path").action(async (opts) => {
@@ -932,7 +994,7 @@ function registerEarnings(program2) {
932
994
  printKeyValue("Total Saved", formatUsd9(result.supplied));
933
995
  if (savePositions.length > 0) {
934
996
  for (const p of savePositions) {
935
- printLine(` ${pc7.dim("\u2022")} ${formatAssetAmount2(p.amount, p.asset)} ${p.asset} (${formatUsd9(p.amountUsd ?? p.amount)}) on ${p.protocol} @ ${p.apy.toFixed(2)}% APY`);
997
+ printLine(` ${pc8.dim("\u2022")} ${formatAssetAmount2(p.amount, p.asset)} ${p.asset} (${formatUsd9(p.amountUsd ?? p.amount)}) on ${p.protocol} @ ${p.apy.toFixed(2)}% APY`);
936
998
  }
937
999
  }
938
1000
  printKeyValue("Blended APY", `${result.currentApy.toFixed(2)}%`);
@@ -946,7 +1008,7 @@ function registerEarnings(program2) {
946
1008
  }
947
1009
 
948
1010
  // src/commands/fundStatus.ts
949
- import pc8 from "picocolors";
1011
+ import pc9 from "picocolors";
950
1012
  import { T2000 as T200017, formatUsd as formatUsd10, formatAssetAmount as formatAssetAmount3 } from "@t2000/sdk";
951
1013
  function registerFundStatus(program2) {
952
1014
  program2.command("fund-status").description("Full savings summary").option("--key <path>", "Key file path").action(async (opts) => {
@@ -970,7 +1032,7 @@ function registerFundStatus(program2) {
970
1032
  printKeyValue("Total Saved", formatUsd10(result.supplied));
971
1033
  if (savePositions.length > 0) {
972
1034
  for (const p of savePositions) {
973
- printLine(` ${pc8.dim("\u2022")} ${formatAssetAmount3(p.amount, p.asset)} ${p.asset} (${formatUsd10(p.amountUsd ?? p.amount)}) on ${p.protocol} @ ${p.apy.toFixed(2)}% APY`);
1035
+ printLine(` ${pc9.dim("\u2022")} ${formatAssetAmount3(p.amount, p.asset)} ${p.asset} (${formatUsd10(p.amountUsd ?? p.amount)}) on ${p.protocol} @ ${p.apy.toFixed(2)}% APY`);
974
1036
  }
975
1037
  }
976
1038
  printKeyValue("Blended APY", `${result.apy.toFixed(2)}%`);
@@ -1455,7 +1517,7 @@ function isRetryable(code) {
1455
1517
  }
1456
1518
 
1457
1519
  // src/commands/pay.ts
1458
- import pc9 from "picocolors";
1520
+ import pc10 from "picocolors";
1459
1521
  import { T2000 as T200019 } from "@t2000/sdk";
1460
1522
  function registerPay(program2) {
1461
1523
  program2.command("pay <url>").description("Pay for an MPP-protected API resource").option("--key <path>", "Key file path").option("--method <method>", "HTTP method (GET, POST, PUT)", "GET").option("--data <json>", "Request body for POST/PUT").option("--header <key=value>", "Additional HTTP header (repeatable)", collectHeaders, {}).option("--max-price <amount>", "Max USDC price to auto-approve", "1.00").action(async (url, opts) => {
@@ -1484,7 +1546,7 @@ function registerPay(program2) {
1484
1546
  if (result.paid && result.receipt) {
1485
1547
  printSuccess(`Paid via MPP (tx: ${result.receipt.reference.slice(0, 10)}...)`);
1486
1548
  }
1487
- printInfo(`\u2190 ${result.status} OK ${pc9.dim(`[${elapsed}ms]`)}`);
1549
+ printInfo(`\u2190 ${result.status} OK ${pc10.dim(`[${elapsed}ms]`)}`);
1488
1550
  }
1489
1551
  if (isJsonMode()) {
1490
1552
  printJson({
@@ -1597,7 +1659,7 @@ function registerLock(program2) {
1597
1659
 
1598
1660
  // src/commands/sentinel.ts
1599
1661
  import { T2000 as T200020, MIST_PER_SUI } from "@t2000/sdk";
1600
- import pc10 from "picocolors";
1662
+ import pc11 from "picocolors";
1601
1663
  function formatSui(mist) {
1602
1664
  return (Number(mist) / Number(MIST_PER_SUI)).toFixed(2);
1603
1665
  }
@@ -1627,8 +1689,8 @@ function registerSentinel(program2) {
1627
1689
  const pool = `${formatSui(s.prizePool)} SUI`.padEnd(12);
1628
1690
  const fee = `${formatSui(s.attackFee)} SUI`.padEnd(12);
1629
1691
  printLine(` ${s.name}`);
1630
- printLine(` ${pc10.dim(`Pool: ${pool}Fee: ${fee}Attacks: ${s.totalAttacks}`)}`);
1631
- printLine(` ${pc10.dim(s.objectId)}`);
1692
+ printLine(` ${pc11.dim(`Pool: ${pool}Fee: ${fee}Attacks: ${s.totalAttacks}`)}`);
1693
+ printLine(` ${pc11.dim(s.objectId)}`);
1632
1694
  printBlank();
1633
1695
  });
1634
1696
  printBlank();
@@ -1663,7 +1725,7 @@ function registerSentinel(program2) {
1663
1725
  if (s.systemPrompt) {
1664
1726
  printBlank();
1665
1727
  printKeyValue("System Prompt", "");
1666
- printLine(` ${pc10.dim(s.systemPrompt.slice(0, 500))}`);
1728
+ printLine(` ${pc11.dim(s.systemPrompt.slice(0, 500))}`);
1667
1729
  }
1668
1730
  printBlank();
1669
1731
  } catch (error) {
@@ -1689,7 +1751,7 @@ function registerSentinel(program2) {
1689
1751
  return;
1690
1752
  }
1691
1753
  printBlank();
1692
- printLine(` ${pc10.dim("\u23F3")} Requesting attack...`);
1754
+ printLine(` ${pc11.dim("\u23F3")} Requesting attack...`);
1693
1755
  const result = await agent.sentinelAttack(id, prompt, feeMist);
1694
1756
  printBlank();
1695
1757
  if (result.won) {
@@ -1716,7 +1778,7 @@ function registerSentinel(program2) {
1716
1778
 
1717
1779
  // src/commands/earn.ts
1718
1780
  import { T2000 as T200021, MIST_PER_SUI as MIST_PER_SUI2, listSentinels, formatUsd as formatUsd12 } from "@t2000/sdk";
1719
- import pc11 from "picocolors";
1781
+ import pc12 from "picocolors";
1720
1782
  function mistToSui(mist) {
1721
1783
  return Number(mist) / Number(MIST_PER_SUI2);
1722
1784
  }
@@ -1788,7 +1850,7 @@ function registerEarn(program2) {
1788
1850
  return;
1789
1851
  }
1790
1852
  printHeader("Earning Opportunities");
1791
- printLine(pc11.bold("SAVINGS") + pc11.dim(" \u2014 Passive Yield"));
1853
+ printLine(pc12.bold("SAVINGS") + pc12.dim(" \u2014 Passive Yield"));
1792
1854
  printDivider();
1793
1855
  if (savePositions.length > 0) {
1794
1856
  for (const pos of savePositions) {
@@ -1797,7 +1859,7 @@ function registerEarn(program2) {
1797
1859
  if (dailyYield > 1e-4) {
1798
1860
  const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd12(dailyYield);
1799
1861
  const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd12(dailyYield * 30);
1800
- printLine(pc11.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
1862
+ printLine(pc12.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
1801
1863
  }
1802
1864
  }
1803
1865
  if (savePositions.length > 1) {
@@ -1812,7 +1874,7 @@ function registerEarn(program2) {
1812
1874
  const example = 100;
1813
1875
  const daily = example * bestSaveApy / 100 / 365;
1814
1876
  const monthly = daily * 30;
1815
- printLine(pc11.dim(` Save $${example} \u2192 ~$${daily.toFixed(2)}/day \xB7 ~$${monthly.toFixed(2)}/month`));
1877
+ printLine(pc12.dim(` Save $${example} \u2192 ~$${daily.toFixed(2)}/day \xB7 ~$${monthly.toFixed(2)}/month`));
1816
1878
  printBlank();
1817
1879
  printInfo("No savings yet \u2014 run `t2000 save <amount>` to start");
1818
1880
  } else if (posData) {
@@ -1822,7 +1884,7 @@ function registerEarn(program2) {
1822
1884
  }
1823
1885
  if (earningInvestments.length > 0) {
1824
1886
  printBlank();
1825
- printLine(pc11.bold("INVESTMENTS") + pc11.dim(" \u2014 Earning Yield"));
1887
+ printLine(pc12.bold("INVESTMENTS") + pc12.dim(" \u2014 Earning Yield"));
1826
1888
  printDivider();
1827
1889
  let totalInvestValue = 0;
1828
1890
  for (const pos of earningInvestments) {
@@ -1835,7 +1897,7 @@ function registerEarn(program2) {
1835
1897
  if (dailyYield > 1e-4) {
1836
1898
  const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd12(dailyYield);
1837
1899
  const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd12(dailyYield * 30);
1838
- printLine(pc11.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
1900
+ printLine(pc12.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
1839
1901
  }
1840
1902
  totalInvestValue += pos.currentValue;
1841
1903
  }
@@ -1845,7 +1907,7 @@ function registerEarn(program2) {
1845
1907
  }
1846
1908
  }
1847
1909
  printBlank();
1848
- printLine(pc11.bold("SENTINEL BOUNTIES") + pc11.dim(" \u2014 Active Red Teaming"));
1910
+ printLine(pc12.bold("SENTINEL BOUNTIES") + pc12.dim(" \u2014 Active Red Teaming"));
1849
1911
  printDivider();
1850
1912
  if (agents && agents.length > 0) {
1851
1913
  const totalPool = agents.reduce((sum, s) => sum + mistToSui(s.prizePool), 0);
@@ -1864,12 +1926,12 @@ function registerEarn(program2) {
1864
1926
  printInfo("Sentinel data unavailable");
1865
1927
  }
1866
1928
  printBlank();
1867
- printLine(pc11.bold("Quick Actions"));
1929
+ printLine(pc12.bold("Quick Actions"));
1868
1930
  printDivider();
1869
- printLine(` ${pc11.dim("t2000 save <amount> [asset]")} Save stablecoins for yield`);
1870
- printLine(` ${pc11.dim("t2000 invest earn <asset>")} Earn yield on investments`);
1871
- printLine(` ${pc11.dim("t2000 sentinel list")} Browse sentinel bounties`);
1872
- printLine(` ${pc11.dim("t2000 sentinel attack <id>")} Attack a sentinel`);
1931
+ printLine(` ${pc12.dim("t2000 save <amount> [asset]")} Save stablecoins for yield`);
1932
+ printLine(` ${pc12.dim("t2000 invest earn <asset>")} Earn yield on investments`);
1933
+ printLine(` ${pc12.dim("t2000 sentinel list")} Browse sentinel bounties`);
1934
+ printLine(` ${pc12.dim("t2000 sentinel attack <id>")} Attack a sentinel`);
1873
1935
  printBlank();
1874
1936
  } catch (error) {
1875
1937
  handleError(error);
@@ -1878,7 +1940,7 @@ function registerEarn(program2) {
1878
1940
  }
1879
1941
 
1880
1942
  // src/commands/rebalance.ts
1881
- import pc12 from "picocolors";
1943
+ import pc13 from "picocolors";
1882
1944
  import { T2000 as T200022, formatUsd as formatUsd13, SUPPORTED_ASSETS as SUPPORTED_ASSETS2 } from "@t2000/sdk";
1883
1945
  function registerRebalance(program2) {
1884
1946
  program2.command("rebalance").description("Optimize yield \u2014 move savings to the best rate across protocols and stablecoins").option("--key <path>", "Key file path").option("--dry-run", "Show what would happen without executing").option("--min-diff <pct>", "Minimum APY difference to trigger (default: 0.5)", "0.5").option("--max-break-even <days>", "Max break-even days for cross-asset moves (default: 30)", "30").action(async (opts) => {
@@ -1906,24 +1968,24 @@ function registerRebalance(program2) {
1906
1968
  const diff = plan.newApy - plan.currentApy;
1907
1969
  if (diff < minYieldDiff) {
1908
1970
  printInfo(`Already optimized \u2014 ${plan.currentApy.toFixed(2)}% APY on ${plan.fromProtocol}`);
1909
- printLine(pc12.dim(` Best available: ${plan.newApy.toFixed(2)}% (${displayAsset(plan.toAsset)} on ${plan.toProtocol})`));
1910
- printLine(pc12.dim(` Difference: ${diff.toFixed(2)}% (below ${minYieldDiff}% threshold)`));
1971
+ printLine(pc13.dim(` Best available: ${plan.newApy.toFixed(2)}% (${displayAsset(plan.toAsset)} on ${plan.toProtocol})`));
1972
+ printLine(pc13.dim(` Difference: ${diff.toFixed(2)}% (below ${minYieldDiff}% threshold)`));
1911
1973
  } else if (plan.breakEvenDays > maxBreakEven && plan.estimatedSwapCost > 0) {
1912
1974
  printInfo(`Skipped \u2014 break-even of ${plan.breakEvenDays} days exceeds ${maxBreakEven}-day limit`);
1913
- printLine(pc12.dim(` ${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}%) \u2192 ${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}%)`));
1975
+ printLine(pc13.dim(` ${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}%) \u2192 ${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}%)`));
1914
1976
  } else {
1915
1977
  printInfo("Already at the best rate. Nothing to rebalance.");
1916
1978
  }
1917
1979
  printBlank();
1918
1980
  return;
1919
1981
  }
1920
- printLine(pc12.bold("Rebalance Plan"));
1982
+ printLine(pc13.bold("Rebalance Plan"));
1921
1983
  printDivider();
1922
1984
  printKeyValue("From", `${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}% APY)`);
1923
1985
  printKeyValue("To", `${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}% APY)`);
1924
1986
  printKeyValue("Amount", formatUsd13(plan.amount));
1925
1987
  printBlank();
1926
- printLine(pc12.bold("Economics"));
1988
+ printLine(pc13.bold("Economics"));
1927
1989
  printDivider();
1928
1990
  printKeyValue("APY Gain", `+${(plan.newApy - plan.currentApy).toFixed(2)}%`);
1929
1991
  printKeyValue("Annual Gain", `${formatUsd13(plan.annualGain)}/year`);
@@ -1933,7 +1995,7 @@ function registerRebalance(program2) {
1933
1995
  }
1934
1996
  printBlank();
1935
1997
  if (plan.steps.length > 0) {
1936
- printLine(pc12.bold("Steps"));
1998
+ printLine(pc13.bold("Steps"));
1937
1999
  printDivider();
1938
2000
  for (let i = 0; i < plan.steps.length; i++) {
1939
2001
  const step = plan.steps[i];
@@ -1949,8 +2011,8 @@ function registerRebalance(program2) {
1949
2011
  printBlank();
1950
2012
  }
1951
2013
  if (opts.dryRun) {
1952
- printLine(pc12.bold(pc12.yellow("DRY RUN \u2014 Preview only, no transactions executed")));
1953
- printLine(pc12.dim(" Run `t2000 rebalance` to execute."));
2014
+ printLine(pc13.bold(pc13.yellow("DRY RUN \u2014 Preview only, no transactions executed")));
2015
+ printLine(pc13.dim(" Run `t2000 rebalance` to execute."));
1954
2016
  printBlank();
1955
2017
  return;
1956
2018
  }
@@ -2063,7 +2125,7 @@ function registerMcp(program2) {
2063
2125
  mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
2064
2126
  let mod;
2065
2127
  try {
2066
- mod = await import("./dist-72NNY4EV.js");
2128
+ mod = await import("./dist-NXFA54RO.js");
2067
2129
  } catch {
2068
2130
  console.error(
2069
2131
  "MCP server not installed. Run:\n npm install -g @t2000/mcp"
@@ -2215,7 +2277,7 @@ function registerContacts(program2) {
2215
2277
  }
2216
2278
 
2217
2279
  // src/commands/invest.ts
2218
- import pc13 from "picocolors";
2280
+ import pc14 from "picocolors";
2219
2281
  import { T2000 as T200024, formatUsd as formatUsd15, formatAssetAmount as formatAssetAmount4, INVESTMENT_ASSETS as INVESTMENT_ASSETS2 } from "@t2000/sdk";
2220
2282
  function registerInvest(program2) {
2221
2283
  const investCmd = program2.command("invest").description("Buy or sell investment assets");
@@ -2223,7 +2285,7 @@ function registerInvest(program2) {
2223
2285
  try {
2224
2286
  const parsed = parseFloat(amount);
2225
2287
  if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
2226
- console.error(pc13.red(" \u2717 Amount must be greater than $0"));
2288
+ console.error(pc14.red(" \u2717 Amount must be greater than $0"));
2227
2289
  process.exitCode = 1;
2228
2290
  return;
2229
2291
  }
@@ -2255,7 +2317,7 @@ function registerInvest(program2) {
2255
2317
  if (!isAll) {
2256
2318
  const parsed = parseFloat(amount);
2257
2319
  if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
2258
- console.error(pc13.red(" \u2717 Amount must be greater than $0"));
2320
+ console.error(pc14.red(" \u2717 Amount must be greater than $0"));
2259
2321
  process.exitCode = 1;
2260
2322
  return;
2261
2323
  }
@@ -2277,7 +2339,7 @@ function registerInvest(program2) {
2277
2339
  printSuccess(`Sold ${formatAssetAmount4(result.amount, sym)} ${sym} at ${formatUsd15(result.price)}`);
2278
2340
  printKeyValue("Proceeds", formatUsd15(result.usdValue));
2279
2341
  if (result.realizedPnL !== void 0) {
2280
- const pnlColor = result.realizedPnL >= 0 ? pc13.green : pc13.red;
2342
+ const pnlColor = result.realizedPnL >= 0 ? pc14.green : pc14.red;
2281
2343
  const pnlSign = result.realizedPnL >= 0 ? "+" : "";
2282
2344
  printKeyValue("Realized P&L", pnlColor(`${pnlSign}${formatUsd15(result.realizedPnL)}`));
2283
2345
  }
@@ -2408,9 +2470,9 @@ function registerInvest(program2) {
2408
2470
  printSeparator();
2409
2471
  for (const [key, def] of Object.entries(all)) {
2410
2472
  const allocs = Object.entries(def.allocations).map(([a, p]) => `${a} ${p}%`).join(", ");
2411
- const tag = def.custom ? pc13.dim(" (custom)") : "";
2473
+ const tag = def.custom ? pc14.dim(" (custom)") : "";
2412
2474
  printKeyValue(key, `${allocs}${tag}`);
2413
- printLine(` ${pc13.dim(def.description)}`);
2475
+ printLine(` ${pc14.dim(def.description)}`);
2414
2476
  }
2415
2477
  printSeparator();
2416
2478
  const hasPositions = Object.keys(all).some((k) => agent.portfolio.hasStrategyPositions(k));
@@ -2426,7 +2488,7 @@ function registerInvest(program2) {
2426
2488
  try {
2427
2489
  const parsed = parseFloat(amount);
2428
2490
  if (isNaN(parsed) || parsed <= 0) {
2429
- console.error(pc13.red(" \u2717 Amount must be greater than $0"));
2491
+ console.error(pc14.red(" \u2717 Amount must be greater than $0"));
2430
2492
  process.exitCode = 1;
2431
2493
  return;
2432
2494
  }
@@ -2460,7 +2522,7 @@ function registerInvest(program2) {
2460
2522
  printKeyValue("Tx", explorerUrl(txDigests[0]));
2461
2523
  } else {
2462
2524
  for (const buy of result.buys) {
2463
- printLine(` ${pc13.dim(`${buy.asset}: ${explorerUrl(buy.tx)}`)}`);
2525
+ printLine(` ${pc14.dim(`${buy.asset}: ${explorerUrl(buy.tx)}`)}`);
2464
2526
  }
2465
2527
  }
2466
2528
  }
@@ -2482,18 +2544,18 @@ function registerInvest(program2) {
2482
2544
  printSuccess(`Sold all ${name} strategy positions`);
2483
2545
  printSeparator();
2484
2546
  for (const sell of result.sells) {
2485
- const pnlColor = sell.realizedPnL >= 0 ? pc13.green : pc13.red;
2547
+ const pnlColor = sell.realizedPnL >= 0 ? pc14.green : pc14.red;
2486
2548
  const pnlSign = sell.realizedPnL >= 0 ? "+" : "";
2487
2549
  printKeyValue(sell.asset, `${formatAssetAmount4(sell.amount, sell.asset)} \u2192 ${formatUsd15(sell.usdValue)} ${pnlColor(`${pnlSign}${formatUsd15(sell.realizedPnL)}`)}`);
2488
2550
  }
2489
2551
  if (result.failed && result.failed.length > 0) {
2490
2552
  for (const f of result.failed) {
2491
- console.error(pc13.yellow(` \u26A0 ${f.asset}: ${f.reason}`));
2553
+ console.error(pc14.yellow(` \u26A0 ${f.asset}: ${f.reason}`));
2492
2554
  }
2493
2555
  }
2494
2556
  printSeparator();
2495
2557
  printKeyValue("Total proceeds", formatUsd15(result.totalProceeds));
2496
- const rpnlColor = result.realizedPnL >= 0 ? pc13.green : pc13.red;
2558
+ const rpnlColor = result.realizedPnL >= 0 ? pc14.green : pc14.red;
2497
2559
  const rpnlSign = result.realizedPnL >= 0 ? "+" : "";
2498
2560
  printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd15(result.realizedPnL)}`));
2499
2561
  printBlank();
@@ -2520,8 +2582,8 @@ function registerInvest(program2) {
2520
2582
  const target = status.definition.allocations[pos.asset] ?? 0;
2521
2583
  const actual = status.currentWeights[pos.asset] ?? 0;
2522
2584
  const drift = actual - target;
2523
- const driftColor = Math.abs(drift) > 3 ? pc13.yellow : pc13.dim;
2524
- const pnlColor = pos.unrealizedPnL >= 0 ? pc13.green : pc13.red;
2585
+ const driftColor = Math.abs(drift) > 3 ? pc14.yellow : pc14.dim;
2586
+ const pnlColor = pos.unrealizedPnL >= 0 ? pc14.green : pc14.red;
2525
2587
  const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
2526
2588
  printKeyValue(
2527
2589
  pos.asset,
@@ -2552,7 +2614,7 @@ function registerInvest(program2) {
2552
2614
  printSuccess(`Rebalanced ${name} strategy`);
2553
2615
  printSeparator();
2554
2616
  for (const t of result.trades) {
2555
- const action = t.action === "buy" ? pc13.green("BUY") : pc13.red("SELL");
2617
+ const action = t.action === "buy" ? pc14.green("BUY") : pc14.red("SELL");
2556
2618
  printKeyValue(t.asset, `${action} ${formatUsd15(t.usdAmount)} (${formatAssetAmount4(t.amount, t.asset)})`);
2557
2619
  }
2558
2620
  printSeparator();
@@ -2569,7 +2631,7 @@ function registerInvest(program2) {
2569
2631
  for (const pair of opts.alloc) {
2570
2632
  const [asset, pctStr] = pair.split(":");
2571
2633
  if (!asset || !pctStr) {
2572
- console.error(pc13.red(` \u2717 Invalid allocation: '${pair}'. Use ASSET:PCT format (e.g. SUI:60)`));
2634
+ console.error(pc14.red(` \u2717 Invalid allocation: '${pair}'. Use ASSET:PCT format (e.g. SUI:60)`));
2573
2635
  process.exitCode = 1;
2574
2636
  return;
2575
2637
  }
@@ -2596,7 +2658,7 @@ function registerInvest(program2) {
2596
2658
  const pin = await resolvePin();
2597
2659
  const agent = await T200024.create({ pin, keyPath: opts.key });
2598
2660
  if (agent.portfolio.hasStrategyPositions(name.toLowerCase())) {
2599
- console.error(pc13.red(` \u2717 Strategy '${name}' has open positions. Sell first: t2000 invest strategy sell ${name}`));
2661
+ console.error(pc14.red(` \u2717 Strategy '${name}' has open positions. Sell first: t2000 invest strategy sell ${name}`));
2600
2662
  process.exitCode = 1;
2601
2663
  return;
2602
2664
  }
@@ -2617,12 +2679,12 @@ function registerInvest(program2) {
2617
2679
  try {
2618
2680
  const parsed = parseFloat(amount);
2619
2681
  if (isNaN(parsed) || parsed < 1) {
2620
- console.error(pc13.red(" \u2717 Amount must be at least $1"));
2682
+ console.error(pc14.red(" \u2717 Amount must be at least $1"));
2621
2683
  process.exitCode = 1;
2622
2684
  return;
2623
2685
  }
2624
2686
  if (!["daily", "weekly", "monthly"].includes(frequency)) {
2625
- console.error(pc13.red(" \u2717 Frequency must be daily, weekly, or monthly"));
2687
+ console.error(pc14.red(" \u2717 Frequency must be daily, weekly, or monthly"));
2626
2688
  process.exitCode = 1;
2627
2689
  return;
2628
2690
  }
@@ -2632,7 +2694,7 @@ function registerInvest(program2) {
2632
2694
  const isStrategy = target ? target.toLowerCase() in allStrategies : false;
2633
2695
  const isAsset = target ? target.toUpperCase() in INVESTMENT_ASSETS2 : false;
2634
2696
  if (target && !isStrategy && !isAsset) {
2635
- console.error(pc13.red(` \u2717 '${target}' is not a valid strategy or asset`));
2697
+ console.error(pc14.red(` \u2717 '${target}' is not a valid strategy or asset`));
2636
2698
  process.exitCode = 1;
2637
2699
  return;
2638
2700
  }
@@ -2679,9 +2741,9 @@ function registerInvest(program2) {
2679
2741
  printSeparator();
2680
2742
  for (const s of status.schedules) {
2681
2743
  const target = s.strategy ?? s.asset ?? "?";
2682
- const statusTag = s.enabled ? pc13.green("active") : pc13.dim("paused");
2744
+ const statusTag = s.enabled ? pc14.green("active") : pc14.dim("paused");
2683
2745
  printKeyValue(s.id, `${formatUsd15(s.amount)} ${s.frequency} \u2192 ${target} ${statusTag}`);
2684
- printLine(` ${pc13.dim(`Next: ${new Date(s.nextRun).toLocaleDateString()} \xB7 Runs: ${s.runCount} \xB7 Total: ${formatUsd15(s.totalInvested)}`)}`);
2746
+ printLine(` ${pc14.dim(`Next: ${new Date(s.nextRun).toLocaleDateString()} \xB7 Runs: ${s.runCount} \xB7 Total: ${formatUsd15(s.totalInvested)}`)}`);
2685
2747
  }
2686
2748
  printSeparator();
2687
2749
  if (status.pendingRuns.length > 0) {
@@ -2724,7 +2786,7 @@ function registerInvest(program2) {
2724
2786
  }
2725
2787
  if (result.skipped.length > 0) {
2726
2788
  for (const skip of result.skipped) {
2727
- printLine(` ${pc13.yellow("\u26A0")} Skipped ${skip.scheduleId}: ${skip.reason}`);
2789
+ printLine(` ${pc14.yellow("\u26A0")} Skipped ${skip.scheduleId}: ${skip.reason}`);
2728
2790
  }
2729
2791
  }
2730
2792
  printBlank();
@@ -2751,22 +2813,22 @@ function registerInvest(program2) {
2751
2813
  }
2752
2814
 
2753
2815
  // src/commands/portfolio.ts
2754
- import pc14 from "picocolors";
2816
+ import pc15 from "picocolors";
2755
2817
  import { T2000 as T200025, formatUsd as formatUsd16, formatAssetAmount as formatAssetAmount5 } from "@t2000/sdk";
2756
2818
  function printPositionLine(pos, rewardKeys) {
2757
2819
  if (pos.currentPrice === 0 && pos.totalAmount > 0) {
2758
2820
  printKeyValue(
2759
2821
  pos.asset,
2760
- `${formatAssetAmount5(pos.totalAmount, pos.asset)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${pc14.yellow("unavailable")}`
2822
+ `${formatAssetAmount5(pos.totalAmount, pos.asset)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${pc15.yellow("unavailable")}`
2761
2823
  );
2762
2824
  } else {
2763
- const pnlColor = pos.unrealizedPnL >= 0 ? pc14.green : pc14.red;
2825
+ const pnlColor = pos.unrealizedPnL >= 0 ? pc15.green : pc15.red;
2764
2826
  const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
2765
2827
  let yieldSuffix = "";
2766
2828
  if (pos.earning && pos.earningApy) {
2767
2829
  const hasRewards = rewardKeys?.has(`${pos.earningProtocol}:${pos.asset}`);
2768
- const rewardTag = hasRewards ? ` ${pc14.yellow("+rewards")}` : "";
2769
- yieldSuffix = ` ${pc14.cyan(`${pos.earningApy.toFixed(1)}% APY (${pos.earningProtocol})`)}${rewardTag}`;
2830
+ const rewardTag = hasRewards ? ` ${pc15.yellow("+rewards")}` : "";
2831
+ yieldSuffix = ` ${pc15.cyan(`${pos.earningApy.toFixed(1)}% APY (${pos.earningProtocol})`)}${rewardTag}`;
2770
2832
  }
2771
2833
  printKeyValue(
2772
2834
  pos.asset,
@@ -2807,19 +2869,19 @@ function registerPortfolio(program2) {
2807
2869
  stratLabel = def.name;
2808
2870
  } catch {
2809
2871
  }
2810
- printLine(` ${pc14.bold(pc14.cyan(`\u25B8 ${stratLabel}`))}`);
2872
+ printLine(` ${pc15.bold(pc15.cyan(`\u25B8 ${stratLabel}`))}`);
2811
2873
  printSeparator();
2812
2874
  for (const pos of positions) {
2813
2875
  printPositionLine(pos, rewardKeys);
2814
2876
  }
2815
2877
  const stratValue = positions.reduce((s, p) => s + p.currentValue, 0);
2816
- printLine(` ${pc14.dim(`Subtotal: ${formatUsd16(stratValue)}`)}`);
2878
+ printLine(` ${pc15.dim(`Subtotal: ${formatUsd16(stratValue)}`)}`);
2817
2879
  printBlank();
2818
2880
  }
2819
2881
  }
2820
2882
  if (hasDirectPositions) {
2821
2883
  if (hasStrategyPositions) {
2822
- printLine(` ${pc14.bold(pc14.cyan("\u25B8 Direct"))}`);
2884
+ printLine(` ${pc15.bold(pc15.cyan("\u25B8 Direct"))}`);
2823
2885
  }
2824
2886
  printSeparator();
2825
2887
  for (const pos of portfolio.positions) {
@@ -2827,21 +2889,21 @@ function registerPortfolio(program2) {
2827
2889
  }
2828
2890
  if (hasStrategyPositions) {
2829
2891
  const directValue = portfolio.positions.reduce((s, p) => s + p.currentValue, 0);
2830
- printLine(` ${pc14.dim(`Subtotal: ${formatUsd16(directValue)}`)}`);
2892
+ printLine(` ${pc15.dim(`Subtotal: ${formatUsd16(directValue)}`)}`);
2831
2893
  }
2832
2894
  }
2833
2895
  printSeparator();
2834
2896
  const hasPriceUnavailable = portfolio.positions.some((p) => p.currentPrice === 0 && p.totalAmount > 0);
2835
2897
  if (hasPriceUnavailable) {
2836
- printInfo(pc14.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
2898
+ printInfo(pc15.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
2837
2899
  }
2838
2900
  printKeyValue("Total invested", formatUsd16(portfolio.totalInvested));
2839
2901
  printKeyValue("Current value", formatUsd16(portfolio.totalValue));
2840
- const upnlColor = portfolio.unrealizedPnL >= 0 ? pc14.green : pc14.red;
2902
+ const upnlColor = portfolio.unrealizedPnL >= 0 ? pc15.green : pc15.red;
2841
2903
  const upnlSign = portfolio.unrealizedPnL >= 0 ? "+" : "";
2842
2904
  printKeyValue("Unrealized P&L", upnlColor(`${upnlSign}${formatUsd16(portfolio.unrealizedPnL)} (${upnlSign}${portfolio.unrealizedPnLPct.toFixed(1)}%)`));
2843
2905
  if (portfolio.realizedPnL !== 0) {
2844
- const rpnlColor = portfolio.realizedPnL >= 0 ? pc14.green : pc14.red;
2906
+ const rpnlColor = portfolio.realizedPnL >= 0 ? pc15.green : pc15.red;
2845
2907
  const rpnlSign = portfolio.realizedPnL >= 0 ? "+" : "";
2846
2908
  printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd16(portfolio.realizedPnL)}`));
2847
2909
  }
@@ -2853,7 +2915,7 @@ function registerPortfolio(program2) {
2853
2915
  }
2854
2916
 
2855
2917
  // src/commands/claimRewards.ts
2856
- import pc15 from "picocolors";
2918
+ import pc16 from "picocolors";
2857
2919
  import { T2000 as T200026, formatUsd as formatUsd17 } from "@t2000/sdk";
2858
2920
  function registerClaimRewards(program2) {
2859
2921
  program2.command("claim-rewards").description("Claim pending protocol rewards").option("--key <path>", "Key file path").action(async (opts) => {
@@ -2867,20 +2929,20 @@ function registerClaimRewards(program2) {
2867
2929
  }
2868
2930
  printBlank();
2869
2931
  if (result.rewards.length === 0) {
2870
- printLine(` ${pc15.dim("No rewards to claim")}`);
2932
+ printLine(` ${pc16.dim("No rewards to claim")}`);
2871
2933
  printBlank();
2872
2934
  return;
2873
2935
  }
2874
2936
  const protocols = [...new Set(result.rewards.map((r) => r.protocol))];
2875
- printLine(` ${pc15.green("\u2713")} Claimed and converted rewards to USDC`);
2937
+ printLine(` ${pc16.green("\u2713")} Claimed and converted rewards to USDC`);
2876
2938
  printSeparator();
2877
2939
  const received = result.usdcReceived;
2878
2940
  if (received >= 0.01) {
2879
- printKeyValue("Received", `${pc15.green(formatUsd17(received))} USDC`);
2941
+ printKeyValue("Received", `${pc16.green(formatUsd17(received))} USDC`);
2880
2942
  } else if (received > 0) {
2881
- printKeyValue("Received", `${pc15.green("< $0.01")} USDC`);
2943
+ printKeyValue("Received", `${pc16.green("< $0.01")} USDC`);
2882
2944
  } else {
2883
- printKeyValue("Received", `${pc15.dim("< $0.01 USDC (rewards are still accruing)")}`);
2945
+ printKeyValue("Received", `${pc16.dim("< $0.01 USDC (rewards are still accruing)")}`);
2884
2946
  }
2885
2947
  printKeyValue("Source", protocols.join(", "));
2886
2948
  if (result.tx) {