@parallel-protocol/x402 0.8.0 → 0.8.2
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 +134 -66
- package/dist/{chunk-SA5ULSG2.js → chunk-KTBFF5HI.js} +68 -20
- package/dist/{chunk-NA7245L5.cjs → chunk-MXGS3HMS.cjs} +67 -19
- package/dist/express.cjs +5 -5
- package/dist/express.js +1 -1
- package/dist/fastify.cjs +11 -11
- package/dist/fastify.js +1 -1
- package/dist/hono.cjs +6 -6
- package/dist/hono.js +1 -1
- package/dist/index.cjs +15 -15
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +1 -1
- package/dist/next.cjs +13 -13
- package/dist/next.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X402_ERROR_CODES,
|
|
1
|
+
import { X402_ERROR_CODES, X402ConfigError, X402RuntimeError, isPriceRejection } from './chunk-QAECRSWF.js';
|
|
2
2
|
import { getTokenDecimals as getTokenDecimals$1 } from '@parallel-protocol/chains';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
@@ -127,8 +127,18 @@ var priceSchema = z.union([
|
|
|
127
127
|
"Price must be a string, a bigint or a function of the request"
|
|
128
128
|
)
|
|
129
129
|
]);
|
|
130
|
+
var LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
131
|
+
function isFacilitatorUrl(value) {
|
|
132
|
+
if (!URL.canParse(value)) return false;
|
|
133
|
+
const { protocol, hostname } = new URL(value);
|
|
134
|
+
return protocol === "https:" || protocol === "http:" && LOCAL_HOSTNAMES.has(hostname);
|
|
135
|
+
}
|
|
136
|
+
var facilitatorUrlSchema = z.string().refine(
|
|
137
|
+
isFacilitatorUrl,
|
|
138
|
+
"The facilitator URL must use https (plain http only on localhost, 127.0.0.1 or [::1])"
|
|
139
|
+
);
|
|
130
140
|
var facilitatorConfigSchema = z.object({
|
|
131
|
-
url:
|
|
141
|
+
url: facilitatorUrlSchema,
|
|
132
142
|
apiKey: z.string().optional()
|
|
133
143
|
});
|
|
134
144
|
var UPTO_MAX_TIMEOUT_SECONDS = 3600;
|
|
@@ -223,6 +233,15 @@ function retryAfterOf(response) {
|
|
|
223
233
|
const value = response.headers.get("retry-after");
|
|
224
234
|
return value !== null && RETRY_AFTER_SHAPE.test(value) ? value : void 0;
|
|
225
235
|
}
|
|
236
|
+
function throwIfRedirect(response) {
|
|
237
|
+
const redirected = response.type === "opaqueredirect" || response.status >= 300 && response.status < 400;
|
|
238
|
+
if (!redirected) return;
|
|
239
|
+
response.body?.cancel().catch(() => {
|
|
240
|
+
});
|
|
241
|
+
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
242
|
+
status: response.status
|
|
243
|
+
});
|
|
244
|
+
}
|
|
226
245
|
function decodePaymentHeader(paymentHeader) {
|
|
227
246
|
try {
|
|
228
247
|
return decodeBase64(paymentHeader);
|
|
@@ -231,20 +250,33 @@ function decodePaymentHeader(paymentHeader) {
|
|
|
231
250
|
}
|
|
232
251
|
}
|
|
233
252
|
var FacilitatorClient = class {
|
|
253
|
+
// Checked and kept when the client is built: a config changed afterwards
|
|
254
|
+
// does not move the calls elsewhere.
|
|
255
|
+
url;
|
|
256
|
+
apiKey;
|
|
234
257
|
constructor(config) {
|
|
235
|
-
|
|
258
|
+
const url = facilitatorUrlSchema.safeParse(config.url);
|
|
259
|
+
if (!url.success) {
|
|
260
|
+
throw new X402ConfigError(
|
|
261
|
+
url.error.issues[0]?.message ?? "Invalid facilitator URL",
|
|
262
|
+
url.error
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
this.url = new URL(url.data).href.replace(/\/+$/, "");
|
|
266
|
+
this.apiKey = config.apiKey;
|
|
236
267
|
}
|
|
237
|
-
config;
|
|
238
268
|
async verify(paymentHeader, paymentRequirements) {
|
|
239
269
|
const paymentPayload = decodePaymentHeader(paymentHeader);
|
|
240
270
|
let json;
|
|
241
271
|
try {
|
|
242
|
-
const response = await fetch(`${this.
|
|
272
|
+
const response = await fetch(`${this.url}/x402/verify`, {
|
|
243
273
|
method: "POST",
|
|
244
274
|
headers: this.buildHeaders(),
|
|
245
275
|
body: JSON.stringify({ paymentPayload, paymentRequirements }),
|
|
276
|
+
redirect: "manual",
|
|
246
277
|
signal: AbortSignal.timeout(FACILITATOR_TIMEOUT_MS)
|
|
247
278
|
});
|
|
279
|
+
throwIfRedirect(response);
|
|
248
280
|
if (!response.ok) {
|
|
249
281
|
const body = await readErrorBody(response);
|
|
250
282
|
throw new X402RuntimeError(
|
|
@@ -272,7 +304,7 @@ var FacilitatorClient = class {
|
|
|
272
304
|
const paymentPayload = decodePaymentHeader(paymentHeader);
|
|
273
305
|
let json;
|
|
274
306
|
try {
|
|
275
|
-
const response = await fetch(`${this.
|
|
307
|
+
const response = await fetch(`${this.url}/x402/settle`, {
|
|
276
308
|
method: "POST",
|
|
277
309
|
headers: this.buildHeaders(),
|
|
278
310
|
// settleAmount only travels for metered routes; the settle token
|
|
@@ -287,18 +319,22 @@ var FacilitatorClient = class {
|
|
|
287
319
|
settleToken: options.settleToken
|
|
288
320
|
}
|
|
289
321
|
}),
|
|
322
|
+
redirect: "manual",
|
|
290
323
|
signal: AbortSignal.timeout(SETTLE_TIMEOUT_MS)
|
|
291
324
|
});
|
|
325
|
+
throwIfRedirect(response);
|
|
292
326
|
if (!response.ok) {
|
|
293
327
|
const body = await readErrorBody(response);
|
|
294
|
-
if (body.error === void 0
|
|
295
|
-
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE
|
|
328
|
+
if (body.error === void 0) {
|
|
329
|
+
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
330
|
+
status: response.status
|
|
331
|
+
});
|
|
296
332
|
}
|
|
297
333
|
const retryAfter = retryAfterOf(response);
|
|
298
334
|
return {
|
|
299
335
|
success: false,
|
|
300
336
|
error: {
|
|
301
|
-
code: body.error
|
|
337
|
+
code: body.error,
|
|
302
338
|
message: body.message ?? "Settlement failed",
|
|
303
339
|
status: response.status,
|
|
304
340
|
...retryAfter !== void 0 && { retryAfter }
|
|
@@ -337,16 +373,22 @@ var FacilitatorClient = class {
|
|
|
337
373
|
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_INVALID_RESPONSE);
|
|
338
374
|
}
|
|
339
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* @deprecated The Parallel facilitator no longer serves `/x402/pay`, so this
|
|
378
|
+
* call fails with `FACILITATOR_UNAVAILABLE`. Use `verify`, then `settle`.
|
|
379
|
+
*/
|
|
340
380
|
async pay(paymentHeader) {
|
|
341
381
|
const headers = this.buildHeaders();
|
|
342
382
|
headers["X-PAYMENT"] = paymentHeader;
|
|
343
383
|
let json;
|
|
344
384
|
try {
|
|
345
|
-
const response = await fetch(`${this.
|
|
385
|
+
const response = await fetch(`${this.url}/x402/pay`, {
|
|
346
386
|
method: "POST",
|
|
347
387
|
headers,
|
|
388
|
+
redirect: "manual",
|
|
348
389
|
signal: AbortSignal.timeout(FACILITATOR_TIMEOUT_MS)
|
|
349
390
|
});
|
|
391
|
+
throwIfRedirect(response);
|
|
350
392
|
if (!response.ok) {
|
|
351
393
|
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE);
|
|
352
394
|
}
|
|
@@ -365,8 +407,8 @@ var FacilitatorClient = class {
|
|
|
365
407
|
const headers = {
|
|
366
408
|
"Content-Type": "application/json"
|
|
367
409
|
};
|
|
368
|
-
if (this.
|
|
369
|
-
headers["X-API-Key"] = this.
|
|
410
|
+
if (this.apiKey) {
|
|
411
|
+
headers["X-API-Key"] = this.apiKey;
|
|
370
412
|
}
|
|
371
413
|
return headers;
|
|
372
414
|
}
|
|
@@ -650,12 +692,13 @@ function paymentRequiredResponse(url, config, resolvedTokens, price, refusal) {
|
|
|
650
692
|
});
|
|
651
693
|
}
|
|
652
694
|
function createPaymentGate(config) {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
695
|
+
const checked = paymentMiddlewareConfigSchema.safeParse(config);
|
|
696
|
+
if (!checked.success) {
|
|
697
|
+
const issue = checked.error.issues[0];
|
|
698
|
+
const where = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
|
|
656
699
|
throw new X402ConfigError(
|
|
657
|
-
|
|
658
|
-
|
|
700
|
+
`Invalid paymentMiddleware config${where}: ${issue?.message ?? "check your routes, facilitator URL and payTo addresses"}`,
|
|
701
|
+
checked.error
|
|
659
702
|
);
|
|
660
703
|
}
|
|
661
704
|
const client = new FacilitatorClient(config.facilitator);
|
|
@@ -731,8 +774,9 @@ function createPaymentGate(config) {
|
|
|
731
774
|
};
|
|
732
775
|
};
|
|
733
776
|
}
|
|
734
|
-
var
|
|
777
|
+
var DEFAULT_SETTLEMENT_MESSAGE = "The payment could not be settled.";
|
|
735
778
|
var MERCHANT_SETTLEMENT_MESSAGE = "The merchant could not complete the settlement of this payment. The payment was not taken: do not sign another payment for this request before checking with the merchant.";
|
|
779
|
+
var UNAVAILABLE_SETTLEMENT_MESSAGE = "The facilitator could not settle the payment for now. It may still settle until its authorization expires, or an earlier attempt may already have settled it: do not sign another payment for this request before checking with the merchant.";
|
|
736
780
|
var AGENT_MESSAGES = {
|
|
737
781
|
[X402_ERROR_CODES.SETTLE_TIMEOUT]: "The facilitator did not confirm the settlement in time. The payment may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
738
782
|
[X402_ERROR_CODES.FACILITATOR_UNAVAILABLE]: "The facilitator could not be reached to settle the payment. It may still have settled: do not sign another payment for this request before checking with the merchant.",
|
|
@@ -741,15 +785,19 @@ var AGENT_MESSAGES = {
|
|
|
741
785
|
RECEIPT_UNAVAILABLE: "The facilitator sent the transaction but could not read its confirmation. The payment may have settled: do not sign another payment for this request before checking with the merchant.",
|
|
742
786
|
SETTLE_TOKEN_INVALID: MERCHANT_SETTLEMENT_MESSAGE,
|
|
743
787
|
SETTLE_TOKEN_REQUIRED: MERCHANT_SETTLEMENT_MESSAGE,
|
|
788
|
+
AUTHORIZATION_USED: "The payment's authorization was already consumed or cancelled on-chain. It may have paid the merchant: do not sign another payment for this request before checking with the merchant.",
|
|
789
|
+
PAYMENT_NOT_VERIFIED: "The facilitator holds no payment it can settle for this request. An earlier attempt may have paid the merchant, or may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
790
|
+
PARALLELIZER_PAUSED: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
791
|
+
SERVICE_UNAVAILABLE: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
744
792
|
AMOUNT_MISMATCH: "The facilitator settled a different amount than this request asked for. The response was not served: do not sign another payment for this request before checking with the merchant.",
|
|
745
|
-
UNKNOWN:
|
|
793
|
+
UNKNOWN: "The facilitator gave no reason for this failure, and the payment may have settled: do not sign another payment for this request before checking with the merchant."
|
|
746
794
|
};
|
|
747
795
|
function settlementFailure(code, failure) {
|
|
748
796
|
const reason = shapedCode(code) ?? "UNKNOWN";
|
|
749
797
|
return {
|
|
750
798
|
settled: false,
|
|
751
799
|
reason,
|
|
752
|
-
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ??
|
|
800
|
+
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ?? DEFAULT_SETTLEMENT_MESSAGE,
|
|
753
801
|
...failure?.retryAfter !== void 0 && {
|
|
754
802
|
retryAfter: failure.retryAfter
|
|
755
803
|
}
|
|
@@ -129,8 +129,18 @@ var priceSchema = zod.z.union([
|
|
|
129
129
|
"Price must be a string, a bigint or a function of the request"
|
|
130
130
|
)
|
|
131
131
|
]);
|
|
132
|
+
var LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
133
|
+
function isFacilitatorUrl(value) {
|
|
134
|
+
if (!URL.canParse(value)) return false;
|
|
135
|
+
const { protocol, hostname } = new URL(value);
|
|
136
|
+
return protocol === "https:" || protocol === "http:" && LOCAL_HOSTNAMES.has(hostname);
|
|
137
|
+
}
|
|
138
|
+
var facilitatorUrlSchema = zod.z.string().refine(
|
|
139
|
+
isFacilitatorUrl,
|
|
140
|
+
"The facilitator URL must use https (plain http only on localhost, 127.0.0.1 or [::1])"
|
|
141
|
+
);
|
|
132
142
|
var facilitatorConfigSchema = zod.z.object({
|
|
133
|
-
url:
|
|
143
|
+
url: facilitatorUrlSchema,
|
|
134
144
|
apiKey: zod.z.string().optional()
|
|
135
145
|
});
|
|
136
146
|
var UPTO_MAX_TIMEOUT_SECONDS = 3600;
|
|
@@ -225,6 +235,15 @@ function retryAfterOf(response) {
|
|
|
225
235
|
const value = response.headers.get("retry-after");
|
|
226
236
|
return value !== null && RETRY_AFTER_SHAPE.test(value) ? value : void 0;
|
|
227
237
|
}
|
|
238
|
+
function throwIfRedirect(response) {
|
|
239
|
+
const redirected = response.type === "opaqueredirect" || response.status >= 300 && response.status < 400;
|
|
240
|
+
if (!redirected) return;
|
|
241
|
+
response.body?.cancel().catch(() => {
|
|
242
|
+
});
|
|
243
|
+
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
244
|
+
status: response.status
|
|
245
|
+
});
|
|
246
|
+
}
|
|
228
247
|
function decodePaymentHeader(paymentHeader) {
|
|
229
248
|
try {
|
|
230
249
|
return decodeBase64(paymentHeader);
|
|
@@ -233,20 +252,33 @@ function decodePaymentHeader(paymentHeader) {
|
|
|
233
252
|
}
|
|
234
253
|
}
|
|
235
254
|
var FacilitatorClient = class {
|
|
255
|
+
// Checked and kept when the client is built: a config changed afterwards
|
|
256
|
+
// does not move the calls elsewhere.
|
|
257
|
+
url;
|
|
258
|
+
apiKey;
|
|
236
259
|
constructor(config) {
|
|
237
|
-
|
|
260
|
+
const url = facilitatorUrlSchema.safeParse(config.url);
|
|
261
|
+
if (!url.success) {
|
|
262
|
+
throw new chunkKZZY5LS6_cjs.X402ConfigError(
|
|
263
|
+
url.error.issues[0]?.message ?? "Invalid facilitator URL",
|
|
264
|
+
url.error
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
this.url = new URL(url.data).href.replace(/\/+$/, "");
|
|
268
|
+
this.apiKey = config.apiKey;
|
|
238
269
|
}
|
|
239
|
-
config;
|
|
240
270
|
async verify(paymentHeader, paymentRequirements) {
|
|
241
271
|
const paymentPayload = decodePaymentHeader(paymentHeader);
|
|
242
272
|
let json;
|
|
243
273
|
try {
|
|
244
|
-
const response = await fetch(`${this.
|
|
274
|
+
const response = await fetch(`${this.url}/x402/verify`, {
|
|
245
275
|
method: "POST",
|
|
246
276
|
headers: this.buildHeaders(),
|
|
247
277
|
body: JSON.stringify({ paymentPayload, paymentRequirements }),
|
|
278
|
+
redirect: "manual",
|
|
248
279
|
signal: AbortSignal.timeout(FACILITATOR_TIMEOUT_MS)
|
|
249
280
|
});
|
|
281
|
+
throwIfRedirect(response);
|
|
250
282
|
if (!response.ok) {
|
|
251
283
|
const body = await readErrorBody(response);
|
|
252
284
|
throw new chunkKZZY5LS6_cjs.X402RuntimeError(
|
|
@@ -274,7 +306,7 @@ var FacilitatorClient = class {
|
|
|
274
306
|
const paymentPayload = decodePaymentHeader(paymentHeader);
|
|
275
307
|
let json;
|
|
276
308
|
try {
|
|
277
|
-
const response = await fetch(`${this.
|
|
309
|
+
const response = await fetch(`${this.url}/x402/settle`, {
|
|
278
310
|
method: "POST",
|
|
279
311
|
headers: this.buildHeaders(),
|
|
280
312
|
// settleAmount only travels for metered routes; the settle token
|
|
@@ -289,18 +321,22 @@ var FacilitatorClient = class {
|
|
|
289
321
|
settleToken: options.settleToken
|
|
290
322
|
}
|
|
291
323
|
}),
|
|
324
|
+
redirect: "manual",
|
|
292
325
|
signal: AbortSignal.timeout(SETTLE_TIMEOUT_MS)
|
|
293
326
|
});
|
|
327
|
+
throwIfRedirect(response);
|
|
294
328
|
if (!response.ok) {
|
|
295
329
|
const body = await readErrorBody(response);
|
|
296
|
-
if (body.error === void 0
|
|
297
|
-
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE
|
|
330
|
+
if (body.error === void 0) {
|
|
331
|
+
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
332
|
+
status: response.status
|
|
333
|
+
});
|
|
298
334
|
}
|
|
299
335
|
const retryAfter = retryAfterOf(response);
|
|
300
336
|
return {
|
|
301
337
|
success: false,
|
|
302
338
|
error: {
|
|
303
|
-
code: body.error
|
|
339
|
+
code: body.error,
|
|
304
340
|
message: body.message ?? "Settlement failed",
|
|
305
341
|
status: response.status,
|
|
306
342
|
...retryAfter !== void 0 && { retryAfter }
|
|
@@ -339,16 +375,22 @@ var FacilitatorClient = class {
|
|
|
339
375
|
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_INVALID_RESPONSE);
|
|
340
376
|
}
|
|
341
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* @deprecated The Parallel facilitator no longer serves `/x402/pay`, so this
|
|
380
|
+
* call fails with `FACILITATOR_UNAVAILABLE`. Use `verify`, then `settle`.
|
|
381
|
+
*/
|
|
342
382
|
async pay(paymentHeader) {
|
|
343
383
|
const headers = this.buildHeaders();
|
|
344
384
|
headers["X-PAYMENT"] = paymentHeader;
|
|
345
385
|
let json;
|
|
346
386
|
try {
|
|
347
|
-
const response = await fetch(`${this.
|
|
387
|
+
const response = await fetch(`${this.url}/x402/pay`, {
|
|
348
388
|
method: "POST",
|
|
349
389
|
headers,
|
|
390
|
+
redirect: "manual",
|
|
350
391
|
signal: AbortSignal.timeout(FACILITATOR_TIMEOUT_MS)
|
|
351
392
|
});
|
|
393
|
+
throwIfRedirect(response);
|
|
352
394
|
if (!response.ok) {
|
|
353
395
|
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE);
|
|
354
396
|
}
|
|
@@ -367,8 +409,8 @@ var FacilitatorClient = class {
|
|
|
367
409
|
const headers = {
|
|
368
410
|
"Content-Type": "application/json"
|
|
369
411
|
};
|
|
370
|
-
if (this.
|
|
371
|
-
headers["X-API-Key"] = this.
|
|
412
|
+
if (this.apiKey) {
|
|
413
|
+
headers["X-API-Key"] = this.apiKey;
|
|
372
414
|
}
|
|
373
415
|
return headers;
|
|
374
416
|
}
|
|
@@ -652,12 +694,13 @@ function paymentRequiredResponse(url, config, resolvedTokens, price, refusal) {
|
|
|
652
694
|
});
|
|
653
695
|
}
|
|
654
696
|
function createPaymentGate(config) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
697
|
+
const checked = paymentMiddlewareConfigSchema.safeParse(config);
|
|
698
|
+
if (!checked.success) {
|
|
699
|
+
const issue = checked.error.issues[0];
|
|
700
|
+
const where = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
|
|
658
701
|
throw new chunkKZZY5LS6_cjs.X402ConfigError(
|
|
659
|
-
|
|
660
|
-
|
|
702
|
+
`Invalid paymentMiddleware config${where}: ${issue?.message ?? "check your routes, facilitator URL and payTo addresses"}`,
|
|
703
|
+
checked.error
|
|
661
704
|
);
|
|
662
705
|
}
|
|
663
706
|
const client = new FacilitatorClient(config.facilitator);
|
|
@@ -733,8 +776,9 @@ function createPaymentGate(config) {
|
|
|
733
776
|
};
|
|
734
777
|
};
|
|
735
778
|
}
|
|
736
|
-
var
|
|
779
|
+
var DEFAULT_SETTLEMENT_MESSAGE = "The payment could not be settled.";
|
|
737
780
|
var MERCHANT_SETTLEMENT_MESSAGE = "The merchant could not complete the settlement of this payment. The payment was not taken: do not sign another payment for this request before checking with the merchant.";
|
|
781
|
+
var UNAVAILABLE_SETTLEMENT_MESSAGE = "The facilitator could not settle the payment for now. It may still settle until its authorization expires, or an earlier attempt may already have settled it: do not sign another payment for this request before checking with the merchant.";
|
|
738
782
|
var AGENT_MESSAGES = {
|
|
739
783
|
[chunkKZZY5LS6_cjs.X402_ERROR_CODES.SETTLE_TIMEOUT]: "The facilitator did not confirm the settlement in time. The payment may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
740
784
|
[chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE]: "The facilitator could not be reached to settle the payment. It may still have settled: do not sign another payment for this request before checking with the merchant.",
|
|
@@ -743,15 +787,19 @@ var AGENT_MESSAGES = {
|
|
|
743
787
|
RECEIPT_UNAVAILABLE: "The facilitator sent the transaction but could not read its confirmation. The payment may have settled: do not sign another payment for this request before checking with the merchant.",
|
|
744
788
|
SETTLE_TOKEN_INVALID: MERCHANT_SETTLEMENT_MESSAGE,
|
|
745
789
|
SETTLE_TOKEN_REQUIRED: MERCHANT_SETTLEMENT_MESSAGE,
|
|
790
|
+
AUTHORIZATION_USED: "The payment's authorization was already consumed or cancelled on-chain. It may have paid the merchant: do not sign another payment for this request before checking with the merchant.",
|
|
791
|
+
PAYMENT_NOT_VERIFIED: "The facilitator holds no payment it can settle for this request. An earlier attempt may have paid the merchant, or may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
792
|
+
PARALLELIZER_PAUSED: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
793
|
+
SERVICE_UNAVAILABLE: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
746
794
|
AMOUNT_MISMATCH: "The facilitator settled a different amount than this request asked for. The response was not served: do not sign another payment for this request before checking with the merchant.",
|
|
747
|
-
UNKNOWN:
|
|
795
|
+
UNKNOWN: "The facilitator gave no reason for this failure, and the payment may have settled: do not sign another payment for this request before checking with the merchant."
|
|
748
796
|
};
|
|
749
797
|
function settlementFailure(code, failure) {
|
|
750
798
|
const reason = shapedCode(code) ?? "UNKNOWN";
|
|
751
799
|
return {
|
|
752
800
|
settled: false,
|
|
753
801
|
reason,
|
|
754
|
-
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ??
|
|
802
|
+
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ?? DEFAULT_SETTLEMENT_MESSAGE,
|
|
755
803
|
...failure?.retryAfter !== void 0 && {
|
|
756
804
|
retryAfter: failure.retryAfter
|
|
757
805
|
}
|
package/dist/express.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/express/adapter.ts
|
|
@@ -108,8 +108,8 @@ var ExpressAdapter = class {
|
|
|
108
108
|
return originalEnd(...args);
|
|
109
109
|
});
|
|
110
110
|
next();
|
|
111
|
-
const outcome = await
|
|
112
|
-
if (outcome ===
|
|
111
|
+
const outcome = await chunkMXGS3HMS_cjs.raceTimeout(endPromise, options?.timeoutMs);
|
|
112
|
+
if (outcome === chunkMXGS3HMS_cjs.HANDLER_TIMEOUT) {
|
|
113
113
|
discarded = true;
|
|
114
114
|
return {
|
|
115
115
|
status: 504,
|
|
@@ -146,7 +146,7 @@ var ExpressAdapter = class {
|
|
|
146
146
|
const chunk = chunkBytes(args);
|
|
147
147
|
if (chunk) bytes.push(chunk);
|
|
148
148
|
}
|
|
149
|
-
return
|
|
149
|
+
return chunkMXGS3HMS_cjs.parseJsonBody(
|
|
150
150
|
contentType,
|
|
151
151
|
Buffer.concat(bytes).toString("utf8")
|
|
152
152
|
);
|
|
@@ -170,7 +170,7 @@ var ExpressAdapter = class {
|
|
|
170
170
|
|
|
171
171
|
// src/express/index.ts
|
|
172
172
|
function paymentMiddleware(config) {
|
|
173
|
-
const middleware =
|
|
173
|
+
const middleware = chunkMXGS3HMS_cjs.createPaymentMiddleware(config);
|
|
174
174
|
return async (req, res, next) => {
|
|
175
175
|
const result = await middleware(new ExpressAdapter(req, res, next));
|
|
176
176
|
if ("pass" in result) {
|
package/dist/express.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-
|
|
1
|
+
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
|
|
4
4
|
// src/express/adapter.ts
|
package/dist/fastify.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
var fp = require('fastify-plugin');
|
|
6
6
|
|
|
@@ -37,7 +37,7 @@ var FastifyAdapter = class {
|
|
|
37
37
|
// src/fastify/index.ts
|
|
38
38
|
function payloadJson(contentType, payload) {
|
|
39
39
|
const text = typeof payload === "string" ? payload : payload instanceof Uint8Array ? Buffer.from(payload).toString("utf8") : void 0;
|
|
40
|
-
return
|
|
40
|
+
return chunkMXGS3HMS_cjs.parseJsonBody(contentType, text);
|
|
41
41
|
}
|
|
42
42
|
function refuse(reply, result) {
|
|
43
43
|
const json = JSON.stringify(result.body);
|
|
@@ -54,11 +54,11 @@ function headerValue(value) {
|
|
|
54
54
|
}
|
|
55
55
|
function paymentMiddleware(config) {
|
|
56
56
|
return fp__default.default(async (fastify) => {
|
|
57
|
-
const gate =
|
|
57
|
+
const gate = chunkMXGS3HMS_cjs.createPaymentGate(config);
|
|
58
58
|
const verifiedMap = /* @__PURE__ */ new WeakMap();
|
|
59
59
|
const rawWriters = /* @__PURE__ */ new WeakMap();
|
|
60
60
|
const needsBody = (req) => {
|
|
61
|
-
const route =
|
|
61
|
+
const route = chunkMXGS3HMS_cjs.matchRoute(
|
|
62
62
|
new FastifyAdapter(req).getPath(),
|
|
63
63
|
config.routes
|
|
64
64
|
);
|
|
@@ -111,29 +111,29 @@ function paymentMiddleware(config) {
|
|
|
111
111
|
if (!verified) return payload;
|
|
112
112
|
let raw;
|
|
113
113
|
if (verified.scheme === "upto") {
|
|
114
|
-
raw = headerValue(reply.getHeader(
|
|
115
|
-
reply.removeHeader(
|
|
114
|
+
raw = headerValue(reply.getHeader(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER));
|
|
115
|
+
reply.removeHeader(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER);
|
|
116
116
|
}
|
|
117
117
|
if (reply.statusCode < 200 || reply.statusCode >= 300) {
|
|
118
118
|
return payload;
|
|
119
119
|
}
|
|
120
120
|
let settleOptions;
|
|
121
121
|
if (verified.scheme === "upto") {
|
|
122
|
-
const resolved = await
|
|
122
|
+
const resolved = await chunkMXGS3HMS_cjs.resolveCharge(verified, raw, {
|
|
123
123
|
status: reply.statusCode,
|
|
124
124
|
header: (name) => headerValue(reply.getHeader(name)),
|
|
125
125
|
body: async () => payloadJson(headerValue(reply.getHeader("content-type")), payload)
|
|
126
126
|
});
|
|
127
127
|
if (resolved.kind === "invalid") {
|
|
128
|
-
return refuse(reply,
|
|
128
|
+
return refuse(reply, chunkMXGS3HMS_cjs.invalidSettleAmountResponse(resolved.reason));
|
|
129
129
|
}
|
|
130
130
|
if (resolved.kind === "skip") return payload;
|
|
131
131
|
settleOptions = { amount: resolved.amount };
|
|
132
132
|
}
|
|
133
|
-
const outcome = await
|
|
133
|
+
const outcome = await chunkMXGS3HMS_cjs.settleVerified(verified, settleOptions);
|
|
134
134
|
if (!outcome.settled)
|
|
135
|
-
return refuse(reply,
|
|
136
|
-
reply.header("payment-response",
|
|
135
|
+
return refuse(reply, chunkMXGS3HMS_cjs.settlementFailureResponse(outcome));
|
|
136
|
+
reply.header("payment-response", chunkMXGS3HMS_cjs.encodeBase64(outcome.confirmation));
|
|
137
137
|
reply.header("access-control-expose-headers", "payment-response");
|
|
138
138
|
return payload;
|
|
139
139
|
});
|
package/dist/fastify.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-
|
|
1
|
+
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
import fp from 'fastify-plugin';
|
|
4
4
|
|
package/dist/hono.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/hono/adapter.ts
|
|
@@ -30,7 +30,7 @@ var HonoAdapter = class {
|
|
|
30
30
|
// Hono caches the parsed body on the request, so the handler can still read
|
|
31
31
|
// it after the price function did.
|
|
32
32
|
async getBody() {
|
|
33
|
-
if (!
|
|
33
|
+
if (!chunkMXGS3HMS_cjs.isJsonContentType(this.c.req.header("content-type"))) return void 0;
|
|
34
34
|
try {
|
|
35
35
|
return await this.c.req.json();
|
|
36
36
|
} catch {
|
|
@@ -38,8 +38,8 @@ var HonoAdapter = class {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
async runHandler(options) {
|
|
41
|
-
const outcome = await
|
|
42
|
-
if (outcome ===
|
|
41
|
+
const outcome = await chunkMXGS3HMS_cjs.raceTimeout(this.next(), options?.timeoutMs);
|
|
42
|
+
if (outcome === chunkMXGS3HMS_cjs.HANDLER_TIMEOUT) {
|
|
43
43
|
return {
|
|
44
44
|
status: 504,
|
|
45
45
|
setResponseHeader: () => {
|
|
@@ -64,7 +64,7 @@ var HonoAdapter = class {
|
|
|
64
64
|
getResponseHeader: (name) => res.headers.get(name) ?? void 0,
|
|
65
65
|
removeResponseHeader: (name) => res.headers.delete(name),
|
|
66
66
|
// Read from a clone: the response body streams once, to the client.
|
|
67
|
-
getResponseBody: () =>
|
|
67
|
+
getResponseBody: () => chunkMXGS3HMS_cjs.jsonFromResponse(res),
|
|
68
68
|
sendResponse: () => {
|
|
69
69
|
},
|
|
70
70
|
// The response is replaced: release its body (and whatever upstream
|
|
@@ -79,7 +79,7 @@ var HonoAdapter = class {
|
|
|
79
79
|
|
|
80
80
|
// src/hono/index.ts
|
|
81
81
|
function paymentMiddleware(config) {
|
|
82
|
-
const middleware =
|
|
82
|
+
const middleware = chunkMXGS3HMS_cjs.createPaymentMiddleware(config);
|
|
83
83
|
return async (c, next) => {
|
|
84
84
|
const result = await middleware(new HonoAdapter(c, next));
|
|
85
85
|
if ("pass" in result) {
|
package/dist/hono.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isJsonContentType, raceTimeout, HANDLER_TIMEOUT, jsonFromResponse, createPaymentMiddleware } from './chunk-
|
|
1
|
+
import { isJsonContentType, raceTimeout, HANDLER_TIMEOUT, jsonFromResponse, createPaymentMiddleware } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
|
|
4
4
|
// src/hono/adapter.ts
|
package/dist/index.cjs
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
var chunkKZZY5LS6_cjs = require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "FacilitatorClient", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkMXGS3HMS_cjs.FacilitatorClient; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "PARALLEL_TOKENS", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkMXGS3HMS_cjs.PARALLEL_TOKENS; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "SETTLE_AMOUNT_HEADER", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "createPaymentGate", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkMXGS3HMS_cjs.createPaymentGate; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "createPaymentMiddleware", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkMXGS3HMS_cjs.createPaymentMiddleware; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "encodeBase64", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
30
|
+
get: function () { return chunkMXGS3HMS_cjs.encodeBase64; }
|
|
31
31
|
});
|
|
32
32
|
Object.defineProperty(exports, "getDefaultAcceptedTokens", {
|
|
33
33
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkMXGS3HMS_cjs.getDefaultAcceptedTokens; }
|
|
35
35
|
});
|
|
36
36
|
Object.defineProperty(exports, "parsePrice", {
|
|
37
37
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkMXGS3HMS_cjs.parsePrice; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "resolveCharge", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkMXGS3HMS_cjs.resolveCharge; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "resolveSettleAmount", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkMXGS3HMS_cjs.resolveSettleAmount; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "settleVerified", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkMXGS3HMS_cjs.settleVerified; }
|
|
51
51
|
});
|
|
52
52
|
Object.defineProperty(exports, "settlementFailureResponse", {
|
|
53
53
|
enumerable: true,
|
|
54
|
-
get: function () { return
|
|
54
|
+
get: function () { return chunkMXGS3HMS_cjs.settlementFailureResponse; }
|
|
55
55
|
});
|
|
56
56
|
Object.defineProperty(exports, "toEip155Network", {
|
|
57
57
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
58
|
+
get: function () { return chunkMXGS3HMS_cjs.toEip155Network; }
|
|
59
59
|
});
|
|
60
60
|
Object.defineProperty(exports, "validateAddress", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
62
|
+
get: function () { return chunkMXGS3HMS_cjs.validateAddress; }
|
|
63
63
|
});
|
|
64
64
|
Object.defineProperty(exports, "X402ConfigError", {
|
|
65
65
|
enumerable: true,
|
package/dist/index.d.cts
CHANGED
|
@@ -3,10 +3,15 @@ export { i as MeterContext, j as MeterFunction, k as PaymentFailure, l as Paymen
|
|
|
3
3
|
import { Address } from 'viem';
|
|
4
4
|
|
|
5
5
|
declare class FacilitatorClient {
|
|
6
|
-
private readonly
|
|
6
|
+
private readonly url;
|
|
7
|
+
private readonly apiKey;
|
|
7
8
|
constructor(config: FacilitatorConfig);
|
|
8
9
|
verify(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements): Promise<VerifyResult>;
|
|
9
10
|
settle(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements, options?: FacilitatorSettleOptions): Promise<FacilitatorResponse>;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated The Parallel facilitator no longer serves `/x402/pay`, so this
|
|
13
|
+
* call fails with `FACILITATOR_UNAVAILABLE`. Use `verify`, then `settle`.
|
|
14
|
+
*/
|
|
10
15
|
pay(paymentHeader: string): Promise<FacilitatorResponse>;
|
|
11
16
|
private buildHeaders;
|
|
12
17
|
}
|