@t2000/cli 0.13.0 → 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
|
@@ -186,16 +186,27 @@ function registerInit(program2) {
|
|
|
186
186
|
// src/commands/send.ts
|
|
187
187
|
import { T2000 as T20002 } from "@t2000/sdk";
|
|
188
188
|
import { truncateAddress, formatUsd } from "@t2000/sdk";
|
|
189
|
+
var KNOWN_ASSETS = /* @__PURE__ */ new Set(["USDC", "USDT", "USDE", "USDSUI", "SUI"]);
|
|
190
|
+
function parseSendArgs(args) {
|
|
191
|
+
const filtered = args.filter((a) => a.toLowerCase() !== "to");
|
|
192
|
+
if (filtered.length >= 3 && KNOWN_ASSETS.has(filtered[1].toUpperCase())) {
|
|
193
|
+
return { amount: parseFloat(filtered[0]), asset: filtered[1].toUpperCase(), recipient: filtered[2] };
|
|
194
|
+
}
|
|
195
|
+
if (filtered.length >= 2) {
|
|
196
|
+
return { amount: parseFloat(filtered[0]), asset: "USDC", recipient: filtered[filtered.length - 1] };
|
|
197
|
+
}
|
|
198
|
+
throw new Error("Usage: t2000 send <amount> [asset] [to] <address_or_contact>");
|
|
199
|
+
}
|
|
189
200
|
function registerSend(program2) {
|
|
190
|
-
program2.command("send
|
|
201
|
+
program2.command("send").argument("<amount>", "Amount to send").argument("[args...]", 'Asset, "to" keyword, and recipient address or contact name').description("Send USDC (or other asset) to an address or contact name").option("--key <path>", "Key file path").action(async (amount, args, opts) => {
|
|
191
202
|
try {
|
|
192
|
-
const recipient =
|
|
203
|
+
const { amount: parsedAmount, asset, recipient } = parseSendArgs([amount, ...args]);
|
|
193
204
|
const pin = await resolvePin();
|
|
194
205
|
const agent = await T20002.create({ pin, keyPath: opts.key });
|
|
195
206
|
const result = await agent.send({
|
|
196
207
|
to: recipient,
|
|
197
|
-
amount:
|
|
198
|
-
asset
|
|
208
|
+
amount: parsedAmount,
|
|
209
|
+
asset
|
|
199
210
|
});
|
|
200
211
|
if (isJsonMode()) {
|
|
201
212
|
printJson(result);
|
|
@@ -263,6 +274,14 @@ function registerBalance(program2) {
|
|
|
263
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;
|
|
264
275
|
printKeyValue("Credit", `${pc3.red(`-${formatUsd2(bal.debt)}`)} ${pc3.dim(`(${borrowApy.toFixed(2)}% APY)`)}`);
|
|
265
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
|
+
}
|
|
266
285
|
printKeyValue("Gas", `${bal.gasReserve.sui.toFixed(2)} SUI ${pc3.dim(`(~${formatUsd2(bal.gasReserve.usdEquiv)})`)}`);
|
|
267
286
|
printSeparator();
|
|
268
287
|
printKeyValue("Total", `${formatUsd2(bal.total)}`);
|
|
@@ -274,6 +293,14 @@ function registerBalance(program2) {
|
|
|
274
293
|
printKeyValue("Credit", `${pc3.red(`-${formatUsd2(bal.debt)}`)}`);
|
|
275
294
|
}
|
|
276
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
|
+
}
|
|
277
304
|
printKeyValue("Gas", `${bal.gasReserve.sui.toFixed(2)} SUI ${pc3.dim(`(~${formatUsd2(bal.gasReserve.usdEquiv)})`)}`);
|
|
278
305
|
printSeparator();
|
|
279
306
|
printKeyValue("Total", `${formatUsd2(bal.total)}`);
|
|
@@ -803,7 +830,7 @@ import { homedir as homedir3 } from "os";
|
|
|
803
830
|
import { SafeguardEnforcer } from "@t2000/sdk";
|
|
804
831
|
var CONFIG_DIR = join(homedir3(), ".t2000");
|
|
805
832
|
var CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
806
|
-
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"]);
|
|
807
834
|
function loadConfig() {
|
|
808
835
|
try {
|
|
809
836
|
return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
@@ -1332,8 +1359,8 @@ function registerLock(program2) {
|
|
|
1332
1359
|
if (!pin) {
|
|
1333
1360
|
throw new Error("PIN required to unlock agent");
|
|
1334
1361
|
}
|
|
1335
|
-
const { T2000:
|
|
1336
|
-
await
|
|
1362
|
+
const { T2000: T200026 } = await import("@t2000/sdk");
|
|
1363
|
+
await T200026.create({ pin });
|
|
1337
1364
|
const enforcer = new SafeguardEnforcer2(CONFIG_DIR3);
|
|
1338
1365
|
enforcer.load();
|
|
1339
1366
|
enforcer.unlock();
|
|
@@ -1760,7 +1787,7 @@ function registerMcp(program2) {
|
|
|
1760
1787
|
mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
|
|
1761
1788
|
let mod;
|
|
1762
1789
|
try {
|
|
1763
|
-
mod = await import("./dist-
|
|
1790
|
+
mod = await import("./dist-4B5R5GWR.js");
|
|
1764
1791
|
} catch {
|
|
1765
1792
|
console.error(
|
|
1766
1793
|
"MCP server not installed. Run:\n npm install -g @t2000/mcp"
|
|
@@ -1911,6 +1938,140 @@ function registerContacts(program2) {
|
|
|
1911
1938
|
});
|
|
1912
1939
|
}
|
|
1913
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
|
+
|
|
1914
2075
|
// src/program.ts
|
|
1915
2076
|
var require2 = createRequire(import.meta.url);
|
|
1916
2077
|
var { version: CLI_VERSION } = require2("../package.json");
|
|
@@ -1947,6 +2108,8 @@ function createProgram() {
|
|
|
1947
2108
|
registerExchange(program2);
|
|
1948
2109
|
registerMcp(program2);
|
|
1949
2110
|
registerContacts(program2);
|
|
2111
|
+
registerInvest(program2);
|
|
2112
|
+
registerPortfolio(program2);
|
|
1950
2113
|
return program2;
|
|
1951
2114
|
}
|
|
1952
2115
|
|