uvd-x402-sdk 2.78.0 → 2.80.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/README.md +107 -0
- package/dist/backend/index.d.mts +179 -21
- package/dist/backend/index.d.ts +179 -21
- package/dist/backend/index.js +133 -31
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs +131 -32
- package/dist/backend/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +102 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/backend/facilitator-error.ts +201 -11
- package/src/backend/index.ts +201 -44
- package/src/index.ts +6 -0
package/dist/index.mjs
CHANGED
|
@@ -3762,6 +3762,7 @@ var REPLAYABLE_LEASE_REASONS = [
|
|
|
3762
3762
|
"body_unreadable"
|
|
3763
3763
|
];
|
|
3764
3764
|
var AMBIGUOUS_LEASE_REASONS = ["forward_failed"];
|
|
3765
|
+
var SETTLEMENT_UNCONFIRMED = "settlement_unconfirmed";
|
|
3765
3766
|
var MAX_RETRY_AFTER_SECONDS = 15;
|
|
3766
3767
|
var DEFAULT_RETRY_AFTER_SECONDS = 5;
|
|
3767
3768
|
var DEFAULT_FACILITATOR_RETRIES = 2;
|
|
@@ -3783,15 +3784,44 @@ function parseRetryAfterSeconds(response) {
|
|
|
3783
3784
|
if (!Number.isFinite(seconds) || seconds < 0) return void 0;
|
|
3784
3785
|
return Math.min(seconds, MAX_RETRY_AFTER_SECONDS);
|
|
3785
3786
|
}
|
|
3786
|
-
function
|
|
3787
|
+
function stringField(source, key) {
|
|
3788
|
+
const value = source[key];
|
|
3789
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
3790
|
+
}
|
|
3791
|
+
function transactionHashIn(source) {
|
|
3792
|
+
const tx = source.transaction;
|
|
3793
|
+
if (tx && typeof tx === "object") {
|
|
3794
|
+
const hash = tx.hash;
|
|
3795
|
+
if (typeof hash === "string" && hash !== "") return hash;
|
|
3796
|
+
}
|
|
3797
|
+
if (typeof tx === "string" && tx !== "") return tx;
|
|
3798
|
+
for (const key of ["txHash", "tx_hash", "transaction_hash"]) {
|
|
3799
|
+
const value = stringField(source, key);
|
|
3800
|
+
if (value !== void 0) return value;
|
|
3801
|
+
}
|
|
3802
|
+
return void 0;
|
|
3803
|
+
}
|
|
3804
|
+
function parseFacilitatorErrorBody(body) {
|
|
3805
|
+
let parsed;
|
|
3787
3806
|
try {
|
|
3788
|
-
|
|
3789
|
-
if (parsed && typeof parsed === "object" && typeof parsed.reason === "string") {
|
|
3790
|
-
return parsed.reason;
|
|
3791
|
-
}
|
|
3807
|
+
parsed = JSON.parse(body);
|
|
3792
3808
|
} catch {
|
|
3809
|
+
return {};
|
|
3793
3810
|
}
|
|
3794
|
-
return
|
|
3811
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
3812
|
+
return {
|
|
3813
|
+
errorCode: stringField(parsed, "error"),
|
|
3814
|
+
reason: stringField(parsed, "reason"),
|
|
3815
|
+
transaction: transactionHashIn(parsed),
|
|
3816
|
+
paymentId: stringField(parsed, "paymentId"),
|
|
3817
|
+
retryable: typeof parsed.retryable === "boolean" ? parsed.retryable : void 0
|
|
3818
|
+
};
|
|
3819
|
+
}
|
|
3820
|
+
function isDeclaredUnretryable(parsed) {
|
|
3821
|
+
return parsed.retryable === false || parsed.errorCode === SETTLEMENT_UNCONFIRMED || parsed.transaction !== void 0;
|
|
3822
|
+
}
|
|
3823
|
+
function isSettlementUnconfirmed(failure) {
|
|
3824
|
+
return failure.errorCode === SETTLEMENT_UNCONFIRMED;
|
|
3795
3825
|
}
|
|
3796
3826
|
async function readFacilitatorError(response) {
|
|
3797
3827
|
let body = "";
|
|
@@ -3801,14 +3831,19 @@ async function readFacilitatorError(response) {
|
|
|
3801
3831
|
body = "";
|
|
3802
3832
|
}
|
|
3803
3833
|
const status = response.status;
|
|
3804
|
-
const
|
|
3805
|
-
const
|
|
3834
|
+
const parsed = parseFacilitatorErrorBody(body);
|
|
3835
|
+
const reason = parsed.reason;
|
|
3836
|
+
const transportRetryable = status === 429 || status === 502 || status === 503 || status === 504;
|
|
3837
|
+
const retryable = transportRetryable && !isDeclaredUnretryable(parsed);
|
|
3806
3838
|
const retryAfterSeconds = retryable ? parseRetryAfterSeconds(response) ?? DEFAULT_RETRY_AFTER_SECONDS : void 0;
|
|
3807
|
-
const safeToReplay = status === 429 || status === 503 && isReplayableLeaseReason(reason);
|
|
3839
|
+
const safeToReplay = retryable && (status === 429 || status === 503 && isReplayableLeaseReason(reason));
|
|
3808
3840
|
return {
|
|
3809
3841
|
error: `Facilitator error: ${status} - ${body}`,
|
|
3810
3842
|
status,
|
|
3811
3843
|
reason,
|
|
3844
|
+
errorCode: parsed.errorCode,
|
|
3845
|
+
transaction: parsed.transaction,
|
|
3846
|
+
paymentId: parsed.paymentId,
|
|
3812
3847
|
retryAfterSeconds,
|
|
3813
3848
|
retryable,
|
|
3814
3849
|
safeToReplay,
|
|
@@ -3821,6 +3856,11 @@ function failureFields(info) {
|
|
|
3821
3856
|
retryable: info.retryable,
|
|
3822
3857
|
safeToReplay: info.safeToReplay,
|
|
3823
3858
|
...info.reason !== void 0 ? { reason: info.reason } : {},
|
|
3859
|
+
...info.errorCode !== void 0 ? { errorCode: info.errorCode } : {},
|
|
3860
|
+
// Without these the caller is told "do not retry" and given nothing to do
|
|
3861
|
+
// instead — an error that swallows the hash is the same defect one layer up.
|
|
3862
|
+
...info.transaction !== void 0 ? { transaction: info.transaction } : {},
|
|
3863
|
+
...info.paymentId !== void 0 ? { paymentId: info.paymentId } : {},
|
|
3824
3864
|
...info.retryAfterSeconds !== void 0 ? { retryAfterSeconds: info.retryAfterSeconds } : {}
|
|
3825
3865
|
};
|
|
3826
3866
|
}
|
|
@@ -3828,6 +3868,9 @@ function carryFailureFields(source) {
|
|
|
3828
3868
|
return {
|
|
3829
3869
|
...source.status !== void 0 ? { status: source.status } : {},
|
|
3830
3870
|
...source.reason !== void 0 ? { reason: source.reason } : {},
|
|
3871
|
+
...source.errorCode !== void 0 ? { errorCode: source.errorCode } : {},
|
|
3872
|
+
...source.transaction !== void 0 ? { transaction: source.transaction } : {},
|
|
3873
|
+
...source.paymentId !== void 0 ? { paymentId: source.paymentId } : {},
|
|
3831
3874
|
...source.retryable !== void 0 ? { retryable: source.retryable } : {},
|
|
3832
3875
|
...source.retryAfterSeconds !== void 0 ? { retryAfterSeconds: source.retryAfterSeconds } : {},
|
|
3833
3876
|
...source.safeToReplay !== void 0 ? { safeToReplay: source.safeToReplay } : {}
|
|
@@ -3915,7 +3958,23 @@ function buildPaymentRequirements(options) {
|
|
|
3915
3958
|
}
|
|
3916
3959
|
function buildVerifyRequest(paymentHeader, requirements) {
|
|
3917
3960
|
return {
|
|
3918
|
-
|
|
3961
|
+
// The literal `1` names THIS ENVELOPE, not the payer's header. Echoing
|
|
3962
|
+
// `paymentHeader.x402Version` here -- what this did until 2026-09-04 --
|
|
3963
|
+
// let a buyer who declared `2` produce a body that says "2" while carrying
|
|
3964
|
+
// `paymentRequirements`, which is the v1 shape. The facilitator serves it
|
|
3965
|
+
// anyway because its envelope enum is untagged and matches on shape, so
|
|
3966
|
+
// nothing broke; but it ALREADY picks the hint in its 400 off this marker:
|
|
3967
|
+
//
|
|
3968
|
+
// "This body declares `x402Version: 2`. x402 v2 is a JSON object with
|
|
3969
|
+
// `paymentPayload`, `resource` and `accepted`..."
|
|
3970
|
+
//
|
|
3971
|
+
// So the day that body fails for any other reason, the diagnosis sends the
|
|
3972
|
+
// integrator to document the wrong shape. That inversion -- being told to
|
|
3973
|
+
// fix the fields when the wrapper is what is wrong -- is what cost two
|
|
3974
|
+
// teams a day. The payer's own marker survives untouched inside
|
|
3975
|
+
// `paymentPayload`, where it belongs: it describes the payment, not the
|
|
3976
|
+
// envelope carrying it.
|
|
3977
|
+
x402Version: 1,
|
|
3919
3978
|
paymentPayload: paymentHeader,
|
|
3920
3979
|
paymentRequirements: requirements
|
|
3921
3980
|
};
|
|
@@ -3938,13 +3997,21 @@ function buildSettleRequestV2(payload, resource, accepted) {
|
|
|
3938
3997
|
}
|
|
3939
3998
|
function buildSettleRequest(paymentHeader, requirements) {
|
|
3940
3999
|
return {
|
|
3941
|
-
|
|
4000
|
+
// `1` for the same reason as {@link buildVerifyRequest}: it names the
|
|
4001
|
+
// envelope, and `/settle` takes the same body as `/verify`.
|
|
4002
|
+
x402Version: 1,
|
|
3942
4003
|
paymentPayload: paymentHeader,
|
|
3943
4004
|
paymentRequirements: requirements
|
|
3944
4005
|
};
|
|
3945
4006
|
}
|
|
3946
4007
|
function isCaip2Network(network) {
|
|
3947
|
-
return network.includes(":");
|
|
4008
|
+
return typeof network === "string" && network.includes(":");
|
|
4009
|
+
}
|
|
4010
|
+
function networkOfPayload(payload) {
|
|
4011
|
+
const top = payload.network;
|
|
4012
|
+
if (typeof top === "string") return top;
|
|
4013
|
+
const accepted = payload.accepted;
|
|
4014
|
+
return typeof accepted?.network === "string" ? accepted.network : void 0;
|
|
3948
4015
|
}
|
|
3949
4016
|
function toResourceInfoV2(requirements) {
|
|
3950
4017
|
return {
|
|
@@ -3954,9 +4021,15 @@ function toResourceInfoV2(requirements) {
|
|
|
3954
4021
|
};
|
|
3955
4022
|
}
|
|
3956
4023
|
function toPaymentRequirementsV2(requirements) {
|
|
4024
|
+
const network = isCaip2Network(requirements.network) ? requirements.network : chainToCAIP2(requirements.network);
|
|
4025
|
+
if (!isCaip2Network(network)) {
|
|
4026
|
+
throw new Error(
|
|
4027
|
+
`Network '${requirements.network}' has no CAIP-2 form, so it cannot travel in the x402 v2 envelope. Use x402Version: 1 for this network.`
|
|
4028
|
+
);
|
|
4029
|
+
}
|
|
3957
4030
|
return {
|
|
3958
4031
|
scheme: requirements.scheme,
|
|
3959
|
-
network
|
|
4032
|
+
network,
|
|
3960
4033
|
asset: requirements.asset,
|
|
3961
4034
|
amount: requirements.maxAmountRequired,
|
|
3962
4035
|
payTo: requirements.payTo,
|
|
@@ -3969,7 +4042,7 @@ function resolveEnvelopeVersion(paymentHeader, requirements, requested = "auto")
|
|
|
3969
4042
|
if (requested !== "auto") {
|
|
3970
4043
|
return requested;
|
|
3971
4044
|
}
|
|
3972
|
-
return isCaip2Network(paymentHeader
|
|
4045
|
+
return isCaip2Network(networkOfPayload(paymentHeader)) || isCaip2Network(requirements.network) ? 2 : 1;
|
|
3973
4046
|
}
|
|
3974
4047
|
function buildVerifyRequestForVersion(paymentHeader, requirements, version) {
|
|
3975
4048
|
if (version === 2) {
|
|
@@ -4642,16 +4715,23 @@ function createPaymentMiddleware(getRequirements, options = {}) {
|
|
|
4642
4715
|
respondUnavailable(res, "Payment settlement unavailable", settleResult);
|
|
4643
4716
|
return;
|
|
4644
4717
|
}
|
|
4645
|
-
res.status(500).json(
|
|
4646
|
-
error: "Payment settlement failed",
|
|
4647
|
-
reason: settleResult.error || "Unknown settlement error"
|
|
4648
|
-
});
|
|
4718
|
+
res.status(500).json(settlementFailureBody(settleResult, "Unknown settlement error"));
|
|
4649
4719
|
return;
|
|
4650
4720
|
}
|
|
4651
4721
|
}
|
|
4652
4722
|
next();
|
|
4653
4723
|
};
|
|
4654
4724
|
}
|
|
4725
|
+
function settlementFailureBody(failure, fallbackReason) {
|
|
4726
|
+
return {
|
|
4727
|
+
error: "Payment settlement failed",
|
|
4728
|
+
reason: failure.error || fallbackReason,
|
|
4729
|
+
retryable: false,
|
|
4730
|
+
...failure.errorCode !== void 0 ? { errorCode: failure.errorCode } : {},
|
|
4731
|
+
...failure.transaction !== void 0 ? { transaction: failure.transaction } : {},
|
|
4732
|
+
...failure.paymentId !== void 0 ? { paymentId: failure.paymentId } : {}
|
|
4733
|
+
};
|
|
4734
|
+
}
|
|
4655
4735
|
function honoUnavailable(c, message, failure) {
|
|
4656
4736
|
const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));
|
|
4657
4737
|
c.header?.("Retry-After", String(seconds));
|
|
@@ -4726,10 +4806,7 @@ function createHonoMiddleware(options) {
|
|
|
4726
4806
|
if (settleResult.retryable) {
|
|
4727
4807
|
return honoUnavailable(c, "Payment settlement unavailable", settleResult);
|
|
4728
4808
|
}
|
|
4729
|
-
return c.json(
|
|
4730
|
-
error: "Payment settlement failed",
|
|
4731
|
-
reason: settleResult.error || "Unknown error"
|
|
4732
|
-
}, 500);
|
|
4809
|
+
return c.json(settlementFailureBody(settleResult, "Unknown error"), 500);
|
|
4733
4810
|
}
|
|
4734
4811
|
}
|
|
4735
4812
|
await next();
|
|
@@ -4758,6 +4835,6 @@ var ESCROW_TIMEOUT_MS = {
|
|
|
4758
4835
|
// Monad: 90s
|
|
4759
4836
|
};
|
|
4760
4837
|
|
|
4761
|
-
export { AMBIGUOUS_LEASE_REASONS, ANCHOR_MAX_REQUEST_BYTES, CAIP2_IDENTIFIERS, CAIP2_TO_CHAIN, ContentHashMismatch, DEFAULT_CHAIN, DEFAULT_CONFIG, DEFAULT_FACILITATOR_RETRIES, DEFAULT_FACILITATOR_URL, DEFAULT_PAYMENT_HEADER, DEFAULT_RETRY_AFTER_SECONDS, DELEGATE_PREFIX, DX402Error, ESCROW_DEPOSIT_LIMIT_USD, ESCROW_TIER_WINDOWS, EVENT_KINDS, EVIDENCE_HEADER, EnvKeyAdapter, EvidenceSkipped, FACILITATOR_ADDRESSES, FacilitatorClient, KEEPALIVE_INTERVAL_MS, MAX_RETRY_AFTER_SECONDS, OPERATOR_FEE_BPS, OWSWalletAdapter, PAYMENT_HEADER_NAMES, REPLAYABLE_LEASE_REASONS, SMA_WRAP_TARGETS, SSEParser, SUPPORTED_CHAINS, TrafficStreamError, WRITER_LEASE_REASONS, X402Client, X402Error, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, anchorDigest, anchorEvidence, availableBackends, buildEscrowPreAuth, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildSignatureBase, buildSignatureParams, buildTokenMetadata, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, caip2ToChain, chainToCAIP2, computeEscrowNonce, contentHash, convertX402Header, create402Response, createHonoMiddleware, createPaymentHeaders, createPaymentMiddleware, createSignedFetch, createX402Header, createX402V1Header, createX402V2Header, decodeBase64Utf8, decodeX402Header, delegateTarget, dereferencePointer, detectX402Version, paymentId as dx402PaymentId, ed25519ToX25519, encodeBase64Json, encodeBase64Utf8, encodeX402Header, evidenceFromHeaders, evidenceHeader, extractPaymentFromHeaders, facilitatorFetch, fetchNonce, generatePaymentOptions, getAlgorandChains, getChainById, getChainByName, getChainsByNetworkType, getChainsByToken, getCorsHeaders, getEVMChainIds, getEnabledChains, getExplorerAddressUrl, getExplorerTxUrl, getFacilitatorAddress, getNetworkType, getPaymentHeader, getSVMChains, getSuiChains, getSupportedTokens, getTokenByAddress, getTokenConfig, getXRPLChains, isAlgorandChain, isAmbiguousLeaseReason, isCAIP2Format, isChainSupported, isDelegated, isEndToEnd, isReplayableLeaseReason, isSVMChain, isSuiChain, isTokenSupported, isXRPLChain, matchesFilters, needsAccountWrap, parseEvidenceHeader, parseNetworkIdentifier, parseRetryAfterSeconds, parseSealed, parseTrafficEvent, payerKeyFromEvmSignature, payerKeyFromSolanaAddress, paymentChallengeFrom, readFacilitatorError, recoverEvidence, replaySafeTypedData, resolveDelegation, resolveEnvelopeVersion, rpcDelegationResolver, sealEvidence, sealEvidenceTo, sealedRoles, sellerDigestFor, signAnchorEd25519, signAnchorEvm, signRequest, signRequestWithSigner, signRequestWithWallet, streamTrafficEvents, toPaymentRequirementsV2, toResourceInfoV2, unseal, validateAmount, validateRecipient, wrapSignature };
|
|
4838
|
+
export { AMBIGUOUS_LEASE_REASONS, ANCHOR_MAX_REQUEST_BYTES, CAIP2_IDENTIFIERS, CAIP2_TO_CHAIN, ContentHashMismatch, DEFAULT_CHAIN, DEFAULT_CONFIG, DEFAULT_FACILITATOR_RETRIES, DEFAULT_FACILITATOR_URL, DEFAULT_PAYMENT_HEADER, DEFAULT_RETRY_AFTER_SECONDS, DELEGATE_PREFIX, DX402Error, ESCROW_DEPOSIT_LIMIT_USD, ESCROW_TIER_WINDOWS, EVENT_KINDS, EVIDENCE_HEADER, EnvKeyAdapter, EvidenceSkipped, FACILITATOR_ADDRESSES, FacilitatorClient, KEEPALIVE_INTERVAL_MS, MAX_RETRY_AFTER_SECONDS, OPERATOR_FEE_BPS, OWSWalletAdapter, PAYMENT_HEADER_NAMES, REPLAYABLE_LEASE_REASONS, SETTLEMENT_UNCONFIRMED, SMA_WRAP_TARGETS, SSEParser, SUPPORTED_CHAINS, TrafficStreamError, WRITER_LEASE_REASONS, X402Client, X402Error, X402_CORS_HEADERS, X402_HEADER_NAMES, ZERO_ADDRESS, anchorDigest, anchorEvidence, availableBackends, buildEscrowPreAuth, buildPaymentRequirements, buildSettleRequest, buildSettleRequestForVersion, buildSettleRequestV2, buildSignatureBase, buildSignatureParams, buildTokenMetadata, buildVerifyRequest, buildVerifyRequestForVersion, buildVerifyRequestV2, caip2ToChain, chainToCAIP2, computeEscrowNonce, contentHash, convertX402Header, create402Response, createHonoMiddleware, createPaymentHeaders, createPaymentMiddleware, createSignedFetch, createX402Header, createX402V1Header, createX402V2Header, decodeBase64Utf8, decodeX402Header, delegateTarget, dereferencePointer, detectX402Version, paymentId as dx402PaymentId, ed25519ToX25519, encodeBase64Json, encodeBase64Utf8, encodeX402Header, evidenceFromHeaders, evidenceHeader, extractPaymentFromHeaders, facilitatorFetch, fetchNonce, generatePaymentOptions, getAlgorandChains, getChainById, getChainByName, getChainsByNetworkType, getChainsByToken, getCorsHeaders, getEVMChainIds, getEnabledChains, getExplorerAddressUrl, getExplorerTxUrl, getFacilitatorAddress, getNetworkType, getPaymentHeader, getSVMChains, getSuiChains, getSupportedTokens, getTokenByAddress, getTokenConfig, getXRPLChains, isAlgorandChain, isAmbiguousLeaseReason, isCAIP2Format, isChainSupported, isDelegated, isEndToEnd, isReplayableLeaseReason, isSVMChain, isSettlementUnconfirmed, isSuiChain, isTokenSupported, isXRPLChain, matchesFilters, needsAccountWrap, parseEvidenceHeader, parseFacilitatorErrorBody, parseNetworkIdentifier, parseRetryAfterSeconds, parseSealed, parseTrafficEvent, payerKeyFromEvmSignature, payerKeyFromSolanaAddress, paymentChallengeFrom, readFacilitatorError, recoverEvidence, replaySafeTypedData, resolveDelegation, resolveEnvelopeVersion, rpcDelegationResolver, sealEvidence, sealEvidenceTo, sealedRoles, sellerDigestFor, signAnchorEd25519, signAnchorEvm, signRequest, signRequestWithSigner, signRequestWithWallet, streamTrafficEvents, toPaymentRequirementsV2, toResourceInfoV2, unseal, validateAmount, validateRecipient, wrapSignature };
|
|
4762
4839
|
//# sourceMappingURL=index.mjs.map
|
|
4763
4840
|
//# sourceMappingURL=index.mjs.map
|