@t2000/cli 5.6.0 → 5.7.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.
@@ -171,11 +171,10 @@ import {
171
171
  processEndpoint,
172
172
  processFlattenRoutes,
173
173
  restituteMsafeFastRouterSwapParams
174
- } from "./chunk-64M2IV26.js";
175
- import "./chunk-D6WAQS6U.js";
176
- import "./chunk-OCLKPYUU.js";
177
- import "./chunk-ITIKLNK5.js";
178
- import "./chunk-MPXYF2CX.js";
174
+ } from "./chunk-SC3LZKLE.js";
175
+ import "./chunk-5AD7I65O.js";
176
+ import "./chunk-TP3M7BAU.js";
177
+ import "./chunk-X6ON6NN5.js";
179
178
  import "./chunk-I2DCISQP.js";
180
179
  import "./chunk-SVEVGZKZ.js";
181
180
  export {
@@ -351,4 +350,4 @@ export {
351
350
  processFlattenRoutes,
352
351
  restituteMsafeFastRouterSwapParams
353
352
  };
354
- //# sourceMappingURL=dist-VXJH2WYL.js.map
353
+ //# sourceMappingURL=dist-PLJ2M72I.js.map
@@ -5,8 +5,8 @@ import {
5
5
  SuiGrpcClient,
6
6
  isSuiGrpcClient,
7
7
  types_exports
8
- } from "./chunk-D6WAQS6U.js";
9
- import "./chunk-MPXYF2CX.js";
8
+ } from "./chunk-5AD7I65O.js";
9
+ import "./chunk-X6ON6NN5.js";
10
10
  import "./chunk-I2DCISQP.js";
11
11
  import "./chunk-SVEVGZKZ.js";
12
12
  export {
@@ -16,4 +16,4 @@ export {
16
16
  SuiGrpcClient,
17
17
  isSuiGrpcClient
18
18
  };
19
- //# sourceMappingURL=grpc-UMZJXRGY.js.map
19
+ //# sourceMappingURL=grpc-OLWNGPHN.js.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'module'; import { fileURLToPat
3
3
  import {
4
4
  AggregatorClient,
5
5
  Env
6
- } from "./chunk-64M2IV26.js";
6
+ } from "./chunk-SC3LZKLE.js";
7
7
  import {
8
8
  BalanceChange,
9
9
  BaseClient,
@@ -16,12 +16,11 @@ import {
16
16
  parseTransactionEffectsBcs,
17
17
  transactionDataToGrpcTransaction,
18
18
  transactionToGrpcJson
19
- } from "./chunk-D6WAQS6U.js";
20
- import "./chunk-OCLKPYUU.js";
19
+ } from "./chunk-5AD7I65O.js";
21
20
  import {
22
21
  Transaction,
23
22
  coinWithBalance
24
- } from "./chunk-ITIKLNK5.js";
23
+ } from "./chunk-TP3M7BAU.js";
25
24
  import {
26
25
  ObjectError,
27
26
  SUI_TYPE_ARG,
@@ -32,7 +31,7 @@ import {
32
31
  fromBase64 as fromBase642,
33
32
  suiBcs,
34
33
  toBase64 as toBase642
35
- } from "./chunk-MPXYF2CX.js";
34
+ } from "./chunk-X6ON6NN5.js";
36
35
  import {
37
36
  SIGNATURE_FLAG_TO_SCHEME,
38
37
  SIGNATURE_SCHEME_TO_FLAG,
@@ -26860,6 +26859,7 @@ var init_token_registry = __esm({
26860
26859
  });
26861
26860
  var coinSelection_exports = {};
26862
26861
  __export(coinSelection_exports, {
26862
+ buildCoinToAddressBalanceMigration: () => buildCoinToAddressBalanceMigration,
26863
26863
  fetchAllCoins: () => fetchAllCoins,
26864
26864
  selectAndSplitCoin: () => selectAndSplitCoin,
26865
26865
  selectSuiCoin: () => selectSuiCoin
@@ -26974,6 +26974,32 @@ async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowS
26974
26974
  });
26975
26975
  return { coin, effectiveAmount, swapAll };
26976
26976
  }
26977
+ function buildCoinToAddressBalanceMigration(args) {
26978
+ const { coins, coinType, owner, minAmount } = args;
26979
+ const sorted = [...coins].filter((c) => c.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
26980
+ const selected = [];
26981
+ let migratedRaw = 0n;
26982
+ for (const c of sorted) {
26983
+ if (migratedRaw >= minAmount) break;
26984
+ selected.push(c);
26985
+ migratedRaw += c.balance;
26986
+ }
26987
+ if (migratedRaw < minAmount) {
26988
+ throw new T2000Error("INSUFFICIENT_BALANCE", `Insufficient ${coinType} coin objects to migrate`, {
26989
+ available: migratedRaw.toString(),
26990
+ required: minAmount.toString()
26991
+ });
26992
+ }
26993
+ const tx = new Transaction();
26994
+ for (const c of selected) {
26995
+ tx.moveCall({
26996
+ target: "0x2::coin::send_funds",
26997
+ typeArguments: [coinType],
26998
+ arguments: [tx.object(c.objectId), tx.pure.address(owner)]
26999
+ });
27000
+ }
27001
+ return { tx, migratedRaw };
27002
+ }
26977
27003
  async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext, mergeCache) {
26978
27004
  if (sponsoredContext) {
26979
27005
  const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
@@ -27676,7 +27702,7 @@ async function pickSuiExactRequirements(response, network) {
27676
27702
  }
27677
27703
  async function payViaX402(args) {
27678
27704
  const { signer, client, options, reqInit, requirements } = args;
27679
- const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./x402-EMQGKUTK.js");
27705
+ const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./x402-UYN72OS3.js");
27680
27706
  const amountRaw = BigInt(requirements.maxAmountRequired);
27681
27707
  const migrationGasSui = await ensureAddressBalanceCovers({
27682
27708
  signer,
@@ -27724,40 +27750,26 @@ async function ensureAddressBalanceCovers(args) {
27724
27750
  required: amountRaw.toString()
27725
27751
  });
27726
27752
  }
27753
+ const coins = [];
27727
27754
  let coinSum = 0n;
27728
27755
  let cursor;
27729
27756
  let hasNext = true;
27730
27757
  while (hasNext) {
27731
27758
  const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? void 0 });
27732
- for (const c of page.objects) coinSum += BigInt(c.balance);
27759
+ for (const c of page.objects) {
27760
+ coins.push({ objectId: c.objectId, balance: BigInt(c.balance) });
27761
+ coinSum += BigInt(c.balance);
27762
+ }
27733
27763
  cursor = page.cursor;
27734
27764
  hasNext = page.hasNextPage;
27735
27765
  }
27736
27766
  const addressBalance = total - coinSum;
27737
27767
  if (addressBalance >= amountRaw) return 0;
27738
27768
  const shortfall = amountRaw - addressBalance;
27739
- const { Transaction: Transaction6 } = await import("./transactions-FSCAFG5Z.js");
27740
- const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
27769
+ const { buildCoinToAddressBalanceMigration: buildCoinToAddressBalanceMigration2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
27741
27770
  const grpcClient = await makeGrpcBuildClient(client);
27742
- const migration = await executeTx(
27743
- client,
27744
- signer,
27745
- async () => {
27746
- const tx = new Transaction6();
27747
- const { coin } = await selectAndSplitCoin2(tx, client, owner, asset, shortfall, {
27748
- sponsoredContext: true,
27749
- // coin-objects-only — never the address balance
27750
- allowSwapAll: false
27751
- });
27752
- tx.moveCall({
27753
- target: "0x2::coin::send_funds",
27754
- typeArguments: [asset],
27755
- arguments: [coin, tx.pure.address(owner)]
27756
- });
27757
- return tx;
27758
- },
27759
- { buildClient: grpcClient }
27760
- );
27771
+ const { tx } = buildCoinToAddressBalanceMigration2({ coins, coinType: asset, owner, minAmount: shortfall });
27772
+ const migration = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
27761
27773
  return migration.gasCostSui;
27762
27774
  }
27763
27775
  async function finalize(response, opts) {
@@ -27771,7 +27783,7 @@ async function finalize(response, opts) {
27771
27783
  return { status: response.status, body, paid: opts.paid };
27772
27784
  }
27773
27785
  async function makeGrpcBuildClient(client) {
27774
- const { SuiGrpcClient: SuiGrpcClient2 } = await import("./grpc-UMZJXRGY.js");
27786
+ const { SuiGrpcClient: SuiGrpcClient2 } = await import("./grpc-OLWNGPHN.js");
27775
27787
  const network = client.network === "testnet" ? "testnet" : "mainnet";
27776
27788
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
27777
27789
  return new SuiGrpcClient2({ baseUrl, network });
@@ -28888,6 +28900,7 @@ init_errors();
28888
28900
  init_swap_quote();
28889
28901
  init_cetus_swap();
28890
28902
  init_token_registry();
28903
+ var AGENT_ID_PARENT_NFT_ID = process.env.AGENT_ID_PARENT_NFT_ID ?? "0xc8c13f5b5a6d4c47c04877014794f65e67e2745d3bfa089b736eb54b0ebd5d1f";
28891
28904
  init_preflight();
28892
28905
 
28893
28906
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@20.19.37/node_modules/@inquirer/core/dist/esm/lib/key.js
@@ -32482,7 +32495,7 @@ function registerMcpStart(parent) {
32482
32495
  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) => {
32483
32496
  let mod2;
32484
32497
  try {
32485
- mod2 = await import("./dist-ULTRYNV7.js");
32498
+ mod2 = await import("./dist-HTKRHJBX.js");
32486
32499
  } catch {
32487
32500
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
32488
32501
  process.exit(1);
@@ -32821,6 +32834,173 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
32821
32834
  registerSkillsUninstall(group);
32822
32835
  }
32823
32836
 
32837
+ // src/commands/agent/index.ts
32838
+ var DEFAULT_API_BASE = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
32839
+ function normalizeTopupAsset(input) {
32840
+ return input?.toLowerCase() === "usdsui" ? "USDsui" : "USDC";
32841
+ }
32842
+ async function fundCredit(agent, base, amountStr, assetOpt) {
32843
+ const amount = Number.parseFloat(amountStr);
32844
+ if (Number.isNaN(amount) || amount <= 0) {
32845
+ throw new Error(`amount must be a positive number (got "${amountStr}").`);
32846
+ }
32847
+ const asset = normalizeTopupAsset(assetOpt);
32848
+ const cfg = await fetchJson(`${base}/agent/topup`, { method: "GET" });
32849
+ const treasury = cfg.treasury;
32850
+ if (!treasury) {
32851
+ throw new Error("Could not resolve the t2000 treasury address.");
32852
+ }
32853
+ const sent = await agent.send({ to: treasury, amount, asset });
32854
+ const topup = await fetchJson(`${base}/agent/topup`, {
32855
+ method: "POST",
32856
+ body: { address: agent.address(), digest: sent.tx }
32857
+ });
32858
+ return { amount, asset, balanceUsd: topup.balanceUsd };
32859
+ }
32860
+ async function fetchJson(url, init) {
32861
+ const res = await fetch(url, {
32862
+ method: init.method,
32863
+ headers: init.body ? { "Content-Type": "application/json" } : void 0,
32864
+ body: init.body ? JSON.stringify(init.body) : void 0
32865
+ });
32866
+ const json = await res.json().catch(() => ({}));
32867
+ if (!res.ok) {
32868
+ const err = json.error;
32869
+ const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
32870
+ throw new Error(msg);
32871
+ }
32872
+ return json;
32873
+ }
32874
+ function registerAgent(program3) {
32875
+ const group = program3.command("agent").description("Agent ID \u2014 onboard this wallet to the t2000 API (api.t2000.ai)").addHelpText(
32876
+ "after",
32877
+ `
32878
+ Subcommands:
32879
+ $ t2 agent onboard --fund 5 Fund 5 USDC \u2192 mint an API key (ready to call)
32880
+ $ t2 agent onboard --fund 5 --asset USDsui
32881
+ $ t2 agent onboard Already funded \u2192 just mint a key
32882
+ `
32883
+ );
32884
+ group.command("onboard").description("Fund credit (gasless USDC/USDsui) + mint an API key for this wallet.").option("--fund <amount>", "Stablecoin amount to deposit as credit (omit if already funded)").option("--asset <asset>", "USDC (default) or USDsui", "USDC").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE})`).action(
32885
+ async (opts) => {
32886
+ try {
32887
+ const base = opts.api ?? DEFAULT_API_BASE;
32888
+ const agent = await withAgent({ keyPath: opts.key });
32889
+ const address = agent.address();
32890
+ if (opts.fund !== void 0) {
32891
+ const funded = await fundCredit(agent, base, opts.fund, opts.asset);
32892
+ if (!isJsonMode()) {
32893
+ printSuccess(
32894
+ `Funded ${formatUsd(funded.amount)} ${funded.asset} \u2192 credit $${funded.balanceUsd}`
32895
+ );
32896
+ }
32897
+ }
32898
+ const challenge = await fetchJson(`${base}/agent/challenge`, {
32899
+ method: "POST",
32900
+ body: { address }
32901
+ });
32902
+ const nonce = challenge.nonce;
32903
+ if (!nonce) {
32904
+ throw new Error("Failed to get a challenge nonce.");
32905
+ }
32906
+ const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
32907
+ const { signature } = await agent.keypair.signPersonalMessage(message);
32908
+ const minted = await fetchJson(`${base}/agent/keys`, {
32909
+ method: "POST",
32910
+ body: { address, nonce, signature }
32911
+ });
32912
+ const key = minted.key;
32913
+ if (!key) {
32914
+ throw new Error("Failed to mint an API key.");
32915
+ }
32916
+ if (isJsonMode()) {
32917
+ printJson({ address, apiKey: key, baseUrl: base });
32918
+ return;
32919
+ }
32920
+ printBlank();
32921
+ printSuccess("Agent onboarded \u2014 API key minted (shown once, store it now)");
32922
+ printKeyValue("Address", truncateAddress(address));
32923
+ printKeyValue("API key", key);
32924
+ printKeyValue("Base URL", base);
32925
+ printBlank();
32926
+ printInfo(`export OPENAI_BASE_URL=${base} OPENAI_API_KEY=${key}`);
32927
+ printBlank();
32928
+ } catch (error) {
32929
+ handleError(error);
32930
+ }
32931
+ }
32932
+ );
32933
+ group.command("topup").argument("<amount>", "Stablecoin amount to deposit as credit").description(
32934
+ "Top up this wallet's t2000 credit with gasless USDC/USDsui (no new key). The 'never runs dry' primitive \u2014 call it on a 402 or a schedule."
32935
+ ).option("--asset <asset>", "USDC (default) or USDsui", "USDC").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE})`).action(
32936
+ async (amount, opts) => {
32937
+ try {
32938
+ const base = opts.api ?? DEFAULT_API_BASE;
32939
+ const agent = await withAgent({ keyPath: opts.key });
32940
+ const funded = await fundCredit(agent, base, amount, opts.asset);
32941
+ if (isJsonMode()) {
32942
+ printJson({
32943
+ address: agent.address(),
32944
+ funded: funded.amount,
32945
+ asset: funded.asset,
32946
+ balanceUsd: funded.balanceUsd
32947
+ });
32948
+ return;
32949
+ }
32950
+ printBlank();
32951
+ printSuccess(
32952
+ `Topped up ${formatUsd(funded.amount)} ${funded.asset} \u2192 credit $${funded.balanceUsd}`
32953
+ );
32954
+ printBlank();
32955
+ } catch (error) {
32956
+ handleError(error);
32957
+ }
32958
+ }
32959
+ );
32960
+ group.command("handle").argument("<label>", "Desired handle (3\u201320 chars: lowercase a\u2013z, 0\u20139, hyphens)").description(
32961
+ "Claim <label>.agent-id.sui \u2192 this wallet \u2014 a human-readable Agent ID handle (custody-minted, gasless for you)."
32962
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE})`).action(
32963
+ async (label, opts) => {
32964
+ try {
32965
+ const base = opts.api ?? DEFAULT_API_BASE;
32966
+ const agent = await withAgent({ keyPath: opts.key });
32967
+ const address = agent.address();
32968
+ const challenge = await fetchJson(`${base}/agent/challenge`, {
32969
+ method: "POST",
32970
+ body: { address }
32971
+ });
32972
+ const nonce = challenge.nonce;
32973
+ if (!nonce) {
32974
+ throw new Error("Failed to get a challenge nonce.");
32975
+ }
32976
+ const message = new TextEncoder().encode(`t2000-agent-handle:${nonce}:${label}`);
32977
+ const { signature } = await agent.keypair.signPersonalMessage(message);
32978
+ const res = await fetchJson(`${base}/agent/handle`, {
32979
+ method: "POST",
32980
+ body: { address, label, nonce, signature }
32981
+ });
32982
+ if (isJsonMode()) {
32983
+ printJson({
32984
+ address,
32985
+ handle: res.handle,
32986
+ display: res.display,
32987
+ digest: res.digest
32988
+ });
32989
+ return;
32990
+ }
32991
+ printBlank();
32992
+ printSuccess(`Handle claimed: ${res.display}`);
32993
+ printKeyValue("Address", truncateAddress(address));
32994
+ printKeyValue("Handle", String(res.handle));
32995
+ printKeyValue("Tx", String(res.digest));
32996
+ printBlank();
32997
+ } catch (error) {
32998
+ handleError(error);
32999
+ }
33000
+ }
33001
+ );
33002
+ }
33003
+
32824
33004
  // src/program.ts
32825
33005
  var require3 = createRequire2(import.meta.url);
32826
33006
  var { version: CLI_VERSION2 } = require3("../package.json");
@@ -32856,6 +33036,7 @@ Examples:
32856
33036
  registerLimit(program3);
32857
33037
  registerMcp(program3);
32858
33038
  registerSkills(program3);
33039
+ registerAgent(program3);
32859
33040
  return program3;
32860
33041
  }
32861
33042