@t2000/cli 0.22.23 → 0.22.25

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
@@ -7,7 +7,6 @@ import {
7
7
  import {
8
8
  ContactManager,
9
9
  INVESTMENT_ASSETS,
10
- MIST_PER_SUI,
11
10
  STABLE_ASSETS,
12
11
  SUPPORTED_ASSETS,
13
12
  SafeguardEnforcer,
@@ -16,13 +15,12 @@ import {
16
15
  formatUsd,
17
16
  getGasStatus,
18
17
  keypairFromPrivateKey,
19
- listSentinels,
20
18
  saveKey,
21
19
  truncateAddress,
22
20
  walletExists
23
- } from "./chunk-RN7Z6TWD.js";
21
+ } from "./chunk-FM4762OE.js";
24
22
  import "./chunk-V7PXDEKG.js";
25
- import "./chunk-KHIL2KNW.js";
23
+ import "./chunk-XOAZJ42V.js";
26
24
  import "./chunk-3XUF7GM3.js";
27
25
  import {
28
26
  __commonJS,
@@ -3639,12 +3637,15 @@ function registerInit(program3) {
3639
3637
  if (pin !== pinConfirm) throw new Error("PINs do not match");
3640
3638
  printBlank();
3641
3639
  printInfo("Creating agent wallet...");
3642
- const { address: addr, sponsored } = await T2000.init({ pin, keyPath: opts.key, sponsored: opts.sponsor });
3640
+ const { address: addr, sponsored, usdcSponsored } = await T2000.init({ pin, keyPath: opts.key, sponsored: opts.sponsor });
3643
3641
  address = addr;
3644
3642
  await saveSession(pin);
3645
3643
  printSuccess("Keypair generated");
3646
3644
  printSuccess(`Network ${import_picocolors2.default.dim("Sui mainnet")}`);
3647
3645
  printSuccess(`Gas sponsorship ${import_picocolors2.default.dim(sponsored ? "enabled" : "disabled")}`);
3646
+ if (usdcSponsored) {
3647
+ printSuccess(`USDC onboarding ${import_picocolors2.default.dim("$1 USDC funded")}`);
3648
+ }
3648
3649
  printBlank();
3649
3650
  printInfo("Setting up accounts...");
3650
3651
  printLine(
@@ -3709,7 +3710,7 @@ function registerInit(program3) {
3709
3710
  console.log(` \u2502 ${import_picocolors2.default.cyan("t2000 buy 100 BTC")} \u2502`);
3710
3711
  console.log(` \u2502 \u2502`);
3711
3712
  }
3712
- console.log(` \u2502 Deposit USDC to get started: \u2502`);
3713
+ console.log(` \u2502 Your address: \u2502`);
3713
3714
  console.log(` \u2502 ${import_picocolors2.default.yellow(address)} \u2502`);
3714
3715
  console.log(` \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518`);
3715
3716
  console.log("");
@@ -4006,7 +4007,7 @@ function registerHistory(program3) {
4006
4007
 
4007
4008
  // src/commands/exportKey.ts
4008
4009
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
4009
- import { resolve as resolve2 } from "path";
4010
+ import { resolve as resolve2, join as join2 } from "path";
4010
4011
  import { homedir as homedir3 } from "os";
4011
4012
  var LOCKFILE = resolve2(homedir3(), ".t2000", ".pin-lock");
4012
4013
  var MAX_ATTEMPTS = 5;
@@ -4026,6 +4027,12 @@ async function setLockState(state) {
4026
4027
  function registerExport(program3) {
4027
4028
  program3.command("export").description("Export private key (raw Ed25519 hex)").option("--key <path>", "Key file path").option("--yes", "Skip confirmation").action(async (opts) => {
4028
4029
  try {
4030
+ const enforcer = new SafeguardEnforcer(join2(homedir3(), ".t2000"));
4031
+ enforcer.load();
4032
+ if (enforcer.getConfig().locked) {
4033
+ printError("Agent is locked. Unlock first: t2000 unlock");
4034
+ return;
4035
+ }
4029
4036
  const lock = await getLockState();
4030
4037
  if (lock.lockedUntil > Date.now()) {
4031
4038
  const remainSec = Math.ceil((lock.lockedUntil - Date.now()) / 1e3);
@@ -4076,9 +4083,17 @@ function registerExport(program3) {
4076
4083
  }
4077
4084
 
4078
4085
  // src/commands/importKey.ts
4086
+ import { join as join3 } from "path";
4087
+ import { homedir as homedir4 } from "os";
4079
4088
  function registerImport(program3) {
4080
4089
  program3.command("import").description("Import a wallet from private key").option("--key <path>", "Key file path").action(async (opts) => {
4081
4090
  try {
4091
+ const enforcer = new SafeguardEnforcer(join3(homedir4(), ".t2000"));
4092
+ enforcer.load();
4093
+ if (enforcer.getConfig().locked) {
4094
+ printError("Agent is locked. Unlock first: t2000 unlock");
4095
+ return;
4096
+ }
4082
4097
  let privateKey;
4083
4098
  if (process.env.T2000_PRIVATE_KEY) {
4084
4099
  privateKey = process.env.T2000_PRIVATE_KEY;
@@ -4457,10 +4472,10 @@ function registerFundStatus(program3) {
4457
4472
 
4458
4473
  // src/commands/config.ts
4459
4474
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
4460
- import { join as join2 } from "path";
4461
- import { homedir as homedir4 } from "os";
4462
- var CONFIG_DIR2 = join2(homedir4(), ".t2000");
4463
- var CONFIG_PATH2 = join2(CONFIG_DIR2, "config.json");
4475
+ import { join as join4 } from "path";
4476
+ import { homedir as homedir5 } from "os";
4477
+ var CONFIG_DIR2 = join4(homedir5(), ".t2000");
4478
+ var CONFIG_PATH2 = join4(CONFIG_DIR2, "config.json");
4464
4479
  var SAFEGUARD_KEYS = /* @__PURE__ */ new Set(["locked", "maxPerTx", "maxDailySend", "dailyUsed", "dailyResetDate", "alertThreshold", "maxLeverage", "maxPositionSize"]);
4465
4480
  function getNestedValue(obj, path) {
4466
4481
  const parts = path.split(".");
@@ -7328,8 +7343,8 @@ var cors = (options) => {
7328
7343
  // src/commands/serve.ts
7329
7344
  import { randomBytes } from "crypto";
7330
7345
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
7331
- import { join as join3 } from "path";
7332
- import { homedir as homedir5 } from "os";
7346
+ import { join as join5 } from "path";
7347
+ import { homedir as homedir6 } from "os";
7333
7348
 
7334
7349
  // ../../node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/utils/stream.js
7335
7350
  var StreamingApi = class {
@@ -7481,8 +7496,8 @@ var streamSSE = (c, cb, onError) => {
7481
7496
  };
7482
7497
 
7483
7498
  // src/commands/serve.ts
7484
- var CONFIG_DIR3 = join3(homedir5(), ".t2000");
7485
- var TOKEN_PATH = join3(CONFIG_DIR3, "config.json");
7499
+ var CONFIG_DIR3 = join5(homedir6(), ".t2000");
7500
+ var TOKEN_PATH = join5(CONFIG_DIR3, "config.json");
7486
7501
  function generateToken() {
7487
7502
  return `t2k_${randomBytes(24).toString("hex")}`;
7488
7503
  }
@@ -7848,9 +7863,9 @@ function collectHeaders(value, previous) {
7848
7863
  }
7849
7864
 
7850
7865
  // src/commands/lock.ts
7851
- import { join as join4 } from "path";
7852
- import { homedir as homedir6 } from "os";
7853
- var CONFIG_DIR4 = join4(homedir6(), ".t2000");
7866
+ import { join as join6 } from "path";
7867
+ import { homedir as homedir7 } from "os";
7868
+ var CONFIG_DIR4 = join6(homedir7(), ".t2000");
7854
7869
  function registerLock(program3) {
7855
7870
  program3.command("lock").description("Lock agent \u2014 freeze all operations").action(async () => {
7856
7871
  try {
@@ -7872,7 +7887,7 @@ function registerLock(program3) {
7872
7887
  });
7873
7888
  program3.command("unlock").description("Unlock agent \u2014 resume operations").action(async () => {
7874
7889
  try {
7875
- const { T2000: T20003 } = await import("./dist-G5YKLWC5.js");
7890
+ const { T2000: T20003 } = await import("./dist-LKHCKFGY.js");
7876
7891
  const MAX_ATTEMPTS2 = 3;
7877
7892
  let pin;
7878
7893
  for (let attempt = 1; attempt <= MAX_ATTEMPTS2; attempt++) {
@@ -7923,161 +7938,26 @@ function registerLock(program3) {
7923
7938
  });
7924
7939
  }
7925
7940
 
7926
- // src/commands/sentinel.ts
7927
- var import_picocolors11 = __toESM(require_picocolors(), 1);
7928
- function formatSui(mist) {
7929
- return (Number(mist) / Number(MIST_PER_SUI)).toFixed(2);
7930
- }
7931
- function registerSentinel(program3) {
7932
- const sentinel = program3.command("sentinel").description("Interact with Sui Sentinel \u2014 attack AI agents, earn bounties");
7933
- sentinel.command("list").description("List active sentinels with prize pools").action(async () => {
7934
- try {
7935
- const pin = await resolvePin();
7936
- const agent = await T2000.create({ pin });
7937
- const sentinels = await agent.sentinelList();
7938
- if (isJsonMode()) {
7939
- printJson(sentinels.map((s) => ({
7940
- ...s,
7941
- attackFee: s.attackFee.toString(),
7942
- prizePool: s.prizePool.toString()
7943
- })));
7944
- return;
7945
- }
7946
- if (sentinels.length === 0) {
7947
- printBlank();
7948
- printInfo("No active sentinels found.");
7949
- printBlank();
7950
- return;
7951
- }
7952
- printHeader("Active Sentinels");
7953
- sentinels.forEach((s) => {
7954
- const pool = `${formatSui(s.prizePool)} SUI`.padEnd(12);
7955
- const fee = `${formatSui(s.attackFee)} SUI`.padEnd(12);
7956
- printLine(` ${s.name}`);
7957
- printLine(` ${import_picocolors11.default.dim(`Pool: ${pool}Fee: ${fee}Attacks: ${s.totalAttacks}`)}`);
7958
- printLine(` ${import_picocolors11.default.dim(s.objectId)}`);
7959
- printBlank();
7960
- });
7961
- printBlank();
7962
- printInfo(`${sentinels.length} active sentinel${sentinels.length === 1 ? "" : "s"}`);
7963
- printBlank();
7964
- } catch (error) {
7965
- handleError(error);
7966
- }
7967
- });
7968
- sentinel.command("info").description("Show details for a sentinel").argument("<id>", "Sentinel object ID").action(async (id) => {
7969
- try {
7970
- const pin = await resolvePin();
7971
- const agent = await T2000.create({ pin });
7972
- const s = await agent.sentinelInfo(id);
7973
- if (isJsonMode()) {
7974
- printJson({
7975
- ...s,
7976
- attackFee: s.attackFee.toString(),
7977
- prizePool: s.prizePool.toString()
7978
- });
7979
- return;
7980
- }
7981
- printHeader(s.name);
7982
- printKeyValue("Object ID", s.objectId);
7983
- printKeyValue("Agent ID", s.id);
7984
- printKeyValue("Model", s.model);
7985
- printKeyValue("State", s.state);
7986
- printKeyValue("Attack Fee", `${formatSui(s.attackFee)} SUI`);
7987
- printKeyValue("Prize Pool", `${formatSui(s.prizePool)} SUI`);
7988
- printKeyValue("Total Attacks", String(s.totalAttacks));
7989
- printKeyValue("Breaches", String(s.successfulBreaches));
7990
- if (s.systemPrompt) {
7991
- printBlank();
7992
- printKeyValue("System Prompt", "");
7993
- printLine(` ${import_picocolors11.default.dim(s.systemPrompt.slice(0, 500))}`);
7994
- }
7995
- printBlank();
7996
- } catch (error) {
7997
- handleError(error);
7998
- }
7999
- });
8000
- sentinel.command("attack").description("Attack a sentinel with a prompt (costs SUI)").argument("<id>", "Sentinel object ID").argument("[prompt]", "Attack prompt").option("--fee <sui>", "Override attack fee in SUI").option("--key <path>", "Key file path").action(async (id, prompt, opts) => {
8001
- try {
8002
- if (!prompt) {
8003
- throw new Error('Prompt is required. Usage: t2000 sentinel attack <id> "your prompt"');
8004
- }
8005
- const pin = await resolvePin();
8006
- const agent = await T2000.create({ pin, keyPath: opts.key });
8007
- const feeMist = opts.fee ? BigInt(Math.round(parseFloat(opts.fee) * Number(MIST_PER_SUI))) : void 0;
8008
- if (isJsonMode()) {
8009
- const result2 = await agent.sentinelAttack(id, prompt, feeMist);
8010
- printJson({
8011
- ...result2,
8012
- verdict: {
8013
- ...result2.verdict
8014
- }
8015
- });
8016
- return;
8017
- }
8018
- printBlank();
8019
- printLine(` ${import_picocolors11.default.dim("\u23F3")} Requesting attack...`);
8020
- const result = await agent.sentinelAttack(id, prompt, feeMist);
8021
- printBlank();
8022
- if (result.won) {
8023
- printSuccess(`BREACHED! (score: ${result.verdict.score}/100)`);
8024
- } else {
8025
- printError(`DEFENDED (score: ${result.verdict.score}/100)`);
8026
- }
8027
- printBlank();
8028
- printKeyValue("Agent", result.verdict.agentResponse.slice(0, 200));
8029
- printKeyValue("Jury", result.verdict.juryResponse.slice(0, 200));
8030
- if (result.verdict.funResponse) {
8031
- printKeyValue("Fun", result.verdict.funResponse.slice(0, 200));
8032
- }
8033
- printBlank();
8034
- printKeyValue("Fee Paid", `${result.feePaid} SUI`);
8035
- printKeyValue("Request Tx", explorerUrl(result.requestTx));
8036
- printKeyValue("Settle Tx", explorerUrl(result.settleTx));
8037
- printBlank();
8038
- } catch (error) {
8039
- handleError(error);
8040
- }
8041
- });
8042
- }
8043
-
8044
7941
  // src/commands/earn.ts
8045
- var import_picocolors12 = __toESM(require_picocolors(), 1);
8046
- function mistToSui(mist) {
8047
- return Number(mist) / Number(MIST_PER_SUI);
8048
- }
8049
- function bestTarget(sentinels) {
8050
- const withPool = sentinels.filter((s) => s.prizePool > 0n && s.attackFee > 0n);
8051
- if (withPool.length === 0) return void 0;
8052
- return withPool.sort((a, b) => {
8053
- const ratioA = Number(a.prizePool) / Number(a.attackFee);
8054
- const ratioB = Number(b.prizePool) / Number(b.attackFee);
8055
- return ratioB - ratioA;
8056
- })[0];
8057
- }
7942
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
8058
7943
  function registerEarn(program3) {
8059
- program3.command("earn").description("Show all earning opportunities \u2014 savings yield + sentinel bounties").option("--key <path>", "Key file path").action(async (opts) => {
7944
+ program3.command("earn").description("Show all earning opportunities \u2014 savings yield + investment yield").option("--key <path>", "Key file path").action(async (opts) => {
8060
7945
  try {
8061
7946
  const pin = await resolvePin();
8062
7947
  const agent = await T2000.create({ pin, keyPath: opts.key });
8063
- const [positionsResult, portfolioResult, ratesResult, sentinels] = await Promise.allSettled([
7948
+ const [positionsResult, portfolioResult, ratesResult] = await Promise.allSettled([
8064
7949
  agent.positions(),
8065
7950
  agent.getPortfolio(),
8066
- agent.allRates("USDC"),
8067
- listSentinels()
7951
+ agent.allRates("USDC")
8068
7952
  ]);
8069
7953
  const posData = positionsResult.status === "fulfilled" ? positionsResult.value : null;
8070
7954
  const portfolio = portfolioResult.status === "fulfilled" ? portfolioResult.value : null;
8071
7955
  const ratesData = ratesResult.status === "fulfilled" ? ratesResult.value : null;
8072
- const agents = sentinels.status === "fulfilled" ? sentinels.value : null;
8073
7956
  const savePositions = posData?.positions.filter((p) => p.type === "save") ?? [];
8074
7957
  const totalSaved = savePositions.reduce((s, p) => s + p.amount, 0);
8075
7958
  const earningInvestments = portfolio?.positions.filter((p) => p.earning && p.currentValue > 0) ?? [];
8076
7959
  const bestSaveApy = ratesData?.length ? Math.max(...ratesData.map((r) => r.rates.saveApy)) : 0;
8077
7960
  if (isJsonMode()) {
8078
- const best = agents ? bestTarget(agents) : void 0;
8079
- const totalPool = agents ? agents.reduce((sum, s) => sum + mistToSui(s.prizePool), 0) : 0;
8080
- const cheapest = agents ? Math.min(...agents.map((s) => mistToSui(s.attackFee))) : 0;
8081
7961
  printJson({
8082
7962
  savings: savePositions.map((p) => ({
8083
7963
  protocol: p.protocol,
@@ -8097,24 +7977,12 @@ function registerEarn(program3) {
8097
7977
  value: p.currentValue,
8098
7978
  protocol: p.earningProtocol,
8099
7979
  apy: p.earningApy
8100
- })),
8101
- sentinel: agents ? {
8102
- activeSentinels: agents.length,
8103
- totalPrizePool: Number(totalPool.toFixed(2)),
8104
- cheapestFee: Number(cheapest.toFixed(2)),
8105
- bestTarget: best ? {
8106
- name: best.name,
8107
- objectId: best.objectId,
8108
- prizePool: mistToSui(best.prizePool),
8109
- attackFee: mistToSui(best.attackFee),
8110
- ratio: Number((Number(best.prizePool) / Number(best.attackFee)).toFixed(1))
8111
- } : null
8112
- } : null
7980
+ }))
8113
7981
  });
8114
7982
  return;
8115
7983
  }
8116
7984
  printHeader("Earning Opportunities");
8117
- printLine(import_picocolors12.default.bold("SAVINGS") + import_picocolors12.default.dim(" \u2014 Passive Yield"));
7985
+ printLine(import_picocolors11.default.bold("SAVINGS") + import_picocolors11.default.dim(" \u2014 Passive Yield"));
8118
7986
  printDivider();
8119
7987
  if (savePositions.length > 0) {
8120
7988
  for (const pos of savePositions) {
@@ -8123,7 +7991,7 @@ function registerEarn(program3) {
8123
7991
  if (dailyYield > 1e-4) {
8124
7992
  const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd(dailyYield);
8125
7993
  const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd(dailyYield * 30);
8126
- printLine(import_picocolors12.default.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
7994
+ printLine(import_picocolors11.default.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
8127
7995
  }
8128
7996
  }
8129
7997
  if (savePositions.length > 1) {
@@ -8138,7 +8006,7 @@ function registerEarn(program3) {
8138
8006
  const example = 100;
8139
8007
  const daily = example * bestSaveApy / 100 / 365;
8140
8008
  const monthly = daily * 30;
8141
- printLine(import_picocolors12.default.dim(` Save $${example} \u2192 ~$${daily.toFixed(2)}/day \xB7 ~$${monthly.toFixed(2)}/month`));
8009
+ printLine(import_picocolors11.default.dim(` Save $${example} \u2192 ~$${daily.toFixed(2)}/day \xB7 ~$${monthly.toFixed(2)}/month`));
8142
8010
  printBlank();
8143
8011
  printInfo("No savings yet \u2014 run `t2000 save <amount>` to start");
8144
8012
  } else if (posData) {
@@ -8148,7 +8016,7 @@ function registerEarn(program3) {
8148
8016
  }
8149
8017
  if (earningInvestments.length > 0) {
8150
8018
  printBlank();
8151
- printLine(import_picocolors12.default.bold("INVESTMENTS") + import_picocolors12.default.dim(" \u2014 Earning Yield"));
8019
+ printLine(import_picocolors11.default.bold("INVESTMENTS") + import_picocolors11.default.dim(" \u2014 Earning Yield"));
8152
8020
  printDivider();
8153
8021
  let totalInvestValue = 0;
8154
8022
  for (const pos of earningInvestments) {
@@ -8161,7 +8029,7 @@ function registerEarn(program3) {
8161
8029
  if (dailyYield > 1e-4) {
8162
8030
  const dailyStr = dailyYield < 0.01 ? `$${dailyYield.toFixed(4)}` : formatUsd(dailyYield);
8163
8031
  const monthlyStr = dailyYield * 30 < 0.01 ? `$${(dailyYield * 30).toFixed(4)}` : formatUsd(dailyYield * 30);
8164
- printLine(import_picocolors12.default.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
8032
+ printLine(import_picocolors11.default.dim(` ~${dailyStr}/day \xB7 ~${monthlyStr}/month`));
8165
8033
  }
8166
8034
  totalInvestValue += pos.currentValue;
8167
8035
  }
@@ -8171,31 +8039,10 @@ function registerEarn(program3) {
8171
8039
  }
8172
8040
  }
8173
8041
  printBlank();
8174
- printLine(import_picocolors12.default.bold("SENTINEL BOUNTIES") + import_picocolors12.default.dim(" \u2014 Active Red Teaming"));
8175
- printDivider();
8176
- if (agents && agents.length > 0) {
8177
- const totalPool = agents.reduce((sum, s) => sum + mistToSui(s.prizePool), 0);
8178
- const cheapest = Math.min(...agents.map((s) => mistToSui(s.attackFee)));
8179
- const best = bestTarget(agents);
8180
- printKeyValue("Active", `${agents.length} sentinels`);
8181
- printKeyValue("Prize Pools", `${totalPool.toFixed(2)} SUI available`);
8182
- printKeyValue("Cheapest Fee", `${cheapest.toFixed(2)} SUI`);
8183
- if (best) {
8184
- const ratio = (Number(best.prizePool) / Number(best.attackFee)).toFixed(1);
8185
- printKeyValue("Best Target", `${best.name} \u2014 ${mistToSui(best.prizePool).toFixed(2)} SUI pool (${ratio}x ratio)`);
8186
- }
8187
- } else if (agents) {
8188
- printInfo("No active bounties right now");
8189
- } else {
8190
- printInfo("Sentinel data unavailable");
8191
- }
8192
- printBlank();
8193
- printLine(import_picocolors12.default.bold("Quick Actions"));
8042
+ printLine(import_picocolors11.default.bold("Quick Actions"));
8194
8043
  printDivider();
8195
- printLine(` ${import_picocolors12.default.dim("t2000 save <amount> [asset]")} Save stablecoins for yield`);
8196
- printLine(` ${import_picocolors12.default.dim("t2000 invest earn <asset>")} Earn yield on investments`);
8197
- printLine(` ${import_picocolors12.default.dim("t2000 sentinel list")} Browse sentinel bounties`);
8198
- printLine(` ${import_picocolors12.default.dim("t2000 sentinel attack <id>")} Attack a sentinel`);
8044
+ printLine(` ${import_picocolors11.default.dim("t2000 save <amount> [asset]")} Save stablecoins for yield`);
8045
+ printLine(` ${import_picocolors11.default.dim("t2000 invest earn <asset>")} Earn yield on investments`);
8199
8046
  printBlank();
8200
8047
  } catch (error) {
8201
8048
  handleError(error);
@@ -8204,7 +8051,7 @@ function registerEarn(program3) {
8204
8051
  }
8205
8052
 
8206
8053
  // src/commands/rebalance.ts
8207
- var import_picocolors13 = __toESM(require_picocolors(), 1);
8054
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
8208
8055
  function registerRebalance(program3) {
8209
8056
  program3.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) => {
8210
8057
  try {
@@ -8231,24 +8078,24 @@ function registerRebalance(program3) {
8231
8078
  const diff = plan.newApy - plan.currentApy;
8232
8079
  if (diff < minYieldDiff) {
8233
8080
  printInfo(`Already optimized \u2014 ${plan.currentApy.toFixed(2)}% APY on ${plan.fromProtocol}`);
8234
- printLine(import_picocolors13.default.dim(` Best available: ${plan.newApy.toFixed(2)}% (${displayAsset(plan.toAsset)} on ${plan.toProtocol})`));
8235
- printLine(import_picocolors13.default.dim(` Difference: ${diff.toFixed(2)}% (below ${minYieldDiff}% threshold)`));
8081
+ printLine(import_picocolors12.default.dim(` Best available: ${plan.newApy.toFixed(2)}% (${displayAsset(plan.toAsset)} on ${plan.toProtocol})`));
8082
+ printLine(import_picocolors12.default.dim(` Difference: ${diff.toFixed(2)}% (below ${minYieldDiff}% threshold)`));
8236
8083
  } else if (plan.breakEvenDays > maxBreakEven && plan.estimatedSwapCost > 0) {
8237
8084
  printInfo(`Skipped \u2014 break-even of ${plan.breakEvenDays} days exceeds ${maxBreakEven}-day limit`);
8238
- printLine(import_picocolors13.default.dim(` ${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}%) \u2192 ${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}%)`));
8085
+ printLine(import_picocolors12.default.dim(` ${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}%) \u2192 ${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}%)`));
8239
8086
  } else {
8240
8087
  printInfo("Already at the best rate. Nothing to rebalance.");
8241
8088
  }
8242
8089
  printBlank();
8243
8090
  return;
8244
8091
  }
8245
- printLine(import_picocolors13.default.bold("Rebalance Plan"));
8092
+ printLine(import_picocolors12.default.bold("Rebalance Plan"));
8246
8093
  printDivider();
8247
8094
  printKeyValue("From", `${displayAsset(plan.fromAsset)} on ${plan.fromProtocol} (${plan.currentApy.toFixed(2)}% APY)`);
8248
8095
  printKeyValue("To", `${displayAsset(plan.toAsset)} on ${plan.toProtocol} (${plan.newApy.toFixed(2)}% APY)`);
8249
8096
  printKeyValue("Amount", formatUsd(plan.amount));
8250
8097
  printBlank();
8251
- printLine(import_picocolors13.default.bold("Economics"));
8098
+ printLine(import_picocolors12.default.bold("Economics"));
8252
8099
  printDivider();
8253
8100
  printKeyValue("APY Gain", `+${(plan.newApy - plan.currentApy).toFixed(2)}%`);
8254
8101
  printKeyValue("Annual Gain", `${formatUsd(plan.annualGain)}/year`);
@@ -8258,7 +8105,7 @@ function registerRebalance(program3) {
8258
8105
  }
8259
8106
  printBlank();
8260
8107
  if (plan.steps.length > 0) {
8261
- printLine(import_picocolors13.default.bold("Steps"));
8108
+ printLine(import_picocolors12.default.bold("Steps"));
8262
8109
  printDivider();
8263
8110
  for (let i = 0; i < plan.steps.length; i++) {
8264
8111
  const step = plan.steps[i];
@@ -8274,8 +8121,8 @@ function registerRebalance(program3) {
8274
8121
  printBlank();
8275
8122
  }
8276
8123
  if (opts.dryRun) {
8277
- printLine(import_picocolors13.default.bold(import_picocolors13.default.yellow("DRY RUN \u2014 Preview only, no transactions executed")));
8278
- printLine(import_picocolors13.default.dim(" Run `t2000 rebalance` to execute."));
8124
+ printLine(import_picocolors12.default.bold(import_picocolors12.default.yellow("DRY RUN \u2014 Preview only, no transactions executed")));
8125
+ printLine(import_picocolors12.default.dim(" Run `t2000 rebalance` to execute."));
8279
8126
  printBlank();
8280
8127
  return;
8281
8128
  }
@@ -8298,7 +8145,7 @@ function displayAsset(asset) {
8298
8145
  }
8299
8146
 
8300
8147
  // src/commands/exchange.ts
8301
- var import_picocolors14 = __toESM(require_picocolors(), 1);
8148
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
8302
8149
  function resolveAssetName(input) {
8303
8150
  const upper = input.toUpperCase();
8304
8151
  for (const key of Object.keys(SUPPORTED_ASSETS)) {
@@ -8309,7 +8156,7 @@ function resolveAssetName(input) {
8309
8156
  function registerExchange(program3) {
8310
8157
  program3.command("exchange <amount> <from> <to>").description('[deprecated \u2014 use "swap" instead] Exchange between tokens').option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percentage (default: 3)", "3").action(async (amount, from, to, opts) => {
8311
8158
  try {
8312
- console.error(import_picocolors14.default.yellow(' \u26A0 "exchange" is deprecated. Use "swap" instead: t2000 swap %s %s %s'), amount, from, to);
8159
+ console.error(import_picocolors13.default.yellow(' \u26A0 "exchange" is deprecated. Use "swap" instead: t2000 swap %s %s %s'), amount, from, to);
8313
8160
  const pin = await resolvePin();
8314
8161
  const agent = await T2000.create({ pin, keyPath: opts.key });
8315
8162
  const parsedAmount = parseFloat(amount);
@@ -8324,7 +8171,7 @@ function registerExchange(program3) {
8324
8171
  printJson(result);
8325
8172
  return;
8326
8173
  }
8327
- console.log(import_picocolors14.default.green(" \u2713 Swapped. Tx: %s"), result.tx);
8174
+ console.log(import_picocolors13.default.green(" \u2713 Swapped. Tx: %s"), result.tx);
8328
8175
  } catch (error) {
8329
8176
  handleError(error);
8330
8177
  }
@@ -8462,27 +8309,27 @@ function registerSwap(program3) {
8462
8309
 
8463
8310
  // src/commands/mcp.ts
8464
8311
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
8465
- import { join as join5, dirname as dirname2 } from "path";
8466
- import { homedir as homedir7 } from "os";
8312
+ import { join as join7, dirname as dirname2 } from "path";
8313
+ import { homedir as homedir8 } from "os";
8467
8314
  import { existsSync as existsSync4 } from "fs";
8468
8315
  var MCP_CONFIG = {
8469
8316
  command: "t2000",
8470
8317
  args: ["mcp"]
8471
8318
  };
8472
8319
  function getPlatformConfigs() {
8473
- const home = homedir7();
8320
+ const home = homedir8();
8474
8321
  return [
8475
8322
  {
8476
8323
  name: "Claude Desktop",
8477
- path: join5(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
8324
+ path: join7(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
8478
8325
  },
8479
8326
  {
8480
8327
  name: "Cursor",
8481
- path: join5(home, ".cursor", "mcp.json")
8328
+ path: join7(home, ".cursor", "mcp.json")
8482
8329
  },
8483
8330
  {
8484
8331
  name: "Windsurf",
8485
- path: join5(home, ".codeium", "windsurf", "mcp_config.json")
8332
+ path: join7(home, ".codeium", "windsurf", "mcp_config.json")
8486
8333
  }
8487
8334
  ];
8488
8335
  }
@@ -8506,7 +8353,7 @@ function registerMcp(program3) {
8506
8353
  mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
8507
8354
  let mod;
8508
8355
  try {
8509
- mod = await import("./dist-FDS4MNUV.js");
8356
+ mod = await import("./dist-ZTFOTMJO.js");
8510
8357
  } catch {
8511
8358
  console.error(
8512
8359
  "MCP server not installed. Run:\n npm install -g @t2000/mcp"
@@ -8657,15 +8504,15 @@ function registerContacts(program3) {
8657
8504
  }
8658
8505
 
8659
8506
  // src/commands/invest.ts
8660
- var import_picocolors15 = __toESM(require_picocolors(), 1);
8507
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
8661
8508
  function registerInvest(program3) {
8662
8509
  const investCmd = program3.command("invest").description("Investment strategies, DCA, and yield earning");
8663
8510
  investCmd.command("buy <amount> <asset>").description('[deprecated \u2014 use "buy" instead] Buy an asset').option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percent", "3").action(async (amount, asset, opts) => {
8664
8511
  try {
8665
- console.error(import_picocolors15.default.yellow(` \u26A0 "invest buy" is deprecated. Use: t2000 buy ${amount} ${asset}`));
8512
+ console.error(import_picocolors14.default.yellow(` \u26A0 "invest buy" is deprecated. Use: t2000 buy ${amount} ${asset}`));
8666
8513
  const parsed = parseFloat(amount);
8667
8514
  if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
8668
- console.error(import_picocolors15.default.red(" \u2717 Amount must be greater than $0"));
8515
+ console.error(import_picocolors14.default.red(" \u2717 Amount must be greater than $0"));
8669
8516
  process.exitCode = 1;
8670
8517
  return;
8671
8518
  }
@@ -8692,12 +8539,12 @@ function registerInvest(program3) {
8692
8539
  });
8693
8540
  investCmd.command("sell <amount> <asset>").description('[deprecated \u2014 use "sell" instead] Sell an asset').option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percent", "3").action(async (amount, asset, opts) => {
8694
8541
  try {
8695
- console.error(import_picocolors15.default.yellow(` \u26A0 "invest sell" is deprecated. Use: t2000 sell ${amount} ${asset}`));
8542
+ console.error(import_picocolors14.default.yellow(` \u26A0 "invest sell" is deprecated. Use: t2000 sell ${amount} ${asset}`));
8696
8543
  const isAll = amount.toLowerCase() === "all";
8697
8544
  if (!isAll) {
8698
8545
  const parsed = parseFloat(amount);
8699
8546
  if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
8700
- console.error(import_picocolors15.default.red(" \u2717 Amount must be greater than $0"));
8547
+ console.error(import_picocolors14.default.red(" \u2717 Amount must be greater than $0"));
8701
8548
  process.exitCode = 1;
8702
8549
  return;
8703
8550
  }
@@ -8719,7 +8566,7 @@ function registerInvest(program3) {
8719
8566
  printSuccess(`Sold ${formatAssetAmount(result.amount, sym)} ${sym} at ${formatUsd(result.price)}`);
8720
8567
  printKeyValue("Proceeds", formatUsd(result.usdValue));
8721
8568
  if (result.realizedPnL !== void 0) {
8722
- const pnlColor = result.realizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
8569
+ const pnlColor = result.realizedPnL >= 0 ? import_picocolors14.default.green : import_picocolors14.default.red;
8723
8570
  const pnlSign = result.realizedPnL >= 0 ? "+" : "";
8724
8571
  printKeyValue("Realized P&L", pnlColor(`${pnlSign}${formatUsd(result.realizedPnL)}`));
8725
8572
  }
@@ -8847,9 +8694,9 @@ function registerInvest(program3) {
8847
8694
  printSeparator();
8848
8695
  for (const [key, def] of Object.entries(all)) {
8849
8696
  const allocs = Object.entries(def.allocations).map(([a, p]) => `${a} ${p}%`).join(", ");
8850
- const tag = def.custom ? import_picocolors15.default.dim(" (custom)") : "";
8697
+ const tag = def.custom ? import_picocolors14.default.dim(" (custom)") : "";
8851
8698
  printKeyValue(key, `${allocs}${tag}`);
8852
- printLine(` ${import_picocolors15.default.dim(def.description)}`);
8699
+ printLine(` ${import_picocolors14.default.dim(def.description)}`);
8853
8700
  }
8854
8701
  printSeparator();
8855
8702
  const hasPositions = Object.keys(all).some((k) => agent.portfolio.hasStrategyPositions(k));
@@ -8865,7 +8712,7 @@ function registerInvest(program3) {
8865
8712
  try {
8866
8713
  const parsed = parseFloat(amount);
8867
8714
  if (isNaN(parsed) || parsed <= 0) {
8868
- console.error(import_picocolors15.default.red(" \u2717 Amount must be greater than $0"));
8715
+ console.error(import_picocolors14.default.red(" \u2717 Amount must be greater than $0"));
8869
8716
  process.exitCode = 1;
8870
8717
  return;
8871
8718
  }
@@ -8899,7 +8746,7 @@ function registerInvest(program3) {
8899
8746
  printKeyValue("Tx", explorerUrl(txDigests[0]));
8900
8747
  } else {
8901
8748
  for (const buy of result.buys) {
8902
- printLine(` ${import_picocolors15.default.dim(`${buy.asset}: ${explorerUrl(buy.tx)}`)}`);
8749
+ printLine(` ${import_picocolors14.default.dim(`${buy.asset}: ${explorerUrl(buy.tx)}`)}`);
8903
8750
  }
8904
8751
  }
8905
8752
  }
@@ -8921,18 +8768,18 @@ function registerInvest(program3) {
8921
8768
  printSuccess(`Sold all ${name} strategy positions`);
8922
8769
  printSeparator();
8923
8770
  for (const sell of result.sells) {
8924
- const pnlColor = sell.realizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
8771
+ const pnlColor = sell.realizedPnL >= 0 ? import_picocolors14.default.green : import_picocolors14.default.red;
8925
8772
  const pnlSign = sell.realizedPnL >= 0 ? "+" : "";
8926
8773
  printKeyValue(sell.asset, `${formatAssetAmount(sell.amount, sell.asset)} \u2192 ${formatUsd(sell.usdValue)} ${pnlColor(`${pnlSign}${formatUsd(sell.realizedPnL)}`)}`);
8927
8774
  }
8928
8775
  if (result.failed && result.failed.length > 0) {
8929
8776
  for (const f of result.failed) {
8930
- console.error(import_picocolors15.default.yellow(` \u26A0 ${f.asset}: ${f.reason}`));
8777
+ console.error(import_picocolors14.default.yellow(` \u26A0 ${f.asset}: ${f.reason}`));
8931
8778
  }
8932
8779
  }
8933
8780
  printSeparator();
8934
8781
  printKeyValue("Total proceeds", formatUsd(result.totalProceeds));
8935
- const rpnlColor = result.realizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
8782
+ const rpnlColor = result.realizedPnL >= 0 ? import_picocolors14.default.green : import_picocolors14.default.red;
8936
8783
  const rpnlSign = result.realizedPnL >= 0 ? "+" : "";
8937
8784
  printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd(result.realizedPnL)}`));
8938
8785
  printBlank();
@@ -8959,8 +8806,8 @@ function registerInvest(program3) {
8959
8806
  const target = status.definition.allocations[pos.asset] ?? 0;
8960
8807
  const actual = status.currentWeights[pos.asset] ?? 0;
8961
8808
  const drift = actual - target;
8962
- const driftColor = Math.abs(drift) > 3 ? import_picocolors15.default.yellow : import_picocolors15.default.dim;
8963
- const pnlColor = pos.unrealizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
8809
+ const driftColor = Math.abs(drift) > 3 ? import_picocolors14.default.yellow : import_picocolors14.default.dim;
8810
+ const pnlColor = pos.unrealizedPnL >= 0 ? import_picocolors14.default.green : import_picocolors14.default.red;
8964
8811
  const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
8965
8812
  printKeyValue(
8966
8813
  pos.asset,
@@ -8991,7 +8838,7 @@ function registerInvest(program3) {
8991
8838
  printSuccess(`Rebalanced ${name} strategy`);
8992
8839
  printSeparator();
8993
8840
  for (const t of result.trades) {
8994
- const action = t.action === "buy" ? import_picocolors15.default.green("BUY") : import_picocolors15.default.red("SELL");
8841
+ const action = t.action === "buy" ? import_picocolors14.default.green("BUY") : import_picocolors14.default.red("SELL");
8995
8842
  printKeyValue(t.asset, `${action} ${formatUsd(t.usdAmount)} (${formatAssetAmount(t.amount, t.asset)})`);
8996
8843
  }
8997
8844
  printSeparator();
@@ -9008,7 +8855,7 @@ function registerInvest(program3) {
9008
8855
  for (const pair of opts.alloc) {
9009
8856
  const [asset, pctStr] = pair.split(":");
9010
8857
  if (!asset || !pctStr) {
9011
- console.error(import_picocolors15.default.red(` \u2717 Invalid allocation: '${pair}'. Use ASSET:PCT format (e.g. SUI:60)`));
8858
+ console.error(import_picocolors14.default.red(` \u2717 Invalid allocation: '${pair}'. Use ASSET:PCT format (e.g. SUI:60)`));
9012
8859
  process.exitCode = 1;
9013
8860
  return;
9014
8861
  }
@@ -9035,7 +8882,7 @@ function registerInvest(program3) {
9035
8882
  const pin = await resolvePin();
9036
8883
  const agent = await T2000.create({ pin, keyPath: opts.key });
9037
8884
  if (agent.portfolio.hasStrategyPositions(name.toLowerCase())) {
9038
- console.error(import_picocolors15.default.red(` \u2717 Strategy '${name}' has open positions. Sell first: t2000 invest strategy sell ${name}`));
8885
+ console.error(import_picocolors14.default.red(` \u2717 Strategy '${name}' has open positions. Sell first: t2000 invest strategy sell ${name}`));
9039
8886
  process.exitCode = 1;
9040
8887
  return;
9041
8888
  }
@@ -9056,12 +8903,12 @@ function registerInvest(program3) {
9056
8903
  try {
9057
8904
  const parsed = parseFloat(amount);
9058
8905
  if (isNaN(parsed) || parsed < 1) {
9059
- console.error(import_picocolors15.default.red(" \u2717 Amount must be at least $1"));
8906
+ console.error(import_picocolors14.default.red(" \u2717 Amount must be at least $1"));
9060
8907
  process.exitCode = 1;
9061
8908
  return;
9062
8909
  }
9063
8910
  if (!["daily", "weekly", "monthly"].includes(frequency)) {
9064
- console.error(import_picocolors15.default.red(" \u2717 Frequency must be daily, weekly, or monthly"));
8911
+ console.error(import_picocolors14.default.red(" \u2717 Frequency must be daily, weekly, or monthly"));
9065
8912
  process.exitCode = 1;
9066
8913
  return;
9067
8914
  }
@@ -9071,7 +8918,7 @@ function registerInvest(program3) {
9071
8918
  const isStrategy = target ? target.toLowerCase() in allStrategies : false;
9072
8919
  const isAsset = target ? target.toUpperCase() in INVESTMENT_ASSETS : false;
9073
8920
  if (target && !isStrategy && !isAsset) {
9074
- console.error(import_picocolors15.default.red(` \u2717 '${target}' is not a valid strategy or asset`));
8921
+ console.error(import_picocolors14.default.red(` \u2717 '${target}' is not a valid strategy or asset`));
9075
8922
  process.exitCode = 1;
9076
8923
  return;
9077
8924
  }
@@ -9118,9 +8965,9 @@ function registerInvest(program3) {
9118
8965
  printSeparator();
9119
8966
  for (const s of status.schedules) {
9120
8967
  const target = s.strategy ?? s.asset ?? "?";
9121
- const statusTag = s.enabled ? import_picocolors15.default.green("active") : import_picocolors15.default.dim("paused");
8968
+ const statusTag = s.enabled ? import_picocolors14.default.green("active") : import_picocolors14.default.dim("paused");
9122
8969
  printKeyValue(s.id, `${formatUsd(s.amount)} ${s.frequency} \u2192 ${target} ${statusTag}`);
9123
- printLine(` ${import_picocolors15.default.dim(`Next: ${new Date(s.nextRun).toLocaleDateString()} \xB7 Runs: ${s.runCount} \xB7 Total: ${formatUsd(s.totalInvested)}`)}`);
8970
+ printLine(` ${import_picocolors14.default.dim(`Next: ${new Date(s.nextRun).toLocaleDateString()} \xB7 Runs: ${s.runCount} \xB7 Total: ${formatUsd(s.totalInvested)}`)}`);
9124
8971
  }
9125
8972
  printSeparator();
9126
8973
  if (status.pendingRuns.length > 0) {
@@ -9163,7 +9010,7 @@ function registerInvest(program3) {
9163
9010
  }
9164
9011
  if (result.skipped.length > 0) {
9165
9012
  for (const skip of result.skipped) {
9166
- printLine(` ${import_picocolors15.default.yellow("\u26A0")} Skipped ${skip.scheduleId}: ${skip.reason}`);
9013
+ printLine(` ${import_picocolors14.default.yellow("\u26A0")} Skipped ${skip.scheduleId}: ${skip.reason}`);
9167
9014
  }
9168
9015
  }
9169
9016
  printBlank();
@@ -9190,21 +9037,21 @@ function registerInvest(program3) {
9190
9037
  }
9191
9038
 
9192
9039
  // src/commands/portfolio.ts
9193
- var import_picocolors16 = __toESM(require_picocolors(), 1);
9040
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
9194
9041
  function printPositionLine(pos, rewardKeys) {
9195
9042
  if (pos.currentPrice === 0 && pos.totalAmount > 0) {
9196
9043
  printKeyValue(
9197
9044
  pos.asset,
9198
- `${formatAssetAmount(pos.totalAmount, pos.asset)} Avg: ${formatUsd(pos.avgPrice)} Now: ${import_picocolors16.default.yellow("unavailable")}`
9045
+ `${formatAssetAmount(pos.totalAmount, pos.asset)} Avg: ${formatUsd(pos.avgPrice)} Now: ${import_picocolors15.default.yellow("unavailable")}`
9199
9046
  );
9200
9047
  } else {
9201
- const pnlColor = pos.unrealizedPnL >= 0 ? import_picocolors16.default.green : import_picocolors16.default.red;
9048
+ const pnlColor = pos.unrealizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
9202
9049
  const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
9203
9050
  let yieldSuffix = "";
9204
9051
  if (pos.earning && pos.earningApy) {
9205
9052
  const hasRewards = rewardKeys?.has(`${pos.earningProtocol}:${pos.asset}`);
9206
- const rewardTag = hasRewards ? ` ${import_picocolors16.default.yellow("+rewards")}` : "";
9207
- yieldSuffix = ` ${import_picocolors16.default.cyan(`${pos.earningApy.toFixed(1)}% APY (${pos.earningProtocol})`)}${rewardTag}`;
9053
+ const rewardTag = hasRewards ? ` ${import_picocolors15.default.yellow("+rewards")}` : "";
9054
+ yieldSuffix = ` ${import_picocolors15.default.cyan(`${pos.earningApy.toFixed(1)}% APY (${pos.earningProtocol})`)}${rewardTag}`;
9208
9055
  }
9209
9056
  printKeyValue(
9210
9057
  pos.asset,
@@ -9245,19 +9092,19 @@ function registerPortfolio(program3) {
9245
9092
  stratLabel = def.name;
9246
9093
  } catch {
9247
9094
  }
9248
- printLine(` ${import_picocolors16.default.bold(import_picocolors16.default.cyan(`\u25B8 ${stratLabel}`))}`);
9095
+ printLine(` ${import_picocolors15.default.bold(import_picocolors15.default.cyan(`\u25B8 ${stratLabel}`))}`);
9249
9096
  printSeparator();
9250
9097
  for (const pos of positions) {
9251
9098
  printPositionLine(pos, rewardKeys);
9252
9099
  }
9253
9100
  const stratValue = positions.reduce((s, p) => s + p.currentValue, 0);
9254
- printLine(` ${import_picocolors16.default.dim(`Subtotal: ${formatUsd(stratValue)}`)}`);
9101
+ printLine(` ${import_picocolors15.default.dim(`Subtotal: ${formatUsd(stratValue)}`)}`);
9255
9102
  printBlank();
9256
9103
  }
9257
9104
  }
9258
9105
  if (hasDirectPositions) {
9259
9106
  if (hasStrategyPositions) {
9260
- printLine(` ${import_picocolors16.default.bold(import_picocolors16.default.cyan("\u25B8 Direct"))}`);
9107
+ printLine(` ${import_picocolors15.default.bold(import_picocolors15.default.cyan("\u25B8 Direct"))}`);
9261
9108
  }
9262
9109
  printSeparator();
9263
9110
  for (const pos of portfolio.positions) {
@@ -9265,21 +9112,21 @@ function registerPortfolio(program3) {
9265
9112
  }
9266
9113
  if (hasStrategyPositions) {
9267
9114
  const directValue = portfolio.positions.reduce((s, p) => s + p.currentValue, 0);
9268
- printLine(` ${import_picocolors16.default.dim(`Subtotal: ${formatUsd(directValue)}`)}`);
9115
+ printLine(` ${import_picocolors15.default.dim(`Subtotal: ${formatUsd(directValue)}`)}`);
9269
9116
  }
9270
9117
  }
9271
9118
  printSeparator();
9272
9119
  const hasPriceUnavailable = portfolio.positions.some((p) => p.currentPrice === 0 && p.totalAmount > 0);
9273
9120
  if (hasPriceUnavailable) {
9274
- printInfo(import_picocolors16.default.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
9121
+ printInfo(import_picocolors15.default.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
9275
9122
  }
9276
9123
  printKeyValue("Total invested", formatUsd(portfolio.totalInvested));
9277
9124
  printKeyValue("Current value", formatUsd(portfolio.totalValue));
9278
- const upnlColor = portfolio.unrealizedPnL >= 0 ? import_picocolors16.default.green : import_picocolors16.default.red;
9125
+ const upnlColor = portfolio.unrealizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
9279
9126
  const upnlSign = portfolio.unrealizedPnL >= 0 ? "+" : "";
9280
9127
  printKeyValue("Unrealized P&L", upnlColor(`${upnlSign}${formatUsd(portfolio.unrealizedPnL)} (${upnlSign}${portfolio.unrealizedPnLPct.toFixed(1)}%)`));
9281
9128
  if (portfolio.realizedPnL !== 0) {
9282
- const rpnlColor = portfolio.realizedPnL >= 0 ? import_picocolors16.default.green : import_picocolors16.default.red;
9129
+ const rpnlColor = portfolio.realizedPnL >= 0 ? import_picocolors15.default.green : import_picocolors15.default.red;
9283
9130
  const rpnlSign = portfolio.realizedPnL >= 0 ? "+" : "";
9284
9131
  printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd(portfolio.realizedPnL)}`));
9285
9132
  }
@@ -9291,7 +9138,7 @@ function registerPortfolio(program3) {
9291
9138
  }
9292
9139
 
9293
9140
  // src/commands/claimRewards.ts
9294
- var import_picocolors17 = __toESM(require_picocolors(), 1);
9141
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
9295
9142
  function registerClaimRewards(program3) {
9296
9143
  program3.command("claim-rewards").description("Claim pending protocol rewards").option("--key <path>", "Key file path").action(async (opts) => {
9297
9144
  try {
@@ -9304,20 +9151,20 @@ function registerClaimRewards(program3) {
9304
9151
  }
9305
9152
  printBlank();
9306
9153
  if (result.rewards.length === 0) {
9307
- printLine(` ${import_picocolors17.default.dim("No rewards to claim")}`);
9154
+ printLine(` ${import_picocolors16.default.dim("No rewards to claim")}`);
9308
9155
  printBlank();
9309
9156
  return;
9310
9157
  }
9311
9158
  const protocols = [...new Set(result.rewards.map((r) => r.protocol))];
9312
- printLine(` ${import_picocolors17.default.green("\u2713")} Claimed and converted rewards to USDC`);
9159
+ printLine(` ${import_picocolors16.default.green("\u2713")} Claimed and converted rewards to USDC`);
9313
9160
  printSeparator();
9314
9161
  const received = result.usdcReceived;
9315
9162
  if (received >= 0.01) {
9316
- printKeyValue("Received", `${import_picocolors17.default.green(formatUsd(received))} USDC`);
9163
+ printKeyValue("Received", `${import_picocolors16.default.green(formatUsd(received))} USDC`);
9317
9164
  } else if (received > 0) {
9318
- printKeyValue("Received", `${import_picocolors17.default.green("< $0.01")} USDC`);
9165
+ printKeyValue("Received", `${import_picocolors16.default.green("< $0.01")} USDC`);
9319
9166
  } else {
9320
- printKeyValue("Received", `${import_picocolors17.default.dim("< $0.01 USDC (rewards are still accruing)")}`);
9167
+ printKeyValue("Received", `${import_picocolors16.default.dim("< $0.01 USDC (rewards are still accruing)")}`);
9321
9168
  }
9322
9169
  printKeyValue("Source", protocols.join(", "));
9323
9170
  if (result.tx) {
@@ -9331,7 +9178,7 @@ function registerClaimRewards(program3) {
9331
9178
  }
9332
9179
 
9333
9180
  // src/commands/gas.ts
9334
- var import_picocolors18 = __toESM(require_picocolors(), 1);
9181
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
9335
9182
  function registerGas(program3) {
9336
9183
  program3.command("gas").description("Check gas station status and wallet gas balance").option("--key <path>", "Key file path").action(async (opts) => {
9337
9184
  try {
@@ -9353,36 +9200,36 @@ function registerGas(program3) {
9353
9200
  }
9354
9201
  printHeader("Gas Status");
9355
9202
  if (gasStatus) {
9356
- const cbStatus = gasStatus.circuitBreaker ? import_picocolors18.default.red("TRIPPED \u2014 sponsorship paused") : import_picocolors18.default.green("OK");
9203
+ const cbStatus = gasStatus.circuitBreaker ? import_picocolors17.default.red("TRIPPED \u2014 sponsorship paused") : import_picocolors17.default.green("OK");
9357
9204
  printKeyValue("Gas Station", cbStatus);
9358
9205
  printKeyValue("SUI Price (TWAP)", `$${gasStatus.suiPrice.toFixed(4)}`);
9359
9206
  if (gasStatus.bootstrapRemaining !== void 0) {
9360
9207
  printKeyValue("Bootstrap", `${gasStatus.bootstrapUsed}/10 used (${gasStatus.bootstrapRemaining} remaining)`);
9361
9208
  }
9362
9209
  } else {
9363
- printKeyValue("Gas Station", import_picocolors18.default.red("unreachable"));
9210
+ printKeyValue("Gas Station", import_picocolors17.default.red("unreachable"));
9364
9211
  const reason = status.status === "rejected" ? status.reason : "unknown";
9365
- printLine(` ${import_picocolors18.default.dim(reason instanceof Error ? reason.message : String(reason))}`);
9212
+ printLine(` ${import_picocolors17.default.dim(reason instanceof Error ? reason.message : String(reason))}`);
9366
9213
  }
9367
9214
  printDivider();
9368
9215
  if (balData) {
9369
9216
  const suiBal = balData.gasReserve.sui;
9370
- const suiColor = suiBal < 0.05 ? import_picocolors18.default.red : import_picocolors18.default.green;
9217
+ const suiColor = suiBal < 0.05 ? import_picocolors17.default.red : import_picocolors17.default.green;
9371
9218
  printKeyValue("SUI (gas)", suiColor(`${suiBal.toFixed(4)} SUI`));
9372
9219
  if (suiBal < 0.05) {
9373
- printLine(` ${import_picocolors18.default.yellow("\u26A0")} Below gas threshold (0.05 SUI) \u2014 transactions will need sponsorship`);
9220
+ printLine(` ${import_picocolors17.default.yellow("\u26A0")} Below gas threshold (0.05 SUI) \u2014 transactions will need sponsorship`);
9374
9221
  }
9375
9222
  printKeyValue("Available", `$${balData.available.toFixed(2)}`);
9376
9223
  } else {
9377
- printKeyValue("Wallet", import_picocolors18.default.dim("could not fetch balances"));
9224
+ printKeyValue("Wallet", import_picocolors17.default.dim("could not fetch balances"));
9378
9225
  }
9379
9226
  printBlank();
9380
9227
  if (gasStatus && !gasStatus.circuitBreaker && (balData?.gasReserve.sui ?? 0) >= 0.05) {
9381
- printLine(` ${import_picocolors18.default.green("\u2713")} Gas is healthy \u2014 transactions should succeed`);
9228
+ printLine(` ${import_picocolors17.default.green("\u2713")} Gas is healthy \u2014 transactions should succeed`);
9382
9229
  } else if (gasStatus && !gasStatus.circuitBreaker) {
9383
- printLine(` ${import_picocolors18.default.yellow("\u26A0")} Low SUI but gas station is online \u2014 sponsorship available`);
9230
+ printLine(` ${import_picocolors17.default.yellow("\u26A0")} Low SUI but gas station is online \u2014 sponsorship available`);
9384
9231
  } else {
9385
- printLine(` ${import_picocolors18.default.red("\u2717")} Gas station issues detected \u2014 fund wallet with SUI directly`);
9232
+ printLine(` ${import_picocolors17.default.red("\u2717")} Gas station issues detected \u2014 fund wallet with SUI directly`);
9386
9233
  printInfo("Send SUI to your address: t2000 address");
9387
9234
  }
9388
9235
  printBlank();
@@ -9433,7 +9280,6 @@ Examples:
9433
9280
  registerServe(program3);
9434
9281
  registerPay(program3);
9435
9282
  registerLock(program3);
9436
- registerSentinel(program3);
9437
9283
  registerEarn(program3);
9438
9284
  registerRebalance(program3);
9439
9285
  registerSwap(program3);