@t2000/cli 0.13.1 → 0.14.0
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
|
@@ -274,6 +274,14 @@ function registerBalance(program2) {
|
|
|
274
274
|
const borrowApy = borrows.length > 0 ? borrows.reduce((sum, p) => sum + p.amount * p.apy, 0) / borrows.reduce((sum, p) => sum + p.amount, 0) : 0;
|
|
275
275
|
printKeyValue("Credit", `${pc3.red(`-${formatUsd2(bal.debt)}`)} ${pc3.dim(`(${borrowApy.toFixed(2)}% APY)`)}`);
|
|
276
276
|
}
|
|
277
|
+
if (bal.investment > 0.01) {
|
|
278
|
+
const pnlColor = bal.investmentPnL >= 0 ? pc3.green : pc3.red;
|
|
279
|
+
const pnlSign = bal.investmentPnL >= 0 ? "+" : "";
|
|
280
|
+
const pnlPct = bal.investment > 0 ? bal.investmentPnL / (bal.investment - bal.investmentPnL) * 100 : 0;
|
|
281
|
+
printKeyValue("Investment", `${formatUsd2(bal.investment)} ${pnlColor(`(${pnlSign}${pnlPct.toFixed(1)}%)`)}`);
|
|
282
|
+
} else {
|
|
283
|
+
printKeyValue("Investment", pc3.dim("\u2014"));
|
|
284
|
+
}
|
|
277
285
|
printKeyValue("Gas", `${bal.gasReserve.sui.toFixed(2)} SUI ${pc3.dim(`(~${formatUsd2(bal.gasReserve.usdEquiv)})`)}`);
|
|
278
286
|
printSeparator();
|
|
279
287
|
printKeyValue("Total", `${formatUsd2(bal.total)}`);
|
|
@@ -285,6 +293,14 @@ function registerBalance(program2) {
|
|
|
285
293
|
printKeyValue("Credit", `${pc3.red(`-${formatUsd2(bal.debt)}`)}`);
|
|
286
294
|
}
|
|
287
295
|
printKeyValue("Savings", `${formatUsd2(bal.savings)}`);
|
|
296
|
+
if (bal.investment > 0.01) {
|
|
297
|
+
const pnlColor = bal.investmentPnL >= 0 ? pc3.green : pc3.red;
|
|
298
|
+
const pnlSign = bal.investmentPnL >= 0 ? "+" : "";
|
|
299
|
+
const pnlPct = bal.investment > 0 ? bal.investmentPnL / (bal.investment - bal.investmentPnL) * 100 : 0;
|
|
300
|
+
printKeyValue("Investment", `${formatUsd2(bal.investment)} ${pnlColor(`(${pnlSign}${pnlPct.toFixed(1)}%)`)}`);
|
|
301
|
+
} else {
|
|
302
|
+
printKeyValue("Investment", pc3.dim("\u2014"));
|
|
303
|
+
}
|
|
288
304
|
printKeyValue("Gas", `${bal.gasReserve.sui.toFixed(2)} SUI ${pc3.dim(`(~${formatUsd2(bal.gasReserve.usdEquiv)})`)}`);
|
|
289
305
|
printSeparator();
|
|
290
306
|
printKeyValue("Total", `${formatUsd2(bal.total)}`);
|
|
@@ -814,7 +830,7 @@ import { homedir as homedir3 } from "os";
|
|
|
814
830
|
import { SafeguardEnforcer } from "@t2000/sdk";
|
|
815
831
|
var CONFIG_DIR = join(homedir3(), ".t2000");
|
|
816
832
|
var CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
817
|
-
var SAFEGUARD_KEYS = /* @__PURE__ */ new Set(["locked", "maxPerTx", "maxDailySend", "dailyUsed", "dailyResetDate", "alertThreshold"]);
|
|
833
|
+
var SAFEGUARD_KEYS = /* @__PURE__ */ new Set(["locked", "maxPerTx", "maxDailySend", "dailyUsed", "dailyResetDate", "alertThreshold", "maxLeverage", "maxPositionSize"]);
|
|
818
834
|
function loadConfig() {
|
|
819
835
|
try {
|
|
820
836
|
return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
@@ -1343,8 +1359,8 @@ function registerLock(program2) {
|
|
|
1343
1359
|
if (!pin) {
|
|
1344
1360
|
throw new Error("PIN required to unlock agent");
|
|
1345
1361
|
}
|
|
1346
|
-
const { T2000:
|
|
1347
|
-
await
|
|
1362
|
+
const { T2000: T200026 } = await import("@t2000/sdk");
|
|
1363
|
+
await T200026.create({ pin });
|
|
1348
1364
|
const enforcer = new SafeguardEnforcer2(CONFIG_DIR3);
|
|
1349
1365
|
enforcer.load();
|
|
1350
1366
|
enforcer.unlock();
|
|
@@ -1771,7 +1787,7 @@ function registerMcp(program2) {
|
|
|
1771
1787
|
mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
|
|
1772
1788
|
let mod;
|
|
1773
1789
|
try {
|
|
1774
|
-
mod = await import("./dist-
|
|
1790
|
+
mod = await import("./dist-4B5R5GWR.js");
|
|
1775
1791
|
} catch {
|
|
1776
1792
|
console.error(
|
|
1777
1793
|
"MCP server not installed. Run:\n npm install -g @t2000/mcp"
|
|
@@ -1922,6 +1938,140 @@ function registerContacts(program2) {
|
|
|
1922
1938
|
});
|
|
1923
1939
|
}
|
|
1924
1940
|
|
|
1941
|
+
// src/commands/invest.ts
|
|
1942
|
+
import pc13 from "picocolors";
|
|
1943
|
+
import { T2000 as T200024, formatUsd as formatUsd15 } from "@t2000/sdk";
|
|
1944
|
+
function registerInvest(program2) {
|
|
1945
|
+
const investCmd = program2.command("invest").description("Buy or sell investment assets");
|
|
1946
|
+
investCmd.command("buy <amount> <asset>").description("Invest USD amount in an asset").option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percent", "3").action(async (amount, asset, opts) => {
|
|
1947
|
+
try {
|
|
1948
|
+
const parsed = parseFloat(amount);
|
|
1949
|
+
if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
|
|
1950
|
+
console.error(pc13.red(" \u2717 Amount must be greater than $0"));
|
|
1951
|
+
process.exitCode = 1;
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
const pin = await resolvePin();
|
|
1955
|
+
const agent = await T200024.create({ pin, keyPath: opts.key });
|
|
1956
|
+
const result = await agent.investBuy({
|
|
1957
|
+
asset: asset.toUpperCase(),
|
|
1958
|
+
usdAmount: parsed,
|
|
1959
|
+
maxSlippage: parseFloat(opts.slippage) / 100
|
|
1960
|
+
});
|
|
1961
|
+
if (isJsonMode()) {
|
|
1962
|
+
printJson(result);
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
printBlank();
|
|
1966
|
+
printSuccess(`Bought ${result.amount.toFixed(4)} ${asset.toUpperCase()} at ${formatUsd15(result.price)}`);
|
|
1967
|
+
printKeyValue("Invested", formatUsd15(result.usdValue));
|
|
1968
|
+
printKeyValue("Portfolio", `${result.position.totalAmount.toFixed(4)} ${asset.toUpperCase()} (avg ${formatUsd15(result.position.avgPrice)})`);
|
|
1969
|
+
printKeyValue("Tx", explorerUrl(result.tx));
|
|
1970
|
+
printBlank();
|
|
1971
|
+
} catch (error) {
|
|
1972
|
+
handleError(error);
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
investCmd.command("sell <amount> <asset>").description('Sell USD amount of an asset (or "all")').option("--key <path>", "Key file path").option("--slippage <pct>", "Max slippage percent", "3").action(async (amount, asset, opts) => {
|
|
1976
|
+
try {
|
|
1977
|
+
const isAll = amount.toLowerCase() === "all";
|
|
1978
|
+
if (!isAll) {
|
|
1979
|
+
const parsed = parseFloat(amount);
|
|
1980
|
+
if (isNaN(parsed) || parsed <= 0 || !isFinite(parsed)) {
|
|
1981
|
+
console.error(pc13.red(" \u2717 Amount must be greater than $0"));
|
|
1982
|
+
process.exitCode = 1;
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
const pin = await resolvePin();
|
|
1987
|
+
const agent = await T200024.create({ pin, keyPath: opts.key });
|
|
1988
|
+
const usdAmount = isAll ? "all" : parseFloat(amount);
|
|
1989
|
+
const result = await agent.investSell({
|
|
1990
|
+
asset: asset.toUpperCase(),
|
|
1991
|
+
usdAmount,
|
|
1992
|
+
maxSlippage: parseFloat(opts.slippage) / 100
|
|
1993
|
+
});
|
|
1994
|
+
if (isJsonMode()) {
|
|
1995
|
+
printJson(result);
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1998
|
+
printBlank();
|
|
1999
|
+
printSuccess(`Sold ${result.amount.toFixed(4)} ${asset.toUpperCase()} at ${formatUsd15(result.price)}`);
|
|
2000
|
+
printKeyValue("Proceeds", formatUsd15(result.usdValue));
|
|
2001
|
+
if (result.realizedPnL !== void 0) {
|
|
2002
|
+
const pnlColor = result.realizedPnL >= 0 ? pc13.green : pc13.red;
|
|
2003
|
+
const pnlSign = result.realizedPnL >= 0 ? "+" : "";
|
|
2004
|
+
printKeyValue("Realized P&L", pnlColor(`${pnlSign}${formatUsd15(result.realizedPnL)}`));
|
|
2005
|
+
}
|
|
2006
|
+
if (result.position.totalAmount > 0) {
|
|
2007
|
+
printKeyValue("Remaining", `${result.position.totalAmount.toFixed(4)} ${asset.toUpperCase()} (avg ${formatUsd15(result.position.avgPrice)})`);
|
|
2008
|
+
}
|
|
2009
|
+
printKeyValue("Tx", explorerUrl(result.tx));
|
|
2010
|
+
printBlank();
|
|
2011
|
+
} catch (error) {
|
|
2012
|
+
handleError(error);
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
// src/commands/portfolio.ts
|
|
2018
|
+
import pc14 from "picocolors";
|
|
2019
|
+
import { T2000 as T200025, formatUsd as formatUsd16 } from "@t2000/sdk";
|
|
2020
|
+
function registerPortfolio(program2) {
|
|
2021
|
+
program2.command("portfolio").description("Show investment portfolio").option("--key <path>", "Key file path").action(async (opts) => {
|
|
2022
|
+
try {
|
|
2023
|
+
const pin = await resolvePin();
|
|
2024
|
+
const agent = await T200025.create({ pin, keyPath: opts.key });
|
|
2025
|
+
const portfolio = await agent.getPortfolio();
|
|
2026
|
+
if (isJsonMode()) {
|
|
2027
|
+
printJson(portfolio);
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
printBlank();
|
|
2031
|
+
if (portfolio.positions.length === 0) {
|
|
2032
|
+
printInfo("No investments yet. Try: t2000 invest buy 100 SUI");
|
|
2033
|
+
printBlank();
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
printHeader("Investment Portfolio");
|
|
2037
|
+
printSeparator();
|
|
2038
|
+
for (const pos of portfolio.positions) {
|
|
2039
|
+
if (pos.currentPrice === 0 && pos.totalAmount > 0) {
|
|
2040
|
+
printKeyValue(
|
|
2041
|
+
pos.asset,
|
|
2042
|
+
`${pos.totalAmount.toFixed(4)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${pc14.yellow("unavailable")}`
|
|
2043
|
+
);
|
|
2044
|
+
} else {
|
|
2045
|
+
const pnlColor = pos.unrealizedPnL >= 0 ? pc14.green : pc14.red;
|
|
2046
|
+
const pnlSign = pos.unrealizedPnL >= 0 ? "+" : "";
|
|
2047
|
+
printKeyValue(
|
|
2048
|
+
pos.asset,
|
|
2049
|
+
`${pos.totalAmount.toFixed(4)} Avg: ${formatUsd16(pos.avgPrice)} Now: ${formatUsd16(pos.currentPrice)} ${pnlColor(`${pnlSign}${formatUsd16(pos.unrealizedPnL)} (${pnlSign}${pos.unrealizedPnLPct.toFixed(1)}%)`)}`
|
|
2050
|
+
);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
printSeparator();
|
|
2054
|
+
const hasPriceUnavailable = portfolio.positions.some((p) => p.currentPrice === 0 && p.totalAmount > 0);
|
|
2055
|
+
if (hasPriceUnavailable) {
|
|
2056
|
+
printInfo(pc14.yellow("\u26A0 Price data unavailable for some assets. Values may be inaccurate."));
|
|
2057
|
+
}
|
|
2058
|
+
printKeyValue("Total invested", formatUsd16(portfolio.totalInvested));
|
|
2059
|
+
printKeyValue("Current value", formatUsd16(portfolio.totalValue));
|
|
2060
|
+
const upnlColor = portfolio.unrealizedPnL >= 0 ? pc14.green : pc14.red;
|
|
2061
|
+
const upnlSign = portfolio.unrealizedPnL >= 0 ? "+" : "";
|
|
2062
|
+
printKeyValue("Unrealized P&L", upnlColor(`${upnlSign}${formatUsd16(portfolio.unrealizedPnL)} (${upnlSign}${portfolio.unrealizedPnLPct.toFixed(1)}%)`));
|
|
2063
|
+
if (portfolio.realizedPnL !== 0) {
|
|
2064
|
+
const rpnlColor = portfolio.realizedPnL >= 0 ? pc14.green : pc14.red;
|
|
2065
|
+
const rpnlSign = portfolio.realizedPnL >= 0 ? "+" : "";
|
|
2066
|
+
printKeyValue("Realized P&L", rpnlColor(`${rpnlSign}${formatUsd16(portfolio.realizedPnL)}`));
|
|
2067
|
+
}
|
|
2068
|
+
printBlank();
|
|
2069
|
+
} catch (error) {
|
|
2070
|
+
handleError(error);
|
|
2071
|
+
}
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
|
|
1925
2075
|
// src/program.ts
|
|
1926
2076
|
var require2 = createRequire(import.meta.url);
|
|
1927
2077
|
var { version: CLI_VERSION } = require2("../package.json");
|
|
@@ -1958,6 +2108,8 @@ function createProgram() {
|
|
|
1958
2108
|
registerExchange(program2);
|
|
1959
2109
|
registerMcp(program2);
|
|
1960
2110
|
registerContacts(program2);
|
|
2111
|
+
registerInvest(program2);
|
|
2112
|
+
registerPortfolio(program2);
|
|
1961
2113
|
return program2;
|
|
1962
2114
|
}
|
|
1963
2115
|
|