@t2000/cli 0.14.0 → 0.14.1
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 +$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 +$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,16 @@ 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 |
|
|
199
|
+
| `t2000 portfolio` | View investment portfolio with cost-basis P&L |
|
|
200
|
+
|
|
201
|
+
Supported assets: SUI, BTC, ETH. Dollar-denominated — `amount` is in USD.
|
|
202
|
+
|
|
179
203
|
### Safeguards
|
|
180
204
|
|
|
181
205
|
| 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 sell investment assets (spot). Amount is in USD. Asset is the crypto to buy/sell (e.g. SUI). Set dryRun: true to preview.",
|
|
21377
|
+
"Buy or sell investment assets (spot). Amount is in USD. Asset is the crypto to buy/sell (e.g. SUI, BTC, ETH). Set dryRun: true to preview.",
|
|
21370
21378
|
{
|
|
21371
21379
|
action: external_exports.enum(["buy", "sell"]).describe("'buy' to invest USD into asset, 'sell' to convert asset back to USDC"),
|
|
21372
|
-
asset: external_exports.enum(
|
|
21380
|
+
asset: external_exports.enum(investAssets).describe("Asset to invest in"),
|
|
21373
21381
|
amount: external_exports.union([external_exports.number(), external_exports.literal("all")]).describe('USD amount, or "all" to sell entire position'),
|
|
21382
|
+
slippage: external_exports.number().optional().describe("Max slippage percent (default: 3)"),
|
|
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",
|
|
@@ -21394,13 +21408,14 @@ function registerWriteTools(server, agent) {
|
|
|
21394
21408
|
}]
|
|
21395
21409
|
};
|
|
21396
21410
|
}
|
|
21411
|
+
const maxSlippage = slippage ? slippage / 100 : void 0;
|
|
21397
21412
|
if (action === "buy") {
|
|
21398
21413
|
if (typeof amount !== "number") throw new Error("Buy amount must be a number");
|
|
21399
|
-
const result = await mutex.run(() => agent.investBuy({ asset, usdAmount: amount }));
|
|
21414
|
+
const result = await mutex.run(() => agent.investBuy({ asset, usdAmount: amount, maxSlippage }));
|
|
21400
21415
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21401
21416
|
} else {
|
|
21402
21417
|
const usdAmount = amount === "all" ? "all" : amount;
|
|
21403
|
-
const result = await mutex.run(() => agent.investSell({ asset, usdAmount }));
|
|
21418
|
+
const result = await mutex.run(() => agent.investSell({ asset, usdAmount, maxSlippage }));
|
|
21404
21419
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
21405
21420
|
}
|
|
21406
21421
|
} catch (err) {
|
|
@@ -21695,4 +21710,4 @@ async function startMcpServer(opts) {
|
|
|
21695
21710
|
export {
|
|
21696
21711
|
startMcpServer
|
|
21697
21712
|
};
|
|
21698
|
-
//# sourceMappingURL=dist-
|
|
21713
|
+
//# sourceMappingURL=dist-4YM7JZSI.js.map
|