@t2000/cli 0.22.7 → 0.22.9
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 +14 -12
- package/dist/{dist-NXFA54RO.js → dist-3RLXPNZ5.js} +16 -14
- package/dist/{dist-NXFA54RO.js.map → dist-3RLXPNZ5.js.map} +1 -1
- package/dist/index.js +188 -108
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -288,7 +288,7 @@ function registerInit(program2) {
|
|
|
288
288
|
} else {
|
|
289
289
|
console.log(` \u2502 Use the CLI directly: \u2502`);
|
|
290
290
|
console.log(` \u2502 ${pc2.cyan("t2000 balance")} \u2502`);
|
|
291
|
-
console.log(` \u2502 ${pc2.cyan("t2000
|
|
291
|
+
console.log(` \u2502 ${pc2.cyan("t2000 buy 100 BTC")} \u2502`);
|
|
292
292
|
console.log(` \u2502 \u2502`);
|
|
293
293
|
}
|
|
294
294
|
console.log(` \u2502 Deposit USDC to get started: \u2502`);
|
|
@@ -1605,7 +1605,7 @@ function registerLock(program2) {
|
|
|
1605
1605
|
});
|
|
1606
1606
|
program2.command("unlock").description("Unlock agent \u2014 resume operations").action(async () => {
|
|
1607
1607
|
try {
|
|
1608
|
-
const { T2000:
|
|
1608
|
+
const { T2000: T200029 } = await import("@t2000/sdk");
|
|
1609
1609
|
const MAX_ATTEMPTS2 = 3;
|
|
1610
1610
|
let pin;
|
|
1611
1611
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS2; attempt++) {
|
|
@@ -1614,7 +1614,7 @@ function registerLock(program2) {
|
|
|
1614
1614
|
throw new Error("PIN required to unlock agent");
|
|
1615
1615
|
}
|
|
1616
1616
|
try {
|
|
1617
|
-
await
|
|
1617
|
+
await T200029.create({ pin });
|
|
1618
1618
|
break;
|
|
1619
1619
|
} catch (error) {
|
|
1620
1620
|
const msg = error instanceof Error ? error.message : "";
|
|
@@ -2034,7 +2034,8 @@ function displayAsset(asset) {
|
|
|
2034
2034
|
}
|
|
2035
2035
|
|
|
2036
2036
|
// src/commands/exchange.ts
|
|
2037
|
-
import { T2000 as T200023,
|
|
2037
|
+
import { T2000 as T200023, SUPPORTED_ASSETS as SUPPORTED_ASSETS3 } from "@t2000/sdk";
|
|
2038
|
+
import pc14 from "picocolors";
|
|
2038
2039
|
function resolveAssetName(input) {
|
|
2039
2040
|
const upper = input.toUpperCase();
|
|
2040
2041
|
for (const key of Object.keys(SUPPORTED_ASSETS3)) {
|
|
@@ -2043,19 +2044,16 @@ function resolveAssetName(input) {
|
|
|
2043
2044
|
return input;
|
|
2044
2045
|
}
|
|
2045
2046
|
function registerExchange(program2) {
|
|
2046
|
-
program2.command("exchange <amount> <from> <to>").description(
|
|
2047
|
+
program2.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) => {
|
|
2047
2048
|
try {
|
|
2049
|
+
console.error(pc14.yellow(' \u26A0 "exchange" is deprecated. Use "swap" instead: t2000 swap %s %s %s'), amount, from, to);
|
|
2048
2050
|
const pin = await resolvePin();
|
|
2049
2051
|
const agent = await T200023.create({ pin, keyPath: opts.key });
|
|
2050
|
-
const fromAsset = resolveAssetName(from);
|
|
2051
|
-
const toAsset = resolveAssetName(to);
|
|
2052
2052
|
const parsedAmount = parseFloat(amount);
|
|
2053
|
-
if (isNaN(parsedAmount) || parsedAmount <= 0)
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
from: fromAsset,
|
|
2058
|
-
to: toAsset,
|
|
2053
|
+
if (isNaN(parsedAmount) || parsedAmount <= 0) throw new Error("Amount must be a positive number");
|
|
2054
|
+
const result = await agent.swap({
|
|
2055
|
+
from: resolveAssetName(from),
|
|
2056
|
+
to: resolveAssetName(to),
|
|
2059
2057
|
amount: parsedAmount,
|
|
2060
2058
|
maxSlippage: parseFloat(opts.slippage ?? "3") / 100
|
|
2061
2059
|
});
|
|
@@ -2063,15 +2061,87 @@ function registerExchange(program2) {
|
|
|
2063
2061
|
printJson(result);
|
|
2064
2062
|
return;
|
|
2065
2063
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2064
|
+
console.log(pc14.green(" \u2713 Swapped. Tx: %s"), result.tx);
|
|
2065
|
+
} catch (error) {
|
|
2066
|
+
handleError(error);
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
// src/commands/swap.ts
|
|
2072
|
+
import { T2000 as T200024, formatUsd as formatUsd14, SUPPORTED_ASSETS as SUPPORTED_ASSETS4 } from "@t2000/sdk";
|
|
2073
|
+
function resolveAssetName2(input) {
|
|
2074
|
+
const upper = input.toUpperCase();
|
|
2075
|
+
for (const key of Object.keys(SUPPORTED_ASSETS4)) {
|
|
2076
|
+
if (key.toUpperCase() === upper) return key;
|
|
2077
|
+
}
|
|
2078
|
+
return input;
|
|
2079
|
+
}
|
|
2080
|
+
function fmtTokenAmount(amount, asset) {
|
|
2081
|
+
if (["USDC", "USDT", "USDE"].includes(asset)) return formatUsd14(amount);
|
|
2082
|
+
if (amount > 0 && amount < 1e-3) return amount.toFixed(8);
|
|
2083
|
+
if (amount > 0 && amount < 1) return amount.toFixed(6);
|
|
2084
|
+
return amount.toFixed(4);
|
|
2085
|
+
}
|
|
2086
|
+
async function executeSwap(from, to, amount, opts, label) {
|
|
2087
|
+
const pin = await resolvePin();
|
|
2088
|
+
const agent = await T200024.create({ pin, keyPath: opts.key });
|
|
2089
|
+
const fromAsset = resolveAssetName2(from);
|
|
2090
|
+
const toAsset = resolveAssetName2(to);
|
|
2091
|
+
const result = await agent.swap({
|
|
2092
|
+
from: fromAsset,
|
|
2093
|
+
to: toAsset,
|
|
2094
|
+
amount,
|
|
2095
|
+
maxSlippage: parseFloat(opts.slippage ?? "3") / 100
|
|
2096
|
+
});
|
|
2097
|
+
if (isJsonMode()) {
|
|
2098
|
+
printJson(result);
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
const fromDisplay = SUPPORTED_ASSETS4[fromAsset]?.displayName ?? fromAsset;
|
|
2102
|
+
const toDisplay = SUPPORTED_ASSETS4[toAsset]?.displayName ?? toAsset;
|
|
2103
|
+
printBlank();
|
|
2104
|
+
if (label === "Bought") {
|
|
2105
|
+
printSuccess(`Bought ${fmtTokenAmount(result.toAmount, toAsset)} ${toDisplay} for ${formatUsd14(amount)}`);
|
|
2106
|
+
} else if (label === "Sold") {
|
|
2107
|
+
printSuccess(`Sold ${fmtTokenAmount(amount, fromAsset)} ${fromDisplay} for ${formatUsd14(result.toAmount)}`);
|
|
2108
|
+
} else {
|
|
2109
|
+
printSuccess(`Swapped ${fmtTokenAmount(amount, fromAsset)} ${fromDisplay} \u2192 ${fmtTokenAmount(result.toAmount, toAsset)} ${toDisplay}`);
|
|
2110
|
+
}
|
|
2111
|
+
printKeyValue("Tx", explorerUrl(result.tx));
|
|
2112
|
+
printKeyValue("Gas", `${result.gasCost.toFixed(4)} SUI (${result.gasMethod})`);
|
|
2113
|
+
printBlank();
|
|
2114
|
+
}
|
|
2115
|
+
function registerSwap(program2) {
|
|
2116
|
+
program2.command("swap <amount> <from> <to>").description("Swap tokens (e.g. swap 100 USDC SUI)").option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percentage (default: 3)", "3").action(async (amount, from, to, opts) => {
|
|
2117
|
+
try {
|
|
2118
|
+
const parsedAmount = parseFloat(amount);
|
|
2119
|
+
if (isNaN(parsedAmount) || parsedAmount <= 0) {
|
|
2120
|
+
throw new Error("Amount must be a positive number");
|
|
2121
|
+
}
|
|
2122
|
+
await executeSwap(from, to, parsedAmount, opts, "Swapped");
|
|
2123
|
+
} catch (error) {
|
|
2124
|
+
handleError(error);
|
|
2125
|
+
}
|
|
2126
|
+
});
|
|
2127
|
+
program2.command("buy <amount> <asset>").description("Buy an asset with USDC (e.g. buy 100 BTC)").option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percentage (default: 3)", "3").action(async (amount, asset, opts) => {
|
|
2128
|
+
try {
|
|
2129
|
+
const parsedAmount = parseFloat(amount);
|
|
2130
|
+
if (isNaN(parsedAmount) || parsedAmount <= 0) {
|
|
2131
|
+
throw new Error("Amount must be a positive number");
|
|
2132
|
+
}
|
|
2133
|
+
await executeSwap("USDC", asset, parsedAmount, opts, "Bought");
|
|
2134
|
+
} catch (error) {
|
|
2135
|
+
handleError(error);
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
2138
|
+
program2.command("sell <amount> <asset>").description("Sell an asset for USDC (e.g. sell 0.001 BTC)").option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percentage (default: 3)", "3").action(async (amount, asset, opts) => {
|
|
2139
|
+
try {
|
|
2140
|
+
const parsedAmount = parseFloat(amount);
|
|
2141
|
+
if (isNaN(parsedAmount) || parsedAmount <= 0) {
|
|
2142
|
+
throw new Error("Amount must be a positive number");
|
|
2143
|
+
}
|
|
2144
|
+
await executeSwap(asset, "USDC", parsedAmount, opts, "Sold");
|
|
2075
2145
|
} catch (error) {
|
|
2076
2146
|
handleError(error);
|
|
2077
2147
|
}
|
|
@@ -2124,7 +2194,7 @@ function registerMcp(program2) {
|
|
|
2124
2194
|
mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2125
2195
|
let mod;
|
|
2126
2196
|
try {
|
|
2127
|
-
mod = await import("./dist-
|
|
2197
|
+
mod = await import("./dist-3RLXPNZ5.js");
|
|
2128
2198
|
} catch {
|
|
2129
2199
|
console.error(
|
|
2130
2200
|
"MCP server not installed. Run:\n npm install -g @t2000/mcp"
|
|
@@ -2276,20 +2346,21 @@ function registerContacts(program2) {
|
|
|
2276
2346
|
}
|
|
2277
2347
|
|
|
2278
2348
|
// src/commands/invest.ts
|
|
2279
|
-
import
|
|
2280
|
-
import { T2000 as
|
|
2349
|
+
import pc15 from "picocolors";
|
|
2350
|
+
import { T2000 as T200025, formatUsd as formatUsd15, formatAssetAmount as formatAssetAmount4, INVESTMENT_ASSETS as INVESTMENT_ASSETS2 } from "@t2000/sdk";
|
|
2281
2351
|
function registerInvest(program2) {
|
|
2282
|
-
const investCmd = program2.command("invest").description("
|
|
2283
|
-
investCmd.command("buy <amount> <asset>").description("
|
|
2352
|
+
const investCmd = program2.command("invest").description("Investment strategies, DCA, and yield earning");
|
|
2353
|
+
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) => {
|
|
2284
2354
|
try {
|
|
2355
|
+
console.error(pc15.yellow(` \u26A0 "invest buy" is deprecated. Use: t2000 buy ${amount} ${asset}`));
|
|
2285
2356
|
const parsed = parseFloat(amount);
|
|
2286
2357
|
if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
|
|
2287
|
-
console.error(
|
|
2358
|
+
console.error(pc15.red(" \u2717 Amount must be greater than $0"));
|
|
2288
2359
|
process.exitCode = 1;
|
|
2289
2360
|
return;
|
|
2290
2361
|
}
|
|
2291
2362
|
const pin = await resolvePin();
|
|
2292
|
-
const agent = await
|
|
2363
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2293
2364
|
const result = await agent.investBuy({
|
|
2294
2365
|
asset: asset.toUpperCase(),
|
|
2295
2366
|
usdAmount: parsed,
|
|
@@ -2303,29 +2374,30 @@ function registerInvest(program2) {
|
|
|
2303
2374
|
const sym = asset.toUpperCase();
|
|
2304
2375
|
printSuccess(`Bought ${formatAssetAmount4(result.amount, sym)} ${sym} at ${formatUsd15(result.price)}`);
|
|
2305
2376
|
printKeyValue("Invested", formatUsd15(result.usdValue));
|
|
2306
|
-
printKeyValue("Portfolio", `${formatAssetAmount4(result.position.totalAmount, sym)} ${sym} (avg ${formatUsd15(result.position.avgPrice)})`);
|
|
2307
2377
|
printKeyValue("Tx", explorerUrl(result.tx));
|
|
2308
2378
|
printBlank();
|
|
2309
2379
|
} catch (error) {
|
|
2310
2380
|
handleError(error);
|
|
2311
2381
|
}
|
|
2312
2382
|
});
|
|
2313
|
-
investCmd.command("sell <amount> <asset>").description('
|
|
2383
|
+
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) => {
|
|
2314
2384
|
try {
|
|
2385
|
+
console.error(pc15.yellow(` \u26A0 "invest sell" is deprecated. Use: t2000 sell ${amount} ${asset}`));
|
|
2315
2386
|
const isAll = amount.toLowerCase() === "all";
|
|
2316
2387
|
if (!isAll) {
|
|
2317
2388
|
const parsed = parseFloat(amount);
|
|
2318
2389
|
if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
|
|
2319
|
-
console.error(
|
|
2390
|
+
console.error(pc15.red(" \u2717 Amount must be greater than $0"));
|
|
2320
2391
|
process.exitCode = 1;
|
|
2321
2392
|
return;
|
|
2322
2393
|
}
|
|
2323
2394
|
}
|
|
2324
2395
|
const pin = await resolvePin();
|
|
2325
|
-
const agent = await
|
|
2396
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2397
|
+
const sym = asset.toUpperCase();
|
|
2326
2398
|
const usdAmount = isAll ? "all" : parseFloat(amount);
|
|
2327
2399
|
const result = await agent.investSell({
|
|
2328
|
-
asset:
|
|
2400
|
+
asset: sym,
|
|
2329
2401
|
usdAmount,
|
|
2330
2402
|
maxSlippage: parseFloat(opts.slippage) / 100
|
|
2331
2403
|
});
|
|
@@ -2334,17 +2406,13 @@ function registerInvest(program2) {
|
|
|
2334
2406
|
return;
|
|
2335
2407
|
}
|
|
2336
2408
|
printBlank();
|
|
2337
|
-
const sym = asset.toUpperCase();
|
|
2338
2409
|
printSuccess(`Sold ${formatAssetAmount4(result.amount, sym)} ${sym} at ${formatUsd15(result.price)}`);
|
|
2339
2410
|
printKeyValue("Proceeds", formatUsd15(result.usdValue));
|
|
2340
2411
|
if (result.realizedPnL !== void 0) {
|
|
2341
|
-
const pnlColor = result.realizedPnL >= 0 ?
|
|
2412
|
+
const pnlColor = result.realizedPnL >= 0 ? pc15.green : pc15.red;
|
|
2342
2413
|
const pnlSign = result.realizedPnL >= 0 ? "+" : "";
|
|
2343
2414
|
printKeyValue("Realized P&L", pnlColor(`${pnlSign}${formatUsd15(result.realizedPnL)}`));
|
|
2344
2415
|
}
|
|
2345
|
-
if (result.position.totalAmount > 0) {
|
|
2346
|
-
printKeyValue("Remaining", `${formatAssetAmount4(result.position.totalAmount, sym)} ${sym} (avg ${formatUsd15(result.position.avgPrice)})`);
|
|
2347
|
-
}
|
|
2348
2416
|
printKeyValue("Tx", explorerUrl(result.tx));
|
|
2349
2417
|
printBlank();
|
|
2350
2418
|
} catch (error) {
|
|
@@ -2354,7 +2422,7 @@ function registerInvest(program2) {
|
|
|
2354
2422
|
investCmd.command("earn <asset>").description("Deposit invested asset into best-rate lending protocol").option("--key <path>", "Key file path").option("--protocol <name>", "Force a specific protocol (navi, suilend)").action(async (asset, opts) => {
|
|
2355
2423
|
try {
|
|
2356
2424
|
const pin = await resolvePin();
|
|
2357
|
-
const agent = await
|
|
2425
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2358
2426
|
const result = await agent.investEarn({
|
|
2359
2427
|
asset: asset.toUpperCase(),
|
|
2360
2428
|
protocol: opts.protocol?.toLowerCase()
|
|
@@ -2382,7 +2450,7 @@ function registerInvest(program2) {
|
|
|
2382
2450
|
investCmd.command("unearn <asset>").description("Withdraw invested asset from lending (keeps in portfolio)").option("--key <path>", "Key file path").action(async (asset, opts) => {
|
|
2383
2451
|
try {
|
|
2384
2452
|
const pin = await resolvePin();
|
|
2385
|
-
const agent = await
|
|
2453
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2386
2454
|
const result = await agent.investUnearn({
|
|
2387
2455
|
asset: asset.toUpperCase()
|
|
2388
2456
|
});
|
|
@@ -2393,7 +2461,7 @@ function registerInvest(program2) {
|
|
|
2393
2461
|
printBlank();
|
|
2394
2462
|
const sym = asset.toUpperCase();
|
|
2395
2463
|
printSuccess(`Withdrew ${formatAssetAmount4(result.amount, sym)} ${sym} from ${result.protocol}`);
|
|
2396
|
-
printKeyValue("Status", `${sym}
|
|
2464
|
+
printKeyValue("Status", `${sym} withdrawn to wallet`);
|
|
2397
2465
|
printKeyValue("Tx", explorerUrl(result.tx));
|
|
2398
2466
|
printBlank();
|
|
2399
2467
|
} catch (error) {
|
|
@@ -2403,7 +2471,7 @@ function registerInvest(program2) {
|
|
|
2403
2471
|
investCmd.command("rebalance").description("Move earning positions to better-rate protocols").option("--key <path>", "Key file path").option("--dry-run", "Preview moves without executing").option("--min-diff <pct>", "Minimum APY difference to trigger move", "0.1").action(async (opts) => {
|
|
2404
2472
|
try {
|
|
2405
2473
|
const pin = await resolvePin();
|
|
2406
|
-
const agent = await
|
|
2474
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2407
2475
|
const result = await agent.investRebalance({
|
|
2408
2476
|
dryRun: opts.dryRun,
|
|
2409
2477
|
minYieldDiff: opts.minDiff ? parseFloat(opts.minDiff) : void 0
|
|
@@ -2458,7 +2526,7 @@ function registerInvest(program2) {
|
|
|
2458
2526
|
strategyCmd.command("list").description("List available strategies").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2459
2527
|
try {
|
|
2460
2528
|
const pin = await resolvePin();
|
|
2461
|
-
const agent = await
|
|
2529
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2462
2530
|
const all = agent.strategies.getAll();
|
|
2463
2531
|
if (isJsonMode()) {
|
|
2464
2532
|
printJson(all);
|
|
@@ -2469,9 +2537,9 @@ function registerInvest(program2) {
|
|
|
2469
2537
|
printSeparator();
|
|
2470
2538
|
for (const [key, def] of Object.entries(all)) {
|
|
2471
2539
|
const allocs = Object.entries(def.allocations).map(([a, p]) => `${a} ${p}%`).join(", ");
|
|
2472
|
-
const tag = def.custom ?
|
|
2540
|
+
const tag = def.custom ? pc15.dim(" (custom)") : "";
|
|
2473
2541
|
printKeyValue(key, `${allocs}${tag}`);
|
|
2474
|
-
printLine(` ${
|
|
2542
|
+
printLine(` ${pc15.dim(def.description)}`);
|
|
2475
2543
|
}
|
|
2476
2544
|
printSeparator();
|
|
2477
2545
|
const hasPositions = Object.keys(all).some((k) => agent.portfolio.hasStrategyPositions(k));
|
|
@@ -2487,12 +2555,12 @@ function registerInvest(program2) {
|
|
|
2487
2555
|
try {
|
|
2488
2556
|
const parsed = parseFloat(amount);
|
|
2489
2557
|
if (isNaN(parsed) || parsed <= 0) {
|
|
2490
|
-
console.error(
|
|
2558
|
+
console.error(pc15.red(" \u2717 Amount must be greater than $0"));
|
|
2491
2559
|
process.exitCode = 1;
|
|
2492
2560
|
return;
|
|
2493
2561
|
}
|
|
2494
2562
|
const pin = await resolvePin();
|
|
2495
|
-
const agent = await
|
|
2563
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2496
2564
|
const result = await agent.investStrategy({ strategy: name.toLowerCase(), usdAmount: parsed, dryRun: opts.dryRun });
|
|
2497
2565
|
if (isJsonMode()) {
|
|
2498
2566
|
printJson(result);
|
|
@@ -2521,7 +2589,7 @@ function registerInvest(program2) {
|
|
|
2521
2589
|
printKeyValue("Tx", explorerUrl(txDigests[0]));
|
|
2522
2590
|
} else {
|
|
2523
2591
|
for (const buy of result.buys) {
|
|
2524
|
-
printLine(` ${
|
|
2592
|
+
printLine(` ${pc15.dim(`${buy.asset}: ${explorerUrl(buy.tx)}`)}`);
|
|
2525
2593
|
}
|
|
2526
2594
|
}
|
|
2527
2595
|
}
|
|
@@ -2533,7 +2601,7 @@ function registerInvest(program2) {
|
|
|
2533
2601
|
strategyCmd.command("sell <name>").description("Sell all positions in a strategy").option("--key <path>", "Key file path").action(async (name, opts) => {
|
|
2534
2602
|
try {
|
|
2535
2603
|
const pin = await resolvePin();
|
|
2536
|
-
const agent = await
|
|
2604
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2537
2605
|
const result = await agent.sellStrategy({ strategy: name.toLowerCase() });
|
|
2538
2606
|
if (isJsonMode()) {
|
|
2539
2607
|
printJson(result);
|
|
@@ -2543,18 +2611,18 @@ function registerInvest(program2) {
|
|
|
2543
2611
|
printSuccess(`Sold all ${name} strategy positions`);
|
|
2544
2612
|
printSeparator();
|
|
2545
2613
|
for (const sell of result.sells) {
|
|
2546
|
-
const pnlColor = sell.realizedPnL >= 0 ?
|
|
2614
|
+
const pnlColor = sell.realizedPnL >= 0 ? pc15.green : pc15.red;
|
|
2547
2615
|
const pnlSign = sell.realizedPnL >= 0 ? "+" : "";
|
|
2548
2616
|
printKeyValue(sell.asset, `${formatAssetAmount4(sell.amount, sell.asset)} \u2192 ${formatUsd15(sell.usdValue)} ${pnlColor(`${pnlSign}${formatUsd15(sell.realizedPnL)}`)}`);
|
|
2549
2617
|
}
|
|
2550
2618
|
if (result.failed && result.failed.length > 0) {
|
|
2551
2619
|
for (const f of result.failed) {
|
|
2552
|
-
console.error(
|
|
2620
|
+
console.error(pc15.yellow(` \u26A0 ${f.asset}: ${f.reason}`));
|
|
2553
2621
|
}
|
|
2554
2622
|
}
|
|
2555
2623
|
printSeparator();
|
|
2556
2624
|
printKeyValue("Total proceeds", formatUsd15(result.totalProceeds));
|
|
2557
|
-
const rpnlColor = result.realizedPnL >= 0 ?
|
|
2625
|
+
const rpnlColor = result.realizedPnL >= 0 ? pc15.green : pc15.red;
|
|
2558
2626
|
const rpnlSign = result.realizedPnL >= 0 ? "+" : "";
|
|
2559
2627
|
printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd15(result.realizedPnL)}`));
|
|
2560
2628
|
printBlank();
|
|
@@ -2565,7 +2633,7 @@ function registerInvest(program2) {
|
|
|
2565
2633
|
strategyCmd.command("status <name>").description("Show current status and weights of a strategy").option("--key <path>", "Key file path").action(async (name, opts) => {
|
|
2566
2634
|
try {
|
|
2567
2635
|
const pin = await resolvePin();
|
|
2568
|
-
const agent = await
|
|
2636
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2569
2637
|
const status = await agent.getStrategyStatus(name.toLowerCase());
|
|
2570
2638
|
if (isJsonMode()) {
|
|
2571
2639
|
printJson(status);
|
|
@@ -2581,8 +2649,8 @@ function registerInvest(program2) {
|
|
|
2581
2649
|
const target = status.definition.allocations[pos.asset] ?? 0;
|
|
2582
2650
|
const actual = status.currentWeights[pos.asset] ?? 0;
|
|
2583
2651
|
const drift = actual - target;
|
|
2584
|
-
const driftColor = Math.abs(drift) > 3 ?
|
|
2585
|
-
const pnlColor = pos.unrealizedPnL >= 0 ?
|
|
2652
|
+
const driftColor = Math.abs(drift) > 3 ? pc15.yellow : pc15.dim;
|
|
2653
|
+
const pnlColor = pos.unrealizedPnL >= 0 ? pc15.green : pc15.red;
|
|
2586
2654
|
const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
|
|
2587
2655
|
printKeyValue(
|
|
2588
2656
|
pos.asset,
|
|
@@ -2600,7 +2668,7 @@ function registerInvest(program2) {
|
|
|
2600
2668
|
strategyCmd.command("rebalance <name>").description("Rebalance a strategy to target weights").option("--key <path>", "Key file path").action(async (name, opts) => {
|
|
2601
2669
|
try {
|
|
2602
2670
|
const pin = await resolvePin();
|
|
2603
|
-
const agent = await
|
|
2671
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2604
2672
|
const result = await agent.rebalanceStrategy({ strategy: name.toLowerCase() });
|
|
2605
2673
|
if (isJsonMode()) {
|
|
2606
2674
|
printJson(result);
|
|
@@ -2613,7 +2681,7 @@ function registerInvest(program2) {
|
|
|
2613
2681
|
printSuccess(`Rebalanced ${name} strategy`);
|
|
2614
2682
|
printSeparator();
|
|
2615
2683
|
for (const t of result.trades) {
|
|
2616
|
-
const action = t.action === "buy" ?
|
|
2684
|
+
const action = t.action === "buy" ? pc15.green("BUY") : pc15.red("SELL");
|
|
2617
2685
|
printKeyValue(t.asset, `${action} ${formatUsd15(t.usdAmount)} (${formatAssetAmount4(t.amount, t.asset)})`);
|
|
2618
2686
|
}
|
|
2619
2687
|
printSeparator();
|
|
@@ -2630,14 +2698,14 @@ function registerInvest(program2) {
|
|
|
2630
2698
|
for (const pair of opts.alloc) {
|
|
2631
2699
|
const [asset, pctStr] = pair.split(":");
|
|
2632
2700
|
if (!asset || !pctStr) {
|
|
2633
|
-
console.error(
|
|
2701
|
+
console.error(pc15.red(` \u2717 Invalid allocation: '${pair}'. Use ASSET:PCT format (e.g. SUI:60)`));
|
|
2634
2702
|
process.exitCode = 1;
|
|
2635
2703
|
return;
|
|
2636
2704
|
}
|
|
2637
2705
|
allocations[asset.toUpperCase()] = parseFloat(pctStr);
|
|
2638
2706
|
}
|
|
2639
2707
|
const pin = await resolvePin();
|
|
2640
|
-
const agent = await
|
|
2708
|
+
const agent = await T200025.create({ pin });
|
|
2641
2709
|
const definition = agent.strategies.create({ name, allocations, description: opts.description });
|
|
2642
2710
|
if (isJsonMode()) {
|
|
2643
2711
|
printJson(definition);
|
|
@@ -2655,9 +2723,9 @@ function registerInvest(program2) {
|
|
|
2655
2723
|
strategyCmd.command("delete <name>").description("Delete a custom strategy").option("--key <path>", "Key file path").action(async (name, opts) => {
|
|
2656
2724
|
try {
|
|
2657
2725
|
const pin = await resolvePin();
|
|
2658
|
-
const agent = await
|
|
2726
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2659
2727
|
if (agent.portfolio.hasStrategyPositions(name.toLowerCase())) {
|
|
2660
|
-
console.error(
|
|
2728
|
+
console.error(pc15.red(` \u2717 Strategy '${name}' has open positions. Sell first: t2000 invest strategy sell ${name}`));
|
|
2661
2729
|
process.exitCode = 1;
|
|
2662
2730
|
return;
|
|
2663
2731
|
}
|
|
@@ -2678,22 +2746,22 @@ function registerInvest(program2) {
|
|
|
2678
2746
|
try {
|
|
2679
2747
|
const parsed = parseFloat(amount);
|
|
2680
2748
|
if (isNaN(parsed) || parsed < 1) {
|
|
2681
|
-
console.error(
|
|
2749
|
+
console.error(pc15.red(" \u2717 Amount must be at least $1"));
|
|
2682
2750
|
process.exitCode = 1;
|
|
2683
2751
|
return;
|
|
2684
2752
|
}
|
|
2685
2753
|
if (!["daily", "weekly", "monthly"].includes(frequency)) {
|
|
2686
|
-
console.error(
|
|
2754
|
+
console.error(pc15.red(" \u2717 Frequency must be daily, weekly, or monthly"));
|
|
2687
2755
|
process.exitCode = 1;
|
|
2688
2756
|
return;
|
|
2689
2757
|
}
|
|
2690
2758
|
const pin = await resolvePin();
|
|
2691
|
-
const agent = await
|
|
2759
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2692
2760
|
const allStrategies = agent.strategies.getAll();
|
|
2693
2761
|
const isStrategy = target ? target.toLowerCase() in allStrategies : false;
|
|
2694
2762
|
const isAsset = target ? target.toUpperCase() in INVESTMENT_ASSETS2 : false;
|
|
2695
2763
|
if (target && !isStrategy && !isAsset) {
|
|
2696
|
-
console.error(
|
|
2764
|
+
console.error(pc15.red(` \u2717 '${target}' is not a valid strategy or asset`));
|
|
2697
2765
|
process.exitCode = 1;
|
|
2698
2766
|
return;
|
|
2699
2767
|
}
|
|
@@ -2724,7 +2792,7 @@ function registerInvest(program2) {
|
|
|
2724
2792
|
autoCmd.command("status").description("Show all DCA schedules").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2725
2793
|
try {
|
|
2726
2794
|
const pin = await resolvePin();
|
|
2727
|
-
const agent = await
|
|
2795
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2728
2796
|
const status = agent.getAutoInvestStatus();
|
|
2729
2797
|
if (isJsonMode()) {
|
|
2730
2798
|
printJson(status);
|
|
@@ -2740,9 +2808,9 @@ function registerInvest(program2) {
|
|
|
2740
2808
|
printSeparator();
|
|
2741
2809
|
for (const s of status.schedules) {
|
|
2742
2810
|
const target = s.strategy ?? s.asset ?? "?";
|
|
2743
|
-
const statusTag = s.enabled ?
|
|
2811
|
+
const statusTag = s.enabled ? pc15.green("active") : pc15.dim("paused");
|
|
2744
2812
|
printKeyValue(s.id, `${formatUsd15(s.amount)} ${s.frequency} \u2192 ${target} ${statusTag}`);
|
|
2745
|
-
printLine(` ${
|
|
2813
|
+
printLine(` ${pc15.dim(`Next: ${new Date(s.nextRun).toLocaleDateString()} \xB7 Runs: ${s.runCount} \xB7 Total: ${formatUsd15(s.totalInvested)}`)}`);
|
|
2746
2814
|
}
|
|
2747
2815
|
printSeparator();
|
|
2748
2816
|
if (status.pendingRuns.length > 0) {
|
|
@@ -2758,7 +2826,7 @@ function registerInvest(program2) {
|
|
|
2758
2826
|
autoCmd.command("run").description("Execute pending DCA purchases").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2759
2827
|
try {
|
|
2760
2828
|
const pin = await resolvePin();
|
|
2761
|
-
const agent = await
|
|
2829
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2762
2830
|
const status = agent.getAutoInvestStatus();
|
|
2763
2831
|
if (status.pendingRuns.length === 0) {
|
|
2764
2832
|
if (isJsonMode()) {
|
|
@@ -2785,7 +2853,7 @@ function registerInvest(program2) {
|
|
|
2785
2853
|
}
|
|
2786
2854
|
if (result.skipped.length > 0) {
|
|
2787
2855
|
for (const skip of result.skipped) {
|
|
2788
|
-
printLine(` ${
|
|
2856
|
+
printLine(` ${pc15.yellow("\u26A0")} Skipped ${skip.scheduleId}: ${skip.reason}`);
|
|
2789
2857
|
}
|
|
2790
2858
|
}
|
|
2791
2859
|
printBlank();
|
|
@@ -2796,7 +2864,7 @@ function registerInvest(program2) {
|
|
|
2796
2864
|
autoCmd.command("stop <id>").description("Stop an auto-invest schedule").option("--key <path>", "Key file path").action(async (id, opts) => {
|
|
2797
2865
|
try {
|
|
2798
2866
|
const pin = await resolvePin();
|
|
2799
|
-
const agent = await
|
|
2867
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2800
2868
|
agent.stopAutoInvest(id);
|
|
2801
2869
|
if (isJsonMode()) {
|
|
2802
2870
|
printJson({ stopped: id });
|
|
@@ -2812,22 +2880,22 @@ function registerInvest(program2) {
|
|
|
2812
2880
|
}
|
|
2813
2881
|
|
|
2814
2882
|
// src/commands/portfolio.ts
|
|
2815
|
-
import
|
|
2816
|
-
import { T2000 as
|
|
2883
|
+
import pc16 from "picocolors";
|
|
2884
|
+
import { T2000 as T200026, formatUsd as formatUsd16, formatAssetAmount as formatAssetAmount5 } from "@t2000/sdk";
|
|
2817
2885
|
function printPositionLine(pos, rewardKeys) {
|
|
2818
2886
|
if (pos.currentPrice === 0 && pos.totalAmount > 0) {
|
|
2819
2887
|
printKeyValue(
|
|
2820
2888
|
pos.asset,
|
|
2821
|
-
`${formatAssetAmount5(pos.totalAmount, pos.asset)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${
|
|
2889
|
+
`${formatAssetAmount5(pos.totalAmount, pos.asset)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${pc16.yellow("unavailable")}`
|
|
2822
2890
|
);
|
|
2823
2891
|
} else {
|
|
2824
|
-
const pnlColor = pos.unrealizedPnL >= 0 ?
|
|
2892
|
+
const pnlColor = pos.unrealizedPnL >= 0 ? pc16.green : pc16.red;
|
|
2825
2893
|
const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
|
|
2826
2894
|
let yieldSuffix = "";
|
|
2827
2895
|
if (pos.earning && pos.earningApy) {
|
|
2828
2896
|
const hasRewards = rewardKeys?.has(`${pos.earningProtocol}:${pos.asset}`);
|
|
2829
|
-
const rewardTag = hasRewards ? ` ${
|
|
2830
|
-
yieldSuffix = ` ${
|
|
2897
|
+
const rewardTag = hasRewards ? ` ${pc16.yellow("+rewards")}` : "";
|
|
2898
|
+
yieldSuffix = ` ${pc16.cyan(`${pos.earningApy.toFixed(1)}% APY (${pos.earningProtocol})`)}${rewardTag}`;
|
|
2831
2899
|
}
|
|
2832
2900
|
printKeyValue(
|
|
2833
2901
|
pos.asset,
|
|
@@ -2839,7 +2907,7 @@ function registerPortfolio(program2) {
|
|
|
2839
2907
|
program2.command("portfolio").description("Show investment portfolio").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2840
2908
|
try {
|
|
2841
2909
|
const pin = await resolvePin();
|
|
2842
|
-
const agent = await
|
|
2910
|
+
const agent = await T200026.create({ pin, keyPath: opts.key });
|
|
2843
2911
|
const portfolio = await agent.getPortfolio();
|
|
2844
2912
|
if (isJsonMode()) {
|
|
2845
2913
|
printJson(portfolio);
|
|
@@ -2855,7 +2923,7 @@ function registerPortfolio(program2) {
|
|
|
2855
2923
|
const hasDirectPositions = portfolio.positions.length > 0;
|
|
2856
2924
|
const hasStrategyPositions = portfolio.strategyPositions && Object.keys(portfolio.strategyPositions).length > 0;
|
|
2857
2925
|
if (!hasDirectPositions && !hasStrategyPositions) {
|
|
2858
|
-
printInfo("No investments yet. Try: t2000
|
|
2926
|
+
printInfo("No investments yet. Try: t2000 buy 100 SUI");
|
|
2859
2927
|
printBlank();
|
|
2860
2928
|
return;
|
|
2861
2929
|
}
|
|
@@ -2868,19 +2936,19 @@ function registerPortfolio(program2) {
|
|
|
2868
2936
|
stratLabel = def.name;
|
|
2869
2937
|
} catch {
|
|
2870
2938
|
}
|
|
2871
|
-
printLine(` ${
|
|
2939
|
+
printLine(` ${pc16.bold(pc16.cyan(`\u25B8 ${stratLabel}`))}`);
|
|
2872
2940
|
printSeparator();
|
|
2873
2941
|
for (const pos of positions) {
|
|
2874
2942
|
printPositionLine(pos, rewardKeys);
|
|
2875
2943
|
}
|
|
2876
2944
|
const stratValue = positions.reduce((s, p) => s + p.currentValue, 0);
|
|
2877
|
-
printLine(` ${
|
|
2945
|
+
printLine(` ${pc16.dim(`Subtotal: ${formatUsd16(stratValue)}`)}`);
|
|
2878
2946
|
printBlank();
|
|
2879
2947
|
}
|
|
2880
2948
|
}
|
|
2881
2949
|
if (hasDirectPositions) {
|
|
2882
2950
|
if (hasStrategyPositions) {
|
|
2883
|
-
printLine(` ${
|
|
2951
|
+
printLine(` ${pc16.bold(pc16.cyan("\u25B8 Direct"))}`);
|
|
2884
2952
|
}
|
|
2885
2953
|
printSeparator();
|
|
2886
2954
|
for (const pos of portfolio.positions) {
|
|
@@ -2888,21 +2956,21 @@ function registerPortfolio(program2) {
|
|
|
2888
2956
|
}
|
|
2889
2957
|
if (hasStrategyPositions) {
|
|
2890
2958
|
const directValue = portfolio.positions.reduce((s, p) => s + p.currentValue, 0);
|
|
2891
|
-
printLine(` ${
|
|
2959
|
+
printLine(` ${pc16.dim(`Subtotal: ${formatUsd16(directValue)}`)}`);
|
|
2892
2960
|
}
|
|
2893
2961
|
}
|
|
2894
2962
|
printSeparator();
|
|
2895
2963
|
const hasPriceUnavailable = portfolio.positions.some((p) => p.currentPrice === 0 && p.totalAmount > 0);
|
|
2896
2964
|
if (hasPriceUnavailable) {
|
|
2897
|
-
printInfo(
|
|
2965
|
+
printInfo(pc16.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
|
|
2898
2966
|
}
|
|
2899
2967
|
printKeyValue("Total invested", formatUsd16(portfolio.totalInvested));
|
|
2900
2968
|
printKeyValue("Current value", formatUsd16(portfolio.totalValue));
|
|
2901
|
-
const upnlColor = portfolio.unrealizedPnL >= 0 ?
|
|
2969
|
+
const upnlColor = portfolio.unrealizedPnL >= 0 ? pc16.green : pc16.red;
|
|
2902
2970
|
const upnlSign = portfolio.unrealizedPnL >= 0 ? "+" : "";
|
|
2903
2971
|
printKeyValue("Unrealized P&L", upnlColor(`${upnlSign}${formatUsd16(portfolio.unrealizedPnL)} (${upnlSign}${portfolio.unrealizedPnLPct.toFixed(1)}%)`));
|
|
2904
2972
|
if (portfolio.realizedPnL !== 0) {
|
|
2905
|
-
const rpnlColor = portfolio.realizedPnL >= 0 ?
|
|
2973
|
+
const rpnlColor = portfolio.realizedPnL >= 0 ? pc16.green : pc16.red;
|
|
2906
2974
|
const rpnlSign = portfolio.realizedPnL >= 0 ? "+" : "";
|
|
2907
2975
|
printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd16(portfolio.realizedPnL)}`));
|
|
2908
2976
|
}
|
|
@@ -2914,13 +2982,13 @@ function registerPortfolio(program2) {
|
|
|
2914
2982
|
}
|
|
2915
2983
|
|
|
2916
2984
|
// src/commands/claimRewards.ts
|
|
2917
|
-
import
|
|
2918
|
-
import { T2000 as
|
|
2985
|
+
import pc17 from "picocolors";
|
|
2986
|
+
import { T2000 as T200027, formatUsd as formatUsd17 } from "@t2000/sdk";
|
|
2919
2987
|
function registerClaimRewards(program2) {
|
|
2920
2988
|
program2.command("claim-rewards").description("Claim pending protocol rewards").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2921
2989
|
try {
|
|
2922
2990
|
const pin = await resolvePin();
|
|
2923
|
-
const agent = await
|
|
2991
|
+
const agent = await T200027.create({ pin, keyPath: opts.key });
|
|
2924
2992
|
const result = await agent.claimRewards();
|
|
2925
2993
|
if (isJsonMode()) {
|
|
2926
2994
|
printJson(result);
|
|
@@ -2928,20 +2996,20 @@ function registerClaimRewards(program2) {
|
|
|
2928
2996
|
}
|
|
2929
2997
|
printBlank();
|
|
2930
2998
|
if (result.rewards.length === 0) {
|
|
2931
|
-
printLine(` ${
|
|
2999
|
+
printLine(` ${pc17.dim("No rewards to claim")}`);
|
|
2932
3000
|
printBlank();
|
|
2933
3001
|
return;
|
|
2934
3002
|
}
|
|
2935
3003
|
const protocols = [...new Set(result.rewards.map((r) => r.protocol))];
|
|
2936
|
-
printLine(` ${
|
|
3004
|
+
printLine(` ${pc17.green("\u2713")} Claimed and converted rewards to USDC`);
|
|
2937
3005
|
printSeparator();
|
|
2938
3006
|
const received = result.usdcReceived;
|
|
2939
3007
|
if (received >= 0.01) {
|
|
2940
|
-
printKeyValue("Received", `${
|
|
3008
|
+
printKeyValue("Received", `${pc17.green(formatUsd17(received))} USDC`);
|
|
2941
3009
|
} else if (received > 0) {
|
|
2942
|
-
printKeyValue("Received", `${
|
|
3010
|
+
printKeyValue("Received", `${pc17.green("< $0.01")} USDC`);
|
|
2943
3011
|
} else {
|
|
2944
|
-
printKeyValue("Received", `${
|
|
3012
|
+
printKeyValue("Received", `${pc17.dim("< $0.01 USDC (rewards are still accruing)")}`);
|
|
2945
3013
|
}
|
|
2946
3014
|
printKeyValue("Source", protocols.join(", "));
|
|
2947
3015
|
if (result.tx) {
|
|
@@ -2955,13 +3023,13 @@ function registerClaimRewards(program2) {
|
|
|
2955
3023
|
}
|
|
2956
3024
|
|
|
2957
3025
|
// src/commands/gas.ts
|
|
2958
|
-
import
|
|
2959
|
-
import { T2000 as
|
|
3026
|
+
import pc18 from "picocolors";
|
|
3027
|
+
import { T2000 as T200028, getGasStatus } from "@t2000/sdk";
|
|
2960
3028
|
function registerGas(program2) {
|
|
2961
3029
|
program2.command("gas").description("Check gas station status and wallet gas balance").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2962
3030
|
try {
|
|
2963
3031
|
const pin = await resolvePin();
|
|
2964
|
-
const agent = await
|
|
3032
|
+
const agent = await T200028.create({ pin, keyPath: opts.key });
|
|
2965
3033
|
const address = agent.address();
|
|
2966
3034
|
const [status, bal] = await Promise.allSettled([
|
|
2967
3035
|
getGasStatus(address),
|
|
@@ -2978,36 +3046,36 @@ function registerGas(program2) {
|
|
|
2978
3046
|
}
|
|
2979
3047
|
printHeader("Gas Status");
|
|
2980
3048
|
if (gasStatus) {
|
|
2981
|
-
const cbStatus = gasStatus.circuitBreaker ?
|
|
3049
|
+
const cbStatus = gasStatus.circuitBreaker ? pc18.red("TRIPPED \u2014 sponsorship paused") : pc18.green("OK");
|
|
2982
3050
|
printKeyValue("Gas Station", cbStatus);
|
|
2983
3051
|
printKeyValue("SUI Price (TWAP)", `$${gasStatus.suiPrice.toFixed(4)}`);
|
|
2984
3052
|
if (gasStatus.bootstrapRemaining !== void 0) {
|
|
2985
3053
|
printKeyValue("Bootstrap", `${gasStatus.bootstrapUsed}/10 used (${gasStatus.bootstrapRemaining} remaining)`);
|
|
2986
3054
|
}
|
|
2987
3055
|
} else {
|
|
2988
|
-
printKeyValue("Gas Station",
|
|
3056
|
+
printKeyValue("Gas Station", pc18.red("unreachable"));
|
|
2989
3057
|
const reason = status.status === "rejected" ? status.reason : "unknown";
|
|
2990
|
-
printLine(` ${
|
|
3058
|
+
printLine(` ${pc18.dim(reason instanceof Error ? reason.message : String(reason))}`);
|
|
2991
3059
|
}
|
|
2992
3060
|
printDivider();
|
|
2993
3061
|
if (balData) {
|
|
2994
3062
|
const suiBal = balData.gasReserve.sui;
|
|
2995
|
-
const suiColor = suiBal < 0.05 ?
|
|
3063
|
+
const suiColor = suiBal < 0.05 ? pc18.red : pc18.green;
|
|
2996
3064
|
printKeyValue("SUI (gas)", suiColor(`${suiBal.toFixed(4)} SUI`));
|
|
2997
3065
|
if (suiBal < 0.05) {
|
|
2998
|
-
printLine(` ${
|
|
3066
|
+
printLine(` ${pc18.yellow("\u26A0")} Below gas threshold (0.05 SUI) \u2014 transactions will need sponsorship`);
|
|
2999
3067
|
}
|
|
3000
3068
|
printKeyValue("Available", `$${balData.available.toFixed(2)}`);
|
|
3001
3069
|
} else {
|
|
3002
|
-
printKeyValue("Wallet",
|
|
3070
|
+
printKeyValue("Wallet", pc18.dim("could not fetch balances"));
|
|
3003
3071
|
}
|
|
3004
3072
|
printBlank();
|
|
3005
3073
|
if (gasStatus && !gasStatus.circuitBreaker && (balData?.gasReserve.sui ?? 0) >= 0.05) {
|
|
3006
|
-
printLine(` ${
|
|
3074
|
+
printLine(` ${pc18.green("\u2713")} Gas is healthy \u2014 transactions should succeed`);
|
|
3007
3075
|
} else if (gasStatus && !gasStatus.circuitBreaker) {
|
|
3008
|
-
printLine(` ${
|
|
3076
|
+
printLine(` ${pc18.yellow("\u26A0")} Low SUI but gas station is online \u2014 sponsorship available`);
|
|
3009
3077
|
} else {
|
|
3010
|
-
printLine(` ${
|
|
3078
|
+
printLine(` ${pc18.red("\u2717")} Gas station issues detected \u2014 fund wallet with SUI directly`);
|
|
3011
3079
|
printInfo("Send SUI to your address: t2000 address");
|
|
3012
3080
|
}
|
|
3013
3081
|
printBlank();
|
|
@@ -3025,7 +3093,18 @@ function createProgram() {
|
|
|
3025
3093
|
program2.name("t2000").description("A bank account for AI agents").version(`${CLI_VERSION} (beta)`).option("--json", "Output in JSON format").hook("preAction", (thisCommand) => {
|
|
3026
3094
|
const opts = thisCommand.optsWithGlobals();
|
|
3027
3095
|
if (opts.json) setJsonMode(true);
|
|
3028
|
-
})
|
|
3096
|
+
}).addHelpText("after", `
|
|
3097
|
+
Examples:
|
|
3098
|
+
$ t2000 init Create a new agent bank account
|
|
3099
|
+
$ t2000 balance Show wallet balance
|
|
3100
|
+
$ t2000 save 100 Save $100 to earn yield
|
|
3101
|
+
$ t2000 send 50 to 0xabc... Send $50 USDC
|
|
3102
|
+
$ t2000 borrow 200 Borrow $200 against savings
|
|
3103
|
+
$ t2000 pay openai ... Pay for an API via MPP gateway
|
|
3104
|
+
$ t2000 buy 100 BTC Buy $100 of BTC
|
|
3105
|
+
$ t2000 sell 0.001 BTC Sell BTC for USDC
|
|
3106
|
+
$ t2000 swap 100 USDC SUI Swap between any tokens
|
|
3107
|
+
$ t2000 mcp install Install MCP for AI platforms`);
|
|
3029
3108
|
registerInit(program2);
|
|
3030
3109
|
registerSend(program2);
|
|
3031
3110
|
registerBalance(program2);
|
|
@@ -3050,6 +3129,7 @@ function createProgram() {
|
|
|
3050
3129
|
registerSentinel(program2);
|
|
3051
3130
|
registerEarn(program2);
|
|
3052
3131
|
registerRebalance(program2);
|
|
3132
|
+
registerSwap(program2);
|
|
3053
3133
|
registerExchange(program2);
|
|
3054
3134
|
registerMcp(program2);
|
|
3055
3135
|
registerContacts(program2);
|