@t2000/cli 5.2.0 → 5.4.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
@@ -22105,7 +22105,7 @@ var {
22105
22105
  } = import_index.default;
22106
22106
 
22107
22107
  // src/program.ts
22108
- import { createRequire } from "module";
22108
+ import { createRequire as createRequire2 } from "module";
22109
22109
 
22110
22110
  // src/output.ts
22111
22111
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -26711,6 +26711,7 @@ __export(token_registry_exports, {
26711
26711
  getCoinMeta: () => getCoinMeta,
26712
26712
  getDecimalsForCoinType: () => getDecimalsForCoinType,
26713
26713
  isInRegistry: () => isInRegistry,
26714
+ resolveCoinDecimals: () => resolveCoinDecimals,
26714
26715
  resolveSymbol: () => resolveSymbol,
26715
26716
  resolveTokenType: () => resolveTokenType
26716
26717
  });
@@ -26732,6 +26733,16 @@ function getDecimalsForCoinType(coinType) {
26732
26733
  }
26733
26734
  return 9;
26734
26735
  }
26736
+ async function resolveCoinDecimals(client, coinType) {
26737
+ if (isInRegistry(coinType)) return getDecimalsForCoinType(coinType);
26738
+ try {
26739
+ const res = await client.core.getCoinMetadata({ coinType });
26740
+ const d = res?.metadata?.decimals ?? res?.decimals;
26741
+ if (typeof d === "number" && Number.isFinite(d)) return d;
26742
+ } catch {
26743
+ }
26744
+ return getDecimalsForCoinType(coinType);
26745
+ }
26735
26746
  function resolveSymbol(coinType) {
26736
26747
  const direct = BY_TYPE.get(coinType);
26737
26748
  if (direct) return direct.symbol;
@@ -27236,7 +27247,7 @@ async function getSwapQuote(params) {
27236
27247
  );
27237
27248
  }
27238
27249
  const byAmountIn = params.byAmountIn ?? true;
27239
- const fromDecimals = getDecimalsForCoinType(fromType);
27250
+ const fromDecimals = params.fromDecimals ?? getDecimalsForCoinType(fromType);
27240
27251
  const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
27241
27252
  const route = await findSwapRoute2({
27242
27253
  walletAddress: params.walletAddress,
@@ -27250,7 +27261,7 @@ async function getSwapQuote(params) {
27250
27261
  if (route.insufficientLiquidity) {
27251
27262
  throw new T2000Error("SWAP_FAILED", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
27252
27263
  }
27253
- const toDecimals = getDecimalsForCoinType(toType);
27264
+ const toDecimals = params.toDecimals ?? getDecimalsForCoinType(toType);
27254
27265
  const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
27255
27266
  const toAmount = Number(route.amountOut) / 10 ** toDecimals;
27256
27267
  const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
@@ -28435,7 +28446,7 @@ var T2000 = class _T2000 extends import_index2.default {
28435
28446
  if (!toType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.to}. Provide the full coin type.`);
28436
28447
  const byAmountIn = params.byAmountIn ?? true;
28437
28448
  const slippage = Math.min(params.slippage ?? 0.01, 0.05);
28438
- const fromDecimals = getDecimalsForCoinType(fromType);
28449
+ const fromDecimals = await resolveCoinDecimals(this.client, fromType);
28439
28450
  const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
28440
28451
  const route = await findSwapRoute2({
28441
28452
  walletAddress: this._address,
@@ -28449,7 +28460,7 @@ var T2000 = class _T2000 extends import_index2.default {
28449
28460
  if (route.priceImpact > 0.05) {
28450
28461
  console.warn(`[swap] High price impact: ${(route.priceImpact * 100).toFixed(2)}%`);
28451
28462
  }
28452
- const toDecimals = getDecimalsForCoinType(toType);
28463
+ const toDecimals = await resolveCoinDecimals(this.client, toType);
28453
28464
  let preBalRaw = 0n;
28454
28465
  try {
28455
28466
  const preBal = await this.client.core.getBalance({ owner: this._address, coinType: toType });
@@ -28542,13 +28553,18 @@ var T2000 = class _T2000 extends import_index2.default {
28542
28553
  */
28543
28554
  async swapQuote(params) {
28544
28555
  const { getSwapQuote: getSwapQuote2 } = await Promise.resolve().then(() => (init_swap_quote(), swap_quote_exports));
28556
+ const { resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
28557
+ const fromType = resolveTokenType2(params.from);
28558
+ const toType = resolveTokenType2(params.to);
28545
28559
  return getSwapQuote2({
28546
28560
  walletAddress: this._address,
28547
28561
  from: params.from,
28548
28562
  to: params.to,
28549
28563
  amount: params.amount,
28550
28564
  byAmountIn: params.byAmountIn,
28551
- providers: params.providers
28565
+ providers: params.providers,
28566
+ fromDecimals: fromType ? await resolveCoinDecimals(this.client, fromType) : void 0,
28567
+ toDecimals: toType ? await resolveCoinDecimals(this.client, toType) : void 0
28552
28568
  });
28553
28569
  }
28554
28570
  // -- Wallet --
@@ -28684,8 +28700,8 @@ var T2000 = class _T2000 extends import_index2.default {
28684
28700
  /**
28685
28701
  * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25; refreshed S.342 / 2026-05-26]
28686
28702
  * Preferred alias of `deposit()`. Was introduced to mirror the v3 `t2000 fund`
28687
- * CLI command; the v4 CLI surface is `t2 receive` (deleted `fund` in the
28688
- * S.332 bulk cut). `deposit()` stays as the canonical method name for
28703
+ * CLI command; the v4 CLI surface is `t2 fund` (renamed back from the
28704
+ * interim `t2 receive` in S.464). `deposit()` stays as the canonical method name for
28689
28705
  * back-compat; `fund()` stays as a programmatic alias for audric + other
28690
28706
  * SDK consumers that prefer the verb.
28691
28707
  */
@@ -31169,7 +31185,9 @@ async function askHidden(message) {
31169
31185
  }
31170
31186
 
31171
31187
  // src/commands/init.ts
31172
- var NO_LIMITS_FOOTER = "No spending limits set. Run `t2 limit set --daily <usd>` to add them.";
31188
+ var DEFAULT_PER_TX_USD = 25;
31189
+ var DEFAULT_DAILY_USD = 100;
31190
+ var limitsFooter = (perTx, daily) => `Spending limits ON: $${perTx}/tx, $${daily}/day (cumulative). Change with \`t2 limit set\`, or override a single call with --force.`;
31173
31191
  function registerInit(program3) {
31174
31192
  program3.command("init").description("Create a new Agent Wallet (no PIN; plain Bech32 key file with 0o600 perms)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option(
31175
31193
  "--import [secret]",
@@ -31196,8 +31214,16 @@ function registerInit(program3) {
31196
31214
  await saveKey(keypair, void 0, opts.key);
31197
31215
  address = getAddress(keypair);
31198
31216
  }
31217
+ if (!hasLimits()) {
31218
+ setLimits({ perTxUsd: DEFAULT_PER_TX_USD, dailyUsd: DEFAULT_DAILY_USD });
31219
+ }
31199
31220
  if (isJsonMode()) {
31200
- printJson({ address, imported, configPath: opts.key ?? "~/.t2000/wallet.key" });
31221
+ printJson({
31222
+ address,
31223
+ imported,
31224
+ configPath: opts.key ?? "~/.t2000/wallet.key",
31225
+ limits: { perTxUsd: DEFAULT_PER_TX_USD, dailyUsd: DEFAULT_DAILY_USD }
31226
+ });
31201
31227
  return;
31202
31228
  }
31203
31229
  printBlank();
@@ -31205,7 +31231,7 @@ function registerInit(program3) {
31205
31231
  printKeyValue("Address", address);
31206
31232
  printKeyValue("Path", opts.key ?? "~/.t2000/wallet.key");
31207
31233
  printBlank();
31208
- printLine(`\u26A0 ${NO_LIMITS_FOOTER}`);
31234
+ printLine(`\u26A0 ${limitsFooter(DEFAULT_PER_TX_USD, DEFAULT_DAILY_USD)}`);
31209
31235
  printBlank();
31210
31236
  try {
31211
31237
  await T2000.create({ keyPath: opts.key });
@@ -31224,6 +31250,17 @@ async function withAgent(options = {}) {
31224
31250
  rpcUrl: options.rpcUrl
31225
31251
  });
31226
31252
  }
31253
+ async function tryWithAgent(options = {}) {
31254
+ try {
31255
+ const agent = await T2000.create({
31256
+ keyPath: options.keyPath,
31257
+ rpcUrl: options.rpcUrl
31258
+ });
31259
+ return { kind: "ok", agent };
31260
+ } catch (error) {
31261
+ return { kind: "error", error };
31262
+ }
31263
+ }
31227
31264
 
31228
31265
  // src/commands/export.ts
31229
31266
  function registerExport(program3) {
@@ -31255,16 +31292,17 @@ function registerExport(program3) {
31255
31292
  });
31256
31293
  }
31257
31294
 
31258
- // src/commands/receive.ts
31295
+ // src/commands/fund.ts
31259
31296
  var import_qrcode = __toESM(require_lib4(), 1);
31260
31297
  var import_picocolors2 = __toESM(require_picocolors(), 1);
31261
- function registerReceive(program3) {
31262
- program3.command("receive").description("Print your wallet address + QR code for incoming transfers").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--qr-only", "Print only the QR code (no address text)").action(async (opts) => {
31298
+ var VALUE_PROMISE = "$5 USDC \u2248 ~250 paid API calls (at the $0.02 floor).";
31299
+ function registerFund(program3) {
31300
+ program3.command("fund").description("Show your wallet address + QR to fund it (USDC / USDsui / SUI on Sui)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--qr-only", "Print only the QR code (no address text)").action(async (opts) => {
31263
31301
  try {
31264
31302
  const agent = await withAgent({ keyPath: opts.key });
31265
31303
  const address = agent.address();
31266
31304
  if (isJsonMode()) {
31267
- printJson({ address, qrEncodedFor: address });
31305
+ printJson({ address, qrEncodedFor: address, valuePromise: VALUE_PROMISE });
31268
31306
  return;
31269
31307
  }
31270
31308
  printBlank();
@@ -31272,6 +31310,7 @@ function registerReceive(program3) {
31272
31310
  printKeyValue("Address", address);
31273
31311
  printBlank();
31274
31312
  printLine(import_picocolors2.default.dim("Accepts USDC, USDsui, or SUI on Sui mainnet."));
31313
+ printLine(import_picocolors2.default.dim(VALUE_PROMISE));
31275
31314
  printLine(import_picocolors2.default.dim("Scan to send to this wallet:"));
31276
31315
  printBlank();
31277
31316
  }
@@ -31422,8 +31461,171 @@ function registerHistory(program3) {
31422
31461
  });
31423
31462
  }
31424
31463
 
31425
- // src/commands/send.ts
31464
+ // src/commands/status.ts
31426
31465
  var import_picocolors5 = __toESM(require_picocolors(), 1);
31466
+ import { createRequire } from "module";
31467
+
31468
+ // src/commands/mcp/platforms.ts
31469
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
31470
+ import { join as join3, dirname as dirname2 } from "path";
31471
+ import { homedir as homedir2 } from "os";
31472
+ import { existsSync as existsSync2 } from "fs";
31473
+ var MCP_SERVER_ENTRY = {
31474
+ command: "t2000",
31475
+ args: ["mcp", "start"]
31476
+ };
31477
+ var MCP_SERVER_KEY = "t2000";
31478
+ function getPlatformConfigs() {
31479
+ const home = homedir2();
31480
+ return [
31481
+ {
31482
+ name: "Claude Desktop",
31483
+ slug: "claude-desktop",
31484
+ path: join3(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
31485
+ },
31486
+ {
31487
+ name: "Cursor",
31488
+ slug: "cursor",
31489
+ path: join3(home, ".cursor", "mcp.json")
31490
+ },
31491
+ {
31492
+ name: "Windsurf",
31493
+ slug: "windsurf",
31494
+ path: join3(home, ".codeium", "windsurf", "mcp_config.json")
31495
+ }
31496
+ ];
31497
+ }
31498
+ async function readJsonFile(path2) {
31499
+ try {
31500
+ const content = await readFile2(path2, "utf-8");
31501
+ return JSON.parse(content);
31502
+ } catch {
31503
+ return {};
31504
+ }
31505
+ }
31506
+ async function writeJsonFile(path2, data) {
31507
+ const dir = dirname2(path2);
31508
+ if (!existsSync2(dir)) {
31509
+ await mkdir2(dir, { recursive: true });
31510
+ }
31511
+ await writeFile2(path2, JSON.stringify(data, null, 2) + "\n", "utf-8");
31512
+ }
31513
+ function withMcpEntry(config) {
31514
+ return {
31515
+ ...config,
31516
+ mcpServers: {
31517
+ ...config.mcpServers ?? {},
31518
+ [MCP_SERVER_KEY]: { ...MCP_SERVER_ENTRY }
31519
+ }
31520
+ };
31521
+ }
31522
+ function hasMcpEntry(config) {
31523
+ return typeof config.mcpServers === "object" && config.mcpServers !== null && MCP_SERVER_KEY in config.mcpServers;
31524
+ }
31525
+ function withoutMcpEntry(config) {
31526
+ if (!hasMcpEntry(config)) return config;
31527
+ const servers = { ...config.mcpServers };
31528
+ delete servers[MCP_SERVER_KEY];
31529
+ return { ...config, mcpServers: servers };
31530
+ }
31531
+
31532
+ // src/commands/status.ts
31533
+ var require2 = createRequire(import.meta.url);
31534
+ var { version: CLI_VERSION } = require2("../package.json");
31535
+ var GATEWAY_URL = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
31536
+ var GATEWAY_TIMEOUT_MS = 3e3;
31537
+ async function checkGateway() {
31538
+ const start = Date.now();
31539
+ try {
31540
+ const controller = new AbortController();
31541
+ const timer = setTimeout(() => controller.abort(), GATEWAY_TIMEOUT_MS);
31542
+ const res = await fetch(`${GATEWAY_URL}/api/services`, { signal: controller.signal });
31543
+ clearTimeout(timer);
31544
+ return { url: GATEWAY_URL, reachable: res.ok, latencyMs: Date.now() - start };
31545
+ } catch {
31546
+ return { url: GATEWAY_URL, reachable: false, latencyMs: null };
31547
+ }
31548
+ }
31549
+ async function checkMcpClients() {
31550
+ const platforms = getPlatformConfigs();
31551
+ return Promise.all(
31552
+ platforms.map(async (p) => ({ name: p.name, wired: hasMcpEntry(await readJsonFile(p.path)) }))
31553
+ );
31554
+ }
31555
+ function registerStatus(program3) {
31556
+ program3.command("status").description("Health check: wallet, balances, limits, MCP wiring, gateway reachability").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
31557
+ try {
31558
+ const [agentResult, gateway, mcpClients] = await Promise.all([
31559
+ tryWithAgent({ keyPath: opts.key }),
31560
+ checkGateway(),
31561
+ checkMcpClients()
31562
+ ]);
31563
+ let wallet = { created: false };
31564
+ let balance = null;
31565
+ let limits = null;
31566
+ if (agentResult.kind === "ok") {
31567
+ const agent = agentResult.agent;
31568
+ wallet = { created: true, address: agent.address() };
31569
+ try {
31570
+ const b = await agent.balance();
31571
+ balance = { totalUsd: b.totalUsd, stables: b.stables, sui: b.sui.amount };
31572
+ } catch {
31573
+ balance = null;
31574
+ }
31575
+ const lim = agent.limits.getLimits();
31576
+ limits = {
31577
+ perTxUsd: lim?.perTxUsd,
31578
+ dailyUsd: lim?.dailyUsd,
31579
+ spentTodayUsd: agent.limits.dailySpentToday()
31580
+ };
31581
+ }
31582
+ if (isJsonMode()) {
31583
+ printJson({ cliVersion: CLI_VERSION, wallet, balance, limits, gateway, mcpClients });
31584
+ return;
31585
+ }
31586
+ printBlank();
31587
+ printLine(import_picocolors5.default.bold("t2000 Agent Wallet \u2014 status"));
31588
+ printBlank();
31589
+ printKeyValue("CLI version", CLI_VERSION);
31590
+ if (wallet.created && wallet.address) {
31591
+ const short = `${wallet.address.slice(0, 6)}\u2026${wallet.address.slice(-4)}`;
31592
+ printKeyValue("Wallet", `${short} ${import_picocolors5.default.green("\u2713")}`);
31593
+ if (balance) {
31594
+ const parts = Object.entries(balance.stables).map(([k, v]) => `${k} ${v}`).concat(`SUI ${balance.sui}`).join(", ");
31595
+ printKeyValue("Balance", `$${balance.totalUsd.toFixed(2)} ${import_picocolors5.default.dim(`(${parts})`)}`);
31596
+ } else {
31597
+ printKeyValue("Balance", import_picocolors5.default.dim("(could not read \u2014 network?)"));
31598
+ }
31599
+ if (limits && (limits.perTxUsd !== void 0 || limits.dailyUsd !== void 0)) {
31600
+ const caps = [
31601
+ limits.perTxUsd !== void 0 ? `$${limits.perTxUsd}/tx` : null,
31602
+ limits.dailyUsd !== void 0 ? `$${limits.dailyUsd}/day` : null
31603
+ ].filter(Boolean).join(" \xB7 ");
31604
+ printKeyValue("Limits", `${caps} ${import_picocolors5.default.dim(`(spent today: $${limits.spentTodayUsd.toFixed(2)})`)}`);
31605
+ } else {
31606
+ printKeyValue("Limits", import_picocolors5.default.dim("off (no caps set)"));
31607
+ }
31608
+ } else {
31609
+ printKeyValue("Wallet", `${import_picocolors5.default.yellow("not created")} ${import_picocolors5.default.dim("\u2014 run `t2 init`")}`);
31610
+ }
31611
+ printKeyValue(
31612
+ "Gateway",
31613
+ gateway.reachable ? `${import_picocolors5.default.green("\u2713 reachable")} ${import_picocolors5.default.dim(`(${gateway.latencyMs}ms)`)}` : `${import_picocolors5.default.red("\u2717 unreachable")} ${import_picocolors5.default.dim(`(${gateway.url})`)}`
31614
+ );
31615
+ const mcpSummary = mcpClients.map((c) => `${c.name} ${c.wired ? import_picocolors5.default.green("\u2713") : import_picocolors5.default.dim("\u2717")}`).join(" \xB7 ");
31616
+ printKeyValue("MCP wired", mcpSummary);
31617
+ if (!mcpClients.some((c) => c.wired)) {
31618
+ printLine(import_picocolors5.default.dim(" Run `t2 mcp install` to connect Claude / Cursor / Windsurf."));
31619
+ }
31620
+ printBlank();
31621
+ } catch (err) {
31622
+ handleError(err);
31623
+ }
31624
+ });
31625
+ }
31626
+
31627
+ // src/commands/send.ts
31628
+ var import_picocolors6 = __toESM(require_picocolors(), 1);
31427
31629
  var ACCEPTED_ASSETS = ["USDC", "USDsui", "SUI"];
31428
31630
  var ACCEPTED_ASSETS_LIST = ACCEPTED_ASSETS.join(", ");
31429
31631
  function parseSendArgs(args) {
@@ -31468,7 +31670,7 @@ function registerSend(program3) {
31468
31670
  program3.command("send").argument("<amount>", "Amount of <asset> to send (denominated in asset units, NOT USD)").argument(
31469
31671
  "[args...]",
31470
31672
  'Asset (USDC | USDsui | SUI), optional "to" keyword, and recipient (0x address, SuiNS name like alice.sui, or @audric handle)'
31471
- ).description("Send USDC, USDsui, or SUI. USDC + USDsui are gasless (no SUI required).").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--force", "Override opt-in spending limits (see `t2 limit`)").addHelpText(
31673
+ ).description("Send USDC, USDsui, or SUI. USDC + USDsui are gasless (no SUI required).").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--force", "Override spending limits for this call (see `t2 limit`)").addHelpText(
31472
31674
  "after",
31473
31675
  `
31474
31676
  Examples:
@@ -31497,12 +31699,12 @@ Examples:
31497
31699
  });
31498
31700
  return;
31499
31701
  }
31500
- const displayTo = result.suinsName ? `${result.suinsName} ${import_picocolors5.default.dim(`(${truncateAddress(result.to)})`)}` : truncateAddress(result.to);
31702
+ const displayTo = result.suinsName ? `${result.suinsName} ${import_picocolors6.default.dim(`(${truncateAddress(result.to)})`)}` : truncateAddress(result.to);
31501
31703
  const amountDisplay = asset === "SUI" ? `${result.amount.toFixed(4)} SUI` : `${formatUsd(result.amount)} ${asset}`;
31502
31704
  printBlank();
31503
31705
  printSuccess(`Sent ${amountDisplay} \u2192 ${displayTo}`);
31504
31706
  if (result.gasCost === 0) {
31505
- printKeyValue("Gas", import_picocolors5.default.green("gasless \u26A1"));
31707
+ printKeyValue("Gas", import_picocolors6.default.green("gasless \u26A1"));
31506
31708
  } else {
31507
31709
  printKeyValue("Gas", `${result.gasCost.toFixed(6)} ${result.gasCostUnit}`);
31508
31710
  }
@@ -31515,7 +31717,7 @@ Examples:
31515
31717
  }
31516
31718
 
31517
31719
  // src/commands/swap.ts
31518
- var import_picocolors6 = __toESM(require_picocolors(), 1);
31720
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
31519
31721
  function parseSwapArgs(amountStr, from, to) {
31520
31722
  const amount = parseFloat(amountStr);
31521
31723
  if (Number.isNaN(amount) || amount <= 0) {
@@ -31529,7 +31731,7 @@ function parseSwapArgs(amountStr, from, to) {
31529
31731
  return { amount, from, to };
31530
31732
  }
31531
31733
  function registerSwap(program3) {
31532
- program3.command("swap").argument("<amount>", "Amount of <from> to swap (denominated in <from> units)").argument("<from>", "Source token symbol (e.g. USDC, SUI, USDsui)").argument("<to>", "Destination token symbol (e.g. SUI, USDC, USDsui)").description("Swap tokens via Cetus aggregator (20+ DEXs)").option("--quote", "Preview the swap (price, route, impact) without executing").option("--slippage <pct>", "Max slippage percentage (default: 1)", "1").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--force", "Override opt-in spending limits (see `t2 limit`)").addHelpText(
31734
+ program3.command("swap").argument("<amount>", "Amount of <from> to swap (denominated in <from> units)").argument("<from>", "Source token \u2014 symbol (USDC, SUI, \u2026) or full coin type (0x\u2026::mod::TOK)").argument("<to>", "Destination token \u2014 symbol (SUI, USDC, \u2026) or full coin type (0x\u2026::mod::TOK)").description("Swap any token pair via Cetus aggregator (20+ DEXs). Unknown coin types resolve decimals on-chain.").option("--quote", "Preview the swap (price, route, impact) without executing").option("--slippage <pct>", "Max slippage percentage (default: 1)", "1").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--force", "Override spending limits for this call (see `t2 limit`)").addHelpText(
31533
31735
  "after",
31534
31736
  `
31535
31737
  Examples:
@@ -31555,9 +31757,9 @@ Examples:
31555
31757
  }
31556
31758
  printBlank();
31557
31759
  printKeyValue("Input", `${quote.fromAmount} ${quote.fromToken}`);
31558
- printKeyValue("Output", import_picocolors6.default.green(`${quote.toAmount.toFixed(6)} ${quote.toToken}`));
31760
+ printKeyValue("Output", import_picocolors7.default.green(`${quote.toAmount.toFixed(6)} ${quote.toToken}`));
31559
31761
  if (quote.priceImpact > 1e-3) {
31560
- printKeyValue("Price impact", import_picocolors6.default.yellow(`${(quote.priceImpact * 100).toFixed(2)}%`));
31762
+ printKeyValue("Price impact", import_picocolors7.default.yellow(`${(quote.priceImpact * 100).toFixed(2)}%`));
31561
31763
  }
31562
31764
  printKeyValue("Route", `${quote.fromToken} \u2192 ${quote.toToken} (${quote.route})`);
31563
31765
  printBlank();
@@ -31577,10 +31779,10 @@ Examples:
31577
31779
  }
31578
31780
  printBlank();
31579
31781
  printSuccess(
31580
- `Swapped ${import_picocolors6.default.yellow(String(result.fromAmount))} ${result.fromToken} \u2192 ${import_picocolors6.default.green(result.toAmount.toFixed(6))} ${result.toToken}`
31782
+ `Swapped ${import_picocolors7.default.yellow(String(result.fromAmount))} ${result.fromToken} \u2192 ${import_picocolors7.default.green(result.toAmount.toFixed(6))} ${result.toToken}`
31581
31783
  );
31582
31784
  if (result.priceImpact > 5e-3) {
31583
- printKeyValue("Price impact", import_picocolors6.default.yellow(`${(result.priceImpact * 100).toFixed(2)}%`));
31785
+ printKeyValue("Price impact", import_picocolors7.default.yellow(`${(result.priceImpact * 100).toFixed(2)}%`));
31584
31786
  }
31585
31787
  printKeyValue("Route", `${result.fromToken} \u2192 ${result.toToken} (${result.route})`);
31586
31788
  printKeyValue("Gas", `${result.gasCost.toFixed(6)} SUI`);
@@ -31594,12 +31796,12 @@ Examples:
31594
31796
  }
31595
31797
 
31596
31798
  // src/commands/pay.ts
31597
- var import_picocolors7 = __toESM(require_picocolors(), 1);
31799
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
31598
31800
  function registerPay(program3) {
31599
31801
  program3.command("pay <url>").description("Pay an MPP / x402 service (USDC on Sui)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--method <method>", "HTTP method (GET, POST, PUT)", "GET").option("--data <json>", "Request body for POST/PUT (auto-promotes --method to POST)").option("--header <key=value>", "Additional HTTP header (repeatable)", collectHeaders, {}).option("--max-price <amount>", "Max USDC price to auto-approve", "1.00").option(
31600
31802
  "--estimate",
31601
31803
  "Preview the price + service info (no signing, no payment). Exits 0 if the service responds with a 402 challenge."
31602
- ).option("--force", "Override opt-in spending limits (see `t2 limit`)").addHelpText(
31804
+ ).option("--force", "Override spending limits for this call (see `t2 limit`)").addHelpText(
31603
31805
  "after",
31604
31806
  `
31605
31807
  Examples:
@@ -31653,10 +31855,10 @@ Examples:
31653
31855
  return;
31654
31856
  }
31655
31857
  if (result.paid && result.receipt) {
31656
- const gasNote = typeof result.gasCostSui === "number" ? result.gasCostSui === 0 ? import_picocolors7.default.green(" \xB7 gasless \u26A1") : import_picocolors7.default.dim(` \xB7 gas: ${result.gasCostSui.toFixed(6)} SUI`) : "";
31657
- printSuccess(`Paid via MPP (tx: ${result.receipt.reference.slice(0, 10)}\u2026)${gasNote}`);
31858
+ const gasNote = typeof result.gasCostSui === "number" ? result.gasCostSui === 0 ? import_picocolors8.default.green(" \xB7 gasless \u26A1") : import_picocolors8.default.dim(` \xB7 gas: ${result.gasCostSui.toFixed(6)} SUI`) : "";
31859
+ printSuccess(`Paid via ${result.dialect ?? "x402"} (tx: ${result.receipt.reference.slice(0, 10)}\u2026)${gasNote}`);
31658
31860
  }
31659
- printInfo(`\u2190 ${result.status} OK ${import_picocolors7.default.dim(`[${elapsed}ms]`)}`);
31861
+ printInfo(`\u2190 ${result.status} OK ${import_picocolors8.default.dim(`[${elapsed}ms]`)}`);
31660
31862
  printBlank();
31661
31863
  if (typeof result.body === "string") {
31662
31864
  console.log(result.body);
@@ -31674,7 +31876,7 @@ async function runEstimate(url, opts) {
31674
31876
  const canHaveBody = method !== "GET" && method !== "HEAD";
31675
31877
  if (!isJsonMode()) {
31676
31878
  printBlank();
31677
- printInfo(`\u2192 ${method} ${url} ${import_picocolors7.default.dim("(estimate \u2014 no payment)")}`);
31879
+ printInfo(`\u2192 ${method} ${url} ${import_picocolors8.default.dim("(estimate \u2014 no payment)")}`);
31678
31880
  }
31679
31881
  const response = await fetch(url, {
31680
31882
  method,
@@ -31724,6 +31926,7 @@ async function runEstimate(url, opts) {
31724
31926
  const recipient = req.payTo ?? "unknown";
31725
31927
  const looksLikeUsdc = /::usdc::USDC/i.test(asset);
31726
31928
  const display = amountRaw && looksLikeUsdc ? `$${(Number(amountRaw) / 1e6).toFixed(4)} USDC` : amountRaw ?? "unknown";
31929
+ const inputSchema = await fetchInputSchema(url, method);
31727
31930
  if (isJsonMode()) {
31728
31931
  printJson({
31729
31932
  url,
@@ -31737,19 +31940,28 @@ async function runEstimate(url, opts) {
31737
31940
  amount: amountRaw,
31738
31941
  amountDisplay: display,
31739
31942
  asset,
31740
- recipient
31943
+ recipient,
31944
+ inputSchema
31741
31945
  }
31742
31946
  });
31743
31947
  return;
31744
31948
  }
31745
31949
  printBlank();
31746
31950
  printSuccess(`Service requires payment (x402 ${req.scheme ?? "exact"} on ${req.network ?? "sui"})`);
31747
- printKeyValue("Price", import_picocolors7.default.green(display));
31951
+ printKeyValue("Price", import_picocolors8.default.green(display));
31748
31952
  printKeyValue("Asset", asset);
31749
31953
  printKeyValue("Recipient", recipient);
31750
31954
  if (req.resource) {
31751
31955
  printKeyValue("Resource", req.resource);
31752
31956
  }
31957
+ const fields = describeSchemaFields(inputSchema);
31958
+ if (fields.length > 0) {
31959
+ printBlank();
31960
+ printInfo("Input (request body):");
31961
+ for (const f of fields) {
31962
+ printLine(" " + import_picocolors8.default.dim(f));
31963
+ }
31964
+ }
31753
31965
  printBlank();
31754
31966
  printInfo(`Run without --estimate to pay and execute.`);
31755
31967
  printBlank();
@@ -31761,9 +31973,31 @@ function collectHeaders(value, previous) {
31761
31973
  }
31762
31974
  return previous;
31763
31975
  }
31976
+ async function fetchInputSchema(url, method) {
31977
+ try {
31978
+ const u = new URL(url);
31979
+ const res = await fetch(`${u.origin}/openapi.json`);
31980
+ if (!res.ok) return null;
31981
+ const doc = await res.json();
31982
+ const op = doc.paths?.[u.pathname]?.[method.toLowerCase()];
31983
+ return op?.requestBody?.content?.["application/json"]?.schema ?? null;
31984
+ } catch {
31985
+ return null;
31986
+ }
31987
+ }
31988
+ function describeSchemaFields(schema) {
31989
+ if (!schema || schema.type !== "object" || !schema.properties) return [];
31990
+ const required = new Set(schema.required ?? []);
31991
+ return Object.entries(schema.properties).map(([name, prop]) => {
31992
+ const type = prop.type ?? (prop.enum ? `enum(${prop.enum.join("|")})` : "any");
31993
+ const opt = required.has(name) ? "" : "?";
31994
+ const desc = prop.description ? ` \u2014 ${prop.description}` : "";
31995
+ return `${name}${opt}: ${type}${desc}`;
31996
+ });
31997
+ }
31764
31998
 
31765
31999
  // src/commands/services/search.ts
31766
- var import_picocolors8 = __toESM(require_picocolors(), 1);
32000
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
31767
32001
 
31768
32002
  // src/commands/services/catalog.ts
31769
32003
  var DEFAULT_GATEWAY_URL = "https://mpp.t2000.ai";
@@ -31865,9 +32099,9 @@ Examples:
31865
32099
  }
31866
32100
  function renderServiceLine(svc) {
31867
32101
  const minPrice = cheapestEndpointPrice(svc);
31868
- const priceTag = minPrice !== null ? import_picocolors8.default.green(`from $${minPrice}`) : import_picocolors8.default.dim("no pricing");
31869
- const catTag = svc.categories.length > 0 ? import_picocolors8.default.dim(`[${svc.categories.join(", ")}]`) : "";
31870
- printKeyValue(import_picocolors8.default.bold(svc.name), `${priceTag} ${catTag}`);
32102
+ const priceTag = minPrice !== null ? import_picocolors9.default.green(`from $${minPrice}`) : import_picocolors9.default.dim("no pricing");
32103
+ const catTag = svc.categories.length > 0 ? import_picocolors9.default.dim(`[${svc.categories.join(", ")}]`) : "";
32104
+ printKeyValue(import_picocolors9.default.bold(svc.name), `${priceTag} ${catTag}`);
31871
32105
  printKeyValue(" url", svc.serviceUrl);
31872
32106
  printKeyValue(" about", svc.description);
31873
32107
  printBlank();
@@ -31881,7 +32115,7 @@ function cheapestEndpointPrice(svc) {
31881
32115
  }
31882
32116
 
31883
32117
  // src/commands/services/inspect.ts
31884
- var import_picocolors9 = __toESM(require_picocolors(), 1);
32118
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
31885
32119
  function registerServicesInspect(parent) {
31886
32120
  parent.command("inspect").description("Show pricing + endpoints for an MPP service or endpoint URL").argument("<url>", "Service base URL or endpoint URL").option("--gateway <url>", "Override gateway base URL (default: https://mpp.t2000.ai)").addHelpText(
31887
32121
  "after",
@@ -31918,7 +32152,7 @@ Examples:
31918
32152
  return;
31919
32153
  }
31920
32154
  printBlank();
31921
- printKeyValue("Service", import_picocolors9.default.bold(service.name));
32155
+ printKeyValue("Service", import_picocolors10.default.bold(service.name));
31922
32156
  printKeyValue("URL", service.serviceUrl);
31923
32157
  printKeyValue("About", service.description);
31924
32158
  if (service.categories.length > 0) {
@@ -31948,7 +32182,7 @@ Examples:
31948
32182
  function renderEndpoint(ep, serviceUrl) {
31949
32183
  const price = `$${ep.price}`;
31950
32184
  const label = `${ep.method} ${ep.path}`.padEnd(40);
31951
- printKeyValue(label, `${import_picocolors9.default.green(price)} ${import_picocolors9.default.dim(ep.description)}`);
32185
+ printKeyValue(label, `${import_picocolors10.default.green(price)} ${import_picocolors10.default.dim(ep.description)}`);
31952
32186
  printKeyValue(" url", `${serviceUrl}${ep.path}`);
31953
32187
  printBlank();
31954
32188
  }
@@ -31971,7 +32205,7 @@ T2000_GATEWAY_URL or --gateway <url> for local development.
31971
32205
  }
31972
32206
 
31973
32207
  // src/commands/limit/show.ts
31974
- var import_picocolors10 = __toESM(require_picocolors(), 1);
32208
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
31975
32209
  function registerLimitShow(parent) {
31976
32210
  parent.command("show").description("Show current spending limits").action(async (opts) => {
31977
32211
  try {
@@ -31994,10 +32228,10 @@ function registerLimitShow(parent) {
31994
32228
  }
31995
32229
  printBlank();
31996
32230
  if (limits.perTxUsd !== void 0) {
31997
- printKeyValue("Per-transaction", import_picocolors10.default.green(`$${limits.perTxUsd}`));
32231
+ printKeyValue("Per-transaction", import_picocolors11.default.green(`$${limits.perTxUsd}`));
31998
32232
  }
31999
32233
  if (limits.dailyUsd !== void 0) {
32000
- printKeyValue("Daily (cumulative)", import_picocolors10.default.green(`$${limits.dailyUsd}`));
32234
+ printKeyValue("Daily (cumulative)", import_picocolors11.default.green(`$${limits.dailyUsd}`));
32001
32235
  }
32002
32236
  printBlank();
32003
32237
  printInfo("Use `--force` on `t2 send` / `t2 swap` / `t2 pay` to override per-call.");
@@ -32009,7 +32243,7 @@ function registerLimitShow(parent) {
32009
32243
  }
32010
32244
 
32011
32245
  // src/commands/limit/set.ts
32012
- var import_picocolors11 = __toESM(require_picocolors(), 1);
32246
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
32013
32247
  function parseLimitSetArgs(opts) {
32014
32248
  const perTx = opts.perTx !== void 0 ? parseUsdFlag("--per-tx", opts.perTx) : void 0;
32015
32249
  const daily = opts.daily !== void 0 ? parseUsdFlag("--daily", opts.daily) : void 0;
@@ -32051,10 +32285,10 @@ Examples:
32051
32285
  printBlank();
32052
32286
  printSuccess("Spending limits updated.");
32053
32287
  if (next?.perTxUsd !== void 0) {
32054
- printKeyValue("Per-transaction", import_picocolors11.default.green(`$${next.perTxUsd}`));
32288
+ printKeyValue("Per-transaction", import_picocolors12.default.green(`$${next.perTxUsd}`));
32055
32289
  }
32056
32290
  if (next?.dailyUsd !== void 0) {
32057
- printKeyValue("Daily (cumulative)", import_picocolors11.default.green(`$${next.dailyUsd}`));
32291
+ printKeyValue("Daily (cumulative)", import_picocolors12.default.green(`$${next.dailyUsd}`));
32058
32292
  }
32059
32293
  printBlank();
32060
32294
  printInfo("Use `t2 limit show` to view; `t2 limit reset` to clear.");
@@ -32096,7 +32330,7 @@ function registerLimitReset(parent) {
32096
32330
 
32097
32331
  // src/commands/limit/index.ts
32098
32332
  function registerLimit(program3) {
32099
- const group = program3.command("limit").description("Manage opt-in spending limits (no defaults)").addHelpText(
32333
+ const group = program3.command("limit").description("Manage spending limits (on by default: $25/tx, $100/day)").addHelpText(
32100
32334
  "after",
32101
32335
  `
32102
32336
  Subcommands:
@@ -32116,7 +32350,7 @@ function registerMcpStart(parent) {
32116
32350
  parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
32117
32351
  let mod2;
32118
32352
  try {
32119
- mod2 = await import("./dist-KVEHGTYJ.js");
32353
+ mod2 = await import("./dist-O4WYNOSR.js");
32120
32354
  } catch {
32121
32355
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
32122
32356
  process.exit(1);
@@ -32125,70 +32359,6 @@ function registerMcpStart(parent) {
32125
32359
  });
32126
32360
  }
32127
32361
 
32128
- // src/commands/mcp/platforms.ts
32129
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
32130
- import { join as join3, dirname as dirname2 } from "path";
32131
- import { homedir as homedir2 } from "os";
32132
- import { existsSync as existsSync2 } from "fs";
32133
- var MCP_SERVER_ENTRY = {
32134
- command: "t2000",
32135
- args: ["mcp", "start"]
32136
- };
32137
- var MCP_SERVER_KEY = "t2000";
32138
- function getPlatformConfigs() {
32139
- const home = homedir2();
32140
- return [
32141
- {
32142
- name: "Claude Desktop",
32143
- slug: "claude-desktop",
32144
- path: join3(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
32145
- },
32146
- {
32147
- name: "Cursor",
32148
- slug: "cursor",
32149
- path: join3(home, ".cursor", "mcp.json")
32150
- },
32151
- {
32152
- name: "Windsurf",
32153
- slug: "windsurf",
32154
- path: join3(home, ".codeium", "windsurf", "mcp_config.json")
32155
- }
32156
- ];
32157
- }
32158
- async function readJsonFile(path2) {
32159
- try {
32160
- const content = await readFile2(path2, "utf-8");
32161
- return JSON.parse(content);
32162
- } catch {
32163
- return {};
32164
- }
32165
- }
32166
- async function writeJsonFile(path2, data) {
32167
- const dir = dirname2(path2);
32168
- if (!existsSync2(dir)) {
32169
- await mkdir2(dir, { recursive: true });
32170
- }
32171
- await writeFile2(path2, JSON.stringify(data, null, 2) + "\n", "utf-8");
32172
- }
32173
- function withMcpEntry(config) {
32174
- return {
32175
- ...config,
32176
- mcpServers: {
32177
- ...config.mcpServers ?? {},
32178
- [MCP_SERVER_KEY]: { ...MCP_SERVER_ENTRY }
32179
- }
32180
- };
32181
- }
32182
- function hasMcpEntry(config) {
32183
- return typeof config.mcpServers === "object" && config.mcpServers !== null && MCP_SERVER_KEY in config.mcpServers;
32184
- }
32185
- function withoutMcpEntry(config) {
32186
- if (!hasMcpEntry(config)) return config;
32187
- const servers = { ...config.mcpServers };
32188
- delete servers[MCP_SERVER_KEY];
32189
- return { ...config, mcpServers: servers };
32190
- }
32191
-
32192
32362
  // src/commands/mcp/install.ts
32193
32363
  async function runInstall() {
32194
32364
  const platforms = getPlatformConfigs();
@@ -32520,31 +32690,33 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
32520
32690
  }
32521
32691
 
32522
32692
  // src/program.ts
32523
- var require2 = createRequire(import.meta.url);
32524
- var { version: CLI_VERSION } = require2("../package.json");
32693
+ var require3 = createRequire2(import.meta.url);
32694
+ var { version: CLI_VERSION2 } = require3("../package.json");
32525
32695
  function createProgram() {
32526
32696
  const program3 = new Command();
32527
- program3.name("t2").description("Agent Wallet \u2014 autonomous Sui USDC + USDsui wallet for AI agents").version(`${CLI_VERSION}`).option("--json", "Output in JSON format").hook("preAction", (thisCommand) => {
32697
+ program3.name("t2").description("Agent Wallet \u2014 autonomous Sui USDC + USDsui wallet for AI agents").version(`${CLI_VERSION2}`).option("--json", "Output in JSON format").hook("preAction", (thisCommand) => {
32528
32698
  const opts = thisCommand.optsWithGlobals();
32529
32699
  if (opts.json) setJsonMode(true);
32530
32700
  }).addHelpText("after", `
32531
32701
  Examples:
32532
32702
  $ t2 init Create a new Agent Wallet
32533
32703
  $ t2 init --import Import an existing Bech32 secret (interactive)
32534
- $ t2 receive Show address + QR for incoming transfers
32704
+ $ t2 fund Show address + QR to fund the wallet
32705
+ $ t2 status Health check: wallet, balances, limits, MCP, gateway
32535
32706
  $ t2 balance Show USDC / USDsui / SUI holdings
32536
32707
  $ t2 send 5 USDC alice.sui Send 5 USDC (gasless; asset required)
32537
32708
  $ t2 swap 100 USDC SUI Swap 100 USDC for SUI via Cetus
32538
- $ t2 pay <mpp_url> Pay an MPP / x402 service
32539
- $ t2 services search "image" Discover MPP services in the gateway catalog
32540
- $ t2 limit set --daily 100 Opt in to a $100 daily-send spending cap
32709
+ $ t2 pay <url> --estimate Preview an x402 service's price + input schema (no payment)
32710
+ $ t2 services search "image" Discover x402 services in the gateway catalog
32711
+ $ t2 limit set --daily 100 Change the daily spend cap (default $100/day)
32541
32712
  $ t2 mcp install Connect Claude / Cursor / Windsurf
32542
32713
  $ t2 skills install Install skills as local SKILL.md files`);
32543
32714
  registerInit(program3);
32544
32715
  registerExport(program3);
32545
- registerReceive(program3);
32716
+ registerFund(program3);
32546
32717
  registerBalance(program3);
32547
32718
  registerHistory(program3);
32719
+ registerStatus(program3);
32548
32720
  registerSend(program3);
32549
32721
  registerSwap(program3);
32550
32722
  registerPay(program3);