@t2000/cli 10.25.1 → 10.27.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
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'module'; import { fileURLToPat
3
3
  import {
4
4
  AggregatorClient,
5
5
  Env
6
- } from "./chunk-PRKQVMED.js";
6
+ } from "./chunk-TVD4WMBT.js";
7
7
  import {
8
8
  BalanceChange,
9
9
  BaseClient,
@@ -16,11 +16,11 @@ import {
16
16
  parseTransactionEffectsBcs,
17
17
  transactionDataToGrpcTransaction,
18
18
  transactionToGrpcJson
19
- } from "./chunk-R6QER65C.js";
19
+ } from "./chunk-SHZC6TMU.js";
20
20
  import {
21
21
  Transaction,
22
22
  coinWithBalance
23
- } from "./chunk-JEIOQF6Q.js";
23
+ } from "./chunk-CNTCUDEZ.js";
24
24
  import {
25
25
  ObjectError,
26
26
  SUI_TYPE_ARG,
@@ -31,7 +31,7 @@ import {
31
31
  fromBase64 as fromBase642,
32
32
  suiBcs,
33
33
  toBase64 as toBase642
34
- } from "./chunk-5MAY6SK7.js";
34
+ } from "./chunk-T32A4PV6.js";
35
35
  import {
36
36
  SIGNATURE_FLAG_TO_SCHEME,
37
37
  SIGNATURE_SCHEME_TO_FLAG,
@@ -79,7 +79,7 @@ import {
79
79
  split,
80
80
  toBase64,
81
81
  toHex
82
- } from "./chunk-D3DUYZYR.js";
82
+ } from "./chunk-BX4V52TZ.js";
83
83
  import {
84
84
  require_bn,
85
85
  require_safer
@@ -3390,79 +3390,6 @@ var require_commander = __commonJS({
3390
3390
  }
3391
3391
  });
3392
3392
 
3393
- // ../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
3394
- var require_picocolors = __commonJS({
3395
- "../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports, module) {
3396
- "use strict";
3397
- var p = process || {};
3398
- var argv = p.argv || [];
3399
- var env = p.env || {};
3400
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
3401
- var formatter = (open, close, replace = open) => (input) => {
3402
- let string = "" + input, index = string.indexOf(close, open.length);
3403
- return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
3404
- };
3405
- var replaceClose = (string, close, replace, index) => {
3406
- let result = "", cursor = 0;
3407
- do {
3408
- result += string.substring(cursor, index) + replace;
3409
- cursor = index + close.length;
3410
- index = string.indexOf(close, cursor);
3411
- } while (~index);
3412
- return result + string.substring(cursor);
3413
- };
3414
- var createColors = (enabled = isColorSupported) => {
3415
- let f = enabled ? formatter : () => String;
3416
- return {
3417
- isColorSupported: enabled,
3418
- reset: f("\x1B[0m", "\x1B[0m"),
3419
- bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
3420
- dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
3421
- italic: f("\x1B[3m", "\x1B[23m"),
3422
- underline: f("\x1B[4m", "\x1B[24m"),
3423
- inverse: f("\x1B[7m", "\x1B[27m"),
3424
- hidden: f("\x1B[8m", "\x1B[28m"),
3425
- strikethrough: f("\x1B[9m", "\x1B[29m"),
3426
- black: f("\x1B[30m", "\x1B[39m"),
3427
- red: f("\x1B[31m", "\x1B[39m"),
3428
- green: f("\x1B[32m", "\x1B[39m"),
3429
- yellow: f("\x1B[33m", "\x1B[39m"),
3430
- blue: f("\x1B[34m", "\x1B[39m"),
3431
- magenta: f("\x1B[35m", "\x1B[39m"),
3432
- cyan: f("\x1B[36m", "\x1B[39m"),
3433
- white: f("\x1B[37m", "\x1B[39m"),
3434
- gray: f("\x1B[90m", "\x1B[39m"),
3435
- bgBlack: f("\x1B[40m", "\x1B[49m"),
3436
- bgRed: f("\x1B[41m", "\x1B[49m"),
3437
- bgGreen: f("\x1B[42m", "\x1B[49m"),
3438
- bgYellow: f("\x1B[43m", "\x1B[49m"),
3439
- bgBlue: f("\x1B[44m", "\x1B[49m"),
3440
- bgMagenta: f("\x1B[45m", "\x1B[49m"),
3441
- bgCyan: f("\x1B[46m", "\x1B[49m"),
3442
- bgWhite: f("\x1B[47m", "\x1B[49m"),
3443
- blackBright: f("\x1B[90m", "\x1B[39m"),
3444
- redBright: f("\x1B[91m", "\x1B[39m"),
3445
- greenBright: f("\x1B[92m", "\x1B[39m"),
3446
- yellowBright: f("\x1B[93m", "\x1B[39m"),
3447
- blueBright: f("\x1B[94m", "\x1B[39m"),
3448
- magentaBright: f("\x1B[95m", "\x1B[39m"),
3449
- cyanBright: f("\x1B[96m", "\x1B[39m"),
3450
- whiteBright: f("\x1B[97m", "\x1B[39m"),
3451
- bgBlackBright: f("\x1B[100m", "\x1B[49m"),
3452
- bgRedBright: f("\x1B[101m", "\x1B[49m"),
3453
- bgGreenBright: f("\x1B[102m", "\x1B[49m"),
3454
- bgYellowBright: f("\x1B[103m", "\x1B[49m"),
3455
- bgBlueBright: f("\x1B[104m", "\x1B[49m"),
3456
- bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
3457
- bgCyanBright: f("\x1B[106m", "\x1B[49m"),
3458
- bgWhiteBright: f("\x1B[107m", "\x1B[49m")
3459
- };
3460
- };
3461
- module.exports = createColors();
3462
- module.exports.createColors = createColors;
3463
- }
3464
- });
3465
-
3466
3393
  // ../../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js
3467
3394
  var require_eventemitter3 = __commonJS({
3468
3395
  "../../node_modules/.pnpm/eventemitter3@5.0.4/node_modules/eventemitter3/index.js"(exports, module) {
@@ -3625,6 +3552,79 @@ var require_eventemitter3 = __commonJS({
3625
3552
  }
3626
3553
  });
3627
3554
 
3555
+ // ../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
3556
+ var require_picocolors = __commonJS({
3557
+ "../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports, module) {
3558
+ "use strict";
3559
+ var p = process || {};
3560
+ var argv = p.argv || [];
3561
+ var env = p.env || {};
3562
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
3563
+ var formatter = (open, close, replace = open) => (input) => {
3564
+ let string = "" + input, index = string.indexOf(close, open.length);
3565
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
3566
+ };
3567
+ var replaceClose = (string, close, replace, index) => {
3568
+ let result = "", cursor = 0;
3569
+ do {
3570
+ result += string.substring(cursor, index) + replace;
3571
+ cursor = index + close.length;
3572
+ index = string.indexOf(close, cursor);
3573
+ } while (~index);
3574
+ return result + string.substring(cursor);
3575
+ };
3576
+ var createColors = (enabled = isColorSupported) => {
3577
+ let f = enabled ? formatter : () => String;
3578
+ return {
3579
+ isColorSupported: enabled,
3580
+ reset: f("\x1B[0m", "\x1B[0m"),
3581
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
3582
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
3583
+ italic: f("\x1B[3m", "\x1B[23m"),
3584
+ underline: f("\x1B[4m", "\x1B[24m"),
3585
+ inverse: f("\x1B[7m", "\x1B[27m"),
3586
+ hidden: f("\x1B[8m", "\x1B[28m"),
3587
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
3588
+ black: f("\x1B[30m", "\x1B[39m"),
3589
+ red: f("\x1B[31m", "\x1B[39m"),
3590
+ green: f("\x1B[32m", "\x1B[39m"),
3591
+ yellow: f("\x1B[33m", "\x1B[39m"),
3592
+ blue: f("\x1B[34m", "\x1B[39m"),
3593
+ magenta: f("\x1B[35m", "\x1B[39m"),
3594
+ cyan: f("\x1B[36m", "\x1B[39m"),
3595
+ white: f("\x1B[37m", "\x1B[39m"),
3596
+ gray: f("\x1B[90m", "\x1B[39m"),
3597
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
3598
+ bgRed: f("\x1B[41m", "\x1B[49m"),
3599
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
3600
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
3601
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
3602
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
3603
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
3604
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
3605
+ blackBright: f("\x1B[90m", "\x1B[39m"),
3606
+ redBright: f("\x1B[91m", "\x1B[39m"),
3607
+ greenBright: f("\x1B[92m", "\x1B[39m"),
3608
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
3609
+ blueBright: f("\x1B[94m", "\x1B[39m"),
3610
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
3611
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
3612
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
3613
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
3614
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
3615
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
3616
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
3617
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
3618
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
3619
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
3620
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
3621
+ };
3622
+ };
3623
+ module.exports = createColors();
3624
+ module.exports.createColors = createColors;
3625
+ }
3626
+ });
3627
+
3628
3628
  // ../../node_modules/.pnpm/yoctocolors-cjs@2.1.3/node_modules/yoctocolors-cjs/index.js
3629
3629
  var require_yoctocolors_cjs = __commonJS({
3630
3630
  "../../node_modules/.pnpm/yoctocolors-cjs@2.1.3/node_modules/yoctocolors-cjs/index.js"(exports, module) {
@@ -19144,80 +19144,6 @@ var {
19144
19144
  Help
19145
19145
  } = import_index.default;
19146
19146
 
19147
- // src/program.ts
19148
- import { createRequire as createRequire2 } from "module";
19149
-
19150
- // src/output.ts
19151
- var import_picocolors = __toESM(require_picocolors(), 1);
19152
- var jsonMode = false;
19153
- function setJsonMode(enabled) {
19154
- jsonMode = enabled;
19155
- }
19156
- function isJsonMode() {
19157
- return jsonMode;
19158
- }
19159
- function printJson(data) {
19160
- console.log(JSON.stringify(data, null, 2));
19161
- }
19162
- function printSuccess(message) {
19163
- if (jsonMode) return;
19164
- console.log(` ${import_picocolors.default.green("\u2713")} ${message}`);
19165
- }
19166
- function printError(message) {
19167
- if (jsonMode) return;
19168
- console.error(` ${import_picocolors.default.red("\u2717")} ${message}`);
19169
- }
19170
- function printWarning(message) {
19171
- if (jsonMode) return;
19172
- console.log(` ${import_picocolors.default.yellow("\u26A0")} ${message}`);
19173
- }
19174
- function printInfo(message) {
19175
- if (jsonMode) return;
19176
- console.log(` ${import_picocolors.default.dim(message)}`);
19177
- }
19178
- function printHeader(title) {
19179
- if (jsonMode) return;
19180
- console.log();
19181
- console.log(` ${import_picocolors.default.bold(title)}`);
19182
- console.log();
19183
- }
19184
- function printKeyValue(key, value, indent2 = 2) {
19185
- if (jsonMode) return;
19186
- const pad = " ".repeat(indent2);
19187
- console.log(`${pad}${import_picocolors.default.dim(key + ":")} ${value}`);
19188
- }
19189
- function printBlank() {
19190
- if (jsonMode) return;
19191
- console.log();
19192
- }
19193
- function printDivider(width = 53) {
19194
- if (jsonMode) return;
19195
- console.log(` ${import_picocolors.default.dim("\u2500".repeat(width))}`);
19196
- }
19197
- function printLine(text) {
19198
- if (jsonMode) return;
19199
- console.log(` ${text}`);
19200
- }
19201
- function printSeparator() {
19202
- if (jsonMode) return;
19203
- console.log(` ${import_picocolors.default.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
19204
- }
19205
- function explorerUrl(txHash, network = "mainnet") {
19206
- const base = network === "testnet" ? "https://suiscan.xyz/testnet/tx" : "https://suiscan.xyz/mainnet/tx";
19207
- const suffix = "";
19208
- return `${base}/${txHash}${suffix}`;
19209
- }
19210
- function handleError(error) {
19211
- if (jsonMode) {
19212
- const data = error instanceof Error && "toJSON" in error ? error.toJSON() : { error: "UNKNOWN", message: String(error) };
19213
- printJson(data);
19214
- } else {
19215
- const msg = error instanceof Error ? error.message : String(error);
19216
- printError(msg);
19217
- }
19218
- process.exit(1);
19219
- }
19220
-
19221
19147
  // ../sdk/dist/index.js
19222
19148
  var import_bn = __toESM(require_bn(), 1);
19223
19149
 
@@ -28618,11 +28544,65 @@ function preflightPay(input) {
28618
28544
  }
28619
28545
  return PREFLIGHT_OK;
28620
28546
  }
28621
- async function payWithX402(args) {
28622
- const { signer, client } = args;
28623
- let options = args.options;
28624
- const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });
28547
+ async function probeX402(args) {
28548
+ const { network } = args;
28549
+ const pf = preflightPay({ url: args.options.url, maxPrice: args.options.maxPrice });
28625
28550
  if (!pf.valid) throw new T2000Error(pf.code, pf.error);
28551
+ const { reqInit } = normalizePayRequest(args.options);
28552
+ const probe = await fetch(args.options.url, reqInit);
28553
+ if (probe.status !== 402) {
28554
+ return {
28555
+ kind: "free",
28556
+ status: probe.status,
28557
+ note: "No payment required \u2014 this endpoint served without a 402."
28558
+ };
28559
+ }
28560
+ const pick = await pickSuiExactRequirements(probe, network);
28561
+ if (pick.kind === "payable") {
28562
+ const requirements = pick.requirements;
28563
+ const priceUsdc = atomicToHuman(
28564
+ BigInt(requirements.maxAmountRequired),
28565
+ await assetDecimals(requirements.asset)
28566
+ );
28567
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28568
+ if (isX402EscrowRequirements(requirements)) {
28569
+ return {
28570
+ kind: "escrow",
28571
+ priceUsdc,
28572
+ payTo: requirements.payTo,
28573
+ note: "This endpoint sells deliverable work through on-chain escrow, not an instant call. Hire it as a job instead \u2014 funds lock in a Job object and release on delivery."
28574
+ };
28575
+ }
28576
+ return {
28577
+ kind: "payable",
28578
+ priceUsdc,
28579
+ asset: requirements.asset,
28580
+ payTo: requirements.payTo,
28581
+ network
28582
+ };
28583
+ }
28584
+ if (hasPaymentAuthenticateHeader(probe)) {
28585
+ return {
28586
+ kind: "unsupported",
28587
+ reason: "header-only-402-unsupported",
28588
+ note: "This seller answered a header-only 402 (WWW-Authenticate: Payment) with no payable x402 accepts[] envelope. That dialect is no longer supported \u2014 the seller must offer x402 (e.g. @t2000/serve emits it)."
28589
+ };
28590
+ }
28591
+ if (pick.kind === "incomplete") {
28592
+ return {
28593
+ kind: "incomplete",
28594
+ reason: "incomplete-x402-accepts",
28595
+ note: "Seller's x402 challenge is incomplete (missing extra.suimpp) \u2014 the 402 advertises an exact/sui entry but carries no settlement challenge to bind a payment to."
28596
+ };
28597
+ }
28598
+ return {
28599
+ kind: "not-x402",
28600
+ status: probe.status,
28601
+ note: `Endpoint returned 402 without an x402 'exact' / sui:${network} requirement in the body. Nothing this SDK can pay.`
28602
+ };
28603
+ }
28604
+ function normalizePayRequest(input) {
28605
+ let options = input;
28626
28606
  const method = (options.method ?? "GET").toUpperCase();
28627
28607
  const canHaveBody = method !== "GET" && method !== "HEAD";
28628
28608
  if (canHaveBody && typeof options.body === "string" && isJsonText(options.body) && !hasContentType(options.headers)) {
@@ -28631,11 +28611,23 @@ async function payWithX402(args) {
28631
28611
  headers: { ...options.headers ?? {}, "content-type": "application/json" }
28632
28612
  };
28633
28613
  }
28634
- const reqInit = {
28635
- method,
28636
- headers: options.headers,
28637
- body: canHaveBody ? options.body : void 0
28614
+ return {
28615
+ options,
28616
+ reqInit: {
28617
+ method,
28618
+ headers: options.headers,
28619
+ body: canHaveBody ? options.body : void 0
28620
+ }
28638
28621
  };
28622
+ }
28623
+ async function payWithX402(args) {
28624
+ const { signer, client } = args;
28625
+ let options = args.options;
28626
+ const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });
28627
+ if (!pf.valid) throw new T2000Error(pf.code, pf.error);
28628
+ const normalized = normalizePayRequest(options);
28629
+ options = normalized.options;
28630
+ const reqInit = normalized.reqInit;
28639
28631
  const probe = await fetch(options.url, reqInit);
28640
28632
  if (probe.status !== 402) {
28641
28633
  return finalize(probe, { paid: false });
@@ -28643,7 +28635,7 @@ async function payWithX402(args) {
28643
28635
  const pick = await pickSuiExactRequirements(probe, client.network);
28644
28636
  if (pick.kind === "payable") {
28645
28637
  const requirements = pick.requirements;
28646
- const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28638
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28647
28639
  if (isX402EscrowRequirements(requirements)) {
28648
28640
  const escrow = requirements.extra.escrow;
28649
28641
  const price = atomicToHuman(
@@ -28689,7 +28681,7 @@ async function pickSuiExactRequirements(response, network) {
28689
28681
  const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
28690
28682
  const entry = body2.accepts?.find((a) => a.scheme === "exact" && a.network === want);
28691
28683
  if (!entry) return { kind: "none" };
28692
- const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28684
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28693
28685
  if (hasCompleteSuimppChallenge(entry) || isX402EscrowRequirements(entry)) {
28694
28686
  return { kind: "payable", requirements: entry };
28695
28687
  }
@@ -28707,7 +28699,7 @@ async function payViaX402(args) {
28707
28699
  { reason: "incomplete-x402-accepts" }
28708
28700
  );
28709
28701
  }
28710
- const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./dist-VUHPQJYY.js");
28702
+ const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./dist-RTAF2SWN.js");
28711
28703
  const amountRaw = BigInt(requirements.maxAmountRequired);
28712
28704
  assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
28713
28705
  const migrationGasSui = await ensureAddressBalanceCovers({
@@ -28838,7 +28830,7 @@ async function finalize(response, opts) {
28838
28830
  return { status: response.status, body: body2, paid: opts.paid };
28839
28831
  }
28840
28832
  async function makeGrpcBuildClient(client) {
28841
- const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-G3RQE2L5.js");
28833
+ const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-AJNSMQ2Y.js");
28842
28834
  const network = client.network === "testnet" ? "testnet" : "mainnet";
28843
28835
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
28844
28836
  return new SuiGrpcClient3({ baseUrl, network });
@@ -28867,7 +28859,7 @@ var ZkLoginSigner = class {
28867
28859
  return this.userAddress;
28868
28860
  }
28869
28861
  async signTransaction(txBytes) {
28870
- const { getZkLoginSignature } = await import("./esm-ZKAIHFAJ.js");
28862
+ const { getZkLoginSignature } = await import("./esm-JVUVZX3G.js");
28871
28863
  const ephSig = await this.ephemeralKeypair.signTransaction(txBytes);
28872
28864
  return {
28873
28865
  signature: getZkLoginSignature({
@@ -28878,7 +28870,7 @@ var ZkLoginSigner = class {
28878
28870
  };
28879
28871
  }
28880
28872
  async signPersonalMessage(messageBytes) {
28881
- const { getZkLoginSignature } = await import("./esm-ZKAIHFAJ.js");
28873
+ const { getZkLoginSignature } = await import("./esm-JVUVZX3G.js");
28882
28874
  const { signature: ephSig, bytes } = await this.ephemeralKeypair.signPersonalMessage(messageBytes);
28883
28875
  return {
28884
28876
  signature: getZkLoginSignature({
@@ -30122,6 +30114,15 @@ var T2000 = class _T2000 extends import_index2.default {
30122
30114
  return this._signer;
30123
30115
  }
30124
30116
  // -- MPP Payments --
30117
+ /**
30118
+ * READ-ONLY price probe for an x402 endpoint (S.919). Reports what `pay()`
30119
+ * would cost without signing or spending, so a caller (Connect's
30120
+ * `t2000_pay_probe`, the CLI, a UI) can show terms before committing.
30121
+ * No limit gate: nothing moves.
30122
+ */
30123
+ async payProbe(options) {
30124
+ return await probeX402({ network: this.client.network, options });
30125
+ }
30125
30126
  async pay(options) {
30126
30127
  this.limits.assert({ operation: "pay", amountUsd: options.maxPrice ?? 0, force: options.force });
30127
30128
  const result = await payWithX402({ signer: this._signer, client: this.client, options });
@@ -30534,8 +30535,10 @@ init_coinSelection();
30534
30535
  init_errors();
30535
30536
  init_token_registry();
30536
30537
  init_coinSelection();
30537
- var A2A_ESCROW_OPENING_PACKAGE_ID = process.env.A2A_ESCROW_OPENING_PACKAGE_ID ?? "0x69ad93c555519de520a5c7f7f2963ad6f8b91cefc098fc2eed75942dcb5bcbe7";
30538
- var A2A_ESCROW_PACKAGE_ID = process.env.A2A_ESCROW_PACKAGE_ID ?? "0x358a819c1c016e2cc84ef5fbea81cba90c31f7f8a62bf45cb5e5276acf198bdd";
30538
+ var MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID = "0x69ad93c555519de520a5c7f7f2963ad6f8b91cefc098fc2eed75942dcb5bcbe7";
30539
+ var A2A_ESCROW_OPENING_PACKAGE_ID = process.env.A2A_ESCROW_OPENING_PACKAGE_ID ?? MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID;
30540
+ var MAINNET_A2A_ESCROW_PACKAGE_ID = "0x358a819c1c016e2cc84ef5fbea81cba90c31f7f8a62bf45cb5e5276acf198bdd";
30541
+ var A2A_ESCROW_PACKAGE_ID = process.env.A2A_ESCROW_PACKAGE_ID ?? MAINNET_A2A_ESCROW_PACKAGE_ID;
30539
30542
  var A2A_ESCROW_FEE_CONFIG_ID = process.env.A2A_ESCROW_FEE_CONFIG_ID ?? "0xddaa25570950b7484dbf20797ebcf75707be9c87cd67bef2a06ed2e81d2c494b";
30540
30543
  var A2A_ESCROW_FEE_CONFIG_VERSION = Number(
30541
30544
  process.env.A2A_ESCROW_FEE_CONFIG_VERSION ?? 931861903
@@ -30774,6 +30777,10 @@ async function fetchJson(url, init) {
30774
30777
  }
30775
30778
  return json;
30776
30779
  }
30780
+ var sponsoredTxGuard = null;
30781
+ function setSponsoredTxGuard(guard) {
30782
+ sponsoredTxGuard = guard;
30783
+ }
30777
30784
  async function listOpenJobs(base, filter = {}) {
30778
30785
  const params = new URLSearchParams();
30779
30786
  if (filter.status) params.set("status", filter.status);
@@ -30786,6 +30793,7 @@ async function listOpenJobs(base, filter = {}) {
30786
30793
  }
30787
30794
  async function sponsoredOpeningVerb(base, signer, action, params) {
30788
30795
  const address = signer.getAddress();
30796
+ sponsoredTxGuard?.({ base, action });
30789
30797
  const prep = await fetchJson(`${base}/job/prepare`, {
30790
30798
  method: "POST",
30791
30799
  body: { address, action, params }
@@ -30795,6 +30803,7 @@ async function sponsoredOpeningVerb(base, signer, action, params) {
30795
30803
  if (!(nonce && txBytes)) {
30796
30804
  throw new Error("Failed to prepare the transaction.");
30797
30805
  }
30806
+ sponsoredTxGuard?.({ base, action, txBytes });
30798
30807
  const { signature } = await signer.signTransaction(fromBase64(txBytes));
30799
30808
  const json = await fetchJson(`${base}/job/submit`, {
30800
30809
  method: "POST",
@@ -30845,6 +30854,247 @@ init_cetus_swap();
30845
30854
  init_token_registry();
30846
30855
  init_preflight();
30847
30856
 
30857
+ // src/lib/tx-guard.ts
30858
+ var CANONICAL_API_ORIGIN = "https://api.t2000.ai";
30859
+ var ALLOW_UNTRUSTED_FLAG = "--allow-untrusted-api";
30860
+ var ACTION_TARGETS = {
30861
+ // v1 escrow package.
30862
+ create: {
30863
+ pkg: MAINNET_A2A_ESCROW_PACKAGE_ID,
30864
+ module: "escrow",
30865
+ functions: ["create"]
30866
+ },
30867
+ deliver: {
30868
+ pkg: MAINNET_A2A_ESCROW_PACKAGE_ID,
30869
+ module: "escrow",
30870
+ functions: ["deliver"]
30871
+ },
30872
+ release: {
30873
+ pkg: MAINNET_A2A_ESCROW_PACKAGE_ID,
30874
+ module: "escrow",
30875
+ functions: ["release"]
30876
+ },
30877
+ reject: {
30878
+ pkg: MAINNET_A2A_ESCROW_PACKAGE_ID,
30879
+ module: "escrow",
30880
+ functions: ["reject"]
30881
+ },
30882
+ refund: {
30883
+ pkg: MAINNET_A2A_ESCROW_PACKAGE_ID,
30884
+ module: "escrow",
30885
+ functions: ["refund"]
30886
+ },
30887
+ // v3 opening package — note the `escrow` module.
30888
+ decline: {
30889
+ pkg: MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID,
30890
+ module: "escrow",
30891
+ functions: ["decline"]
30892
+ },
30893
+ // Open board.
30894
+ "open-create": {
30895
+ pkg: MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID,
30896
+ module: "opening",
30897
+ functions: ["create_open"]
30898
+ },
30899
+ "open-claim": {
30900
+ pkg: MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID,
30901
+ module: "opening",
30902
+ functions: ["claim"]
30903
+ },
30904
+ "open-cancel": {
30905
+ pkg: MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID,
30906
+ module: "opening",
30907
+ functions: ["cancel_open"]
30908
+ },
30909
+ "open-refund": {
30910
+ pkg: MAINNET_A2A_ESCROW_OPENING_PACKAGE_ID,
30911
+ module: "opening",
30912
+ functions: ["refund_unclaimed"]
30913
+ }
30914
+ };
30915
+ var HOST_PINNED_ONLY = /* @__PURE__ */ new Set(["register", "link", "confirm"]);
30916
+ var allowUntrustedApi = false;
30917
+ function setAllowUntrustedApi(value) {
30918
+ allowUntrustedApi = value;
30919
+ }
30920
+ function isAllowUntrustedApi() {
30921
+ return allowUntrustedApi;
30922
+ }
30923
+ var UntrustedHostError = class extends Error {
30924
+ };
30925
+ var IntentMismatchError = class extends Error {
30926
+ };
30927
+ function apiOrigin(base) {
30928
+ try {
30929
+ return new URL(base).origin;
30930
+ } catch {
30931
+ return base;
30932
+ }
30933
+ }
30934
+ function isDefaultApiHost(base) {
30935
+ return apiOrigin(base) === CANONICAL_API_ORIGIN;
30936
+ }
30937
+ function assertSigningHostAllowed(base, allowUntrusted) {
30938
+ if (isDefaultApiHost(base) || allowUntrusted) {
30939
+ return;
30940
+ }
30941
+ throw new UntrustedHostError(
30942
+ `Refusing to sign transactions built by ${apiOrigin(base)}.
30943
+ Only ${CANONICAL_API_ORIGIN} is trusted by default. If you really mean to use
30944
+ another host (a local or staging API), re-run with ${ALLOW_UNTRUSTED_FLAG}.
30945
+ If you did not set T2000_API_URL or --api yourself, treat this as an attack.`
30946
+ );
30947
+ }
30948
+ function assertTxMatchesIntent(txBytes, intent, opts = {}) {
30949
+ if (opts.allowUntrusted) {
30950
+ return;
30951
+ }
30952
+ if (HOST_PINNED_ONLY.has(intent.action)) {
30953
+ return;
30954
+ }
30955
+ const expected = ACTION_TARGETS[intent.action];
30956
+ if (!expected) {
30957
+ throw new IntentMismatchError(
30958
+ `Refusing to sign: "${intent.action}" is not a verb this wallet knows how to verify.`
30959
+ );
30960
+ }
30961
+ let calls;
30962
+ try {
30963
+ const tx = Transaction.from(
30964
+ new Uint8Array(Buffer.from(txBytes, "base64"))
30965
+ );
30966
+ calls = tx.getData().commands.flatMap(
30967
+ (c) => c.$kind === "MoveCall" && c.MoveCall ? [
30968
+ {
30969
+ pkg: c.MoveCall.package,
30970
+ module: c.MoveCall.module,
30971
+ fn: c.MoveCall.function
30972
+ }
30973
+ ] : []
30974
+ );
30975
+ } catch (e) {
30976
+ throw new IntentMismatchError(
30977
+ `Refusing to sign: could not decode the prepared transaction (${e instanceof Error ? e.message : "unreadable"}).`
30978
+ );
30979
+ }
30980
+ if (calls.length === 0) {
30981
+ throw new IntentMismatchError(
30982
+ "Refusing to sign: the prepared transaction contains no Move calls."
30983
+ );
30984
+ }
30985
+ for (const call of calls) {
30986
+ if (call.pkg !== expected.pkg) {
30987
+ throw new IntentMismatchError(
30988
+ `Refusing to sign: "${intent.action}" targets package ${expected.pkg}, but the transaction calls ${call.pkg}.`
30989
+ );
30990
+ }
30991
+ if (call.module !== expected.module) {
30992
+ throw new IntentMismatchError(
30993
+ `Refusing to sign: "${intent.action}" should call ${expected.module}, but the transaction calls ${call.module}.`
30994
+ );
30995
+ }
30996
+ if (!expected.functions.includes(call.fn)) {
30997
+ throw new IntentMismatchError(
30998
+ `Refusing to sign: "${intent.action}" should call ${expected.module}::${expected.functions.join("|")}, but the transaction calls ${call.module}::${call.fn}.`
30999
+ );
31000
+ }
31001
+ }
31002
+ }
31003
+ function describeIntent(intent, base) {
31004
+ const bits = [intent.action];
31005
+ if (intent.amountUsdc !== void 0) {
31006
+ bits.push(`$${intent.amountUsdc}`);
31007
+ }
31008
+ if (intent.seller) {
31009
+ bits.push(`\u2192 ${intent.seller.slice(0, 6)}\u2026${intent.seller.slice(-4)}`);
31010
+ }
31011
+ return `About to sign: ${bits.join(" ")} (${apiOrigin(base).replace("https://", "")})`;
31012
+ }
31013
+ function installSponsoredTxGuard() {
31014
+ setSponsoredTxGuard(({ base, action, txBytes }) => {
31015
+ const allowUntrusted = isAllowUntrustedApi();
31016
+ if (txBytes === void 0) {
31017
+ assertSigningHostAllowed(base, allowUntrusted);
31018
+ return;
31019
+ }
31020
+ assertTxMatchesIntent(txBytes, { action }, { allowUntrusted });
31021
+ });
31022
+ }
31023
+
31024
+ // src/program.ts
31025
+ import { createRequire as createRequire2 } from "module";
31026
+
31027
+ // src/output.ts
31028
+ var import_picocolors = __toESM(require_picocolors(), 1);
31029
+ var jsonMode = false;
31030
+ function setJsonMode(enabled) {
31031
+ jsonMode = enabled;
31032
+ }
31033
+ function isJsonMode() {
31034
+ return jsonMode;
31035
+ }
31036
+ function printJson(data) {
31037
+ console.log(JSON.stringify(data, null, 2));
31038
+ }
31039
+ function printSuccess(message) {
31040
+ if (jsonMode) return;
31041
+ console.log(` ${import_picocolors.default.green("\u2713")} ${message}`);
31042
+ }
31043
+ function printError(message) {
31044
+ if (jsonMode) return;
31045
+ console.error(` ${import_picocolors.default.red("\u2717")} ${message}`);
31046
+ }
31047
+ function printWarning(message) {
31048
+ if (jsonMode) return;
31049
+ console.log(` ${import_picocolors.default.yellow("\u26A0")} ${message}`);
31050
+ }
31051
+ function printInfo(message) {
31052
+ if (jsonMode) return;
31053
+ console.log(` ${import_picocolors.default.dim(message)}`);
31054
+ }
31055
+ function printHeader(title) {
31056
+ if (jsonMode) return;
31057
+ console.log();
31058
+ console.log(` ${import_picocolors.default.bold(title)}`);
31059
+ console.log();
31060
+ }
31061
+ function printKeyValue(key, value, indent2 = 2) {
31062
+ if (jsonMode) return;
31063
+ const pad = " ".repeat(indent2);
31064
+ console.log(`${pad}${import_picocolors.default.dim(key + ":")} ${value}`);
31065
+ }
31066
+ function printBlank() {
31067
+ if (jsonMode) return;
31068
+ console.log();
31069
+ }
31070
+ function printDivider(width = 53) {
31071
+ if (jsonMode) return;
31072
+ console.log(` ${import_picocolors.default.dim("\u2500".repeat(width))}`);
31073
+ }
31074
+ function printLine(text) {
31075
+ if (jsonMode) return;
31076
+ console.log(` ${text}`);
31077
+ }
31078
+ function printSeparator() {
31079
+ if (jsonMode) return;
31080
+ console.log(` ${import_picocolors.default.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
31081
+ }
31082
+ function explorerUrl(txHash, network = "mainnet") {
31083
+ const base = network === "testnet" ? "https://suiscan.xyz/testnet/tx" : "https://suiscan.xyz/mainnet/tx";
31084
+ const suffix = "";
31085
+ return `${base}/${txHash}${suffix}`;
31086
+ }
31087
+ function handleError(error) {
31088
+ if (jsonMode) {
31089
+ const data = error instanceof Error && "toJSON" in error ? error.toJSON() : { error: "UNKNOWN", message: String(error) };
31090
+ printJson(data);
31091
+ } else {
31092
+ const msg = error instanceof Error ? error.message : String(error);
31093
+ printError(msg);
31094
+ }
31095
+ process.exit(1);
31096
+ }
31097
+
30848
31098
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@20.19.37/node_modules/@inquirer/core/dist/esm/lib/key.js
30849
31099
  var isUpKey = (key, keybindings = []) => (
30850
31100
  // The up key
@@ -33271,12 +33521,16 @@ async function postJson(url, body2) {
33271
33521
  return json;
33272
33522
  }
33273
33523
  async function runSponsoredTx(opts) {
33524
+ const allowUntrusted = isAllowUntrustedApi();
33525
+ assertSigningHostAllowed(opts.prepareUrl, allowUntrusted);
33274
33526
  const prep = await postJson(opts.prepareUrl, opts.prepareBody);
33275
33527
  const nonce = prep.nonce;
33276
33528
  const txBytes = prep.txBytes;
33277
33529
  if (!(nonce && txBytes)) {
33278
33530
  throw new Error("Failed to prepare the transaction.");
33279
33531
  }
33532
+ assertTxMatchesIntent(txBytes, opts.intent, { allowUntrusted });
33533
+ printLine(describeIntent(opts.intent, opts.prepareUrl));
33280
33534
  const bytes = new Uint8Array(Buffer.from(txBytes, "base64"));
33281
33535
  const { signature } = await opts.keypair.signTransaction(bytes);
33282
33536
  const res = await postJson(opts.submitUrl, {
@@ -33287,6 +33541,8 @@ async function runSponsoredTx(opts) {
33287
33541
  return { digest: res.digest };
33288
33542
  }
33289
33543
  async function registerWallet(opts) {
33544
+ const allowUntrusted = isAllowUntrustedApi();
33545
+ assertSigningHostAllowed(opts.base, allowUntrusted);
33290
33546
  const prep = await postJson(`${opts.base}/agent/register/prepare`, {
33291
33547
  address: opts.address
33292
33548
  });
@@ -33298,6 +33554,7 @@ async function registerWallet(opts) {
33298
33554
  if (!(regNonce && txBytes)) {
33299
33555
  throw new Error("Failed to prepare registration.");
33300
33556
  }
33557
+ assertTxMatchesIntent(txBytes, { action: "register" }, { allowUntrusted });
33301
33558
  const bytes = new Uint8Array(Buffer.from(txBytes, "base64"));
33302
33559
  const { signature } = await opts.keypair.signTransaction(bytes);
33303
33560
  const res = await postJson(`${opts.base}/agent/register/submit`, {
@@ -33400,7 +33657,15 @@ function registerInit(program3) {
33400
33657
  }
33401
33658
 
33402
33659
  // src/lib/with-agent.ts
33660
+ function assertEnvApiHostTrusted() {
33661
+ const envBase = process.env.T2000_API_URL;
33662
+ if (!envBase) {
33663
+ return;
33664
+ }
33665
+ assertSigningHostAllowed(envBase, isAllowUntrustedApi());
33666
+ }
33403
33667
  async function withAgent(options = {}) {
33668
+ assertEnvApiHostTrusted();
33404
33669
  return T2000.create({
33405
33670
  keyPath: options.keyPath,
33406
33671
  rpcUrl: options.rpcUrl
@@ -33408,6 +33673,7 @@ async function withAgent(options = {}) {
33408
33673
  }
33409
33674
  async function tryWithAgent(options = {}) {
33410
33675
  try {
33676
+ assertEnvApiHostTrusted();
33411
33677
  const agent = await T2000.create({
33412
33678
  keyPath: options.keyPath,
33413
33679
  rpcUrl: options.rpcUrl
@@ -35132,7 +35398,8 @@ function registerAgentCreate(group) {
35132
35398
  actor: address,
35133
35399
  prepareUrl: `${base}/agent/owner/propose`,
35134
35400
  prepareBody: { address, owner },
35135
- submitUrl: `${base}/agent/owner/submit`
35401
+ submitUrl: `${base}/agent/owner/submit`,
35402
+ intent: { action: "link" }
35136
35403
  });
35137
35404
  ownerProposed = true;
35138
35405
  }
@@ -35255,7 +35522,8 @@ Subcommands:
35255
35522
  actor: address,
35256
35523
  prepareUrl: `${base}/agent/owner/propose`,
35257
35524
  prepareBody: { address, owner },
35258
- submitUrl: `${base}/agent/owner/submit`
35525
+ submitUrl: `${base}/agent/owner/submit`,
35526
+ intent: { action: "link" }
35259
35527
  });
35260
35528
  if (isJsonMode()) {
35261
35529
  printJson({ agent: address, pendingOwner: owner, digest });
@@ -35284,7 +35552,8 @@ Subcommands:
35284
35552
  actor: address,
35285
35553
  prepareUrl: `${base}/agent/owner/confirm`,
35286
35554
  prepareBody: { owner: address, agent: agentAddress },
35287
- submitUrl: `${base}/agent/owner/submit`
35555
+ submitUrl: `${base}/agent/owner/submit`,
35556
+ intent: { action: "confirm" }
35288
35557
  });
35289
35558
  if (isJsonMode()) {
35290
35559
  printJson({ owner: address, agent: agentAddress, digest });
@@ -35310,7 +35579,8 @@ Subcommands:
35310
35579
  actor: address,
35311
35580
  prepareUrl: `${base}/agent/owner/renounce`,
35312
35581
  prepareBody: { owner: address, agent: agentAddress },
35313
- submitUrl: `${base}/agent/owner/submit`
35582
+ submitUrl: `${base}/agent/owner/submit`,
35583
+ intent: { action: "confirm" }
35314
35584
  });
35315
35585
  if (isJsonMode()) {
35316
35586
  printJson({ owner: address, agent: agentAddress, unlinked: true, digest });
@@ -35406,6 +35676,7 @@ Subcommands:
35406
35676
  if (!opts.remove) {
35407
35677
  await ensureSellerCategory({ base, agent, category });
35408
35678
  }
35679
+ assertSigningHostAllowed(base, isAllowUntrustedApi());
35409
35680
  const prepRes = await fetch(`${base}/agent/endpoint/prepare`, {
35410
35681
  method: "POST",
35411
35682
  headers: { "Content-Type": "application/json" },
@@ -35572,13 +35843,99 @@ function registerAgents(program3) {
35572
35843
  }
35573
35844
 
35574
35845
  // src/commands/job.ts
35575
- var import_picocolors13 = __toESM(require_picocolors(), 1);
35576
35846
  import { createHash } from "crypto";
35847
+
35848
+ // src/lib/spend-gate.ts
35849
+ var FORCE_HINT_RE = /\s*Use --force[^.]*\.\s*$/;
35850
+ function assertSpendAllowed(amountUsdc, force) {
35851
+ if (!(Number.isFinite(amountUsdc) && amountUsdc > 0)) {
35852
+ return;
35853
+ }
35854
+ try {
35855
+ assertLimitConfig({
35856
+ limits: getLimits(),
35857
+ spentTodayUsd: dailySpentToday(),
35858
+ operation: "send",
35859
+ amountUsd: amountUsdc,
35860
+ force
35861
+ });
35862
+ } catch (e) {
35863
+ if (e instanceof LimitExceededError) {
35864
+ throw new Error(
35865
+ `${e.message.replace(FORCE_HINT_RE, "")} Raise the cap with \`t2 limit set\` \u2014 job verbs have no --force.`
35866
+ );
35867
+ }
35868
+ throw e;
35869
+ }
35870
+ }
35871
+ function recordSpendIfLanded(amountUsdc, digest) {
35872
+ if (digest && Number.isFinite(amountUsdc) && amountUsdc > 0) {
35873
+ recordDailySpend(amountUsdc);
35874
+ }
35875
+ }
35876
+
35877
+ // src/lib/agent-ref.ts
35878
+ var HASH_ID_RE = /^#\d{1,10}$/;
35879
+ var BARE_DIGITS_RE = /^\d{1,10}$/;
35880
+ var HANDLE_REF_RE = /^@[a-z0-9_-]{1,20}$/i;
35881
+ var HEX_REF_RE = /^0x[0-9a-fA-F]+$/;
35882
+ var AGENT_REF_KEY_RE = /agent|address|wallet|subject|recipient|pay[_-]?to|target/i;
35883
+ var FALLBACK_MISS = "Use an Agent ID (#93), @handle, or full 0x\u2026 address.";
35884
+ function looksLikeAgentRefValue(value) {
35885
+ const v = value.trim();
35886
+ return HASH_ID_RE.test(v) || HANDLE_REF_RE.test(v) || HEX_REF_RE.test(v);
35887
+ }
35888
+ function looksLikeAgentRefKey(key) {
35889
+ return AGENT_REF_KEY_RE.test(key);
35890
+ }
35891
+ function isAgentRefField(key, value) {
35892
+ const v = value.trim();
35893
+ if (looksLikeAgentRefValue(v)) {
35894
+ return true;
35895
+ }
35896
+ return BARE_DIGITS_RE.test(v) && looksLikeAgentRefKey(key);
35897
+ }
35898
+ function agentRefFields(requirements) {
35899
+ if (requirements == null || typeof requirements !== "object" || Array.isArray(requirements)) {
35900
+ return [];
35901
+ }
35902
+ return Object.entries(requirements).filter((e) => typeof e[1] === "string").filter(([k, v]) => isAgentRefField(k, v));
35903
+ }
35904
+ async function resolveAgentRef(base, q) {
35905
+ const res = await fetch(
35906
+ `${base}/agents/resolve?q=${encodeURIComponent(q.trim())}`
35907
+ );
35908
+ const json = await res.json().catch(() => ({}));
35909
+ if (!(res.ok && json.address)) {
35910
+ throw new Error(json.error ?? FALLBACK_MISS);
35911
+ }
35912
+ return { address: json.address, numericId: json.numericId, name: json.name };
35913
+ }
35914
+ async function expandAgentRefs(base, requirements) {
35915
+ const fields = agentRefFields(requirements);
35916
+ if (fields.length === 0) {
35917
+ return requirements;
35918
+ }
35919
+ const out = { ...requirements };
35920
+ for (const [key, raw] of fields) {
35921
+ try {
35922
+ out[key] = (await resolveAgentRef(base, raw)).address;
35923
+ } catch (e) {
35924
+ throw new Error(
35925
+ `${key}: ${e instanceof Error ? e.message : FALLBACK_MISS}`
35926
+ );
35927
+ }
35928
+ }
35929
+ return out;
35930
+ }
35931
+
35932
+ // src/commands/job.ts
35933
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
35577
35934
  import { readFile as readFile4 } from "fs/promises";
35578
35935
 
35579
35936
  // src/commands/open.ts
35580
- var import_picocolors12 = __toESM(require_picocolors(), 1);
35581
35937
  import { readFile as readFile3 } from "fs/promises";
35938
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
35582
35939
  var DEFAULT_API_BASE6 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
35583
35940
  var MAX_BRIEF_BYTES = 16 * 1024;
35584
35941
  async function resolveBrief(input) {
@@ -35626,6 +35983,7 @@ function registerOpenVerbs(group) {
35626
35983
  throw new Error(`--max must be between 0.01 and ${MAX_JOB_USDC} USDC.`);
35627
35984
  }
35628
35985
  const brief = await resolveBrief(opts.brief);
35986
+ assertSpendAllowed(maxUsdc);
35629
35987
  const agent = await withAgent({ keyPath: opts.key });
35630
35988
  const digest = await postOpenJob(base, agent.signer, {
35631
35989
  title: opts.title.trim(),
@@ -35634,6 +35992,7 @@ function registerOpenVerbs(group) {
35634
35992
  slaMinutes: Math.round(parseDuration(opts.sla) / 6e4),
35635
35993
  openHours: parseDuration(opts.openFor) / 36e5
35636
35994
  });
35995
+ recordSpendIfLanded(maxUsdc, digest);
35637
35996
  const openingId = await resolveCreated(digest, "::opening::Opening<");
35638
35997
  if (isJsonMode()) {
35639
35998
  printJson({ digest, openingId });
@@ -35848,13 +36207,22 @@ function printInboxRow(job) {
35848
36207
  async function sponsoredJobVerb(opts) {
35849
36208
  const agent = await withAgent({ keyPath: opts.keyPath });
35850
36209
  const address = agent.address();
36210
+ if (opts.spendUsdc !== void 0) {
36211
+ assertSpendAllowed(opts.spendUsdc, opts.force);
36212
+ }
35851
36213
  const { digest } = await runSponsoredTx({
35852
36214
  keypair: agent.keypair,
35853
36215
  actor: address,
35854
36216
  prepareUrl: `${opts.base}/job/prepare`,
35855
36217
  prepareBody: { address, action: opts.action, params: opts.params },
35856
- submitUrl: `${opts.base}/job/submit`
36218
+ submitUrl: `${opts.base}/job/submit`,
36219
+ intent: {
36220
+ action: opts.action,
36221
+ amountUsdc: opts.spendUsdc,
36222
+ seller: opts.seller
36223
+ }
35857
36224
  });
36225
+ recordSpendIfLanded(opts.spendUsdc ?? 0, digest);
35858
36226
  return { address, digest };
35859
36227
  }
35860
36228
  function registerJob(program3) {
@@ -35890,7 +36258,10 @@ no fund step; unclaimed openings refund fee-free):
35890
36258
  ASP $ t2 job board \xB7 t2 job claim <openingId>
35891
36259
  `
35892
36260
  );
35893
- group.command("hire").alias("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when hiring a --service listing)`).argument("[seller]", "The ASP's Sui address (omit when hiring a --service listing)").description("Hire \u2014 fund an escrow job in one transaction (buyer): a listing (--agent + --service) or your own terms (amount + seller + --spec)").option("--spec <file-or-text>", "Job spec \u2014 a file path or inline text (UPLOADED so the seller can read it; sha256 pinned on-chain), or a bare 0x\u2026 sha256 (confidential: pins without uploading)").option("--agent <address>", "Hire a listing: the ASP's agent address").option("--service <slug>", "The service slug (see t2 services / t2 service list <agent>)").option("--requirements <file-or-json-or-text>", "What the seller asked buyers to provide \u2014 if the listing lists JSON keys, fill EVERY key (JSON object; extra keys OK)").option("--deadline <duration>", "Time the seller has to deliver (e.g. 30m, 24h, 7d)", "24h").option("--review <duration>", "Your accept/reject window after delivery", "24h").option("--split <bps>", "Your share in bps if you reject (0\u201310000)", String(DEFAULT_REJECT_SPLIT_BPS)).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE7})`).action(
36261
+ group.command("hire").alias("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when hiring a --service listing)`).argument("[seller]", "The ASP's Sui address (omit when hiring a --service listing)").description("Hire \u2014 fund an escrow job in one transaction (buyer): a listing (--agent + --service) or your own terms (amount + seller + --spec)").option("--spec <file-or-text>", "Job spec \u2014 a file path or inline text (UPLOADED so the seller can read it; sha256 pinned on-chain), or a bare 0x\u2026 sha256 (confidential: pins without uploading)").option(
36262
+ "--agent <address|#id|@handle>",
36263
+ "Hire a listing: the ASP's agent address, #id, or @handle"
36264
+ ).option("--service <slug>", "The service slug (see t2 services / t2 service list <agent>)").option("--requirements <file-or-json-or-text>", "What the seller asked buyers to provide \u2014 if the listing lists JSON keys, fill EVERY key (JSON object; extra keys OK)").option("--deadline <duration>", "Time the seller has to deliver (e.g. 30m, 24h, 7d)", "24h").option("--review <duration>", "Your accept/reject window after delivery", "24h").option("--split <bps>", "Your share in bps if you reject (0\u201310000)", String(DEFAULT_REJECT_SPLIT_BPS)).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE7})`).action(
35894
36265
  async (amountArg, sellerArg, opts) => {
35895
36266
  try {
35896
36267
  const base = opts.api ?? DEFAULT_API_BASE7;
@@ -35911,7 +36282,9 @@ no fund step; unclaimed openings refund fee-free):
35911
36282
  "Omit the amount/seller arguments when buying a service \u2014 the listing sets the price and the seller."
35912
36283
  );
35913
36284
  }
35914
- const sellerAgent = validateAddress(opts.agent);
36285
+ const sellerAgent = validateAddress(
36286
+ (await resolveAgentRef(base, opts.agent)).address
36287
+ );
35915
36288
  const service = await fetchService(base, sellerAgent, serviceSlugOpt);
35916
36289
  serviceSlug = service.slug;
35917
36290
  let requirements = null;
@@ -35927,6 +36300,7 @@ no fund step; unclaimed openings refund fee-free):
35927
36300
  requirements = text.trim();
35928
36301
  }
35929
36302
  }
36303
+ requirements = await expandAgentRefs(base, requirements);
35930
36304
  assertBuyerRequirements(service.requirements, requirements);
35931
36305
  const buyer = (await withAgent({ keyPath: opts.key })).address();
35932
36306
  const spec = JSON.stringify({
@@ -35961,7 +36335,9 @@ no fund step; unclaimed openings refund fee-free):
35961
36335
  if (!Number.isFinite(amountUsdc) || amountUsdc <= 0) {
35962
36336
  throw new Error(`Amount must be a positive number (got "${amountArg}").`);
35963
36337
  }
35964
- seller = validateAddress(sellerArg);
36338
+ seller = validateAddress(
36339
+ (await resolveAgentRef(base, sellerArg)).address
36340
+ );
35965
36341
  ({ hash: specHash } = await resolveSpecUpload(base, opts.spec));
35966
36342
  deliverByMs = Date.now() + parseDuration(opts.deadline);
35967
36343
  reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
@@ -35971,7 +36347,10 @@ no fund step; unclaimed openings refund fee-free):
35971
36347
  base,
35972
36348
  keyPath: opts.key,
35973
36349
  action: "create",
35974
- params: { seller, amountUsdc, specHash, deliverByMs, reviewWindowMs, rejectSplitBps }
36350
+ params: { seller, amountUsdc, specHash, deliverByMs, reviewWindowMs, rejectSplitBps },
36351
+ // The buyer's USDC leaves here — the one job verb that spends.
36352
+ spendUsdc: amountUsdc,
36353
+ seller
35975
36354
  });
35976
36355
  const client = getSuiClient();
35977
36356
  let jobId;
@@ -36544,9 +36923,24 @@ var require3 = createRequire2(import.meta.url);
36544
36923
  var { version: CLI_VERSION2 } = require3("../package.json");
36545
36924
  function createProgram() {
36546
36925
  const program3 = new Command();
36547
- 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) => {
36926
+ program3.name("t2").description("Agent Wallet \u2014 autonomous Sui USDC + USDsui wallet for AI agents").version(`${CLI_VERSION2}`).option("--json", "Output in JSON format").option(
36927
+ "--allow-untrusted-api",
36928
+ `Permit signing transactions built by a non-default API host (${CANONICAL_API_ORIGIN} is the only trusted host). Only for local/staging work \u2014 a host you did not choose can propose any transaction.`
36929
+ ).hook("preAction", (thisCommand) => {
36548
36930
  const opts = thisCommand.optsWithGlobals();
36549
36931
  if (opts.json) setJsonMode(true);
36932
+ setAllowUntrustedApi(Boolean(opts.allowUntrustedApi));
36933
+ installSponsoredTxGuard();
36934
+ if (process.env.T2000_API_URL) {
36935
+ try {
36936
+ assertSigningHostAllowed(
36937
+ process.env.T2000_API_URL,
36938
+ Boolean(opts.allowUntrustedApi)
36939
+ );
36940
+ } catch (e) {
36941
+ handleError(e);
36942
+ }
36943
+ }
36550
36944
  }).addHelpText("after", `
36551
36945
  Setup:
36552
36946
  $ t2 init Create a new Agent Wallet