@t2000/cli 10.25.0 → 10.26.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
@@ -28618,11 +28618,65 @@ function preflightPay(input) {
28618
28618
  }
28619
28619
  return PREFLIGHT_OK;
28620
28620
  }
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 });
28621
+ async function probeX402(args) {
28622
+ const { network } = args;
28623
+ const pf = preflightPay({ url: args.options.url, maxPrice: args.options.maxPrice });
28625
28624
  if (!pf.valid) throw new T2000Error(pf.code, pf.error);
28625
+ const { reqInit } = normalizePayRequest(args.options);
28626
+ const probe = await fetch(args.options.url, reqInit);
28627
+ if (probe.status !== 402) {
28628
+ return {
28629
+ kind: "free",
28630
+ status: probe.status,
28631
+ note: "No payment required \u2014 this endpoint served without a 402."
28632
+ };
28633
+ }
28634
+ const pick = await pickSuiExactRequirements(probe, network);
28635
+ if (pick.kind === "payable") {
28636
+ const requirements = pick.requirements;
28637
+ const priceUsdc = atomicToHuman(
28638
+ BigInt(requirements.maxAmountRequired),
28639
+ await assetDecimals(requirements.asset)
28640
+ );
28641
+ const { isX402EscrowRequirements } = await import("./dist-VUHPQJYY.js");
28642
+ if (isX402EscrowRequirements(requirements)) {
28643
+ return {
28644
+ kind: "escrow",
28645
+ priceUsdc,
28646
+ payTo: requirements.payTo,
28647
+ 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."
28648
+ };
28649
+ }
28650
+ return {
28651
+ kind: "payable",
28652
+ priceUsdc,
28653
+ asset: requirements.asset,
28654
+ payTo: requirements.payTo,
28655
+ network
28656
+ };
28657
+ }
28658
+ if (hasPaymentAuthenticateHeader(probe)) {
28659
+ return {
28660
+ kind: "unsupported",
28661
+ reason: "header-only-402-unsupported",
28662
+ 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)."
28663
+ };
28664
+ }
28665
+ if (pick.kind === "incomplete") {
28666
+ return {
28667
+ kind: "incomplete",
28668
+ reason: "incomplete-x402-accepts",
28669
+ 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."
28670
+ };
28671
+ }
28672
+ return {
28673
+ kind: "not-x402",
28674
+ status: probe.status,
28675
+ note: `Endpoint returned 402 without an x402 'exact' / sui:${network} requirement in the body. Nothing this SDK can pay.`
28676
+ };
28677
+ }
28678
+ function normalizePayRequest(input) {
28679
+ let options = input;
28626
28680
  const method = (options.method ?? "GET").toUpperCase();
28627
28681
  const canHaveBody = method !== "GET" && method !== "HEAD";
28628
28682
  if (canHaveBody && typeof options.body === "string" && isJsonText(options.body) && !hasContentType(options.headers)) {
@@ -28631,11 +28685,23 @@ async function payWithX402(args) {
28631
28685
  headers: { ...options.headers ?? {}, "content-type": "application/json" }
28632
28686
  };
28633
28687
  }
28634
- const reqInit = {
28635
- method,
28636
- headers: options.headers,
28637
- body: canHaveBody ? options.body : void 0
28688
+ return {
28689
+ options,
28690
+ reqInit: {
28691
+ method,
28692
+ headers: options.headers,
28693
+ body: canHaveBody ? options.body : void 0
28694
+ }
28638
28695
  };
28696
+ }
28697
+ async function payWithX402(args) {
28698
+ const { signer, client } = args;
28699
+ let options = args.options;
28700
+ const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });
28701
+ if (!pf.valid) throw new T2000Error(pf.code, pf.error);
28702
+ const normalized = normalizePayRequest(options);
28703
+ options = normalized.options;
28704
+ const reqInit = normalized.reqInit;
28639
28705
  const probe = await fetch(options.url, reqInit);
28640
28706
  if (probe.status !== 402) {
28641
28707
  return finalize(probe, { paid: false });
@@ -29311,10 +29377,19 @@ var RESOLVE_NAME_QUERY = `query ResolveSuins($name: String!) {
29311
29377
  }`;
29312
29378
  var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
29313
29379
  var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
29380
+ var AUDRIC_HANDLE_RE = /^([a-z0-9-]+)@audric$/i;
29381
+ function canonicalizeRecipientInput(raw) {
29382
+ const trimmed = raw.trim();
29383
+ const m = AUDRIC_HANDLE_RE.exec(trimmed);
29384
+ if (m) {
29385
+ return `${m[1].toLowerCase()}.audric.sui`;
29386
+ }
29387
+ return trimmed;
29388
+ }
29314
29389
  var InvalidAddressError = class extends Error {
29315
29390
  constructor(raw) {
29316
29391
  super(
29317
- `"${raw}" isn't a valid Sui address or SuiNS name. Pass a 0x-prefixed hex address (e.g. 0x40cd\u20263e62) or a SuiNS name ending in .sui (e.g. alex.sui).`
29392
+ `"${raw}" isn't a valid Sui address or SuiNS name. Pass a 0x-prefixed hex address (e.g. 0x40cd\u20263e62), a SuiNS name ending in .sui (e.g. alex.sui), or a Passport handle (e.g. alex@audric).`
29318
29393
  );
29319
29394
  this.raw = raw;
29320
29395
  this.name = "InvalidAddressError";
@@ -29338,10 +29413,10 @@ var SuinsRpcError = class extends Error {
29338
29413
  };
29339
29414
  function looksLikeSuiNs(value) {
29340
29415
  if (!value) return false;
29341
- return SUINS_NAME_REGEX.test(value.trim().toLowerCase());
29416
+ return SUINS_NAME_REGEX.test(canonicalizeRecipientInput(value).toLowerCase());
29342
29417
  }
29343
29418
  async function resolveSuinsViaRpc(rawName, ctx = {}) {
29344
- const name = rawName.trim().toLowerCase();
29419
+ const name = canonicalizeRecipientInput(rawName).toLowerCase();
29345
29420
  if (!SUINS_NAME_REGEX.test(name)) {
29346
29421
  throw new InvalidAddressError(rawName);
29347
29422
  }
@@ -30113,6 +30188,15 @@ var T2000 = class _T2000 extends import_index2.default {
30113
30188
  return this._signer;
30114
30189
  }
30115
30190
  // -- MPP Payments --
30191
+ /**
30192
+ * READ-ONLY price probe for an x402 endpoint (S.919). Reports what `pay()`
30193
+ * would cost without signing or spending, so a caller (Connect's
30194
+ * `t2000_pay_probe`, the CLI, a UI) can show terms before committing.
30195
+ * No limit gate: nothing moves.
30196
+ */
30197
+ async payProbe(options) {
30198
+ return await probeX402({ network: this.client.network, options });
30199
+ }
30116
30200
  async pay(options) {
30117
30201
  this.limits.assert({ operation: "pay", amountUsd: options.maxPrice ?? 0, force: options.force });
30118
30202
  const result = await payWithX402({ signer: this._signer, client: this.client, options });
@@ -30403,7 +30487,7 @@ var T2000 = class _T2000 extends import_index2.default {
30403
30487
  * with the live execute path (never resolve the same input two ways).
30404
30488
  */
30405
30489
  async resolveRecipient(input) {
30406
- const trimmed = input.trim();
30490
+ const trimmed = canonicalizeRecipientInput(input);
30407
30491
  if (SUI_ADDRESS_REGEX.test(trimmed)) {
30408
30492
  return { address: trimmed.toLowerCase() };
30409
30493
  }
@@ -30427,7 +30511,7 @@ var T2000 = class _T2000 extends import_index2.default {
30427
30511
  }
30428
30512
  throw new T2000Error(
30429
30513
  "INVALID_ADDRESS",
30430
- `Cannot resolve recipient "${input}". Provide a 0x address or a .sui name.`
30514
+ `Cannot resolve recipient "${input}". Provide a 0x address, a .sui name, or a Passport handle (name@audric).`
30431
30515
  );
30432
30516
  }
30433
30517
  async balance() {