@parallel-protocol/x402 0.7.1 → 0.8.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 +53 -20
- package/dist/{chunk-JPMK5YBU.cjs → chunk-KZZY5LS6.cjs} +13 -2
- package/dist/{chunk-POU7EH3E.cjs → chunk-NA7245L5.cjs} +201 -84
- package/dist/{chunk-AFRDHGDT.js → chunk-QAECRSWF.js} +13 -2
- package/dist/{chunk-AENXD4OC.js → chunk-SA5ULSG2.js} +179 -64
- package/dist/express.cjs +6 -6
- package/dist/express.d.cts +1 -1
- package/dist/express.d.ts +1 -1
- package/dist/express.js +2 -2
- package/dist/fastify.cjs +20 -29
- package/dist/fastify.d.cts +1 -1
- package/dist/fastify.d.ts +1 -1
- package/dist/fastify.js +13 -22
- package/dist/hono.cjs +7 -7
- package/dist/hono.d.cts +1 -1
- package/dist/hono.d.ts +1 -1
- package/dist/hono.js +2 -2
- package/dist/index.cjs +27 -19
- package/dist/index.d.cts +50 -6
- package/dist/index.d.ts +50 -6
- package/dist/index.js +2 -2
- package/dist/llm.cjs +13 -13
- package/dist/llm.d.cts +1 -1
- package/dist/llm.d.ts +1 -1
- package/dist/llm.js +1 -1
- package/dist/next.cjs +28 -44
- package/dist/next.d.cts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +20 -36
- package/dist/{types-q_gu5wjz.d.cts → types-BkGQ2lPA.d.cts} +30 -1
- package/dist/{types-q_gu5wjz.d.ts → types-BkGQ2lPA.d.ts} +30 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X402_ERROR_CODES, X402RuntimeError, X402ConfigError, isPriceRejection } from './chunk-
|
|
1
|
+
import { X402_ERROR_CODES, X402RuntimeError, X402ConfigError, isPriceRejection } from './chunk-QAECRSWF.js';
|
|
2
2
|
import { getTokenDecimals as getTokenDecimals$1 } from '@parallel-protocol/chains';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
@@ -170,26 +170,32 @@ var facilitatorResponseSchema = z.discriminatedUnion("success", [
|
|
|
170
170
|
chain: z.string(),
|
|
171
171
|
gasSponsored: z.boolean(),
|
|
172
172
|
networkId: z.string(),
|
|
173
|
-
amountSettled: z.string().optional()
|
|
173
|
+
amountSettled: z.string().optional(),
|
|
174
|
+
alreadySettled: z.boolean().optional()
|
|
174
175
|
}),
|
|
175
176
|
z.object({
|
|
176
177
|
success: z.literal(false),
|
|
177
178
|
error: z.object({
|
|
178
179
|
code: z.string(),
|
|
179
180
|
message: z.string(),
|
|
180
|
-
hint: z.string().optional()
|
|
181
|
+
hint: z.string().optional(),
|
|
182
|
+
status: z.number().optional(),
|
|
183
|
+
retryAfter: z.string().optional()
|
|
181
184
|
})
|
|
182
185
|
})
|
|
183
186
|
]);
|
|
184
187
|
var verifyResponseSchema = z.object({
|
|
185
|
-
isValid: z.literal(true)
|
|
188
|
+
isValid: z.literal(true),
|
|
189
|
+
settleToken: z.string().min(1)
|
|
186
190
|
});
|
|
187
191
|
var settleSuccessSchema = z.object({
|
|
188
192
|
txHash: txHashSchema,
|
|
189
193
|
route: z.string(),
|
|
190
194
|
gasSponsored: z.boolean(),
|
|
191
195
|
// Metered routes: the amount actually charged (smallest unit).
|
|
192
|
-
amountSettled: z.string().optional()
|
|
196
|
+
amountSettled: z.string().optional(),
|
|
197
|
+
// The facilitator answered from a recorded outcome, nothing was broadcast.
|
|
198
|
+
alreadySettled: z.boolean().optional()
|
|
193
199
|
});
|
|
194
200
|
var settleErrorSchema = z.object({
|
|
195
201
|
error: z.string(),
|
|
@@ -203,6 +209,20 @@ var settleResponseSchema = z.union([
|
|
|
203
209
|
// src/client.ts
|
|
204
210
|
var FACILITATOR_TIMEOUT_MS = 1e4;
|
|
205
211
|
var SETTLE_TIMEOUT_MS = 6e4;
|
|
212
|
+
var RETRY_AFTER_SHAPE = /^(?:\d{1,10}|[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} GMT)$/;
|
|
213
|
+
async function readErrorBody(response) {
|
|
214
|
+
const json = await response.json().catch(() => null);
|
|
215
|
+
if (typeof json !== "object" || json === null) return {};
|
|
216
|
+
const { error, message } = json;
|
|
217
|
+
return {
|
|
218
|
+
...typeof error === "string" && { error },
|
|
219
|
+
...typeof message === "string" && { message }
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function retryAfterOf(response) {
|
|
223
|
+
const value = response.headers.get("retry-after");
|
|
224
|
+
return value !== null && RETRY_AFTER_SHAPE.test(value) ? value : void 0;
|
|
225
|
+
}
|
|
206
226
|
function decodePaymentHeader(paymentHeader) {
|
|
207
227
|
try {
|
|
208
228
|
return decodeBase64(paymentHeader);
|
|
@@ -226,9 +246,15 @@ var FacilitatorClient = class {
|
|
|
226
246
|
signal: AbortSignal.timeout(FACILITATOR_TIMEOUT_MS)
|
|
227
247
|
});
|
|
228
248
|
if (!response.ok) {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
249
|
+
const body = await readErrorBody(response);
|
|
250
|
+
throw new X402RuntimeError(
|
|
251
|
+
body.error ?? X402_ERROR_CODES.FACILITATOR_UNAVAILABLE,
|
|
252
|
+
{
|
|
253
|
+
detail: body.message,
|
|
254
|
+
status: response.status,
|
|
255
|
+
retryAfter: retryAfterOf(response)
|
|
256
|
+
}
|
|
257
|
+
);
|
|
232
258
|
}
|
|
233
259
|
json = await response.json();
|
|
234
260
|
} catch (e) {
|
|
@@ -236,7 +262,8 @@ var FacilitatorClient = class {
|
|
|
236
262
|
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE);
|
|
237
263
|
}
|
|
238
264
|
try {
|
|
239
|
-
verifyResponseSchema.parse(json);
|
|
265
|
+
const { settleToken } = verifyResponseSchema.parse(json);
|
|
266
|
+
return { settleToken };
|
|
240
267
|
} catch {
|
|
241
268
|
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_INVALID_RESPONSE);
|
|
242
269
|
}
|
|
@@ -248,25 +275,42 @@ var FacilitatorClient = class {
|
|
|
248
275
|
const response = await fetch(`${this.config.url}/x402/settle`, {
|
|
249
276
|
method: "POST",
|
|
250
277
|
headers: this.buildHeaders(),
|
|
251
|
-
// settleAmount only travels for metered routes
|
|
278
|
+
// settleAmount only travels for metered routes; the settle token
|
|
279
|
+
// travels whenever verify issued one.
|
|
252
280
|
body: JSON.stringify({
|
|
253
281
|
paymentPayload,
|
|
254
282
|
paymentRequirements,
|
|
255
283
|
...options?.amount !== void 0 && {
|
|
256
284
|
settleAmount: options.amount
|
|
285
|
+
},
|
|
286
|
+
...options?.settleToken !== void 0 && {
|
|
287
|
+
settleToken: options.settleToken
|
|
257
288
|
}
|
|
258
289
|
}),
|
|
259
290
|
signal: AbortSignal.timeout(SETTLE_TIMEOUT_MS)
|
|
260
291
|
});
|
|
261
292
|
if (!response.ok) {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
293
|
+
const body = await readErrorBody(response);
|
|
294
|
+
if (body.error === void 0 && response.status >= 500) {
|
|
295
|
+
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE);
|
|
296
|
+
}
|
|
297
|
+
const retryAfter = retryAfterOf(response);
|
|
298
|
+
return {
|
|
299
|
+
success: false,
|
|
300
|
+
error: {
|
|
301
|
+
code: body.error ?? "SUBMISSION_FAILED",
|
|
302
|
+
message: body.message ?? "Settlement failed",
|
|
303
|
+
status: response.status,
|
|
304
|
+
...retryAfter !== void 0 && { retryAfter }
|
|
305
|
+
}
|
|
306
|
+
};
|
|
266
307
|
}
|
|
267
308
|
json = await response.json();
|
|
268
309
|
} catch (e) {
|
|
269
310
|
if (e instanceof X402RuntimeError) throw e;
|
|
311
|
+
if (e instanceof Error && e.name === "TimeoutError") {
|
|
312
|
+
throw new X402RuntimeError(X402_ERROR_CODES.SETTLE_TIMEOUT);
|
|
313
|
+
}
|
|
270
314
|
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE);
|
|
271
315
|
}
|
|
272
316
|
try {
|
|
@@ -281,7 +325,8 @@ var FacilitatorClient = class {
|
|
|
281
325
|
networkId: toEip155Network(paymentRequirements.network),
|
|
282
326
|
...parsed.amountSettled !== void 0 && {
|
|
283
327
|
amountSettled: parsed.amountSettled
|
|
284
|
-
}
|
|
328
|
+
},
|
|
329
|
+
...parsed.alreadySettled && { alreadySettled: true }
|
|
285
330
|
};
|
|
286
331
|
}
|
|
287
332
|
return {
|
|
@@ -379,10 +424,21 @@ async function resolvePrice(config, ctx) {
|
|
|
379
424
|
}
|
|
380
425
|
var SETTLE_AMOUNT_HEADER = "payment-settle-amount";
|
|
381
426
|
var DEFAULT_MAX_TIMEOUT_SECONDS = 300;
|
|
427
|
+
var SETTLEMENT_RESERVE_SECONDS = 120;
|
|
382
428
|
function handlerTimeoutFor(config) {
|
|
383
429
|
if ((config.scheme ?? "exact") !== "upto") return HANDLER_TIMEOUT_MS;
|
|
384
430
|
const seconds = config.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;
|
|
385
|
-
return Math.max(
|
|
431
|
+
return Math.max(
|
|
432
|
+
HANDLER_TIMEOUT_MS,
|
|
433
|
+
(seconds - SETTLEMENT_RESERVE_SECONDS) * 1e3
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
function jsonResult(status, body, headers = {}) {
|
|
437
|
+
return {
|
|
438
|
+
status,
|
|
439
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
440
|
+
body
|
|
441
|
+
};
|
|
386
442
|
}
|
|
387
443
|
function resolveSettleAmount(raw, maxAmount, decimals) {
|
|
388
444
|
if (raw === void 0)
|
|
@@ -410,7 +466,10 @@ var INVALID_METER_RESPONSE = {
|
|
|
410
466
|
message: "The route's meter function failed or returned something that is not an amount; the response was discarded and nothing was charged."
|
|
411
467
|
};
|
|
412
468
|
function invalidSettleAmountResponse(reason) {
|
|
413
|
-
return
|
|
469
|
+
return jsonResult(
|
|
470
|
+
402,
|
|
471
|
+
reason === "meter" ? INVALID_METER_RESPONSE : INVALID_SETTLE_AMOUNT_RESPONSE
|
|
472
|
+
);
|
|
414
473
|
}
|
|
415
474
|
var AMOUNT_FORMAT = /^\d+(?:\.\d+)?$/;
|
|
416
475
|
async function resolveCharge(verified, settleHeader, response) {
|
|
@@ -558,23 +617,37 @@ function buildFacilitatorRequirements(config, asset, price) {
|
|
|
558
617
|
}
|
|
559
618
|
};
|
|
560
619
|
}
|
|
561
|
-
|
|
620
|
+
var CODE_SHAPE = /^[A-Z][A-Z0-9_]{2,63}$/;
|
|
621
|
+
var MESSAGE_MAX_LENGTH = 300;
|
|
622
|
+
function shapedCode(code) {
|
|
623
|
+
return typeof code === "string" && CODE_SHAPE.test(code) ? code : void 0;
|
|
624
|
+
}
|
|
625
|
+
function boundedMessage(message) {
|
|
626
|
+
if (typeof message !== "string") return void 0;
|
|
627
|
+
const oneLine = message.replace(/[\p{Cc}\p{Cf}]+/gu, " ").replace(/\s+/g, " ").trim();
|
|
628
|
+
if (!oneLine) return void 0;
|
|
629
|
+
const chars = Array.from(oneLine);
|
|
630
|
+
return chars.length > MESSAGE_MAX_LENGTH ? `${chars.slice(0, MESSAGE_MAX_LENGTH).join("")}\u2026` : oneLine;
|
|
631
|
+
}
|
|
632
|
+
function paymentRequiredResponse(url, config, resolvedTokens, price, refusal) {
|
|
562
633
|
const paymentRequired = buildPaymentRequired(
|
|
563
634
|
url,
|
|
564
635
|
config,
|
|
565
636
|
resolvedTokens,
|
|
566
637
|
price
|
|
567
638
|
);
|
|
568
|
-
if (
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
639
|
+
if (refusal) {
|
|
640
|
+
paymentRequired.error = shapedCode(refusal.code) ?? X402_ERROR_CODES.FACILITATOR_INVALID_RESPONSE;
|
|
641
|
+
const message = boundedMessage(refusal.detail);
|
|
642
|
+
if (message) paymentRequired.message = message;
|
|
643
|
+
}
|
|
644
|
+
return jsonResult(402, paymentRequired, {
|
|
645
|
+
"payment-required": encodeBase64(paymentRequired),
|
|
646
|
+
"access-control-expose-headers": "payment-required",
|
|
647
|
+
...refusal?.retryAfter !== void 0 && {
|
|
648
|
+
"Retry-After": refusal.retryAfter
|
|
649
|
+
}
|
|
650
|
+
});
|
|
578
651
|
}
|
|
579
652
|
function createPaymentGate(config) {
|
|
580
653
|
try {
|
|
@@ -630,10 +703,11 @@ function createPaymentGate(config) {
|
|
|
630
703
|
asset,
|
|
631
704
|
price
|
|
632
705
|
);
|
|
706
|
+
let settleToken;
|
|
633
707
|
try {
|
|
634
|
-
await client.verify(paymentHeader, requirements);
|
|
708
|
+
({ settleToken } = await client.verify(paymentHeader, requirements));
|
|
635
709
|
} catch (e) {
|
|
636
|
-
const
|
|
710
|
+
const refusal = e instanceof X402RuntimeError ? { code: e.code, detail: e.detail, retryAfter: e.retryAfter } : { code: X402_ERROR_CODES.FACILITATOR_UNAVAILABLE };
|
|
637
711
|
return {
|
|
638
712
|
type: "error",
|
|
639
713
|
result: paymentRequiredResponse(
|
|
@@ -641,7 +715,7 @@ function createPaymentGate(config) {
|
|
|
641
715
|
routeConfig,
|
|
642
716
|
resolvedTokens,
|
|
643
717
|
price,
|
|
644
|
-
|
|
718
|
+
refusal
|
|
645
719
|
)
|
|
646
720
|
};
|
|
647
721
|
}
|
|
@@ -652,12 +726,71 @@ function createPaymentGate(config) {
|
|
|
652
726
|
maxAmount: BigInt(requirements.maxAmountRequired),
|
|
653
727
|
decimals: resolveDecimals(routeConfig, asset),
|
|
654
728
|
handlerTimeoutMs: handlerTimeoutFor(routeConfig),
|
|
655
|
-
|
|
656
|
-
settle: (options) => options ? client.settle(paymentHeader, requirements, options) : client.settle(paymentHeader, requirements),
|
|
729
|
+
settle: (options) => client.settle(paymentHeader, requirements, { ...options, settleToken }),
|
|
657
730
|
...routeConfig.meter && { meter: routeConfig.meter, request }
|
|
658
731
|
};
|
|
659
732
|
};
|
|
660
733
|
}
|
|
734
|
+
var UNKNOWN_SETTLEMENT_MESSAGE = "The payment could not be settled.";
|
|
735
|
+
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.";
|
|
736
|
+
var AGENT_MESSAGES = {
|
|
737
|
+
[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
|
+
[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.",
|
|
739
|
+
[X402_ERROR_CODES.FACILITATOR_INVALID_RESPONSE]: "The facilitator answered the settlement with an unexpected response. The payment may have settled: do not sign another payment for this request before checking with the merchant.",
|
|
740
|
+
SETTLE_IN_PROGRESS: "The facilitator is still settling this payment. Do not sign another payment for this request before checking with the merchant.",
|
|
741
|
+
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
|
+
SETTLE_TOKEN_INVALID: MERCHANT_SETTLEMENT_MESSAGE,
|
|
743
|
+
SETTLE_TOKEN_REQUIRED: MERCHANT_SETTLEMENT_MESSAGE,
|
|
744
|
+
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: UNKNOWN_SETTLEMENT_MESSAGE
|
|
746
|
+
};
|
|
747
|
+
function settlementFailure(code, failure) {
|
|
748
|
+
const reason = shapedCode(code) ?? "UNKNOWN";
|
|
749
|
+
return {
|
|
750
|
+
settled: false,
|
|
751
|
+
reason,
|
|
752
|
+
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ?? UNKNOWN_SETTLEMENT_MESSAGE,
|
|
753
|
+
...failure?.retryAfter !== void 0 && {
|
|
754
|
+
retryAfter: failure.retryAfter
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
var RETRY_ONCE_CODES = /* @__PURE__ */ new Set([
|
|
759
|
+
X402_ERROR_CODES.SETTLE_TIMEOUT,
|
|
760
|
+
X402_ERROR_CODES.FACILITATOR_UNAVAILABLE
|
|
761
|
+
]);
|
|
762
|
+
async function settleVerified(verified, options) {
|
|
763
|
+
let response;
|
|
764
|
+
for (let attempt = 0; response === void 0; attempt++) {
|
|
765
|
+
try {
|
|
766
|
+
response = await verified.settle(options);
|
|
767
|
+
} catch (e) {
|
|
768
|
+
const code = e instanceof X402RuntimeError ? e.code : "UNKNOWN";
|
|
769
|
+
if (attempt > 0 || !RETRY_ONCE_CODES.has(code)) {
|
|
770
|
+
return settlementFailure(code);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (!response.success) {
|
|
775
|
+
return settlementFailure(response.error.code, response.error);
|
|
776
|
+
}
|
|
777
|
+
if (options?.amount !== void 0 && response.amountSettled !== options.amount) {
|
|
778
|
+
return settlementFailure("AMOUNT_MISMATCH");
|
|
779
|
+
}
|
|
780
|
+
return { settled: true, confirmation: response };
|
|
781
|
+
}
|
|
782
|
+
function settlementFailureResponse(failure) {
|
|
783
|
+
const body = {
|
|
784
|
+
error: "PAYMENT_SETTLEMENT_FAILED",
|
|
785
|
+
reason: failure.reason,
|
|
786
|
+
message: failure.message
|
|
787
|
+
};
|
|
788
|
+
return jsonResult(402, body, {
|
|
789
|
+
...failure.retryAfter !== void 0 && {
|
|
790
|
+
"Retry-After": failure.retryAfter
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
}
|
|
661
794
|
function createPaymentMiddleware(config) {
|
|
662
795
|
const gate = createPaymentGate(config);
|
|
663
796
|
return async (adapter) => {
|
|
@@ -687,11 +820,7 @@ function createPaymentMiddleware(config) {
|
|
|
687
820
|
});
|
|
688
821
|
if (resolved.kind === "invalid") {
|
|
689
822
|
handlerResult.discardResponse();
|
|
690
|
-
return
|
|
691
|
-
status: 402,
|
|
692
|
-
headers: { "Content-Type": "application/json" },
|
|
693
|
-
body: invalidSettleAmountResponse(resolved.reason)
|
|
694
|
-
};
|
|
823
|
+
return invalidSettleAmountResponse(resolved.reason);
|
|
695
824
|
}
|
|
696
825
|
if (resolved.kind === "skip") {
|
|
697
826
|
handlerResult.sendResponse();
|
|
@@ -699,37 +828,23 @@ function createPaymentMiddleware(config) {
|
|
|
699
828
|
}
|
|
700
829
|
settleOptions = { amount: resolved.amount };
|
|
701
830
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const settleResponse = settleOptions ? await gateResult.settle(settleOptions) : await gateResult.settle();
|
|
705
|
-
if (settleResponse.success) {
|
|
706
|
-
handlerResult.setResponseHeader(
|
|
707
|
-
"payment-response",
|
|
708
|
-
encodeBase64(settleResponse)
|
|
709
|
-
);
|
|
710
|
-
handlerResult.setResponseHeader(
|
|
711
|
-
"access-control-expose-headers",
|
|
712
|
-
"payment-response"
|
|
713
|
-
);
|
|
714
|
-
settled = true;
|
|
715
|
-
}
|
|
716
|
-
} catch {
|
|
717
|
-
}
|
|
718
|
-
if (!settled) {
|
|
831
|
+
const outcome = await settleVerified(gateResult, settleOptions);
|
|
832
|
+
if (!outcome.settled) {
|
|
719
833
|
handlerResult.discardResponse();
|
|
720
|
-
return
|
|
721
|
-
status: 402,
|
|
722
|
-
headers: { "Content-Type": "application/json" },
|
|
723
|
-
body: {
|
|
724
|
-
error: "PAYMENT_SETTLEMENT_FAILED",
|
|
725
|
-
message: "Payment could not be confirmed after multiple attempts. Please retry."
|
|
726
|
-
}
|
|
727
|
-
};
|
|
834
|
+
return settlementFailureResponse(outcome);
|
|
728
835
|
}
|
|
836
|
+
handlerResult.setResponseHeader(
|
|
837
|
+
"payment-response",
|
|
838
|
+
encodeBase64(outcome.confirmation)
|
|
839
|
+
);
|
|
840
|
+
handlerResult.setResponseHeader(
|
|
841
|
+
"access-control-expose-headers",
|
|
842
|
+
"payment-response"
|
|
843
|
+
);
|
|
729
844
|
}
|
|
730
845
|
handlerResult.sendResponse();
|
|
731
846
|
return { pass: true, handlerRan: true };
|
|
732
847
|
};
|
|
733
848
|
}
|
|
734
849
|
|
|
735
|
-
export { FacilitatorClient, HANDLER_TIMEOUT, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, invalidSettleAmountResponse, isJsonContentType, jsonFromResponse, matchRoute, parseJsonBody, parsePrice, raceTimeout, resolveCharge, resolveSettleAmount, toEip155Network, validateAddress };
|
|
850
|
+
export { FacilitatorClient, HANDLER_TIMEOUT, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, invalidSettleAmountResponse, isJsonContentType, jsonFromResponse, matchRoute, parseJsonBody, parsePrice, raceTimeout, resolveCharge, resolveSettleAmount, settleVerified, settlementFailureResponse, toEip155Network, validateAddress };
|
package/dist/express.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
3
|
+
var chunkNA7245L5_cjs = require('./chunk-NA7245L5.cjs');
|
|
4
|
+
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/express/adapter.ts
|
|
7
7
|
function chunkBytes(args) {
|
|
@@ -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 chunkNA7245L5_cjs.raceTimeout(endPromise, options?.timeoutMs);
|
|
112
|
+
if (outcome === chunkNA7245L5_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 chunkNA7245L5_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 = chunkNA7245L5_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.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.cjs';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class ExpressAdapter implements HTTPAdapter {
|
package/dist/express.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, R as RunHandlerOptions, a as RunHandlerResult, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.js';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class ExpressAdapter implements HTTPAdapter {
|
package/dist/express.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-SA5ULSG2.js';
|
|
2
|
+
import './chunk-QAECRSWF.js';
|
|
3
3
|
|
|
4
4
|
// src/express/adapter.ts
|
|
5
5
|
function chunkBytes(args) {
|
package/dist/fastify.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
3
|
+
var chunkNA7245L5_cjs = require('./chunk-NA7245L5.cjs');
|
|
4
|
+
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
var fp = require('fastify-plugin');
|
|
6
6
|
|
|
7
7
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -37,12 +37,14 @@ 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 chunkNA7245L5_cjs.parseJsonBody(contentType, text);
|
|
41
41
|
}
|
|
42
|
-
function refuse(reply,
|
|
43
|
-
const json = JSON.stringify(body);
|
|
44
|
-
reply.status(
|
|
45
|
-
|
|
42
|
+
function refuse(reply, result) {
|
|
43
|
+
const json = JSON.stringify(result.body);
|
|
44
|
+
reply.status(result.status);
|
|
45
|
+
for (const [name, value] of Object.entries(result.headers)) {
|
|
46
|
+
reply.header(name, value);
|
|
47
|
+
}
|
|
46
48
|
reply.header("Content-Length", Buffer.byteLength(json));
|
|
47
49
|
return json;
|
|
48
50
|
}
|
|
@@ -52,11 +54,11 @@ function headerValue(value) {
|
|
|
52
54
|
}
|
|
53
55
|
function paymentMiddleware(config) {
|
|
54
56
|
return fp__default.default(async (fastify) => {
|
|
55
|
-
const gate =
|
|
57
|
+
const gate = chunkNA7245L5_cjs.createPaymentGate(config);
|
|
56
58
|
const verifiedMap = /* @__PURE__ */ new WeakMap();
|
|
57
59
|
const rawWriters = /* @__PURE__ */ new WeakMap();
|
|
58
60
|
const needsBody = (req) => {
|
|
59
|
-
const route =
|
|
61
|
+
const route = chunkNA7245L5_cjs.matchRoute(
|
|
60
62
|
new FastifyAdapter(req).getPath(),
|
|
61
63
|
config.routes
|
|
62
64
|
);
|
|
@@ -109,41 +111,30 @@ function paymentMiddleware(config) {
|
|
|
109
111
|
if (!verified) return payload;
|
|
110
112
|
let raw;
|
|
111
113
|
if (verified.scheme === "upto") {
|
|
112
|
-
raw = headerValue(reply.getHeader(
|
|
113
|
-
reply.removeHeader(
|
|
114
|
+
raw = headerValue(reply.getHeader(chunkNA7245L5_cjs.SETTLE_AMOUNT_HEADER));
|
|
115
|
+
reply.removeHeader(chunkNA7245L5_cjs.SETTLE_AMOUNT_HEADER);
|
|
114
116
|
}
|
|
115
117
|
if (reply.statusCode < 200 || reply.statusCode >= 300) {
|
|
116
118
|
return payload;
|
|
117
119
|
}
|
|
118
120
|
let settleOptions;
|
|
119
121
|
if (verified.scheme === "upto") {
|
|
120
|
-
const resolved = await
|
|
122
|
+
const resolved = await chunkNA7245L5_cjs.resolveCharge(verified, raw, {
|
|
121
123
|
status: reply.statusCode,
|
|
122
124
|
header: (name) => headerValue(reply.getHeader(name)),
|
|
123
125
|
body: async () => payloadJson(headerValue(reply.getHeader("content-type")), payload)
|
|
124
126
|
});
|
|
125
127
|
if (resolved.kind === "invalid") {
|
|
126
|
-
return refuse(reply,
|
|
128
|
+
return refuse(reply, chunkNA7245L5_cjs.invalidSettleAmountResponse(resolved.reason));
|
|
127
129
|
}
|
|
128
130
|
if (resolved.kind === "skip") return payload;
|
|
129
131
|
settleOptions = { amount: resolved.amount };
|
|
130
132
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
reply.header("access-control-expose-headers", "payment-response");
|
|
137
|
-
settled = true;
|
|
138
|
-
}
|
|
139
|
-
} catch {
|
|
140
|
-
}
|
|
141
|
-
if (!settled) {
|
|
142
|
-
return refuse(reply, {
|
|
143
|
-
error: "PAYMENT_SETTLEMENT_FAILED",
|
|
144
|
-
message: "Payment could not be confirmed after multiple attempts. Please retry."
|
|
145
|
-
});
|
|
146
|
-
}
|
|
133
|
+
const outcome = await chunkNA7245L5_cjs.settleVerified(verified, settleOptions);
|
|
134
|
+
if (!outcome.settled)
|
|
135
|
+
return refuse(reply, chunkNA7245L5_cjs.settlementFailureResponse(outcome));
|
|
136
|
+
reply.header("payment-response", chunkNA7245L5_cjs.encodeBase64(outcome.confirmation));
|
|
137
|
+
reply.header("access-control-expose-headers", "payment-response");
|
|
147
138
|
return payload;
|
|
148
139
|
});
|
|
149
140
|
});
|
package/dist/fastify.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FastifyRequest, FastifyPluginAsync } from 'fastify';
|
|
2
|
-
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.cjs';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class FastifyAdapter implements HTTPAdapter {
|
package/dist/fastify.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FastifyRequest, FastifyPluginAsync } from 'fastify';
|
|
2
|
-
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-BkGQ2lPA.js';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class FastifyAdapter implements HTTPAdapter {
|
package/dist/fastify.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-SA5ULSG2.js';
|
|
2
|
+
import './chunk-QAECRSWF.js';
|
|
3
3
|
import fp from 'fastify-plugin';
|
|
4
4
|
|
|
5
5
|
// src/fastify/adapter.ts
|
|
@@ -33,10 +33,12 @@ function payloadJson(contentType, payload) {
|
|
|
33
33
|
const text = typeof payload === "string" ? payload : payload instanceof Uint8Array ? Buffer.from(payload).toString("utf8") : void 0;
|
|
34
34
|
return parseJsonBody(contentType, text);
|
|
35
35
|
}
|
|
36
|
-
function refuse(reply,
|
|
37
|
-
const json = JSON.stringify(body);
|
|
38
|
-
reply.status(
|
|
39
|
-
|
|
36
|
+
function refuse(reply, result) {
|
|
37
|
+
const json = JSON.stringify(result.body);
|
|
38
|
+
reply.status(result.status);
|
|
39
|
+
for (const [name, value] of Object.entries(result.headers)) {
|
|
40
|
+
reply.header(name, value);
|
|
41
|
+
}
|
|
40
42
|
reply.header("Content-Length", Buffer.byteLength(json));
|
|
41
43
|
return json;
|
|
42
44
|
}
|
|
@@ -122,22 +124,11 @@ function paymentMiddleware(config) {
|
|
|
122
124
|
if (resolved.kind === "skip") return payload;
|
|
123
125
|
settleOptions = { amount: resolved.amount };
|
|
124
126
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
reply.header("access-control-expose-headers", "payment-response");
|
|
131
|
-
settled = true;
|
|
132
|
-
}
|
|
133
|
-
} catch {
|
|
134
|
-
}
|
|
135
|
-
if (!settled) {
|
|
136
|
-
return refuse(reply, {
|
|
137
|
-
error: "PAYMENT_SETTLEMENT_FAILED",
|
|
138
|
-
message: "Payment could not be confirmed after multiple attempts. Please retry."
|
|
139
|
-
});
|
|
140
|
-
}
|
|
127
|
+
const outcome = await settleVerified(verified, settleOptions);
|
|
128
|
+
if (!outcome.settled)
|
|
129
|
+
return refuse(reply, settlementFailureResponse(outcome));
|
|
130
|
+
reply.header("payment-response", encodeBase64(outcome.confirmation));
|
|
131
|
+
reply.header("access-control-expose-headers", "payment-response");
|
|
141
132
|
return payload;
|
|
142
133
|
});
|
|
143
134
|
});
|
package/dist/hono.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
3
|
+
var chunkNA7245L5_cjs = require('./chunk-NA7245L5.cjs');
|
|
4
|
+
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/hono/adapter.ts
|
|
7
7
|
var TIMEOUT_BODY = JSON.stringify({
|
|
@@ -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 (!chunkNA7245L5_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 chunkNA7245L5_cjs.raceTimeout(this.next(), options?.timeoutMs);
|
|
42
|
+
if (outcome === chunkNA7245L5_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: () => chunkNA7245L5_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 = chunkNA7245L5_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) {
|