@t2000/cli 10.26.0 → 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
 
@@ -28638,7 +28564,7 @@ async function probeX402(args) {
28638
28564
  BigInt(requirements.maxAmountRequired),
28639
28565
  await assetDecimals(requirements.asset)
28640
28566
  );
28641
- const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28567
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28642
28568
  if (isX402EscrowRequirements(requirements)) {
28643
28569
  return {
28644
28570
  kind: "escrow",
@@ -28709,7 +28635,7 @@ async function payWithX402(args) {
28709
28635
  const pick = await pickSuiExactRequirements(probe, client.network);
28710
28636
  if (pick.kind === "payable") {
28711
28637
  const requirements = pick.requirements;
28712
- const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28638
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28713
28639
  if (isX402EscrowRequirements(requirements)) {
28714
28640
  const escrow = requirements.extra.escrow;
28715
28641
  const price = atomicToHuman(
@@ -28755,7 +28681,7 @@ async function pickSuiExactRequirements(response, network) {
28755
28681
  const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
28756
28682
  const entry = body2.accepts?.find((a) => a.scheme === "exact" && a.network === want);
28757
28683
  if (!entry) return { kind: "none" };
28758
- const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28684
+ const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28759
28685
  if (hasCompleteSuimppChallenge(entry) || isX402EscrowRequirements(entry)) {
28760
28686
  return { kind: "payable", requirements: entry };
28761
28687
  }
@@ -28773,7 +28699,7 @@ async function payViaX402(args) {
28773
28699
  { reason: "incomplete-x402-accepts" }
28774
28700
  );
28775
28701
  }
28776
- 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");
28777
28703
  const amountRaw = BigInt(requirements.maxAmountRequired);
28778
28704
  assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
28779
28705
  const migrationGasSui = await ensureAddressBalanceCovers({
@@ -28904,7 +28830,7 @@ async function finalize(response, opts) {
28904
28830
  return { status: response.status, body: body2, paid: opts.paid };
28905
28831
  }
28906
28832
  async function makeGrpcBuildClient(client) {
28907
- const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-G3RQE2L5.js");
28833
+ const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-AJNSMQ2Y.js");
28908
28834
  const network = client.network === "testnet" ? "testnet" : "mainnet";
28909
28835
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
28910
28836
  return new SuiGrpcClient3({ baseUrl, network });
@@ -28933,7 +28859,7 @@ var ZkLoginSigner = class {
28933
28859
  return this.userAddress;
28934
28860
  }
28935
28861
  async signTransaction(txBytes) {
28936
- const { getZkLoginSignature } = await import("./esm-ZKAIHFAJ.js");
28862
+ const { getZkLoginSignature } = await import("./esm-JVUVZX3G.js");
28937
28863
  const ephSig = await this.ephemeralKeypair.signTransaction(txBytes);
28938
28864
  return {
28939
28865
  signature: getZkLoginSignature({
@@ -28944,7 +28870,7 @@ var ZkLoginSigner = class {
28944
28870
  };
28945
28871
  }
28946
28872
  async signPersonalMessage(messageBytes) {
28947
- const { getZkLoginSignature } = await import("./esm-ZKAIHFAJ.js");
28873
+ const { getZkLoginSignature } = await import("./esm-JVUVZX3G.js");
28948
28874
  const { signature: ephSig, bytes } = await this.ephemeralKeypair.signPersonalMessage(messageBytes);
28949
28875
  return {
28950
28876
  signature: getZkLoginSignature({
@@ -30609,8 +30535,10 @@ init_coinSelection();
30609
30535
  init_errors();
30610
30536
  init_token_registry();
30611
30537
  init_coinSelection();
30612
- var A2A_ESCROW_OPENING_PACKAGE_ID = process.env.A2A_ESCROW_OPENING_PACKAGE_ID ?? "0x69ad93c555519de520a5c7f7f2963ad6f8b91cefc098fc2eed75942dcb5bcbe7";
30613
- 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;
30614
30542
  var A2A_ESCROW_FEE_CONFIG_ID = process.env.A2A_ESCROW_FEE_CONFIG_ID ?? "0xddaa25570950b7484dbf20797ebcf75707be9c87cd67bef2a06ed2e81d2c494b";
30615
30543
  var A2A_ESCROW_FEE_CONFIG_VERSION = Number(
30616
30544
  process.env.A2A_ESCROW_FEE_CONFIG_VERSION ?? 931861903
@@ -30849,6 +30777,10 @@ async function fetchJson(url, init) {
30849
30777
  }
30850
30778
  return json;
30851
30779
  }
30780
+ var sponsoredTxGuard = null;
30781
+ function setSponsoredTxGuard(guard) {
30782
+ sponsoredTxGuard = guard;
30783
+ }
30852
30784
  async function listOpenJobs(base, filter = {}) {
30853
30785
  const params = new URLSearchParams();
30854
30786
  if (filter.status) params.set("status", filter.status);
@@ -30861,6 +30793,7 @@ async function listOpenJobs(base, filter = {}) {
30861
30793
  }
30862
30794
  async function sponsoredOpeningVerb(base, signer, action, params) {
30863
30795
  const address = signer.getAddress();
30796
+ sponsoredTxGuard?.({ base, action });
30864
30797
  const prep = await fetchJson(`${base}/job/prepare`, {
30865
30798
  method: "POST",
30866
30799
  body: { address, action, params }
@@ -30870,6 +30803,7 @@ async function sponsoredOpeningVerb(base, signer, action, params) {
30870
30803
  if (!(nonce && txBytes)) {
30871
30804
  throw new Error("Failed to prepare the transaction.");
30872
30805
  }
30806
+ sponsoredTxGuard?.({ base, action, txBytes });
30873
30807
  const { signature } = await signer.signTransaction(fromBase64(txBytes));
30874
30808
  const json = await fetchJson(`${base}/job/submit`, {
30875
30809
  method: "POST",
@@ -30920,6 +30854,247 @@ init_cetus_swap();
30920
30854
  init_token_registry();
30921
30855
  init_preflight();
30922
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
+
30923
31098
  // ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@20.19.37/node_modules/@inquirer/core/dist/esm/lib/key.js
30924
31099
  var isUpKey = (key, keybindings = []) => (
30925
31100
  // The up key
@@ -33346,12 +33521,16 @@ async function postJson(url, body2) {
33346
33521
  return json;
33347
33522
  }
33348
33523
  async function runSponsoredTx(opts) {
33524
+ const allowUntrusted = isAllowUntrustedApi();
33525
+ assertSigningHostAllowed(opts.prepareUrl, allowUntrusted);
33349
33526
  const prep = await postJson(opts.prepareUrl, opts.prepareBody);
33350
33527
  const nonce = prep.nonce;
33351
33528
  const txBytes = prep.txBytes;
33352
33529
  if (!(nonce && txBytes)) {
33353
33530
  throw new Error("Failed to prepare the transaction.");
33354
33531
  }
33532
+ assertTxMatchesIntent(txBytes, opts.intent, { allowUntrusted });
33533
+ printLine(describeIntent(opts.intent, opts.prepareUrl));
33355
33534
  const bytes = new Uint8Array(Buffer.from(txBytes, "base64"));
33356
33535
  const { signature } = await opts.keypair.signTransaction(bytes);
33357
33536
  const res = await postJson(opts.submitUrl, {
@@ -33362,6 +33541,8 @@ async function runSponsoredTx(opts) {
33362
33541
  return { digest: res.digest };
33363
33542
  }
33364
33543
  async function registerWallet(opts) {
33544
+ const allowUntrusted = isAllowUntrustedApi();
33545
+ assertSigningHostAllowed(opts.base, allowUntrusted);
33365
33546
  const prep = await postJson(`${opts.base}/agent/register/prepare`, {
33366
33547
  address: opts.address
33367
33548
  });
@@ -33373,6 +33554,7 @@ async function registerWallet(opts) {
33373
33554
  if (!(regNonce && txBytes)) {
33374
33555
  throw new Error("Failed to prepare registration.");
33375
33556
  }
33557
+ assertTxMatchesIntent(txBytes, { action: "register" }, { allowUntrusted });
33376
33558
  const bytes = new Uint8Array(Buffer.from(txBytes, "base64"));
33377
33559
  const { signature } = await opts.keypair.signTransaction(bytes);
33378
33560
  const res = await postJson(`${opts.base}/agent/register/submit`, {
@@ -33475,7 +33657,15 @@ function registerInit(program3) {
33475
33657
  }
33476
33658
 
33477
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
+ }
33478
33667
  async function withAgent(options = {}) {
33668
+ assertEnvApiHostTrusted();
33479
33669
  return T2000.create({
33480
33670
  keyPath: options.keyPath,
33481
33671
  rpcUrl: options.rpcUrl
@@ -33483,6 +33673,7 @@ async function withAgent(options = {}) {
33483
33673
  }
33484
33674
  async function tryWithAgent(options = {}) {
33485
33675
  try {
33676
+ assertEnvApiHostTrusted();
33486
33677
  const agent = await T2000.create({
33487
33678
  keyPath: options.keyPath,
33488
33679
  rpcUrl: options.rpcUrl
@@ -35207,7 +35398,8 @@ function registerAgentCreate(group) {
35207
35398
  actor: address,
35208
35399
  prepareUrl: `${base}/agent/owner/propose`,
35209
35400
  prepareBody: { address, owner },
35210
- submitUrl: `${base}/agent/owner/submit`
35401
+ submitUrl: `${base}/agent/owner/submit`,
35402
+ intent: { action: "link" }
35211
35403
  });
35212
35404
  ownerProposed = true;
35213
35405
  }
@@ -35330,7 +35522,8 @@ Subcommands:
35330
35522
  actor: address,
35331
35523
  prepareUrl: `${base}/agent/owner/propose`,
35332
35524
  prepareBody: { address, owner },
35333
- submitUrl: `${base}/agent/owner/submit`
35525
+ submitUrl: `${base}/agent/owner/submit`,
35526
+ intent: { action: "link" }
35334
35527
  });
35335
35528
  if (isJsonMode()) {
35336
35529
  printJson({ agent: address, pendingOwner: owner, digest });
@@ -35359,7 +35552,8 @@ Subcommands:
35359
35552
  actor: address,
35360
35553
  prepareUrl: `${base}/agent/owner/confirm`,
35361
35554
  prepareBody: { owner: address, agent: agentAddress },
35362
- submitUrl: `${base}/agent/owner/submit`
35555
+ submitUrl: `${base}/agent/owner/submit`,
35556
+ intent: { action: "confirm" }
35363
35557
  });
35364
35558
  if (isJsonMode()) {
35365
35559
  printJson({ owner: address, agent: agentAddress, digest });
@@ -35385,7 +35579,8 @@ Subcommands:
35385
35579
  actor: address,
35386
35580
  prepareUrl: `${base}/agent/owner/renounce`,
35387
35581
  prepareBody: { owner: address, agent: agentAddress },
35388
- submitUrl: `${base}/agent/owner/submit`
35582
+ submitUrl: `${base}/agent/owner/submit`,
35583
+ intent: { action: "confirm" }
35389
35584
  });
35390
35585
  if (isJsonMode()) {
35391
35586
  printJson({ owner: address, agent: agentAddress, unlinked: true, digest });
@@ -35481,6 +35676,7 @@ Subcommands:
35481
35676
  if (!opts.remove) {
35482
35677
  await ensureSellerCategory({ base, agent, category });
35483
35678
  }
35679
+ assertSigningHostAllowed(base, isAllowUntrustedApi());
35484
35680
  const prepRes = await fetch(`${base}/agent/endpoint/prepare`, {
35485
35681
  method: "POST",
35486
35682
  headers: { "Content-Type": "application/json" },
@@ -35647,13 +35843,99 @@ function registerAgents(program3) {
35647
35843
  }
35648
35844
 
35649
35845
  // src/commands/job.ts
35650
- var import_picocolors13 = __toESM(require_picocolors(), 1);
35651
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);
35652
35934
  import { readFile as readFile4 } from "fs/promises";
35653
35935
 
35654
35936
  // src/commands/open.ts
35655
- var import_picocolors12 = __toESM(require_picocolors(), 1);
35656
35937
  import { readFile as readFile3 } from "fs/promises";
35938
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
35657
35939
  var DEFAULT_API_BASE6 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
35658
35940
  var MAX_BRIEF_BYTES = 16 * 1024;
35659
35941
  async function resolveBrief(input) {
@@ -35701,6 +35983,7 @@ function registerOpenVerbs(group) {
35701
35983
  throw new Error(`--max must be between 0.01 and ${MAX_JOB_USDC} USDC.`);
35702
35984
  }
35703
35985
  const brief = await resolveBrief(opts.brief);
35986
+ assertSpendAllowed(maxUsdc);
35704
35987
  const agent = await withAgent({ keyPath: opts.key });
35705
35988
  const digest = await postOpenJob(base, agent.signer, {
35706
35989
  title: opts.title.trim(),
@@ -35709,6 +35992,7 @@ function registerOpenVerbs(group) {
35709
35992
  slaMinutes: Math.round(parseDuration(opts.sla) / 6e4),
35710
35993
  openHours: parseDuration(opts.openFor) / 36e5
35711
35994
  });
35995
+ recordSpendIfLanded(maxUsdc, digest);
35712
35996
  const openingId = await resolveCreated(digest, "::opening::Opening<");
35713
35997
  if (isJsonMode()) {
35714
35998
  printJson({ digest, openingId });
@@ -35923,13 +36207,22 @@ function printInboxRow(job) {
35923
36207
  async function sponsoredJobVerb(opts) {
35924
36208
  const agent = await withAgent({ keyPath: opts.keyPath });
35925
36209
  const address = agent.address();
36210
+ if (opts.spendUsdc !== void 0) {
36211
+ assertSpendAllowed(opts.spendUsdc, opts.force);
36212
+ }
35926
36213
  const { digest } = await runSponsoredTx({
35927
36214
  keypair: agent.keypair,
35928
36215
  actor: address,
35929
36216
  prepareUrl: `${opts.base}/job/prepare`,
35930
36217
  prepareBody: { address, action: opts.action, params: opts.params },
35931
- 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
+ }
35932
36224
  });
36225
+ recordSpendIfLanded(opts.spendUsdc ?? 0, digest);
35933
36226
  return { address, digest };
35934
36227
  }
35935
36228
  function registerJob(program3) {
@@ -35965,7 +36258,10 @@ no fund step; unclaimed openings refund fee-free):
35965
36258
  ASP $ t2 job board \xB7 t2 job claim <openingId>
35966
36259
  `
35967
36260
  );
35968
- 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(
35969
36265
  async (amountArg, sellerArg, opts) => {
35970
36266
  try {
35971
36267
  const base = opts.api ?? DEFAULT_API_BASE7;
@@ -35986,7 +36282,9 @@ no fund step; unclaimed openings refund fee-free):
35986
36282
  "Omit the amount/seller arguments when buying a service \u2014 the listing sets the price and the seller."
35987
36283
  );
35988
36284
  }
35989
- const sellerAgent = validateAddress(opts.agent);
36285
+ const sellerAgent = validateAddress(
36286
+ (await resolveAgentRef(base, opts.agent)).address
36287
+ );
35990
36288
  const service = await fetchService(base, sellerAgent, serviceSlugOpt);
35991
36289
  serviceSlug = service.slug;
35992
36290
  let requirements = null;
@@ -36002,6 +36300,7 @@ no fund step; unclaimed openings refund fee-free):
36002
36300
  requirements = text.trim();
36003
36301
  }
36004
36302
  }
36303
+ requirements = await expandAgentRefs(base, requirements);
36005
36304
  assertBuyerRequirements(service.requirements, requirements);
36006
36305
  const buyer = (await withAgent({ keyPath: opts.key })).address();
36007
36306
  const spec = JSON.stringify({
@@ -36036,7 +36335,9 @@ no fund step; unclaimed openings refund fee-free):
36036
36335
  if (!Number.isFinite(amountUsdc) || amountUsdc <= 0) {
36037
36336
  throw new Error(`Amount must be a positive number (got "${amountArg}").`);
36038
36337
  }
36039
- seller = validateAddress(sellerArg);
36338
+ seller = validateAddress(
36339
+ (await resolveAgentRef(base, sellerArg)).address
36340
+ );
36040
36341
  ({ hash: specHash } = await resolveSpecUpload(base, opts.spec));
36041
36342
  deliverByMs = Date.now() + parseDuration(opts.deadline);
36042
36343
  reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
@@ -36046,7 +36347,10 @@ no fund step; unclaimed openings refund fee-free):
36046
36347
  base,
36047
36348
  keyPath: opts.key,
36048
36349
  action: "create",
36049
- 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
36050
36354
  });
36051
36355
  const client = getSuiClient();
36052
36356
  let jobId;
@@ -36619,9 +36923,24 @@ var require3 = createRequire2(import.meta.url);
36619
36923
  var { version: CLI_VERSION2 } = require3("../package.json");
36620
36924
  function createProgram() {
36621
36925
  const program3 = new Command();
36622
- 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) => {
36623
36930
  const opts = thisCommand.optsWithGlobals();
36624
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
+ }
36625
36944
  }).addHelpText("after", `
36626
36945
  Setup:
36627
36946
  $ t2 init Create a new Agent Wallet