@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 +97 -13
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -28618,11 +28618,65 @@ function preflightPay(input) {
|
|
|
28618
28618
|
}
|
|
28619
28619
|
return PREFLIGHT_OK;
|
|
28620
28620
|
}
|
|
28621
|
-
async function
|
|
28622
|
-
const {
|
|
28623
|
-
|
|
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
|
-
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
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)
|
|
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
|
|
29416
|
+
return SUINS_NAME_REGEX.test(canonicalizeRecipientInput(value).toLowerCase());
|
|
29342
29417
|
}
|
|
29343
29418
|
async function resolveSuinsViaRpc(rawName, ctx = {}) {
|
|
29344
|
-
const name = rawName
|
|
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
|
|
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
|
|
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() {
|