@puga-labs/x402-mantle-sdk 0.3.1 → 0.3.3
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-HTZ3QFY4.js → chunk-23QNUJIB.js} +4 -3
- package/dist/chunk-CXRILT3C.js +68 -0
- package/dist/{chunk-CTI5CRDY.js → chunk-E46A7I6B.js} +1 -1
- package/dist/{chunk-XAQGMFSR.js → chunk-HEZZ74SI.js} +6 -0
- package/dist/chunk-NQWSCY44.js +70 -0
- package/dist/chunk-PCJEJYP6.js +68 -0
- package/dist/chunk-PPVS3X5Z.js +99 -0
- package/dist/chunk-QWQUSRLY.js +99 -0
- package/dist/chunk-U73CZU3X.js +237 -0
- package/dist/chunk-WO2MYZXT.js +0 -0
- package/dist/chunk-ZLCKBFVJ.js +237 -0
- package/dist/chunk-ZROK2XOB.js +70 -0
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.js +2 -2
- package/dist/{constants-CVFF0ray.d.ts → constants-0ncqvV_O.d.ts} +1 -1
- package/dist/{constants-DzCGK0Q3.d.cts → constants-CsIL25uQ.d.cts} +1 -1
- package/dist/{createMantleClient-NN0Nitp9.d.cts → createMantleClient-CO0uWPb-.d.cts} +1 -1
- package/dist/{createMantleClient-DVFkbBfS.d.ts → createMantleClient-CuiPsTa6.d.ts} +1 -1
- package/dist/express-D8EwEcOL.d.ts +66 -0
- package/dist/express-eQOPxfnI.d.cts +66 -0
- package/dist/index.cjs +186 -109
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +6 -4
- package/dist/nextjs-Duecps0q.d.cts +45 -0
- package/dist/nextjs-TFhFiQuL.d.ts +45 -0
- package/dist/react.cjs +3 -2
- package/dist/react.d.cts +7 -4
- package/dist/react.d.ts +7 -4
- package/dist/react.js +3 -3
- package/dist/server-express.cjs +368 -0
- package/dist/server-express.d.cts +5 -0
- package/dist/server-express.d.ts +5 -0
- package/dist/server-express.js +13 -0
- package/dist/server-nextjs.cjs +339 -0
- package/dist/server-nextjs.d.cts +5 -0
- package/dist/server-nextjs.d.ts +5 -0
- package/dist/server-nextjs.js +11 -0
- package/dist/server-web.cjs +339 -0
- package/dist/server-web.d.cts +4 -0
- package/dist/server-web.d.ts +4 -0
- package/dist/server-web.js +11 -0
- package/dist/server.cjs +316 -111
- package/dist/server.d.cts +67 -104
- package/dist/server.d.ts +67 -104
- package/dist/server.js +29 -5
- package/dist/{types-2zqbJvcz.d.cts → types-BFUqKBBO.d.cts} +1 -1
- package/dist/{types-2zqbJvcz.d.ts → types-BFUqKBBO.d.ts} +1 -1
- package/dist/types-CoOdbZSp.d.cts +97 -0
- package/dist/types-CqQ6OgRi.d.ts +85 -0
- package/dist/types-CrOsOHcX.d.cts +85 -0
- package/dist/types-DTzov_EE.d.ts +97 -0
- package/dist/web-standards-BNQyWzBC.d.cts +77 -0
- package/dist/web-standards-D8j1kZxd.d.ts +77 -0
- package/package.json +49 -2
- package/dist/chunk-DA6ZBXNO.js +0 -275
- package/dist/chunk-FD4HG7KR.js +0 -135
- package/dist/chunk-GWVWPS3R.js +0 -277
- package/dist/chunk-MQALBRGV.js +0 -135
- package/dist/chunk-PYIYE3HI.js +0 -135
- package/dist/chunk-Q6SPMEIW.js +0 -235
- package/dist/chunk-RNKXSBT7.js +0 -135
- package/dist/chunk-SPCXFN7C.js +0 -284
- package/dist/chunk-T5DRYLNB.js +0 -135
- package/dist/chunk-TSEE5NSJ.js +0 -297
- package/dist/chunk-WELDWRDX.js +0 -307
- package/dist/constants-C7aY8u5b.d.cts +0 -77
- package/dist/constants-C7aY8u5b.d.ts +0 -77
- package/dist/createMantleClient-DS1Ghqrz.d.cts +0 -51
- package/dist/createMantleClient-DS1Ghqrz.d.ts +0 -51
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { W as WebHandler, a as WebPaywallWrapper, m as mantlePaywall } from './web-standards-D8j1kZxd.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-CqQ6OgRi.js';
|
|
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
|
+
export { M as MANTLE_DEFAULTS } from './constants-0ncqvV_O.js';
|
package/dist/server.cjs
CHANGED
|
@@ -20,12 +20,69 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/server.ts
|
|
21
21
|
var server_exports = {};
|
|
22
22
|
__export(server_exports, {
|
|
23
|
-
|
|
23
|
+
DEFAULT_TELEMETRY_ENDPOINT: () => DEFAULT_TELEMETRY_ENDPOINT,
|
|
24
|
+
buildRouteKey: () => buildRouteKey,
|
|
25
|
+
checkPayment: () => checkPayment,
|
|
24
26
|
createPaymentMiddleware: () => createPaymentMiddleware,
|
|
25
|
-
|
|
27
|
+
createTelemetryEvent: () => createTelemetryEvent,
|
|
28
|
+
decodePaymentHeader: () => decodePaymentHeader,
|
|
29
|
+
express: () => express_exports,
|
|
30
|
+
mantlePaywall: () => mantlePaywall,
|
|
31
|
+
nextjs: () => nextjs_exports,
|
|
32
|
+
sendTelemetry: () => sendTelemetry,
|
|
33
|
+
validateAddress: () => validateAddress,
|
|
34
|
+
web: () => web_standards_exports
|
|
26
35
|
});
|
|
27
36
|
module.exports = __toCommonJS(server_exports);
|
|
28
37
|
|
|
38
|
+
// src/server/core/utils.ts
|
|
39
|
+
function validateAddress(address, paramName = "address") {
|
|
40
|
+
if (!address) {
|
|
41
|
+
throw new Error(`${paramName} is required`);
|
|
42
|
+
}
|
|
43
|
+
if (typeof address !== "string") {
|
|
44
|
+
throw new Error(`${paramName} must be a string, got ${typeof address}`);
|
|
45
|
+
}
|
|
46
|
+
if (!address.startsWith("0x")) {
|
|
47
|
+
const preview = address.length > 10 ? `${address.substring(0, 10)}...` : address;
|
|
48
|
+
throw new Error(
|
|
49
|
+
`${paramName} must start with "0x", got: ${preview}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (address.length !== 42) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`${paramName} must be 42 characters (0x + 40 hex), got ${address.length} characters`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const hexPart = address.slice(2);
|
|
58
|
+
if (!/^[0-9a-fA-F]{40}$/.test(hexPart)) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`${paramName} must contain only hexadecimal characters (0-9, a-f, A-F) after "0x"`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function decodePaymentHeader(paymentHeaderBase64) {
|
|
65
|
+
try {
|
|
66
|
+
if (typeof Buffer !== "undefined") {
|
|
67
|
+
const json = Buffer.from(paymentHeaderBase64, "base64").toString("utf8");
|
|
68
|
+
return JSON.parse(json);
|
|
69
|
+
}
|
|
70
|
+
if (typeof atob === "function") {
|
|
71
|
+
const json = atob(paymentHeaderBase64);
|
|
72
|
+
return JSON.parse(json);
|
|
73
|
+
}
|
|
74
|
+
throw new Error("No base64 decoding available in this environment");
|
|
75
|
+
} catch (err) {
|
|
76
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
77
|
+
throw new Error(`Failed to decode paymentHeader: ${msg}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function buildRouteKey(method, path) {
|
|
81
|
+
const normalizedMethod = (method || "GET").toUpperCase();
|
|
82
|
+
const normalizedPath = path || "/";
|
|
83
|
+
return `${normalizedMethod} ${normalizedPath}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
29
86
|
// src/shared/constants.ts
|
|
30
87
|
var MANTLE_MAINNET_NETWORK_ID = "mantle-mainnet";
|
|
31
88
|
var MANTLE_MAINNET_USDC = {
|
|
@@ -113,28 +170,135 @@ async function sendTelemetry(event, endpoint) {
|
|
|
113
170
|
}
|
|
114
171
|
}
|
|
115
172
|
|
|
116
|
-
// src/server/
|
|
117
|
-
function
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
173
|
+
// src/server/core/verifyPayment.ts
|
|
174
|
+
async function checkPayment(input) {
|
|
175
|
+
const {
|
|
176
|
+
paymentHeader,
|
|
177
|
+
paymentRequirements,
|
|
178
|
+
facilitatorUrl,
|
|
179
|
+
routeKey,
|
|
180
|
+
network,
|
|
181
|
+
asset,
|
|
182
|
+
telemetry,
|
|
183
|
+
onPaymentSettled
|
|
184
|
+
} = input;
|
|
185
|
+
if (!paymentHeader || paymentHeader.trim() === "") {
|
|
186
|
+
return {
|
|
187
|
+
status: "require_payment",
|
|
188
|
+
statusCode: 402,
|
|
189
|
+
responseBody: {
|
|
190
|
+
error: "Payment Required",
|
|
191
|
+
paymentRequirements,
|
|
192
|
+
paymentHeader: null
|
|
193
|
+
},
|
|
194
|
+
isValid: false
|
|
195
|
+
};
|
|
196
|
+
}
|
|
123
197
|
try {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
198
|
+
const verifyUrl = `${facilitatorUrl.replace(/\/+$/, "")}/verify`;
|
|
199
|
+
const verifyRes = await fetch(verifyUrl, {
|
|
200
|
+
method: "POST",
|
|
201
|
+
headers: {
|
|
202
|
+
"Content-Type": "application/json"
|
|
203
|
+
},
|
|
204
|
+
body: JSON.stringify({
|
|
205
|
+
x402Version: 1,
|
|
206
|
+
paymentHeader,
|
|
207
|
+
paymentRequirements
|
|
208
|
+
})
|
|
209
|
+
});
|
|
210
|
+
if (!verifyRes.ok) {
|
|
211
|
+
const text = await verifyRes.text().catch(() => "");
|
|
212
|
+
console.error(
|
|
213
|
+
"[x402-mantle-sdk] Facilitator /verify returned non-OK:",
|
|
214
|
+
verifyRes.status,
|
|
215
|
+
text
|
|
216
|
+
);
|
|
217
|
+
return {
|
|
218
|
+
status: "verification_error",
|
|
219
|
+
statusCode: 500,
|
|
220
|
+
responseBody: {
|
|
221
|
+
error: "Payment verification error",
|
|
222
|
+
details: `Facilitator responded with HTTP ${verifyRes.status}`
|
|
223
|
+
},
|
|
224
|
+
isValid: false
|
|
225
|
+
};
|
|
127
226
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return
|
|
227
|
+
const verifyJson = await verifyRes.json();
|
|
228
|
+
if (!verifyJson.isValid) {
|
|
229
|
+
return {
|
|
230
|
+
status: "invalid_payment",
|
|
231
|
+
statusCode: 402,
|
|
232
|
+
responseBody: {
|
|
233
|
+
error: "Payment verification failed",
|
|
234
|
+
invalidReason: verifyJson.invalidReason ?? null,
|
|
235
|
+
paymentRequirements,
|
|
236
|
+
paymentHeader: null
|
|
237
|
+
},
|
|
238
|
+
isValid: false
|
|
239
|
+
};
|
|
131
240
|
}
|
|
132
|
-
|
|
241
|
+
if (onPaymentSettled) {
|
|
242
|
+
try {
|
|
243
|
+
const headerObj = decodePaymentHeader(paymentHeader);
|
|
244
|
+
const { authorization } = headerObj.payload;
|
|
245
|
+
const assetConfig = getDefaultAssetForNetwork(network);
|
|
246
|
+
const logEntry = {
|
|
247
|
+
id: authorization.nonce,
|
|
248
|
+
from: authorization.from,
|
|
249
|
+
to: authorization.to,
|
|
250
|
+
valueAtomic: authorization.value,
|
|
251
|
+
network,
|
|
252
|
+
asset,
|
|
253
|
+
route: routeKey,
|
|
254
|
+
timestamp: Date.now(),
|
|
255
|
+
facilitatorUrl,
|
|
256
|
+
paymentRequirements
|
|
257
|
+
};
|
|
258
|
+
onPaymentSettled(logEntry);
|
|
259
|
+
if (telemetry) {
|
|
260
|
+
const event = createTelemetryEvent(logEntry, telemetry);
|
|
261
|
+
sendTelemetry(event, telemetry.endpoint).catch(
|
|
262
|
+
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.error(
|
|
267
|
+
"[x402-mantle-sdk] Error calling onPaymentSettled hook:",
|
|
268
|
+
err
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
status: "verified",
|
|
274
|
+
statusCode: 200,
|
|
275
|
+
responseBody: null,
|
|
276
|
+
isValid: true
|
|
277
|
+
};
|
|
133
278
|
} catch (err) {
|
|
134
|
-
|
|
135
|
-
|
|
279
|
+
console.error(
|
|
280
|
+
"[x402-mantle-sdk] Error while calling facilitator /verify:",
|
|
281
|
+
err
|
|
282
|
+
);
|
|
283
|
+
const message = err instanceof Error ? err.message : "Unknown verification error";
|
|
284
|
+
return {
|
|
285
|
+
status: "verification_error",
|
|
286
|
+
statusCode: 500,
|
|
287
|
+
responseBody: {
|
|
288
|
+
error: "Payment verification error",
|
|
289
|
+
details: message
|
|
290
|
+
},
|
|
291
|
+
isValid: false
|
|
292
|
+
};
|
|
136
293
|
}
|
|
137
294
|
}
|
|
295
|
+
|
|
296
|
+
// src/server/adapters/express.ts
|
|
297
|
+
var express_exports = {};
|
|
298
|
+
__export(express_exports, {
|
|
299
|
+
createPaymentMiddleware: () => createPaymentMiddleware,
|
|
300
|
+
mantlePaywall: () => mantlePaywall
|
|
301
|
+
});
|
|
138
302
|
function createPaymentMiddleware(config) {
|
|
139
303
|
const { facilitatorUrl, receiverAddress, routes, onPaymentSettled, telemetry } = config;
|
|
140
304
|
if (!facilitatorUrl) {
|
|
@@ -143,11 +307,12 @@ function createPaymentMiddleware(config) {
|
|
|
143
307
|
if (!receiverAddress) {
|
|
144
308
|
throw new Error("receiverAddress is required");
|
|
145
309
|
}
|
|
310
|
+
validateAddress(receiverAddress, "receiverAddress");
|
|
146
311
|
if (!routes || Object.keys(routes).length === 0) {
|
|
147
312
|
throw new Error("routes config must not be empty");
|
|
148
313
|
}
|
|
149
314
|
return async function paymentMiddleware(req, res, next) {
|
|
150
|
-
const routeKey =
|
|
315
|
+
const routeKey = buildRouteKey(req.method, req.path);
|
|
151
316
|
const routeConfig = routes[routeKey];
|
|
152
317
|
if (!routeConfig) {
|
|
153
318
|
next();
|
|
@@ -168,102 +333,27 @@ function createPaymentMiddleware(config) {
|
|
|
168
333
|
price: `$${(priceUsdCents / 100).toFixed(2)}`,
|
|
169
334
|
currency: "USD"
|
|
170
335
|
};
|
|
171
|
-
const paymentHeader = req.header("X-PAYMENT")
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
headers: {
|
|
185
|
-
"Content-Type": "application/json"
|
|
186
|
-
},
|
|
187
|
-
body: JSON.stringify({
|
|
188
|
-
x402Version: 1,
|
|
189
|
-
paymentHeader,
|
|
190
|
-
paymentRequirements
|
|
191
|
-
})
|
|
192
|
-
});
|
|
193
|
-
if (!verifyRes.ok) {
|
|
194
|
-
const text = await verifyRes.text().catch(() => "");
|
|
195
|
-
console.error(
|
|
196
|
-
"[x402-mantle-sdk] Facilitator /verify returned non-OK:",
|
|
197
|
-
verifyRes.status,
|
|
198
|
-
text
|
|
199
|
-
);
|
|
200
|
-
res.status(500).json({
|
|
201
|
-
error: "Payment verification error",
|
|
202
|
-
details: `Facilitator responded with HTTP ${verifyRes.status}`
|
|
203
|
-
});
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
const verifyJson = await verifyRes.json();
|
|
207
|
-
if (!verifyJson.isValid) {
|
|
208
|
-
res.status(402).json({
|
|
209
|
-
error: "Payment verification failed",
|
|
210
|
-
invalidReason: verifyJson.invalidReason ?? null,
|
|
211
|
-
paymentRequirements,
|
|
212
|
-
paymentHeader: null
|
|
213
|
-
});
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (onPaymentSettled) {
|
|
217
|
-
try {
|
|
218
|
-
const headerObj = decodePaymentHeader(paymentHeader);
|
|
219
|
-
const { authorization } = headerObj.payload;
|
|
220
|
-
const logEntry = {
|
|
221
|
-
id: authorization.nonce,
|
|
222
|
-
from: authorization.from,
|
|
223
|
-
to: authorization.to,
|
|
224
|
-
valueAtomic: authorization.value,
|
|
225
|
-
network,
|
|
226
|
-
asset: assetConfig.address,
|
|
227
|
-
route: routeKey,
|
|
228
|
-
timestamp: Date.now(),
|
|
229
|
-
facilitatorUrl,
|
|
230
|
-
// Pass from config closure
|
|
231
|
-
paymentRequirements
|
|
232
|
-
};
|
|
233
|
-
onPaymentSettled(logEntry);
|
|
234
|
-
if (telemetry) {
|
|
235
|
-
const event = createTelemetryEvent(logEntry, telemetry);
|
|
236
|
-
sendTelemetry(event, telemetry.endpoint).catch(
|
|
237
|
-
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
} catch (err) {
|
|
241
|
-
console.error(
|
|
242
|
-
"[x402-mantle-sdk] Error calling onPaymentSettled hook:",
|
|
243
|
-
err
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
next();
|
|
248
|
-
return;
|
|
249
|
-
} catch (err) {
|
|
250
|
-
console.error(
|
|
251
|
-
"[x402-mantle-sdk] Error while calling facilitator /verify:",
|
|
252
|
-
err
|
|
253
|
-
);
|
|
254
|
-
const message = err instanceof Error ? err.message : "Unknown verification error";
|
|
255
|
-
res.status(500).json({
|
|
256
|
-
error: "Payment verification error",
|
|
257
|
-
details: message
|
|
258
|
-
});
|
|
336
|
+
const paymentHeader = req.header("X-PAYMENT") || req.header("x-payment") || null;
|
|
337
|
+
const result = await checkPayment({
|
|
338
|
+
paymentHeader,
|
|
339
|
+
paymentRequirements,
|
|
340
|
+
facilitatorUrl,
|
|
341
|
+
routeKey,
|
|
342
|
+
network,
|
|
343
|
+
asset: assetConfig.address,
|
|
344
|
+
telemetry,
|
|
345
|
+
onPaymentSettled
|
|
346
|
+
});
|
|
347
|
+
if (!result.isValid) {
|
|
348
|
+
res.status(result.statusCode).json(result.responseBody);
|
|
259
349
|
return;
|
|
260
350
|
}
|
|
351
|
+
next();
|
|
261
352
|
};
|
|
262
353
|
}
|
|
263
|
-
|
|
264
|
-
// src/server/mantlePaywall.ts
|
|
265
354
|
function mantlePaywall(opts) {
|
|
266
355
|
const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
|
|
356
|
+
validateAddress(payTo, "payTo");
|
|
267
357
|
const priceUsdCents = Math.round(priceUsd * 100);
|
|
268
358
|
return async (req, res, next) => {
|
|
269
359
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -284,9 +374,124 @@ function mantlePaywall(opts) {
|
|
|
284
374
|
return middleware(req, res, next);
|
|
285
375
|
};
|
|
286
376
|
}
|
|
377
|
+
|
|
378
|
+
// src/server/adapters/nextjs.ts
|
|
379
|
+
var nextjs_exports = {};
|
|
380
|
+
__export(nextjs_exports, {
|
|
381
|
+
mantlePaywall: () => mantlePaywall2
|
|
382
|
+
});
|
|
383
|
+
var import_server = require("next/server");
|
|
384
|
+
function mantlePaywall2(opts) {
|
|
385
|
+
const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
|
|
386
|
+
validateAddress(payTo, "payTo");
|
|
387
|
+
const priceUsdCents = Math.round(priceUsd * 100);
|
|
388
|
+
return function(handler) {
|
|
389
|
+
return async (req) => {
|
|
390
|
+
const url = new URL(req.url);
|
|
391
|
+
const method = req.method;
|
|
392
|
+
const path = url.pathname;
|
|
393
|
+
const routeKey = buildRouteKey(method, path);
|
|
394
|
+
const network = MANTLE_DEFAULTS.NETWORK;
|
|
395
|
+
const assetConfig = getDefaultAssetForNetwork(network);
|
|
396
|
+
const maxAmountRequiredBigInt = usdCentsToAtomic(
|
|
397
|
+
priceUsdCents,
|
|
398
|
+
assetConfig.decimals
|
|
399
|
+
);
|
|
400
|
+
const paymentRequirements = {
|
|
401
|
+
scheme: "exact",
|
|
402
|
+
network,
|
|
403
|
+
asset: assetConfig.address,
|
|
404
|
+
maxAmountRequired: maxAmountRequiredBigInt.toString(),
|
|
405
|
+
payTo,
|
|
406
|
+
price: `$${(priceUsdCents / 100).toFixed(2)}`,
|
|
407
|
+
currency: "USD"
|
|
408
|
+
};
|
|
409
|
+
const paymentHeader = req.headers.get("X-PAYMENT") || req.headers.get("x-payment") || null;
|
|
410
|
+
const result = await checkPayment({
|
|
411
|
+
paymentHeader,
|
|
412
|
+
paymentRequirements,
|
|
413
|
+
facilitatorUrl: facilitatorUrl || MANTLE_DEFAULTS.FACILITATOR_URL,
|
|
414
|
+
routeKey,
|
|
415
|
+
network,
|
|
416
|
+
asset: assetConfig.address,
|
|
417
|
+
telemetry,
|
|
418
|
+
onPaymentSettled
|
|
419
|
+
});
|
|
420
|
+
if (!result.isValid) {
|
|
421
|
+
return import_server.NextResponse.json(result.responseBody, {
|
|
422
|
+
status: result.statusCode
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return handler(req);
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/server/adapters/web-standards.ts
|
|
431
|
+
var web_standards_exports = {};
|
|
432
|
+
__export(web_standards_exports, {
|
|
433
|
+
mantlePaywall: () => mantlePaywall3
|
|
434
|
+
});
|
|
435
|
+
function mantlePaywall3(opts) {
|
|
436
|
+
const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
|
|
437
|
+
validateAddress(payTo, "payTo");
|
|
438
|
+
const priceUsdCents = Math.round(priceUsd * 100);
|
|
439
|
+
return function(handler) {
|
|
440
|
+
return async (request) => {
|
|
441
|
+
const url = new URL(request.url);
|
|
442
|
+
const method = request.method;
|
|
443
|
+
const path = url.pathname;
|
|
444
|
+
const routeKey = buildRouteKey(method, path);
|
|
445
|
+
const network = MANTLE_DEFAULTS.NETWORK;
|
|
446
|
+
const assetConfig = getDefaultAssetForNetwork(network);
|
|
447
|
+
const maxAmountRequiredBigInt = usdCentsToAtomic(
|
|
448
|
+
priceUsdCents,
|
|
449
|
+
assetConfig.decimals
|
|
450
|
+
);
|
|
451
|
+
const paymentRequirements = {
|
|
452
|
+
scheme: "exact",
|
|
453
|
+
network,
|
|
454
|
+
asset: assetConfig.address,
|
|
455
|
+
maxAmountRequired: maxAmountRequiredBigInt.toString(),
|
|
456
|
+
payTo,
|
|
457
|
+
price: `$${(priceUsdCents / 100).toFixed(2)}`,
|
|
458
|
+
currency: "USD"
|
|
459
|
+
};
|
|
460
|
+
const paymentHeader = request.headers.get("X-PAYMENT") || request.headers.get("x-payment") || null;
|
|
461
|
+
const result = await checkPayment({
|
|
462
|
+
paymentHeader,
|
|
463
|
+
paymentRequirements,
|
|
464
|
+
facilitatorUrl: facilitatorUrl || MANTLE_DEFAULTS.FACILITATOR_URL,
|
|
465
|
+
routeKey,
|
|
466
|
+
network,
|
|
467
|
+
asset: assetConfig.address,
|
|
468
|
+
telemetry,
|
|
469
|
+
onPaymentSettled
|
|
470
|
+
});
|
|
471
|
+
if (!result.isValid) {
|
|
472
|
+
return new Response(JSON.stringify(result.responseBody), {
|
|
473
|
+
status: result.statusCode,
|
|
474
|
+
headers: {
|
|
475
|
+
"Content-Type": "application/json"
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
return handler(request);
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
}
|
|
287
483
|
// Annotate the CommonJS export names for ESM import in node:
|
|
288
484
|
0 && (module.exports = {
|
|
289
|
-
|
|
485
|
+
DEFAULT_TELEMETRY_ENDPOINT,
|
|
486
|
+
buildRouteKey,
|
|
487
|
+
checkPayment,
|
|
290
488
|
createPaymentMiddleware,
|
|
291
|
-
|
|
489
|
+
createTelemetryEvent,
|
|
490
|
+
decodePaymentHeader,
|
|
491
|
+
express,
|
|
492
|
+
mantlePaywall,
|
|
493
|
+
nextjs,
|
|
494
|
+
sendTelemetry,
|
|
495
|
+
validateAddress,
|
|
496
|
+
web
|
|
292
497
|
});
|
package/dist/server.d.cts
CHANGED
|
@@ -1,116 +1,79 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export { M as
|
|
1
|
+
import { c as PaymentCheckInput, d as PaymentCheckResult } from './types-CrOsOHcX.cjs';
|
|
2
|
+
export { M as MinimalPaywallOptions, P as PaymentLogEntry, R as RouteKey, a as RoutePricingConfig, b as RoutesConfig, T as TelemetryConfig } from './types-CrOsOHcX.cjs';
|
|
3
|
+
import { c as PaymentHeaderObject } from './types-BFUqKBBO.cjs';
|
|
4
|
+
export { M as MantleMiddleware, c as createPaymentMiddleware, e as express, m as mantlePaywall } from './express-eQOPxfnI.cjs';
|
|
5
|
+
export { n as nextjs } from './nextjs-Duecps0q.cjs';
|
|
6
|
+
export { w as web } from './web-standards-BNQyWzBC.cjs';
|
|
7
|
+
import { P as PaymentLogEntry, T as TelemetryConfig, c as TelemetryEvent } from './types-CoOdbZSp.cjs';
|
|
8
|
+
import 'express';
|
|
9
|
+
import 'next/server';
|
|
5
10
|
|
|
6
|
-
/** Unique key for a protected route, e.g. "GET /api/protected". */
|
|
7
|
-
type RouteKey = string;
|
|
8
|
-
/** Pricing config for a single route. */
|
|
9
|
-
interface RoutePricingConfig {
|
|
10
|
-
/** Price in USD cents, e.g. 1 => $0.01. */
|
|
11
|
-
priceUsdCents: number;
|
|
12
|
-
/** Network identifier (e.g. "mantle-mainnet"). */
|
|
13
|
-
network: NetworkId;
|
|
14
|
-
}
|
|
15
|
-
/** Map of route keys to pricing config. */
|
|
16
|
-
type RoutesConfig = Record<RouteKey, RoutePricingConfig>;
|
|
17
|
-
/** Log entry for a successfully settled payment. */
|
|
18
|
-
interface PaymentLogEntry {
|
|
19
|
-
id: string;
|
|
20
|
-
from: string;
|
|
21
|
-
to: string;
|
|
22
|
-
valueAtomic: string;
|
|
23
|
-
network: NetworkId;
|
|
24
|
-
asset: string;
|
|
25
|
-
route?: RouteKey;
|
|
26
|
-
txHash?: string;
|
|
27
|
-
timestamp: number;
|
|
28
|
-
facilitatorUrl?: string;
|
|
29
|
-
paymentRequirements?: PaymentRequirements;
|
|
30
|
-
}
|
|
31
|
-
/** Config for optional telemetry (billing/analytics). */
|
|
32
|
-
interface TelemetryConfig {
|
|
33
|
-
/** Project key from nosubs.ai dashboard. */
|
|
34
|
-
projectKey: string;
|
|
35
|
-
/**
|
|
36
|
-
* Telemetry endpoint URL.
|
|
37
|
-
* If not specified, uses DEFAULT_TELEMETRY_ENDPOINT (see server/constants.ts).
|
|
38
|
-
* If both are undefined, telemetry is not sent.
|
|
39
|
-
*/
|
|
40
|
-
endpoint?: string;
|
|
41
|
-
}
|
|
42
|
-
/** Telemetry event payload for payment_verified. */
|
|
43
|
-
interface TelemetryEvent {
|
|
44
|
-
event: "payment_verified";
|
|
45
|
-
ts: number;
|
|
46
|
-
projectKey: string;
|
|
47
|
-
network: string;
|
|
48
|
-
buyer: string;
|
|
49
|
-
payTo: string;
|
|
50
|
-
amountAtomic: string;
|
|
51
|
-
asset: string;
|
|
52
|
-
decimals: number;
|
|
53
|
-
nonce: string;
|
|
54
|
-
route: string;
|
|
55
|
-
facilitatorType: "hosted" | "self-hosted";
|
|
56
|
-
facilitatorUrl?: string;
|
|
57
|
-
facilitatorAddress?: string;
|
|
58
|
-
txHash?: string;
|
|
59
|
-
priceUsd?: string;
|
|
60
|
-
}
|
|
61
|
-
/** Config for createPaymentMiddleware. */
|
|
62
|
-
interface PaymentMiddlewareConfig {
|
|
63
|
-
/** Base URL of facilitator, e.g. https://facilitator.nosubs.ai */
|
|
64
|
-
facilitatorUrl: string;
|
|
65
|
-
/** Recipient address (developer). */
|
|
66
|
-
receiverAddress: `0x${string}`;
|
|
67
|
-
/** Map of protected routes and their pricing. */
|
|
68
|
-
routes: RoutesConfig;
|
|
69
|
-
/**
|
|
70
|
-
* Optional hook called whenever a payment is successfully settled.
|
|
71
|
-
* You can use this to push logs into your DB / analytics pipeline.
|
|
72
|
-
*/
|
|
73
|
-
onPaymentSettled?: (entry: PaymentLogEntry) => void;
|
|
74
|
-
/** Optional: Send usage telemetry for billing/analytics. */
|
|
75
|
-
telemetry?: TelemetryConfig;
|
|
76
|
-
}
|
|
77
11
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
12
|
+
* Validate Ethereum address format.
|
|
13
|
+
* Throws descriptive error if invalid.
|
|
14
|
+
*
|
|
15
|
+
* @param address - Address to validate
|
|
16
|
+
* @param paramName - Parameter name for error messages (default: "address")
|
|
17
|
+
* @throws Error if address is invalid
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* validateAddress("0x1234567890123456789012345678901234567890", "payTo");
|
|
22
|
+
* // Valid - no error thrown
|
|
23
|
+
*
|
|
24
|
+
* validateAddress("invalid", "payTo");
|
|
25
|
+
* // Throws: "payTo must start with \"0x\"..."
|
|
26
|
+
* ```
|
|
80
27
|
*/
|
|
81
|
-
|
|
82
|
-
/** Price in USD (e.g. 0.01 for 1 cent). */
|
|
83
|
-
priceUsd: number;
|
|
84
|
-
/** Recipient address (developer wallet). */
|
|
85
|
-
payTo: `0x${string}`;
|
|
86
|
-
/** Optional facilitator URL (defaults to localhost:8080 or NEXT_PUBLIC_FACILITATOR_URL). */
|
|
87
|
-
facilitatorUrl?: string;
|
|
88
|
-
/** Optional telemetry config. */
|
|
89
|
-
telemetry?: TelemetryConfig;
|
|
90
|
-
/** Optional payment settled hook. */
|
|
91
|
-
onPaymentSettled?: (entry: PaymentLogEntry) => void;
|
|
92
|
-
}
|
|
28
|
+
declare function validateAddress(address: string, paramName?: string): void;
|
|
93
29
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
30
|
+
* Decode base64 payment header into JSON object.
|
|
31
|
+
* Works in both Node.js and browser environments.
|
|
96
32
|
*/
|
|
97
|
-
|
|
33
|
+
declare function decodePaymentHeader(paymentHeaderBase64: string): PaymentHeaderObject;
|
|
34
|
+
/**
|
|
35
|
+
* Build a route key from HTTP method and path.
|
|
36
|
+
* @param method - HTTP method (GET, POST, etc.)
|
|
37
|
+
* @param path - URL path (e.g. "/api/protected")
|
|
38
|
+
* @returns Route key string (e.g. "POST /api/protected")
|
|
39
|
+
*/
|
|
40
|
+
declare function buildRouteKey(method: string, path: string): string;
|
|
98
41
|
|
|
99
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Check payment header and verify with facilitator.
|
|
44
|
+
* This function is framework-agnostic and can be used with any HTTP framework.
|
|
45
|
+
*
|
|
46
|
+
* @param input - Payment check configuration
|
|
47
|
+
* @returns Result indicating whether to allow access or return error response
|
|
48
|
+
*/
|
|
49
|
+
declare function checkPayment(input: PaymentCheckInput): Promise<PaymentCheckResult>;
|
|
100
50
|
|
|
101
51
|
/**
|
|
102
|
-
*
|
|
103
|
-
* Uses Mantle mainnet defaults (USDC, exact scheme, etc.).
|
|
52
|
+
* Default telemetry endpoint URL.
|
|
104
53
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
|
|
109
|
-
|
|
54
|
+
* Set to a valid URL when the official analytics backend is ready.
|
|
55
|
+
* If undefined, telemetry will only be sent if explicitly configured
|
|
56
|
+
* via TelemetryConfig.endpoint.
|
|
57
|
+
*/
|
|
58
|
+
declare const DEFAULT_TELEMETRY_ENDPOINT: string | undefined;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Converts PaymentLogEntry to TelemetryEvent.
|
|
62
|
+
*
|
|
63
|
+
* This function transforms the internal PaymentLogEntry format
|
|
64
|
+
* to the telemetry event format expected by the analytics backend.
|
|
65
|
+
*/
|
|
66
|
+
declare function createTelemetryEvent(entry: PaymentLogEntry, config: TelemetryConfig): TelemetryEvent;
|
|
67
|
+
/**
|
|
68
|
+
* Sends telemetry event to endpoint (fire-and-forget).
|
|
69
|
+
*
|
|
70
|
+
* This function sends the telemetry event asynchronously and never throws.
|
|
71
|
+
* Errors are logged but never propagate to the caller, ensuring that
|
|
72
|
+
* telemetry failures never break the payment flow.
|
|
110
73
|
*
|
|
111
|
-
* @param
|
|
112
|
-
* @
|
|
74
|
+
* @param event - The telemetry event to send
|
|
75
|
+
* @param endpoint - The telemetry endpoint URL (optional, falls back to DEFAULT_TELEMETRY_ENDPOINT)
|
|
113
76
|
*/
|
|
114
|
-
declare function
|
|
77
|
+
declare function sendTelemetry(event: TelemetryEvent, endpoint?: string): Promise<void>;
|
|
115
78
|
|
|
116
|
-
export {
|
|
79
|
+
export { DEFAULT_TELEMETRY_ENDPOINT, PaymentCheckInput, PaymentCheckResult, buildRouteKey, checkPayment, createTelemetryEvent, decodePaymentHeader, sendTelemetry, validateAddress };
|