@t2000/cli 0.14.0 → 0.15.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/README.md
CHANGED
|
@@ -90,14 +90,28 @@ t2000 init
|
|
|
90
90
|
Portfolio: 105.26 SUI (avg $0.95)
|
|
91
91
|
Tx: https://suiscan.xyz/mainnet/tx/...
|
|
92
92
|
|
|
93
|
+
❯ t2000 invest buy 500 BTC
|
|
94
|
+
✓ Bought 0.00512820 BTC at $97,500.00
|
|
95
|
+
Invested: $500.00
|
|
96
|
+
Portfolio: 0.00512820 BTC (avg $97,500.00)
|
|
97
|
+
Tx: https://suiscan.xyz/mainnet/tx/...
|
|
98
|
+
|
|
99
|
+
❯ t2000 invest buy 200 ETH
|
|
100
|
+
✓ Bought 0.10526316 ETH at $1,900.00
|
|
101
|
+
Invested: $200.00
|
|
102
|
+
Portfolio: 0.10526316 ETH (avg $1,900.00)
|
|
103
|
+
Tx: https://suiscan.xyz/mainnet/tx/...
|
|
104
|
+
|
|
93
105
|
❯ t2000 portfolio
|
|
94
106
|
Investment Portfolio
|
|
95
107
|
─────────────────────────────────────────────────────
|
|
96
|
-
SUI 105.
|
|
108
|
+
SUI 105.26000000 Avg: $0.95 Now: $0.97 APY: 2.10% +$2.10 (+2.1%)
|
|
109
|
+
BTC 0.00512820 Avg: $97,500 Now: $98,200 — +$3.59 (+0.7%)
|
|
110
|
+
ETH 0.10526316 Avg: $1,900 Now: $1,920 APY: 1.85% +$2.11 (+1.1%)
|
|
97
111
|
─────────────────────────────────────────────────────
|
|
98
|
-
Total invested: $
|
|
99
|
-
Current value: $
|
|
100
|
-
Unrealized P&L: +$
|
|
112
|
+
Total invested: $800.00
|
|
113
|
+
Current value: $807.80
|
|
114
|
+
Unrealized P&L: +$7.80 (+1.0%)
|
|
101
115
|
```
|
|
102
116
|
|
|
103
117
|
30 seconds. Send → save → borrow → pay → repay → withdraw.
|
|
@@ -176,6 +190,18 @@ t2000 init
|
|
|
176
190
|
| `t2000 contacts add <name> <address>` | Save a named contact |
|
|
177
191
|
| `t2000 contacts remove <name>` | Remove a contact |
|
|
178
192
|
|
|
193
|
+
### Investment
|
|
194
|
+
|
|
195
|
+
| Command | Description |
|
|
196
|
+
|---------|-------------|
|
|
197
|
+
| `t2000 invest buy <amount> <asset>` | Buy crypto with USDC (e.g. `t2000 invest buy 500 BTC`, `t2000 invest buy 200 ETH`) |
|
|
198
|
+
| `t2000 invest sell <amount\|all> <asset>` | Sell crypto back to USDC (auto-withdraws if earning) |
|
|
199
|
+
| `t2000 invest earn <asset>` | Deposit invested asset into best-rate lending for yield |
|
|
200
|
+
| `t2000 invest unearn <asset>` | Withdraw from lending, keep in portfolio |
|
|
201
|
+
| `t2000 portfolio` | View investment portfolio with cost-basis P&L (shows APY when earning) |
|
|
202
|
+
|
|
203
|
+
Supported assets: SUI, BTC, ETH. Dollar-denominated — `amount` is in USD.
|
|
204
|
+
|
|
179
205
|
### Safeguards
|
|
180
206
|
|
|
181
207
|
| Command | Description |
|
|
@@ -20965,7 +20965,7 @@ var StdioServerTransport = class {
|
|
|
20965
20965
|
import { readFile } from "fs/promises";
|
|
20966
20966
|
import { resolve } from "path";
|
|
20967
20967
|
import { homedir } from "os";
|
|
20968
|
-
import { T2000, SafeguardError, T2000Error } from "@t2000/sdk";
|
|
20968
|
+
import { T2000, INVESTMENT_ASSETS, SafeguardError, T2000Error } from "@t2000/sdk";
|
|
20969
20969
|
var SESSION_PATH = resolve(homedir(), ".t2000", ".session");
|
|
20970
20970
|
async function resolvePin() {
|
|
20971
20971
|
const envPin = process.env.T2000_PIN ?? process.env.T2000_PASSPHRASE;
|
|
@@ -21124,7 +21124,14 @@ function registerReadTools(server, agent) {
|
|
|
21124
21124
|
async () => {
|
|
21125
21125
|
try {
|
|
21126
21126
|
const result = await agent.getPortfolio();
|
|
21127
|
-
|
|
21127
|
+
const enriched = {
|
|
21128
|
+
...result,
|
|
21129
|
+
positions: result.positions.map((p) => ({
|
|
21130
|
+
...p,
|
|
21131
|
+
...p.currentPrice === 0 && p.totalAmount > 0 ? { note: "price unavailable" } : {}
|
|
21132
|
+
}))
|
|
21133
|
+
};
|
|
21134
|
+
return { content: [{ type: "text", text: JSON.stringify(enriched) }] };
|
|
21128
21135
|
} catch (err) {
|
|
21129
21136
|
return errorResult(err);
|
|
21130
21137
|
}
|
|
@@ -21364,22 +21371,29 @@ function registerWriteTools(server, agent) {
|
|
|
21364
21371
|
}
|
|
21365
21372
|
}
|
|
21366
21373
|
);
|
|
21374
|
+
const investAssets = Object.keys(INVESTMENT_ASSETS);
|
|
21367
21375
|
server.tool(
|
|
21368
21376
|
"t2000_invest",
|
|
21369
|
-
"Buy or
|
|
21377
|
+
"Buy, sell, earn yield, or stop earning on investment assets. Actions: buy (invest USD), sell (convert to USDC), earn (deposit into best-rate lending for yield), unearn (withdraw from lending, keep in portfolio). Amount required for buy/sell only.",
|
|
21370
21378
|
{
|
|
21371
|
-
action: external_exports.enum(["buy", "sell"]).describe("'buy' to invest
|
|
21372
|
-
asset: external_exports.enum(
|
|
21373
|
-
amount: external_exports.union([external_exports.number(), external_exports.literal("all")]).describe(
|
|
21379
|
+
action: external_exports.enum(["buy", "sell", "earn", "unearn"]).describe("'buy' to invest, 'sell' to liquidate, 'earn' to deposit into lending for yield, 'unearn' to withdraw from lending"),
|
|
21380
|
+
asset: external_exports.enum(investAssets).describe("Asset to invest in"),
|
|
21381
|
+
amount: external_exports.union([external_exports.number(), external_exports.literal("all")]).optional().describe("USD amount (required for buy/sell, ignored for earn/unearn)"),
|
|
21382
|
+
slippage: external_exports.number().optional().describe("Max slippage percent (default: 3, for buy/sell only)"),
|
|
21374
21383
|
dryRun: external_exports.boolean().optional().describe("Preview without signing (default: false)")
|
|
21375
21384
|
},
|
|
21376
|
-
async ({ action, asset, amount, dryRun }) => {
|
|
21385
|
+
async ({ action, asset, amount, slippage, dryRun }) => {
|
|
21377
21386
|
try {
|
|
21378
21387
|
if (dryRun) {
|
|
21379
21388
|
agent.enforcer.assertNotLocked();
|
|
21380
21389
|
const balance = await agent.balance();
|
|
21381
21390
|
const portfolio = await agent.getPortfolio();
|
|
21382
21391
|
const position = portfolio.positions.find((p) => p.asset === asset);
|
|
21392
|
+
if (action === "sell" && amount === "all" && !position) {
|
|
21393
|
+
return {
|
|
21394
|
+
content: [{ type: "text", text: JSON.stringify({ preview: true, error: `No ${asset} position to sell` }) }]
|
|
21395
|
+
};
|
|
21396
|
+
}
|
|
21383
21397
|
return {
|
|
21384
21398
|
content: [{
|
|
21385
21399
|
type: "text",
|
|
@@ -21387,20 +21401,30 @@ function registerWriteTools(server, agent) {
|
|
|
21387
21401
|
preview: true,
|
|
21388
21402
|
action,
|
|
21389
21403
|
asset,
|
|
21390
|
-
amount: amount === "all" ? position?.currentValue ?? 0 : amount,
|
|
21404
|
+
amount: amount === "all" ? position?.currentValue ?? 0 : amount ?? position?.totalAmount ?? 0,
|
|
21391
21405
|
currentBalance: balance.available,
|
|
21392
|
-
currentPosition: position ?? null
|
|
21406
|
+
currentPosition: position ?? null,
|
|
21407
|
+
earning: position?.earning ?? false,
|
|
21408
|
+
earningProtocol: position?.earningProtocol ?? null,
|
|
21409
|
+
earningApy: position?.earningApy ?? null
|
|
21393
21410
|
})
|
|
21394
21411
|
}]
|
|
21395
21412
|
};
|
|
21396
21413
|
}
|
|
21414
|
+
const maxSlippage = slippage ? slippage / 100 : void 0;
|
|
21397
21415
|
if (action === "buy") {
|
|
21398
21416
|
if (typeof amount !== "number") throw new Error("Buy amount must be a number");
|
|
21399
|
-
const result = await mutex.run(() => agent.investBuy({ asset, usdAmount: amount }));
|
|
21417
|
+
const result = await mutex.run(() => agent.investBuy({ asset, usdAmount: amount, maxSlippage }));
|
|
21400
21418
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21401
|
-
} else {
|
|
21419
|
+
} else if (action === "sell") {
|
|
21402
21420
|
const usdAmount = amount === "all" ? "all" : amount;
|
|
21403
|
-
const result = await mutex.run(() => agent.investSell({ asset, usdAmount }));
|
|
21421
|
+
const result = await mutex.run(() => agent.investSell({ asset, usdAmount, maxSlippage }));
|
|
21422
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21423
|
+
} else if (action === "earn") {
|
|
21424
|
+
const result = await mutex.run(() => agent.investEarn({ asset }));
|
|
21425
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21426
|
+
} else {
|
|
21427
|
+
const result = await mutex.run(() => agent.investUnearn({ asset }));
|
|
21404
21428
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21405
21429
|
}
|
|
21406
21430
|
} catch (err) {
|
|
@@ -21640,6 +21664,7 @@ ${context}
|
|
|
21640
21664
|
"- Expected annual yield on the recommended amount",
|
|
21641
21665
|
"- If they should rebalance existing savings (t2000_rebalance with dryRun: true)",
|
|
21642
21666
|
"- Whether investing in SUI or other assets could complement their savings strategy",
|
|
21667
|
+
'- Note: investment assets (SUI, ETH) can also earn yield via t2000_invest action: "earn"',
|
|
21643
21668
|
"",
|
|
21644
21669
|
"If they want to proceed, use t2000_save to deposit. Always preview first."
|
|
21645
21670
|
].join("\n")
|
|
@@ -21667,9 +21692,13 @@ ${context}
|
|
|
21667
21692
|
"- Portfolio allocation assessment (what % is in checking vs savings vs investment)",
|
|
21668
21693
|
"- Whether current positions are performing well or need adjustment",
|
|
21669
21694
|
"- If idle checking funds should be invested or saved for yield",
|
|
21695
|
+
'- Whether invested assets should earn yield (t2000_invest action: "earn") \u2014 this deposits the asset into the best lending protocol',
|
|
21696
|
+
"- If a position is earning, mention the APY and protocol",
|
|
21670
21697
|
"- Risk assessment \u2014 concentration, unrealized losses, cost basis vs current price",
|
|
21671
21698
|
"",
|
|
21672
|
-
"If they want to invest, use t2000_invest with dryRun: true to preview first."
|
|
21699
|
+
"If they want to invest, use t2000_invest with dryRun: true to preview first.",
|
|
21700
|
+
'If they want to earn yield on investments, use t2000_invest action: "earn".',
|
|
21701
|
+
'If they want to stop earning, use t2000_invest action: "unearn".'
|
|
21673
21702
|
].join("\n")
|
|
21674
21703
|
}
|
|
21675
21704
|
}]
|
|
@@ -21695,4 +21724,4 @@ async function startMcpServer(opts) {
|
|
|
21695
21724
|
export {
|
|
21696
21725
|
startMcpServer
|
|
21697
21726
|
};
|
|
21698
|
-
//# sourceMappingURL=dist-
|
|
21727
|
+
//# sourceMappingURL=dist-TXXQC3NH.js.map
|