@seedhape/x402-merchant-sdk 0.3.5 → 0.5.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 CHANGED
@@ -1,5 +1,72 @@
1
1
  # @seedhape/x402-merchant-sdk
2
2
 
3
+ ## One catalog for agent commerce
4
+
5
+ Use `createMerchantCommerce` to define products once. The same product
6
+ definitions can feed the SDK's current x402 paywall and future ACP/UCP/MPP
7
+ adapters; merchants do not maintain protocol-specific catalogs.
8
+
9
+ ```ts
10
+ const commerce = createMerchantCommerce({
11
+ paywall: { payTo, ...base, facilitator: base.facilitator },
12
+ products: [{
13
+ id: "weather", name: "Weather API", description: "Current weather",
14
+ endpoint: "/weather",
15
+ price: { amount: 50_000n, ...base },
16
+ }],
17
+ });
18
+
19
+ commerce.catalog(); // publish to your agent-facing catalog
20
+ commerce.paywallFor("weather"); // pass to existing paywall middleware
21
+ ```
22
+
23
+ The helper normalizes discovery metadata and product lookup. Fulfillment and
24
+ refunds remain merchant-owned and should use the purchase ID as their durable
25
+ idempotency key.
26
+
27
+ ## Unified seller facade (preview)
28
+
29
+ `createSeedhapeSeller` is the single-drop-in entry point for a server-side
30
+ Express route. Define each product once and keep provider credentials in the
31
+ server environment:
32
+
33
+ ```ts
34
+ import { base, createSeedhapeSeller } from "@seedhape/x402-merchant-sdk";
35
+
36
+ const seller = createSeedhapeSeller({
37
+ products: [{
38
+ id: "weather",
39
+ name: "Weather API",
40
+ description: "Current weather data",
41
+ endpoint: "/weather",
42
+ price: "0.50",
43
+ fulfill: async () => ({ temperature: 24 }),
44
+ }],
45
+ payments: {
46
+ x402: {
47
+ payTo: process.env.MERCHANT_WALLET!,
48
+ network: base.network,
49
+ asset: base.asset,
50
+ decimals: base.decimals,
51
+ facilitator: base.facilitator,
52
+ },
53
+ stripeMpp: {
54
+ stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
55
+ profileId: process.env.STRIPE_PROFILE_ID!,
56
+ mppSecretKey: process.env.MPP_SECRET_KEY!,
57
+ },
58
+ },
59
+ });
60
+
61
+ app.all("/weather", seller.route("weather"));
62
+ ```
63
+
64
+ The facade preserves the existing x402 Bazaar discovery challenge. It selects
65
+ Stripe MPP when a client advertises the MPP payment scheme and selects x402
66
+ otherwise. ACP/UCP checkout remains a separate integration gate; it will
67
+ consume the same catalog rather than requiring another merchant catalog or
68
+ middleware stack.
69
+
3
70
  Add an x402 payment gate to an existing Express, Hono, or `node:http` service. The SDK returns a standard `402 Payment Required` challenge, verifies the buyer's payment through an x402 facilitator, settles USDC directly to the merchant wallet, and exposes a receipt for your application ledger.
4
71
 
5
72
  ## Install
@@ -8,6 +75,44 @@ Add an x402 payment gate to an existing Express, Hono, or `node:http` service. T
8
75
  npm install @seedhape/x402-merchant-sdk
9
76
  ```
10
77
 
78
+ ## Stripe machine payments (MPP)
79
+
80
+ Install the optional MPP runtime when you want agents to pay with Stripe cards
81
+ or Shared Payment Tokens:
82
+
83
+ ```bash
84
+ npm install mppx
85
+ ```
86
+
87
+ Create one Stripe MPP paywall per seller endpoint. The seller keeps the Stripe
88
+ secret key and `profile_test_...` profile ID on the server; the SDK returns the
89
+ payment challenge and settles the credential without exposing either value:
90
+
91
+ ```ts
92
+ import { createStripeMppPaywall } from "@seedhape/x402-merchant-sdk";
93
+
94
+ const mpp = await createStripeMppPaywall({
95
+ stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
96
+ profileId: process.env.STRIPE_PROFILE_ID!,
97
+ mppSecretKey: process.env.MPP_SECRET_KEY!,
98
+ amount: "0.50",
99
+ currency: "usd",
100
+ description: "Weather API request",
101
+ });
102
+
103
+ export async function weather(request: Request) {
104
+ return mpp.handle(request, async () =>
105
+ Response.json({ temperature: 24, conditions: "clear" }),
106
+ );
107
+ }
108
+ ```
109
+
110
+ An unpaid agent receives HTTP `402`; a valid credential is verified and
111
+ settled before the fulfillment callback runs. For a Stripe Connect direct
112
+ charge, pass `connect: { stripeAccount: "acct_..." }`. To enable Stripe's
113
+ stablecoin MPP rail as well, supply a Stripe SDK client and a test Tempo deposit
114
+ address. Use `profile_test_...` and `sk_test_...` in a Stripe Sandbox.
115
+
11
116
  ## Express
12
117
 
13
118
  ```ts
@@ -43,7 +148,7 @@ app.get("/weather", (req, res) => {
43
148
 
44
149
  ## Network presets and payment methods
45
150
 
46
- Use `base` or `baseSepolia` to preconfigure the CAIP-2 network, USDC contract, decimals, and default facilitator:
151
+ Use `base`, `baseSepolia`, `solana`, or `solanaDevnet` to preconfigure the CAIP-2 network, USDC mint/contract, decimals, and default facilitator:
47
152
 
48
153
  ```ts
49
154
  import { baseSepolia, expressPaywall, merchantConfig } from "@seedhape/x402-merchant-sdk";
@@ -59,6 +164,76 @@ app.use(expressPaywall(merchantConfig(baseSepolia, {
59
164
 
60
165
  `paymentMethods` defaults to `['eip3009']`, the broadly supported payment method. Set `['eip3009', 'erc7710']` to let the buyer/client choose both methods. Only advertise ERC-7710 when the configured facilitator supports it. If the methods use different facilitators, configure `facilitators: { eip3009: {...}, erc7710: {...} }`; the SDK selects the facilitator matching the buyer's selected method.
61
166
 
167
+ ### Base and Solana on one route
168
+
169
+ Use `accepts` to expose both chains from the same resource. Bazaar and downstream catalogs such as Agentic Market treat these as payment choices on one service listing:
170
+
171
+ ```ts
172
+ import { base, solana, expressPaywall, merchantConfig } from "@seedhape/x402-merchant-sdk";
173
+
174
+ // Create cdpFacilitator with createCdpFacilitatorClient as shown below.
175
+
176
+ app.use(expressPaywall(merchantConfig(base, {
177
+ accepts: [{
178
+ ...base,
179
+ payTo: process.env.BASE_MERCHANT_WALLET!,
180
+ paymentMethods: ["eip3009"],
181
+ }, {
182
+ ...solana,
183
+ payTo: process.env.SOLANA_MERCHANT_WALLET!,
184
+ feePayer: process.env.SOLANA_FEE_PAYER!,
185
+ }],
186
+ price: { amount: 10_000n, ...base },
187
+ facilitator: {
188
+ url: "https://api.cdp.coinbase.com/platform/v2/x402",
189
+ client: cdpFacilitator,
190
+ },
191
+ route: {
192
+ name: "Market Data",
193
+ description: "Paid market data on Base or Solana",
194
+ inputSchema: { type: "object", properties: { symbol: { type: "string" } } },
195
+ outputSchema: { type: "object" },
196
+ },
197
+ })));
198
+ ```
199
+
200
+ `feePayer` is the Solana facilitator signer advertised by its `/supported` response; it is not the merchant wallet. Use a facilitator that supports every advertised network, or set a per-option `facilitator`. Solana payments use the official x402 `exact` SVM scheme and a base64-encoded, partially signed versioned transaction in `PAYMENT-SIGNATURE`.
201
+
202
+ The built-in Solana mainnet preset uses `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` and native USDC mint `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. Solana addresses are case-sensitive.
203
+ Its default facilitator is `https://facilitator.payai.network`; the devnet preset uses the test-only `https://x402.org/facilitator`.
204
+
205
+ ### Browser wallet paywall
206
+
207
+ Install the optional official UI when people should be able to open the paid route directly and pay with an EVM or Solana browser wallet:
208
+
209
+ ```bash
210
+ npm install @seedhape/x402-merchant-sdk @x402/paywall react react-dom
211
+ ```
212
+
213
+ Then enable it on the same configuration:
214
+
215
+ ```ts
216
+ const config = merchantConfig(base, {
217
+ accepts: [
218
+ { ...base, payTo: process.env.BASE_MERCHANT_WALLET! },
219
+ {
220
+ ...solana,
221
+ payTo: process.env.SOLANA_MERCHANT_WALLET!,
222
+ feePayer: process.env.SOLANA_FEE_PAYER!,
223
+ },
224
+ ],
225
+ price: { amount: 10_000n, ...base },
226
+ browserPaywall: {
227
+ appName: "Market Data",
228
+ appLogo: "https://api.example.com/icon-512.png",
229
+ testnet: false,
230
+ },
231
+ facilitator: { url: "https://facilitator.payai.network" },
232
+ });
233
+ ```
234
+
235
+ Express, Hono, and `node:http` adapters now return the official `@x402/paywall` HTML when the request accepts `text/html`. Programmatic callers continue receiving the normal JSON challenge and `PAYMENT-REQUIRED` header. The UI registers both official `evmPaywall` and `svmPaywall` handlers. Because `@x402/paywall` is an optional peer dependency, API-only installations do not pull its browser-wallet and React dependency tree.
236
+
62
237
  ### Coinbase CDP Facilitator and Bazaar
63
238
 
64
239
  For Coinbase Bazaar indexing, use Coinbase's authenticated facilitator client rather than passing the CDP API secret as a bearer token:
@@ -169,7 +344,7 @@ The HTTP route and MCP tool produce separate x402 resources, so each can have it
169
344
 
170
345
  Enable AP2 on an HTTP paywall to issue a signed merchant Checkout JWT with every unpaid or rejected `402` response. The SDK returns it in the `AP2-CHECKOUT-JWT` header; this does not change x402 verification or settlement.
171
346
 
172
- AP2 is optional. A route without the `ap2` option behaves exactly like a normal x402 route. AP2 adds signed checkout context for AP2-aware buyers and agents; the facilitator still verifies and settles the EIP-3009 or ERC-7710 payment.
347
+ AP2 is optional. A route without the `ap2` option behaves exactly like a normal x402 route. AP2 adds signed checkout context for AP2-aware buyers and agents; the facilitator still verifies and settles the EIP-3009 or ERC-7710 payment. The current Checkout JWT binds one network, so SDK routes using `ap2` must configure a single payment option; multi-network Solana AP2 mandates are a separate follow-up.
173
348
 
174
349
  ```ts
175
350
  app.use(expressPaywall(merchantConfig(base, {
@@ -217,8 +392,8 @@ PAYMENT-REQUIRED: eyJ...
217
392
 
218
393
  ## Payment flow
219
394
 
220
- 1. An unpaid request receives a v2 `402` challenge with a `PAYMENT-REQUIRED` header containing the merchant wallet, USDC asset, Base network, amount, and resource URL.
221
- 2. The buyer creates an x402 payment using EIP-3009 or ERC-7710 and sends it in `PAYMENT-SIGNATURE`.
395
+ 1. An unpaid request receives a v2 `402` challenge with a `PAYMENT-REQUIRED` header containing one or more accepted networks, recipient wallets, USDC assets, the amount, and resource URL.
396
+ 2. The buyer selects an accepted option, creates an EVM authorization or Solana transaction, and sends it in `PAYMENT-SIGNATURE`.
222
397
  3. The facilitator verifies and settles the payment.
223
398
  4. USDC settles directly to `payTo`; Seedhape never holds merchant funds.
224
399
  5. The request continues and the settlement is returned in `PAYMENT-RESPONSE`.
@@ -227,7 +402,7 @@ The SDK emits the current x402 v2 challenge shape. For migration, it also accept
227
402
 
228
403
  ## Official x402 integrations
229
404
 
230
- The SDK is built on the official `@x402/core` and `@x402/evm` packages. EIP-3009 verification and settlement use `x402ResourceServer`, `HTTPFacilitatorClient`, and the official EVM exact scheme. Bazaar declarations use `@x402/extensions/bazaar` and are registered with the resource server.
405
+ The SDK is built on the official `@x402/core`, `@x402/evm`, and `@x402/svm` packages. EIP-3009 and exact-SVM verification and settlement use `x402ResourceServer`, `HTTPFacilitatorClient`, and the official chain scheme. Bazaar declarations use `@x402/extensions/bazaar` and are registered with the resource server.
231
406
 
232
407
  ERC-7710 remains an opt-in Seedhape facilitator method because the official EVM exact server currently covers EIP-3009 and Permit2, not ERC-7710. When `erc7710` is selected, the SDK routes it to the configured facilitator override; it never silently sends an ERC-7710 payload through the EIP-3009 verifier.
233
408
 
@@ -250,7 +425,7 @@ Sonar listing does not replace Bazaar metadata. A merchant can publish Bazaar di
250
425
  ## Production checklist
251
426
 
252
427
  - Use a self-custodial merchant receiving address.
253
- - Use `eip155:8453` and Base USDC in production; use Base Sepolia only for testing.
428
+ - Use Base mainnet or Solana mainnet presets in production and their testnet/devnet presets only for testing.
254
429
  - Configure a production facilitator URL and keep it server-side.
255
430
  - Keep health, documentation, and discovery metadata routes free.
256
431
  - Record the receipt ID, resource, payer, amount, network, and transaction hash.
@@ -0,0 +1,50 @@
1
+ /** Structural subset of the official renderer, kept local so server-only users do not need its types. */
2
+ export interface BrowserPaywallProvider {
3
+ generateHtml(paymentRequired: BrowserPaymentRequired, config?: BrowserPaywallRuntimeConfig): string;
4
+ }
5
+ export interface BrowserPaywallRuntimeConfig {
6
+ appName?: string;
7
+ appLogo?: string;
8
+ currentUrl?: string;
9
+ testnet?: boolean;
10
+ faucetUrls?: Record<string, string>;
11
+ }
12
+ export interface BrowserPaymentRequired {
13
+ x402Version: number;
14
+ error?: string;
15
+ resource?: {
16
+ url: string;
17
+ description?: string;
18
+ mimeType?: string;
19
+ };
20
+ accepts: Array<{
21
+ scheme: string;
22
+ network: string;
23
+ asset: string;
24
+ payTo: string;
25
+ maxTimeoutSeconds: number;
26
+ extra?: Record<string, unknown>;
27
+ amount?: string;
28
+ maxAmountRequired?: string;
29
+ description?: string;
30
+ resource?: string;
31
+ mimeType?: string;
32
+ }>;
33
+ extensions?: Record<string, unknown>;
34
+ }
35
+ /** Runtime options passed to the official browser paywall renderer. */
36
+ export interface BrowserPaywallConfig extends BrowserPaywallRuntimeConfig {
37
+ /** Inject a custom provider, primarily for custom themes or tests. */
38
+ provider?: BrowserPaywallProvider;
39
+ }
40
+ /**
41
+ * Build the official x402 browser paywall with handlers for both EVM and Solana.
42
+ * `@x402/paywall` is an optional peer so server-only SDK installs stay lean.
43
+ */
44
+ export declare function createBrowserPaywallProvider(config?: BrowserPaywallRuntimeConfig): Promise<BrowserPaywallProvider>;
45
+ export declare function renderBrowserPaywall(args: {
46
+ paymentRequired: unknown;
47
+ accept?: string | string[];
48
+ config: true | BrowserPaywallConfig;
49
+ }): Promise<string | undefined>;
50
+ //# sourceMappingURL=browser-paywall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-paywall.d.ts","sourceRoot":"","sources":["../src/browser-paywall.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,eAAe,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE,2BAA2B,GAAG,MAAM,CAAC;CACrG;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,iBAAiB,EAAE,MAAM,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAqB,SAAQ,2BAA2B;IACvE,sEAAsE;IACtE,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,GAAE,2BAAgC,GACvC,OAAO,CAAC,sBAAsB,CAAC,CAkBjC;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,IAAI,GAAG,oBAAoB,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY9B"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Build the official x402 browser paywall with handlers for both EVM and Solana.
3
+ * `@x402/paywall` is an optional peer so server-only SDK installs stay lean.
4
+ */
5
+ export async function createBrowserPaywallProvider(config = {}) {
6
+ try {
7
+ const [{ createPaywall }, { evmPaywall }, { svmPaywall }] = await Promise.all([
8
+ import("@x402/paywall"),
9
+ import("@x402/paywall/evm"),
10
+ import("@x402/paywall/svm"),
11
+ ]);
12
+ return createPaywall()
13
+ .withNetwork(evmPaywall)
14
+ .withNetwork(svmPaywall)
15
+ .withConfig(config)
16
+ .build();
17
+ }
18
+ catch (cause) {
19
+ throw new Error("Browser paywall support requires the optional @x402/paywall peer dependency (version 2.23.0 or newer).", { cause });
20
+ }
21
+ }
22
+ export async function renderBrowserPaywall(args) {
23
+ const accept = Array.isArray(args.accept) ? args.accept.join(",") : args.accept ?? "";
24
+ if (!accept.toLowerCase().includes("text/html"))
25
+ return undefined;
26
+ const configured = args.config === true ? {} : args.config;
27
+ const { provider, ...runtimeConfig } = configured;
28
+ const resolvedProvider = provider ?? await createBrowserPaywallProvider(runtimeConfig);
29
+ const paymentRequired = args.paymentRequired;
30
+ return resolvedProvider.generateHtml(paymentRequired, {
31
+ ...runtimeConfig,
32
+ currentUrl: runtimeConfig.currentUrl ?? paymentRequired.resource?.url,
33
+ });
34
+ }
35
+ //# sourceMappingURL=browser-paywall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-paywall.js","sourceRoot":"","sources":["../src/browser-paywall.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,SAAsC,EAAE;IAExC,IAAI,CAAC;QACH,MAAM,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5E,MAAM,CAAC,eAAe,CAAC;YACvB,MAAM,CAAC,mBAAmB,CAAC;YAC3B,MAAM,CAAC,mBAAmB,CAAC;SAC5B,CAAC,CAAC;QACH,OAAO,aAAa,EAAE;aACnB,WAAW,CAAC,UAAU,CAAC;aACvB,WAAW,CAAC,UAAU,CAAC;aACvB,UAAU,CAAC,MAAM,CAAC;aAClB,KAAK,EAAE,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,wGAAwG,EACxG,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAI1C;IACC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACtF,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAC;IAElE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAC3D,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,GAAG,UAAU,CAAC;IAClD,MAAM,gBAAgB,GAAG,QAAQ,IAAI,MAAM,4BAA4B,CAAC,aAAa,CAAC,CAAC;IACvF,MAAM,eAAe,GAAG,IAAI,CAAC,eAAyC,CAAC;IACvE,OAAO,gBAAgB,CAAC,YAAY,CAAC,eAAe,EAAE;QACpD,GAAG,aAAa;QAChB,UAAU,EAAE,aAAa,CAAC,UAAU,IAAI,eAAe,CAAC,QAAQ,EAAE,GAAG;KACtE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { Money, PaywallConfig, RouteMetadata } from "./middleware.js";
2
+ /** A merchant's protocol-neutral, agent-readable product definition. */
3
+ export interface MerchantProduct {
4
+ id: string;
5
+ name: string;
6
+ description: string;
7
+ price: Money;
8
+ endpoint: string;
9
+ /** A human-readable policy; fulfillment/refund behavior stays merchant-owned. */
10
+ refundPolicy?: string;
11
+ metadata?: RouteMetadata;
12
+ }
13
+ export interface MerchantCommerceConfig {
14
+ /** Base paywall/provider configuration shared by every product. */
15
+ paywall: Omit<PaywallConfig, "price">;
16
+ products: readonly MerchantProduct[];
17
+ }
18
+ export interface MerchantCatalogProduct extends Omit<MerchantProduct, "price"> {
19
+ price: {
20
+ amount: string;
21
+ asset: string;
22
+ network: string;
23
+ decimals: number;
24
+ };
25
+ capabilities: readonly ["quote", "purchase", "receipt"];
26
+ }
27
+ /**
28
+ * One merchant integration surface for catalogs and paid routes. Protocol
29
+ * adapters consume the same product definitions, so a merchant does not keep
30
+ * separate ACP/UCP/x402/MPP catalogs. The returned PaywallConfig remains
31
+ * compatible with the existing Express/Hono/node:http middleware.
32
+ */
33
+ export declare function createMerchantCommerce(config: MerchantCommerceConfig): {
34
+ catalog(): MerchantCatalogProduct[];
35
+ product(id: string): MerchantProduct | null;
36
+ paywallFor(id: string): PaywallConfig;
37
+ };
38
+ //# sourceMappingURL=commerce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../src/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3E,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACtC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC;IAC5E,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,YAAY,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;CACzD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB;eAKtD,sBAAsB,EAAE;gBAOvB,MAAM,GAAG,eAAe,GAAG,IAAI;mBAG5B,MAAM,GAAG,aAAa;EAWxC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * One merchant integration surface for catalogs and paid routes. Protocol
3
+ * adapters consume the same product definitions, so a merchant does not keep
4
+ * separate ACP/UCP/x402/MPP catalogs. The returned PaywallConfig remains
5
+ * compatible with the existing Express/Hono/node:http middleware.
6
+ */
7
+ export function createMerchantCommerce(config) {
8
+ const byId = new Map(config.products.map((product) => [product.id, product]));
9
+ if (byId.size !== config.products.length)
10
+ throw new Error("Merchant product IDs must be unique.");
11
+ return {
12
+ catalog() {
13
+ return config.products.map((product) => ({
14
+ ...product,
15
+ price: { ...product.price, amount: product.price.amount.toString() },
16
+ capabilities: ["quote", "purchase", "receipt"],
17
+ }));
18
+ },
19
+ product(id) {
20
+ return byId.get(id) ?? null;
21
+ },
22
+ paywallFor(id) {
23
+ const product = byId.get(id);
24
+ if (!product)
25
+ throw new Error(`Unknown merchant product: ${id}`);
26
+ return {
27
+ ...config.paywall,
28
+ price: product.price,
29
+ description: product.description,
30
+ route: { ...product.metadata, name: product.metadata?.name ?? product.name, description: product.description },
31
+ };
32
+ },
33
+ };
34
+ }
35
+ //# sourceMappingURL=commerce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commerce.js","sourceRoot":"","sources":["../src/commerce.ts"],"names":[],"mappings":"AAyBA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAElG,OAAO;QACL,OAAO;YACL,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACvC,GAAG,OAAO;gBACV,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE;gBACpE,YAAY,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU;aACxD,CAAC,CAAC,CAAC;QACN,CAAC;QACD,OAAO,CAAC,EAAU;YAChB,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;QAC9B,CAAC;QACD,UAAU,CAAC,EAAU;YACnB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;YACjE,OAAO;gBACL,GAAG,MAAM,CAAC,OAAO;gBACjB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;aAC/G,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  export * from "./middleware.js";
2
2
  export * from "./mcp.js";
3
3
  export * from "./ap2.js";
4
+ export * from "./browser-paywall.js";
5
+ export * from "./commerce.js";
6
+ export * from "./mpp.js";
7
+ export * from "./stripe-mpp.js";
8
+ export * from "./seller.js";
4
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,9 @@
1
1
  export * from "./middleware.js";
2
2
  export * from "./mcp.js";
3
3
  export * from "./ap2.js";
4
+ export * from "./browser-paywall.js";
5
+ export * from "./commerce.js";
6
+ export * from "./mpp.js";
7
+ export * from "./stripe-mpp.js";
8
+ export * from "./seller.js";
4
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
package/dist/mcp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4CAA4C;IAC5C,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACxF,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE9C;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrG,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAmEf"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,aAAa,EAEnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4CAA4C;IAC5C,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACxF,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE9C;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrG,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CA4Ef"}
package/dist/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { createPaymentWrapper } from "@x402/mcp";
3
3
  import { declareDiscoveryExtension } from "@x402/extensions/bazaar";
4
- import { createOfficialResourceServer, } from "./middleware.js";
4
+ import { createOfficialResourceServer, resolvePaymentOptions, } from "./middleware.js";
5
5
  /**
6
6
  * Register a paid MCP tool using the same merchant configuration as HTTP routes.
7
7
  * The official @x402/mcp wrapper handles the MCP payment challenge, verification,
@@ -13,22 +13,29 @@ export async function createPaidMcpTool(server, paywall, tool, handler) {
13
13
  const price = typeof paywall.price === "function"
14
14
  ? (() => { throw new Error("MCP tools require a fixed price; configure per-call pricing in the MCP handler layer."); })()
15
15
  : paywall.price;
16
- const accepts = await resourceServer.buildPaymentRequirements({
16
+ const paymentOptions = resolvePaymentOptions(paywall);
17
+ if (paymentOptions.some((option) => option.facilitator)) {
18
+ throw new Error("MCP multi-network tools currently require one shared facilitator.");
19
+ }
20
+ const accepts = (await Promise.all(paymentOptions.map((option) => resourceServer.buildPaymentRequirements({
17
21
  scheme: "exact",
18
- network: paywall.network,
19
- payTo: paywall.payTo,
22
+ network: option.network,
23
+ payTo: option.payTo,
20
24
  price: {
21
- asset: paywall.asset,
25
+ asset: option.asset,
22
26
  amount: price.amount.toString(),
23
- extra: {
24
- name: "USD Coin",
25
- version: "2",
26
- decimals: paywall.decimals ?? 6,
27
- assetTransferMethod: "eip3009",
28
- },
27
+ extra: option.network.startsWith("solana:")
28
+ ? { ...(option.extra ?? {}), feePayer: option.feePayer ?? option.extra?.feePayer }
29
+ : {
30
+ name: "USD Coin",
31
+ version: "2",
32
+ decimals: option.decimals ?? 6,
33
+ assetTransferMethod: option.paymentMethods?.[0] ?? paywall.paymentMethods?.[0] ?? "eip3009",
34
+ ...(option.extra ?? {}),
35
+ },
29
36
  },
30
37
  maxTimeoutSeconds: paywall.maxTimeoutSeconds,
31
- });
38
+ })))).flat();
32
39
  const wrapped = createPaymentWrapper(resourceServer, {
33
40
  accepts,
34
41
  resource: {
@@ -51,18 +58,18 @@ export async function createPaidMcpTool(server, paywall, tool, handler) {
51
58
  onAfterSettlement: async ({ settlement, paymentPayload }) => {
52
59
  if (!settlement.success)
53
60
  return;
61
+ const accepted = paymentPayload.accepted;
54
62
  await paywall.receipts?.record({
55
63
  id: randomUUID(),
56
64
  resource: tool.resourceUrl ?? `mcp://tool/${tool.name}`,
57
65
  payer: settlement.payer,
58
- payTo: paywall.payTo,
66
+ payTo: accepted.payTo,
59
67
  amount: price.amount,
60
- asset: paywall.asset,
61
- network: paywall.network,
68
+ asset: accepted.asset,
69
+ network: accepted.network,
62
70
  txHash: settlement.transaction,
63
71
  settledAt: Math.floor(Date.now() / 1000),
64
72
  });
65
- void paymentPayload;
66
73
  },
67
74
  } : undefined,
68
75
  })(async (args) => ({
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@
12
12
  import type { IncomingMessage, ServerResponse } from "node:http";
13
13
  import { x402ResourceServer, type FacilitatorClient } from "@x402/core/server";
14
14
  import type { Ap2MerchantConfig } from "./ap2.js";
15
+ import { type BrowserPaywallConfig } from "./browser-paywall.js";
15
16
  export interface Money {
16
17
  /** Base units of the asset. USDC has 6 decimals. */
17
18
  amount: bigint;
@@ -53,6 +54,21 @@ export interface FacilitatorConfig {
53
54
  client?: FacilitatorClient;
54
55
  }
55
56
  export type PaymentMethod = "eip3009" | "erc7710";
57
+ /** One chain-specific way a buyer may pay for the same resource. */
58
+ export interface MerchantPaymentOption {
59
+ network: string;
60
+ asset: string;
61
+ payTo: string;
62
+ decimals?: number;
63
+ /** EVM transfer methods. Solana always uses the x402 `exact` SVM scheme. */
64
+ paymentMethods?: PaymentMethod[];
65
+ /** Override the route-level facilitator for this network. */
66
+ facilitator?: FacilitatorConfig;
67
+ /** Required for Solana HTTP challenges unless supplied in `extra.feePayer`. */
68
+ feePayer?: string;
69
+ /** Additional scheme-specific payment requirement fields. */
70
+ extra?: Record<string, unknown>;
71
+ }
56
72
  export interface JsonSchema {
57
73
  [key: string]: unknown;
58
74
  }
@@ -83,6 +99,8 @@ export interface MerchantNetworkConfig {
83
99
  decimals: number;
84
100
  facilitator: FacilitatorConfig;
85
101
  }
102
+ export declare const SOLANA_MAINNET: MerchantNetworkConfig;
103
+ export declare const SOLANA_DEVNET: MerchantNetworkConfig;
86
104
  /** Base mainnet + USDC defaults. Override any field for a custom facilitator. */
87
105
  export declare const BASE_MAINNET: MerchantNetworkConfig;
88
106
  /** Base Sepolia + USDC defaults for development and staging. */
@@ -90,16 +108,21 @@ export declare const BASE_SEPOLIA: MerchantNetworkConfig;
90
108
  /** Lowercase aliases make preset usage read naturally in route definitions. */
91
109
  export declare const base: MerchantNetworkConfig;
92
110
  export declare const baseSepolia: MerchantNetworkConfig;
111
+ export declare const solana: MerchantNetworkConfig;
112
+ export declare const solanaDevnet: MerchantNetworkConfig;
93
113
  export interface MerchantPresetConfig extends MerchantNetworkConfig {
94
114
  paymentMethods?: PaymentMethod[];
95
115
  }
96
116
  /** Compose a route configuration from a network preset without mutation. */
97
117
  export declare function merchantConfig(preset: MerchantPresetConfig, config: Omit<PaywallConfig, "network" | "asset" | "decimals" | "facilitator"> & Partial<Pick<PaywallConfig, "network" | "asset" | "decimals" | "facilitator">>): PaywallConfig;
98
118
  export interface PaywallConfig {
99
- payTo: string;
100
- network: string;
101
- asset: string;
119
+ /** Legacy single-network fields. Omit these when `accepts` is provided. */
120
+ payTo?: string;
121
+ network?: string;
122
+ asset?: string;
102
123
  decimals?: number;
124
+ /** Multiple chain-specific payment choices shown in one Bazaar/Agentic Market listing. */
125
+ accepts?: MerchantPaymentOption[];
103
126
  /** Payment authorization methods advertised in the 402 response. */
104
127
  paymentMethods?: PaymentMethod[];
105
128
  /** Optional facilitator overrides for individual transfer methods. */
@@ -122,6 +145,8 @@ export interface PaywallConfig {
122
145
  bazaar?: boolean;
123
146
  /** Optional merchant AP2 issuer. Adds AP2-CHECKOUT-JWT to 402 responses. */
124
147
  ap2?: Ap2MerchantConfig;
148
+ /** Render the official EVM + Solana browser UI for requests accepting text/html. */
149
+ browserPaywall?: true | BrowserPaywallConfig;
125
150
  maxTimeoutSeconds?: number;
126
151
  /** Routes that never require payment, e.g. ["/health", "/.well-known/*"]. */
127
152
  free?: string[];
@@ -168,9 +193,10 @@ export interface PaywallOutcome {
168
193
  export declare class Paywall {
169
194
  private readonly cfg;
170
195
  private readonly facilitator;
171
- private readonly decimals;
196
+ private readonly paymentOptions;
172
197
  constructor(cfg: PaywallConfig);
173
198
  priceFor(path: string, method: string, query: URLSearchParams): Money | null;
199
+ renderBrowserChallenge(challenge: unknown, accept?: string | string[]): Promise<string | undefined>;
174
200
  buildChallenge(price: Money, resource: string, method?: string): {
175
201
  x402Version: number;
176
202
  error: string;
@@ -195,6 +221,7 @@ export declare class Paywall {
195
221
  private facilitatorFor;
196
222
  private writeReceipt;
197
223
  }
224
+ export declare function resolvePaymentOptions(cfg: PaywallConfig): MerchantPaymentOption[];
198
225
  export declare function expressPaywall(cfg: PaywallConfig): (req: any, res: any, next: any) => Promise<any>;
199
226
  export declare function honoPaywall(cfg: PaywallConfig): (c: any, next: any) => Promise<any>;
200
227
  export declare function nodePaywall(cfg: PaywallConfig): (req: IncomingMessage, res: ServerResponse) => Promise<Receipt | "free" | null>;