@puga-labs/x402-mantle-sdk 0.3.9 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3DGAB7HD.js +126 -0
- package/dist/chunk-JXMWK3BO.js +96 -0
- package/dist/chunk-P5FKQVHW.js +99 -0
- package/dist/chunk-UVYA6H32.js +293 -0
- package/dist/express-BWE0nQty.d.cts +68 -0
- package/dist/express-BvuN0Lx1.d.ts +68 -0
- package/dist/index.cjs +58 -2
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/nextjs-Bujo9Okf.d.cts +89 -0
- package/dist/nextjs-CzSejZe8.d.ts +89 -0
- package/dist/server-express.cjs +58 -2
- package/dist/server-express.d.cts +2 -2
- package/dist/server-express.d.ts +2 -2
- package/dist/server-express.js +2 -2
- package/dist/server-nextjs.cjs +58 -2
- package/dist/server-nextjs.d.cts +2 -2
- package/dist/server-nextjs.d.ts +2 -2
- package/dist/server-nextjs.js +2 -2
- package/dist/server-web.cjs +58 -2
- package/dist/server-web.d.cts +2 -2
- package/dist/server-web.d.ts +2 -2
- package/dist/server-web.js +2 -2
- package/dist/server.cjs +84 -2
- package/dist/server.d.cts +8 -7
- package/dist/server.d.ts +8 -7
- package/dist/server.js +4 -4
- package/dist/types-Ba0v9XsC.d.ts +108 -0
- package/dist/types-BkGUHT4x.d.cts +108 -0
- package/dist/types-DEpSrXCf.d.ts +112 -0
- package/dist/types-DrBw0xwj.d.cts +112 -0
- package/dist/web-standards-DsCZRJPE.d.ts +77 -0
- package/dist/web-standards-QCbyQ14G.d.cts +77 -0
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { b as RoutesConfig, M as MinimalPaywallOptions } from './types-Ba0v9XsC.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Express middleware function type for Mantle paywall.
|
|
6
|
+
*/
|
|
7
|
+
type MantleMiddleware = (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
8
|
+
/** Config for createPaymentMiddleware. */
|
|
9
|
+
interface PaymentMiddlewareConfig {
|
|
10
|
+
/** Base URL of facilitator, e.g. https://facilitator.nosubs.ai */
|
|
11
|
+
facilitatorUrl: string;
|
|
12
|
+
/** Recipient address (developer). Validated at runtime. */
|
|
13
|
+
receiverAddress: string;
|
|
14
|
+
/** Map of protected routes and their pricing. */
|
|
15
|
+
routes: RoutesConfig;
|
|
16
|
+
/** Optional API key for hosted facilitator billing. */
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Optional hook called whenever a payment is successfully settled.
|
|
20
|
+
*/
|
|
21
|
+
onPaymentSettled?: MinimalPaywallOptions["onPaymentSettled"];
|
|
22
|
+
/** Optional: Send usage telemetry for billing/analytics. */
|
|
23
|
+
telemetry?: MinimalPaywallOptions["telemetry"];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create Express middleware for x402 payment verification on multiple routes.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const middleware = createPaymentMiddleware({
|
|
31
|
+
* facilitatorUrl: 'https://facilitator.nosubs.ai',
|
|
32
|
+
* receiverAddress: '0x...',
|
|
33
|
+
* routes: {
|
|
34
|
+
* 'POST /api/generate': { priceUsdCents: 1, network: 'mantle-mainnet' },
|
|
35
|
+
* 'GET /api/data': { priceUsdCents: 5, network: 'mantle-mainnet' },
|
|
36
|
+
* }
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* app.use(middleware);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function createPaymentMiddleware(config: PaymentMiddlewareConfig): MantleMiddleware;
|
|
43
|
+
/**
|
|
44
|
+
* Simplified wrapper for protecting a single route with x402 payments.
|
|
45
|
+
* Uses Mantle mainnet defaults (USDC, exact scheme, etc.).
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const pay = mantlePaywall({ priceUsd: 0.01, payTo: "0x..." });
|
|
50
|
+
* app.post('/api/generate', pay, async (req, res) => {
|
|
51
|
+
* // Your handler code here
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param opts - Minimal configuration (price, payTo, optional facilitator/telemetry).
|
|
56
|
+
* @returns Express middleware function for single-route protection.
|
|
57
|
+
*/
|
|
58
|
+
declare function mantlePaywall(opts: MinimalPaywallOptions): MantleMiddleware;
|
|
59
|
+
|
|
60
|
+
type express_MantleMiddleware = MantleMiddleware;
|
|
61
|
+
type express_PaymentMiddlewareConfig = PaymentMiddlewareConfig;
|
|
62
|
+
declare const express_createPaymentMiddleware: typeof createPaymentMiddleware;
|
|
63
|
+
declare const express_mantlePaywall: typeof mantlePaywall;
|
|
64
|
+
declare namespace express {
|
|
65
|
+
export { type express_MantleMiddleware as MantleMiddleware, type express_PaymentMiddlewareConfig as PaymentMiddlewareConfig, express_createPaymentMiddleware as createPaymentMiddleware, express_mantlePaywall as mantlePaywall };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { type MantleMiddleware as M, type PaymentMiddlewareConfig as P, createPaymentMiddleware as c, express as e, mantlePaywall as m };
|
package/dist/index.cjs
CHANGED
|
@@ -159,9 +159,20 @@ function createTelemetryEvent(entry, config) {
|
|
|
159
159
|
priceUsd: entry.paymentRequirements?.price
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
|
-
async function sendTelemetry(event, endpoint) {
|
|
162
|
+
async function sendTelemetry(event, endpoint, debug) {
|
|
163
163
|
const targetEndpoint = endpoint ?? DEFAULT_TELEMETRY_ENDPOINT;
|
|
164
|
+
if (debug) {
|
|
165
|
+
console.log(`[x402-debug:telemetry] \u{1F4E4} Sending telemetry event:`, {
|
|
166
|
+
event: event.event,
|
|
167
|
+
endpoint: targetEndpoint,
|
|
168
|
+
projectKey: event.projectKey.substring(0, 10) + "...",
|
|
169
|
+
route: event.route,
|
|
170
|
+
responseStatus: event.responseStatus,
|
|
171
|
+
serviceDelivered: event.serviceDelivered
|
|
172
|
+
});
|
|
173
|
+
}
|
|
164
174
|
if (!targetEndpoint) {
|
|
175
|
+
if (debug) console.log(`[x402-debug:telemetry] \u26A0\uFE0F No endpoint configured, skipping`);
|
|
165
176
|
return;
|
|
166
177
|
}
|
|
167
178
|
try {
|
|
@@ -173,17 +184,29 @@ async function sendTelemetry(event, endpoint) {
|
|
|
173
184
|
},
|
|
174
185
|
body: JSON.stringify(event)
|
|
175
186
|
});
|
|
187
|
+
if (debug) {
|
|
188
|
+
console.log(`[x402-debug:telemetry] ${response.ok ? "\u2705" : "\u274C"} Telemetry sent: HTTP ${response.status}`);
|
|
189
|
+
}
|
|
176
190
|
if (!response.ok) {
|
|
177
191
|
console.warn(
|
|
178
192
|
`[x402-telemetry] Failed to send event: HTTP ${response.status}`
|
|
179
193
|
);
|
|
180
194
|
}
|
|
181
195
|
} catch (err) {
|
|
196
|
+
if (debug) {
|
|
197
|
+
console.error(`[x402-debug:telemetry] \u274C Error sending:`, err);
|
|
198
|
+
}
|
|
182
199
|
console.error("[x402-telemetry] Error sending telemetry:", err);
|
|
183
200
|
}
|
|
184
201
|
}
|
|
185
202
|
|
|
186
203
|
// src/server/core/verifyPayment.ts
|
|
204
|
+
function debugLog(config, prefix, message, data) {
|
|
205
|
+
if (config?.debug) {
|
|
206
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
207
|
+
console.log(`[${timestamp}] [x402-debug:${prefix}]`, message, data || "");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
187
210
|
async function checkPayment(input) {
|
|
188
211
|
const {
|
|
189
212
|
paymentHeader,
|
|
@@ -271,6 +294,10 @@ async function checkPayment(input) {
|
|
|
271
294
|
facilitatorUrl,
|
|
272
295
|
paymentRequirements
|
|
273
296
|
};
|
|
297
|
+
debugLog(telemetry, "verify", "\u2705 Payment verified", {
|
|
298
|
+
nonce: authorization.nonce,
|
|
299
|
+
route: routeKey
|
|
300
|
+
});
|
|
274
301
|
if (onPaymentSettled) {
|
|
275
302
|
onPaymentSettled(baseLogEntry);
|
|
276
303
|
}
|
|
@@ -283,17 +310,33 @@ async function checkPayment(input) {
|
|
|
283
310
|
}
|
|
284
311
|
const sendTelemetryAfterResponse = telemetry && baseLogEntry ? (responseStatus, error) => {
|
|
285
312
|
try {
|
|
313
|
+
debugLog(telemetry, "callback", "\u{1F4E4} Telemetry callback invoked", {
|
|
314
|
+
responseStatus,
|
|
315
|
+
hasError: !!error
|
|
316
|
+
});
|
|
286
317
|
const event = createTelemetryEvent(baseLogEntry, telemetry);
|
|
287
318
|
event.responseStatus = responseStatus;
|
|
288
319
|
event.errorMessage = error;
|
|
289
320
|
event.serviceDelivered = responseStatus >= 200 && responseStatus < 300;
|
|
290
|
-
sendTelemetry(event, telemetry.endpoint).catch(
|
|
321
|
+
sendTelemetry(event, telemetry.endpoint, telemetry.debug).catch(
|
|
291
322
|
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
292
323
|
);
|
|
293
324
|
} catch (err) {
|
|
294
325
|
console.error("[x402-telemetry] Error creating telemetry event:", err);
|
|
295
326
|
}
|
|
296
327
|
} : void 0;
|
|
328
|
+
if (telemetry && baseLogEntry) {
|
|
329
|
+
debugLog(telemetry, "callback", "\u2705 Telemetry callback created", {
|
|
330
|
+
route: routeKey,
|
|
331
|
+
hasTelemetryConfig: !!telemetry,
|
|
332
|
+
hasLogEntry: !!baseLogEntry
|
|
333
|
+
});
|
|
334
|
+
} else if (telemetry) {
|
|
335
|
+
debugLog(telemetry, "callback", "\u26A0\uFE0F Telemetry callback NOT created", {
|
|
336
|
+
hasTelemetryConfig: !!telemetry,
|
|
337
|
+
hasLogEntry: !!baseLogEntry
|
|
338
|
+
});
|
|
339
|
+
}
|
|
297
340
|
return {
|
|
298
341
|
status: "verified",
|
|
299
342
|
statusCode: 200,
|
|
@@ -320,6 +363,12 @@ async function checkPayment(input) {
|
|
|
320
363
|
}
|
|
321
364
|
|
|
322
365
|
// src/server/adapters/express.ts
|
|
366
|
+
function debugLog2(config, prefix, message, data) {
|
|
367
|
+
if (config?.debug) {
|
|
368
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
369
|
+
console.log(`[${timestamp}] [x402-debug:${prefix}]`, message, data || "");
|
|
370
|
+
}
|
|
371
|
+
}
|
|
323
372
|
function createPaymentMiddleware(config) {
|
|
324
373
|
const { facilitatorUrl, receiverAddress, routes, apiKey, onPaymentSettled, telemetry } = config;
|
|
325
374
|
if (!facilitatorUrl) {
|
|
@@ -370,17 +419,24 @@ function createPaymentMiddleware(config) {
|
|
|
370
419
|
res.status(result.statusCode).json(result.responseBody);
|
|
371
420
|
return;
|
|
372
421
|
}
|
|
422
|
+
debugLog2(telemetry, "handler", "\u25B6\uFE0F Handler execution started (Express middleware)");
|
|
373
423
|
if (result.sendTelemetryAfterResponse) {
|
|
374
424
|
res.on("finish", () => {
|
|
375
425
|
const statusCode = res.statusCode;
|
|
426
|
+
debugLog2(telemetry, "handler", `\u2705 Handler completed: ${statusCode}`);
|
|
376
427
|
const errorMessage = statusCode >= 400 ? `Handler returned ${statusCode}` : void 0;
|
|
428
|
+
debugLog2(telemetry, "callback", `\u{1F4E4} Calling telemetry callback with status ${statusCode}`);
|
|
377
429
|
result.sendTelemetryAfterResponse(statusCode, errorMessage);
|
|
378
430
|
});
|
|
379
431
|
res.on("close", () => {
|
|
380
432
|
if (!res.writableEnded) {
|
|
433
|
+
debugLog2(telemetry, "handler", "\u274C Response closed without finishing");
|
|
434
|
+
debugLog2(telemetry, "callback", "\u{1F4E4} Calling telemetry callback with error");
|
|
381
435
|
result.sendTelemetryAfterResponse(500, "Response closed without finishing");
|
|
382
436
|
}
|
|
383
437
|
});
|
|
438
|
+
} else {
|
|
439
|
+
debugLog2(telemetry, "callback", "\u26A0\uFE0F No telemetry callback to call");
|
|
384
440
|
}
|
|
385
441
|
next();
|
|
386
442
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { A as AssetConfig, a as Authorization, E as EIP1193Provider, N as NetworkId, d as PaymentHeaderBase64, c as PaymentHeaderObject, b as PaymentHeaderPayload, P as PaymentRequirements } from './types-BFUqKBBO.cjs';
|
|
2
2
|
export { M as MANTLE_DEFAULTS } from './constants-CsIL25uQ.cjs';
|
|
3
|
-
export { M as MantleMiddleware, e as MinimalPaywallOptions, P as PaymentLogEntry, d as PaymentMiddlewareConfig, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig, c as TelemetryEvent } from './types-
|
|
4
|
-
export { c as createPaymentMiddleware, m as mantlePaywall } from './express-
|
|
3
|
+
export { M as MantleMiddleware, e as MinimalPaywallOptions, P as PaymentLogEntry, d as PaymentMiddlewareConfig, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig, c as TelemetryEvent } from './types-DrBw0xwj.cjs';
|
|
4
|
+
export { c as createPaymentMiddleware, m as mantlePaywall } from './express-BWE0nQty.cjs';
|
|
5
5
|
export { C as CallWithPaymentResult, M as MantleClient, a as MantleClientConfig, b as PaymentClient, P as PaymentClientConfig, c as createMantleClient } from './createMantleClient-CO0uWPb-.cjs';
|
|
6
6
|
export { createPaymentClient } from './client.cjs';
|
|
7
7
|
export { UseEthersWalletOptions, UseEthersWalletReturn, UseMantleX402Options, useEthersWallet, useMantleX402 } from './react.cjs';
|
|
8
8
|
import 'express';
|
|
9
|
-
import './types-
|
|
9
|
+
import './types-BkGUHT4x.cjs';
|
|
10
10
|
import 'ethers';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { A as AssetConfig, a as Authorization, E as EIP1193Provider, N as NetworkId, d as PaymentHeaderBase64, c as PaymentHeaderObject, b as PaymentHeaderPayload, P as PaymentRequirements } from './types-BFUqKBBO.js';
|
|
2
2
|
export { M as MANTLE_DEFAULTS } from './constants-0ncqvV_O.js';
|
|
3
|
-
export { M as MantleMiddleware, e as MinimalPaywallOptions, P as PaymentLogEntry, d as PaymentMiddlewareConfig, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig, c as TelemetryEvent } from './types-
|
|
4
|
-
export { c as createPaymentMiddleware, m as mantlePaywall } from './express-
|
|
3
|
+
export { M as MantleMiddleware, e as MinimalPaywallOptions, P as PaymentLogEntry, d as PaymentMiddlewareConfig, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig, c as TelemetryEvent } from './types-DEpSrXCf.js';
|
|
4
|
+
export { c as createPaymentMiddleware, m as mantlePaywall } from './express-BvuN0Lx1.js';
|
|
5
5
|
export { C as CallWithPaymentResult, M as MantleClient, a as MantleClientConfig, b as PaymentClient, P as PaymentClientConfig, c as createMantleClient } from './createMantleClient-CuiPsTa6.js';
|
|
6
6
|
export { createPaymentClient } from './client.js';
|
|
7
7
|
export { UseEthersWalletOptions, UseEthersWalletReturn, UseMantleX402Options, useEthersWallet, useMantleX402 } from './react.js';
|
|
8
8
|
import 'express';
|
|
9
|
-
import './types-
|
|
9
|
+
import './types-Ba0v9XsC.js';
|
|
10
10
|
import 'ethers';
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,8 @@ import "./chunk-WO2MYZXT.js";
|
|
|
10
10
|
import {
|
|
11
11
|
createPaymentMiddleware,
|
|
12
12
|
mantlePaywall
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-3DGAB7HD.js";
|
|
14
|
+
import "./chunk-UVYA6H32.js";
|
|
15
15
|
import {
|
|
16
16
|
MANTLE_DEFAULTS
|
|
17
17
|
} from "./chunk-HEZZ74SI.js";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
import { M as MinimalPaywallOptions } from './types-BkGUHT4x.cjs';
|
|
3
|
+
import { P as PaymentRequirements } from './types-BFUqKBBO.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Error response returned when payment verification fails.
|
|
7
|
+
* This can be due to missing payment, invalid payment, or verification errors.
|
|
8
|
+
*/
|
|
9
|
+
interface PaywallErrorResponse {
|
|
10
|
+
error: string;
|
|
11
|
+
paymentRequirements?: PaymentRequirements;
|
|
12
|
+
paymentHeader?: null;
|
|
13
|
+
invalidReason?: string | null;
|
|
14
|
+
details?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Simple promise-or-value helper.
|
|
18
|
+
*/
|
|
19
|
+
type Awaitable<T> = T | Promise<T>;
|
|
20
|
+
/**
|
|
21
|
+
* Next.js App Router route handler type.
|
|
22
|
+
*
|
|
23
|
+
* Accepts anything that is a valid `Response` to avoid forcing users
|
|
24
|
+
* to annotate union bodies on every handler.
|
|
25
|
+
*/
|
|
26
|
+
type NextJSHandler = (req: NextRequest) => Awaitable<Response>;
|
|
27
|
+
/**
|
|
28
|
+
* Wrapper function that adds x402 payment verification to Next.js route handler.
|
|
29
|
+
* Returns a handler that may return either the original handler's response
|
|
30
|
+
* or a PaywallErrorResponse if payment verification fails.
|
|
31
|
+
*/
|
|
32
|
+
type NextJSPaywallWrapper = (handler: NextJSHandler) => NextJSHandler;
|
|
33
|
+
/**
|
|
34
|
+
* Create Next.js App Router middleware for x402 payment verification.
|
|
35
|
+
* Uses Mantle mainnet defaults (USDC, exact scheme, etc.).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // app/api/generate-image/route.ts
|
|
40
|
+
* import { mantlePaywall } from '@puga-labs/x402-mantle-sdk/server/nextjs'
|
|
41
|
+
*
|
|
42
|
+
* const pay = mantlePaywall({
|
|
43
|
+
* priceUsd: 0.01,
|
|
44
|
+
* payTo: process.env.PAY_TO!,
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // No 'as any' needed! TypeScript correctly infers the union type
|
|
48
|
+
* export const POST = pay(async (req: NextRequest) => {
|
|
49
|
+
* const { prompt } = await req.json();
|
|
50
|
+
* // Your handler code here
|
|
51
|
+
* return NextResponse.json({ success: true, imageUrl: "..." });
|
|
52
|
+
* });
|
|
53
|
+
* // TypeScript knows POST returns: NextResponse<{ success: boolean; imageUrl: string } | PaywallErrorResponse>
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param opts - Minimal configuration (price, payTo, optional facilitator/telemetry).
|
|
57
|
+
* @returns Function that wraps Next.js route handlers with payment verification.
|
|
58
|
+
*/
|
|
59
|
+
declare function mantlePaywall(opts: MinimalPaywallOptions): NextJSPaywallWrapper;
|
|
60
|
+
/**
|
|
61
|
+
* Type guard to check if a response is a paywall error response.
|
|
62
|
+
* Useful for handling the union type returned by the paywall wrapper.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const response = await fetch('/api/protected');
|
|
67
|
+
* const data = await response.json();
|
|
68
|
+
*
|
|
69
|
+
* if (isPaywallErrorResponse(data)) {
|
|
70
|
+
* // Handle error: data.error, data.paymentRequirements, etc.
|
|
71
|
+
* console.error('Payment required:', data.paymentRequirements);
|
|
72
|
+
* } else {
|
|
73
|
+
* // Handle success: data has type T
|
|
74
|
+
* console.log('Success:', data);
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
declare function isPaywallErrorResponse(response: unknown): response is PaywallErrorResponse;
|
|
79
|
+
|
|
80
|
+
type nextjs_NextJSHandler = NextJSHandler;
|
|
81
|
+
type nextjs_NextJSPaywallWrapper = NextJSPaywallWrapper;
|
|
82
|
+
type nextjs_PaywallErrorResponse = PaywallErrorResponse;
|
|
83
|
+
declare const nextjs_isPaywallErrorResponse: typeof isPaywallErrorResponse;
|
|
84
|
+
declare const nextjs_mantlePaywall: typeof mantlePaywall;
|
|
85
|
+
declare namespace nextjs {
|
|
86
|
+
export { type nextjs_NextJSHandler as NextJSHandler, type nextjs_NextJSPaywallWrapper as NextJSPaywallWrapper, type nextjs_PaywallErrorResponse as PaywallErrorResponse, nextjs_isPaywallErrorResponse as isPaywallErrorResponse, nextjs_mantlePaywall as mantlePaywall };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { type NextJSHandler as N, type PaywallErrorResponse as P, type NextJSPaywallWrapper as a, isPaywallErrorResponse as i, mantlePaywall as m, nextjs as n };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
import { M as MinimalPaywallOptions } from './types-Ba0v9XsC.js';
|
|
3
|
+
import { P as PaymentRequirements } from './types-BFUqKBBO.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Error response returned when payment verification fails.
|
|
7
|
+
* This can be due to missing payment, invalid payment, or verification errors.
|
|
8
|
+
*/
|
|
9
|
+
interface PaywallErrorResponse {
|
|
10
|
+
error: string;
|
|
11
|
+
paymentRequirements?: PaymentRequirements;
|
|
12
|
+
paymentHeader?: null;
|
|
13
|
+
invalidReason?: string | null;
|
|
14
|
+
details?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Simple promise-or-value helper.
|
|
18
|
+
*/
|
|
19
|
+
type Awaitable<T> = T | Promise<T>;
|
|
20
|
+
/**
|
|
21
|
+
* Next.js App Router route handler type.
|
|
22
|
+
*
|
|
23
|
+
* Accepts anything that is a valid `Response` to avoid forcing users
|
|
24
|
+
* to annotate union bodies on every handler.
|
|
25
|
+
*/
|
|
26
|
+
type NextJSHandler = (req: NextRequest) => Awaitable<Response>;
|
|
27
|
+
/**
|
|
28
|
+
* Wrapper function that adds x402 payment verification to Next.js route handler.
|
|
29
|
+
* Returns a handler that may return either the original handler's response
|
|
30
|
+
* or a PaywallErrorResponse if payment verification fails.
|
|
31
|
+
*/
|
|
32
|
+
type NextJSPaywallWrapper = (handler: NextJSHandler) => NextJSHandler;
|
|
33
|
+
/**
|
|
34
|
+
* Create Next.js App Router middleware for x402 payment verification.
|
|
35
|
+
* Uses Mantle mainnet defaults (USDC, exact scheme, etc.).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // app/api/generate-image/route.ts
|
|
40
|
+
* import { mantlePaywall } from '@puga-labs/x402-mantle-sdk/server/nextjs'
|
|
41
|
+
*
|
|
42
|
+
* const pay = mantlePaywall({
|
|
43
|
+
* priceUsd: 0.01,
|
|
44
|
+
* payTo: process.env.PAY_TO!,
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // No 'as any' needed! TypeScript correctly infers the union type
|
|
48
|
+
* export const POST = pay(async (req: NextRequest) => {
|
|
49
|
+
* const { prompt } = await req.json();
|
|
50
|
+
* // Your handler code here
|
|
51
|
+
* return NextResponse.json({ success: true, imageUrl: "..." });
|
|
52
|
+
* });
|
|
53
|
+
* // TypeScript knows POST returns: NextResponse<{ success: boolean; imageUrl: string } | PaywallErrorResponse>
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param opts - Minimal configuration (price, payTo, optional facilitator/telemetry).
|
|
57
|
+
* @returns Function that wraps Next.js route handlers with payment verification.
|
|
58
|
+
*/
|
|
59
|
+
declare function mantlePaywall(opts: MinimalPaywallOptions): NextJSPaywallWrapper;
|
|
60
|
+
/**
|
|
61
|
+
* Type guard to check if a response is a paywall error response.
|
|
62
|
+
* Useful for handling the union type returned by the paywall wrapper.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const response = await fetch('/api/protected');
|
|
67
|
+
* const data = await response.json();
|
|
68
|
+
*
|
|
69
|
+
* if (isPaywallErrorResponse(data)) {
|
|
70
|
+
* // Handle error: data.error, data.paymentRequirements, etc.
|
|
71
|
+
* console.error('Payment required:', data.paymentRequirements);
|
|
72
|
+
* } else {
|
|
73
|
+
* // Handle success: data has type T
|
|
74
|
+
* console.log('Success:', data);
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
declare function isPaywallErrorResponse(response: unknown): response is PaywallErrorResponse;
|
|
79
|
+
|
|
80
|
+
type nextjs_NextJSHandler = NextJSHandler;
|
|
81
|
+
type nextjs_NextJSPaywallWrapper = NextJSPaywallWrapper;
|
|
82
|
+
type nextjs_PaywallErrorResponse = PaywallErrorResponse;
|
|
83
|
+
declare const nextjs_isPaywallErrorResponse: typeof isPaywallErrorResponse;
|
|
84
|
+
declare const nextjs_mantlePaywall: typeof mantlePaywall;
|
|
85
|
+
declare namespace nextjs {
|
|
86
|
+
export { type nextjs_NextJSHandler as NextJSHandler, type nextjs_NextJSPaywallWrapper as NextJSPaywallWrapper, type nextjs_PaywallErrorResponse as PaywallErrorResponse, nextjs_isPaywallErrorResponse as isPaywallErrorResponse, nextjs_mantlePaywall as mantlePaywall };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { type NextJSHandler as N, type PaywallErrorResponse as P, type NextJSPaywallWrapper as a, isPaywallErrorResponse as i, mantlePaywall as m, nextjs as n };
|
package/dist/server-express.cjs
CHANGED
|
@@ -137,9 +137,20 @@ function createTelemetryEvent(entry, config) {
|
|
|
137
137
|
priceUsd: entry.paymentRequirements?.price
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
|
-
async function sendTelemetry(event, endpoint) {
|
|
140
|
+
async function sendTelemetry(event, endpoint, debug) {
|
|
141
141
|
const targetEndpoint = endpoint ?? DEFAULT_TELEMETRY_ENDPOINT;
|
|
142
|
+
if (debug) {
|
|
143
|
+
console.log(`[x402-debug:telemetry] \u{1F4E4} Sending telemetry event:`, {
|
|
144
|
+
event: event.event,
|
|
145
|
+
endpoint: targetEndpoint,
|
|
146
|
+
projectKey: event.projectKey.substring(0, 10) + "...",
|
|
147
|
+
route: event.route,
|
|
148
|
+
responseStatus: event.responseStatus,
|
|
149
|
+
serviceDelivered: event.serviceDelivered
|
|
150
|
+
});
|
|
151
|
+
}
|
|
142
152
|
if (!targetEndpoint) {
|
|
153
|
+
if (debug) console.log(`[x402-debug:telemetry] \u26A0\uFE0F No endpoint configured, skipping`);
|
|
143
154
|
return;
|
|
144
155
|
}
|
|
145
156
|
try {
|
|
@@ -151,17 +162,29 @@ async function sendTelemetry(event, endpoint) {
|
|
|
151
162
|
},
|
|
152
163
|
body: JSON.stringify(event)
|
|
153
164
|
});
|
|
165
|
+
if (debug) {
|
|
166
|
+
console.log(`[x402-debug:telemetry] ${response.ok ? "\u2705" : "\u274C"} Telemetry sent: HTTP ${response.status}`);
|
|
167
|
+
}
|
|
154
168
|
if (!response.ok) {
|
|
155
169
|
console.warn(
|
|
156
170
|
`[x402-telemetry] Failed to send event: HTTP ${response.status}`
|
|
157
171
|
);
|
|
158
172
|
}
|
|
159
173
|
} catch (err) {
|
|
174
|
+
if (debug) {
|
|
175
|
+
console.error(`[x402-debug:telemetry] \u274C Error sending:`, err);
|
|
176
|
+
}
|
|
160
177
|
console.error("[x402-telemetry] Error sending telemetry:", err);
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
180
|
|
|
164
181
|
// src/server/core/verifyPayment.ts
|
|
182
|
+
function debugLog(config, prefix, message, data) {
|
|
183
|
+
if (config?.debug) {
|
|
184
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
185
|
+
console.log(`[${timestamp}] [x402-debug:${prefix}]`, message, data || "");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
165
188
|
async function checkPayment(input) {
|
|
166
189
|
const {
|
|
167
190
|
paymentHeader,
|
|
@@ -249,6 +272,10 @@ async function checkPayment(input) {
|
|
|
249
272
|
facilitatorUrl,
|
|
250
273
|
paymentRequirements
|
|
251
274
|
};
|
|
275
|
+
debugLog(telemetry, "verify", "\u2705 Payment verified", {
|
|
276
|
+
nonce: authorization.nonce,
|
|
277
|
+
route: routeKey
|
|
278
|
+
});
|
|
252
279
|
if (onPaymentSettled) {
|
|
253
280
|
onPaymentSettled(baseLogEntry);
|
|
254
281
|
}
|
|
@@ -261,17 +288,33 @@ async function checkPayment(input) {
|
|
|
261
288
|
}
|
|
262
289
|
const sendTelemetryAfterResponse = telemetry && baseLogEntry ? (responseStatus, error) => {
|
|
263
290
|
try {
|
|
291
|
+
debugLog(telemetry, "callback", "\u{1F4E4} Telemetry callback invoked", {
|
|
292
|
+
responseStatus,
|
|
293
|
+
hasError: !!error
|
|
294
|
+
});
|
|
264
295
|
const event = createTelemetryEvent(baseLogEntry, telemetry);
|
|
265
296
|
event.responseStatus = responseStatus;
|
|
266
297
|
event.errorMessage = error;
|
|
267
298
|
event.serviceDelivered = responseStatus >= 200 && responseStatus < 300;
|
|
268
|
-
sendTelemetry(event, telemetry.endpoint).catch(
|
|
299
|
+
sendTelemetry(event, telemetry.endpoint, telemetry.debug).catch(
|
|
269
300
|
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
270
301
|
);
|
|
271
302
|
} catch (err) {
|
|
272
303
|
console.error("[x402-telemetry] Error creating telemetry event:", err);
|
|
273
304
|
}
|
|
274
305
|
} : void 0;
|
|
306
|
+
if (telemetry && baseLogEntry) {
|
|
307
|
+
debugLog(telemetry, "callback", "\u2705 Telemetry callback created", {
|
|
308
|
+
route: routeKey,
|
|
309
|
+
hasTelemetryConfig: !!telemetry,
|
|
310
|
+
hasLogEntry: !!baseLogEntry
|
|
311
|
+
});
|
|
312
|
+
} else if (telemetry) {
|
|
313
|
+
debugLog(telemetry, "callback", "\u26A0\uFE0F Telemetry callback NOT created", {
|
|
314
|
+
hasTelemetryConfig: !!telemetry,
|
|
315
|
+
hasLogEntry: !!baseLogEntry
|
|
316
|
+
});
|
|
317
|
+
}
|
|
275
318
|
return {
|
|
276
319
|
status: "verified",
|
|
277
320
|
statusCode: 200,
|
|
@@ -298,6 +341,12 @@ async function checkPayment(input) {
|
|
|
298
341
|
}
|
|
299
342
|
|
|
300
343
|
// src/server/adapters/express.ts
|
|
344
|
+
function debugLog2(config, prefix, message, data) {
|
|
345
|
+
if (config?.debug) {
|
|
346
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
347
|
+
console.log(`[${timestamp}] [x402-debug:${prefix}]`, message, data || "");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
301
350
|
function createPaymentMiddleware(config) {
|
|
302
351
|
const { facilitatorUrl, receiverAddress, routes, apiKey, onPaymentSettled, telemetry } = config;
|
|
303
352
|
if (!facilitatorUrl) {
|
|
@@ -348,17 +397,24 @@ function createPaymentMiddleware(config) {
|
|
|
348
397
|
res.status(result.statusCode).json(result.responseBody);
|
|
349
398
|
return;
|
|
350
399
|
}
|
|
400
|
+
debugLog2(telemetry, "handler", "\u25B6\uFE0F Handler execution started (Express middleware)");
|
|
351
401
|
if (result.sendTelemetryAfterResponse) {
|
|
352
402
|
res.on("finish", () => {
|
|
353
403
|
const statusCode = res.statusCode;
|
|
404
|
+
debugLog2(telemetry, "handler", `\u2705 Handler completed: ${statusCode}`);
|
|
354
405
|
const errorMessage = statusCode >= 400 ? `Handler returned ${statusCode}` : void 0;
|
|
406
|
+
debugLog2(telemetry, "callback", `\u{1F4E4} Calling telemetry callback with status ${statusCode}`);
|
|
355
407
|
result.sendTelemetryAfterResponse(statusCode, errorMessage);
|
|
356
408
|
});
|
|
357
409
|
res.on("close", () => {
|
|
358
410
|
if (!res.writableEnded) {
|
|
411
|
+
debugLog2(telemetry, "handler", "\u274C Response closed without finishing");
|
|
412
|
+
debugLog2(telemetry, "callback", "\u{1F4E4} Calling telemetry callback with error");
|
|
359
413
|
result.sendTelemetryAfterResponse(500, "Response closed without finishing");
|
|
360
414
|
}
|
|
361
415
|
});
|
|
416
|
+
} else {
|
|
417
|
+
debugLog2(telemetry, "callback", "\u26A0\uFE0F No telemetry callback to call");
|
|
362
418
|
}
|
|
363
419
|
next();
|
|
364
420
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { M as MantleMiddleware, P as PaymentMiddlewareConfig, c as createPaymentMiddleware, m as mantlePaywall } from './express-
|
|
2
|
-
export { M as MinimalPaywallOptions, c as PaymentCheckInput, d as PaymentCheckResult, P as PaymentLogEntry, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig } from './types-
|
|
1
|
+
export { M as MantleMiddleware, P as PaymentMiddlewareConfig, c as createPaymentMiddleware, m as mantlePaywall } from './express-BWE0nQty.cjs';
|
|
2
|
+
export { M as MinimalPaywallOptions, c as PaymentCheckInput, d as PaymentCheckResult, P as PaymentLogEntry, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig } from './types-BkGUHT4x.cjs';
|
|
3
3
|
export { A as AssetConfig, a as Authorization, E as EIP1193Provider, N as NetworkId, d as PaymentHeaderBase64, c as PaymentHeaderObject, b as PaymentHeaderPayload, P as PaymentRequirements } from './types-BFUqKBBO.cjs';
|
|
4
4
|
export { M as MANTLE_DEFAULTS } from './constants-CsIL25uQ.cjs';
|
|
5
5
|
import 'express';
|
package/dist/server-express.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { M as MantleMiddleware, P as PaymentMiddlewareConfig, c as createPaymentMiddleware, m as mantlePaywall } from './express-
|
|
2
|
-
export { M as MinimalPaywallOptions, c as PaymentCheckInput, d as PaymentCheckResult, P as PaymentLogEntry, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig } from './types-
|
|
1
|
+
export { M as MantleMiddleware, P as PaymentMiddlewareConfig, c as createPaymentMiddleware, m as mantlePaywall } from './express-BvuN0Lx1.js';
|
|
2
|
+
export { M as MinimalPaywallOptions, c as PaymentCheckInput, d as PaymentCheckResult, P as PaymentLogEntry, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig } from './types-Ba0v9XsC.js';
|
|
3
3
|
export { A as AssetConfig, a as Authorization, E as EIP1193Provider, N as NetworkId, d as PaymentHeaderBase64, c as PaymentHeaderObject, b as PaymentHeaderPayload, P as PaymentRequirements } from './types-BFUqKBBO.js';
|
|
4
4
|
export { M as MANTLE_DEFAULTS } from './constants-0ncqvV_O.js';
|
|
5
5
|
import 'express';
|
package/dist/server-express.js
CHANGED