@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/README.md +1 -10
- package/dist/{chunk-RN7Z6TWD.js → chunk-FM4762OE.js} +108 -306
- package/dist/chunk-FM4762OE.js.map +1 -0
- package/dist/{chunk-KHIL2KNW.js → chunk-XOAZJ42V.js} +32 -32
- package/dist/{chunk-KHIL2KNW.js.map → chunk-XOAZJ42V.js.map} +1 -1
- package/dist/{client-I4SGZLVD.js → client-CK5OR2TP.js} +2 -2
- package/dist/{dist-G5YKLWC5.js → dist-LKHCKFGY.js} +9 -25
- package/dist/{dist-FDS4MNUV.js → dist-ZTFOTMJO.js} +6 -113
- package/dist/{dist-FDS4MNUV.js.map → dist-ZTFOTMJO.js.map} +1 -1
- package/dist/index.js +118 -272
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-RN7Z6TWD.js.map +0 -1
- /package/dist/{client-I4SGZLVD.js.map → client-CK5OR2TP.js.map} +0 -0
- /package/dist/{dist-G5YKLWC5.js.map → dist-LKHCKFGY.js.map} +0 -0
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-
|
|
21
|
+
} from "./chunk-FM4762OE.js";
|
|
24
22
|
import "./chunk-V7PXDEKG.js";
|
|
25
|
-
import "./chunk-
|
|
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
|
|
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
|
|
4461
|
-
import { homedir as
|
|
4462
|
-
var CONFIG_DIR2 =
|
|
4463
|
-
var CONFIG_PATH2 =
|
|
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
|
|
7332
|
-
import { homedir as
|
|
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 =
|
|
7485
|
-
var TOKEN_PATH =
|
|
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
|
|
7852
|
-
import { homedir as
|
|
7853
|
-
var CONFIG_DIR4 =
|
|
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-
|
|
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
|
|
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 +
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(` ${
|
|
8196
|
-
printLine(` ${
|
|
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
|
|
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(
|
|
8235
|
-
printLine(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
8278
|
-
printLine(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
8466
|
-
import { homedir as
|
|
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 =
|
|
8320
|
+
const home = homedir8();
|
|
8474
8321
|
return [
|
|
8475
8322
|
{
|
|
8476
8323
|
name: "Claude Desktop",
|
|
8477
|
-
path:
|
|
8324
|
+
path: join7(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
|
|
8478
8325
|
},
|
|
8479
8326
|
{
|
|
8480
8327
|
name: "Cursor",
|
|
8481
|
-
path:
|
|
8328
|
+
path: join7(home, ".cursor", "mcp.json")
|
|
8482
8329
|
},
|
|
8483
8330
|
{
|
|
8484
8331
|
name: "Windsurf",
|
|
8485
|
-
path:
|
|
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-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 ?
|
|
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 ?
|
|
8697
|
+
const tag = def.custom ? import_picocolors14.default.dim(" (custom)") : "";
|
|
8851
8698
|
printKeyValue(key, `${allocs}${tag}`);
|
|
8852
|
-
printLine(` ${
|
|
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(
|
|
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(` ${
|
|
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 ?
|
|
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(
|
|
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 ?
|
|
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 ?
|
|
8963
|
-
const pnlColor = pos.unrealizedPnL >= 0 ?
|
|
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" ?
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 ?
|
|
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(` ${
|
|
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(` ${
|
|
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
|
|
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: ${
|
|
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 ?
|
|
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 ? ` ${
|
|
9207
|
-
yieldSuffix = ` ${
|
|
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(` ${
|
|
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(` ${
|
|
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(` ${
|
|
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(` ${
|
|
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(
|
|
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 ?
|
|
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 ?
|
|
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
|
|
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(` ${
|
|
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(` ${
|
|
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", `${
|
|
9163
|
+
printKeyValue("Received", `${import_picocolors16.default.green(formatUsd(received))} USDC`);
|
|
9317
9164
|
} else if (received > 0) {
|
|
9318
|
-
printKeyValue("Received", `${
|
|
9165
|
+
printKeyValue("Received", `${import_picocolors16.default.green("< $0.01")} USDC`);
|
|
9319
9166
|
} else {
|
|
9320
|
-
printKeyValue("Received", `${
|
|
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
|
|
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 ?
|
|
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",
|
|
9210
|
+
printKeyValue("Gas Station", import_picocolors17.default.red("unreachable"));
|
|
9364
9211
|
const reason = status.status === "rejected" ? status.reason : "unknown";
|
|
9365
|
-
printLine(` ${
|
|
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 ?
|
|
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(` ${
|
|
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",
|
|
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(` ${
|
|
9228
|
+
printLine(` ${import_picocolors17.default.green("\u2713")} Gas is healthy \u2014 transactions should succeed`);
|
|
9382
9229
|
} else if (gasStatus && !gasStatus.circuitBreaker) {
|
|
9383
|
-
printLine(` ${
|
|
9230
|
+
printLine(` ${import_picocolors17.default.yellow("\u26A0")} Low SUI but gas station is online \u2014 sponsorship available`);
|
|
9384
9231
|
} else {
|
|
9385
|
-
printLine(` ${
|
|
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);
|