@puga-labs/x402-mantle-sdk 0.3.2 → 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.
Files changed (53) hide show
  1. package/dist/{chunk-GHUWTX7J.js → chunk-CXRILT3C.js} +4 -2
  2. package/dist/{chunk-6GLR5EBK.js → chunk-QWQUSRLY.js} +5 -2
  3. package/dist/{chunk-BRGW36P7.js → chunk-ZLCKBFVJ.js} +27 -1
  4. package/dist/{chunk-WFUDGBKK.js → chunk-ZROK2XOB.js} +4 -2
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.js +2 -2
  7. package/dist/server-express.cjs +1 -1
  8. package/dist/server-express.js +2 -2
  9. package/dist/server-nextjs.cjs +1 -1
  10. package/dist/server-nextjs.js +2 -2
  11. package/dist/server-web.cjs +1 -1
  12. package/dist/server-web.js +2 -2
  13. package/dist/server.cjs +1 -1
  14. package/dist/server.js +4 -4
  15. package/package.json +2 -2
  16. package/dist/chunk-CTI5CRDY.js +0 -274
  17. package/dist/chunk-DA6ZBXNO.js +0 -275
  18. package/dist/chunk-FD4HG7KR.js +0 -135
  19. package/dist/chunk-FHU6CFHF.js +0 -0
  20. package/dist/chunk-GWVWPS3R.js +0 -277
  21. package/dist/chunk-HTZ3QFY4.js +0 -135
  22. package/dist/chunk-MQALBRGV.js +0 -135
  23. package/dist/chunk-PYIYE3HI.js +0 -135
  24. package/dist/chunk-Q6SPMEIW.js +0 -235
  25. package/dist/chunk-RNKXSBT7.js +0 -135
  26. package/dist/chunk-SPCXFN7C.js +0 -284
  27. package/dist/chunk-T5DRYLNB.js +0 -135
  28. package/dist/chunk-TSEE5NSJ.js +0 -297
  29. package/dist/chunk-WAKJRVUP.js +0 -135
  30. package/dist/chunk-WELDWRDX.js +0 -307
  31. package/dist/chunk-XAQGMFSR.js +0 -56
  32. package/dist/constants-C7aY8u5b.d.cts +0 -77
  33. package/dist/constants-C7aY8u5b.d.ts +0 -77
  34. package/dist/constants-CVFF0ray.d.ts +0 -17
  35. package/dist/constants-DzCGK0Q3.d.cts +0 -17
  36. package/dist/createMantleClient-DS1Ghqrz.d.cts +0 -51
  37. package/dist/createMantleClient-DS1Ghqrz.d.ts +0 -51
  38. package/dist/createMantleClient-DVFkbBfS.d.ts +0 -87
  39. package/dist/createMantleClient-NN0Nitp9.d.cts +0 -87
  40. package/dist/express-Ck7eryef.d.cts +0 -66
  41. package/dist/express-CmEg5hR3.d.ts +0 -66
  42. package/dist/nextjs-Bp8DxYDN.d.ts +0 -45
  43. package/dist/nextjs-CliiaTPe.d.cts +0 -45
  44. package/dist/nextjs-D7t-BC4N.d.ts +0 -45
  45. package/dist/nextjs-ZO2J9mdo.d.cts +0 -45
  46. package/dist/types-2zqbJvcz.d.cts +0 -63
  47. package/dist/types-2zqbJvcz.d.ts +0 -63
  48. package/dist/types-C7EPJ6Hd.d.ts +0 -85
  49. package/dist/types-CEttmr1U.d.cts +0 -97
  50. package/dist/types-D20K36pc.d.ts +0 -97
  51. package/dist/types-xkNm0uzE.d.cts +0 -85
  52. package/dist/web-standards-C3D2vdTg.d.ts +0 -77
  53. package/dist/web-standards-DOYp0UDT.d.cts +0 -77
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  buildRouteKey,
3
- checkPayment
4
- } from "./chunk-BRGW36P7.js";
3
+ checkPayment,
4
+ validateAddress
5
+ } from "./chunk-ZLCKBFVJ.js";
5
6
  import {
6
7
  MANTLE_DEFAULTS,
7
8
  __export,
@@ -17,6 +18,7 @@ __export(nextjs_exports, {
17
18
  import { NextResponse } from "next/server";
18
19
  function mantlePaywall(opts) {
19
20
  const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
21
+ validateAddress(payTo, "payTo");
20
22
  const priceUsdCents = Math.round(priceUsd * 100);
21
23
  return function(handler) {
22
24
  return async (req) => {
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  buildRouteKey,
3
- checkPayment
4
- } from "./chunk-BRGW36P7.js";
3
+ checkPayment,
4
+ validateAddress
5
+ } from "./chunk-ZLCKBFVJ.js";
5
6
  import {
6
7
  MANTLE_DEFAULTS,
7
8
  __export,
@@ -23,6 +24,7 @@ function createPaymentMiddleware(config) {
23
24
  if (!receiverAddress) {
24
25
  throw new Error("receiverAddress is required");
25
26
  }
27
+ validateAddress(receiverAddress, "receiverAddress");
26
28
  if (!routes || Object.keys(routes).length === 0) {
27
29
  throw new Error("routes config must not be empty");
28
30
  }
@@ -68,6 +70,7 @@ function createPaymentMiddleware(config) {
68
70
  }
69
71
  function mantlePaywall(opts) {
70
72
  const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
73
+ validateAddress(payTo, "payTo");
71
74
  const priceUsdCents = Math.round(priceUsd * 100);
72
75
  return async (req, res, next) => {
73
76
  const method = (req.method || "GET").toUpperCase();
@@ -3,6 +3,31 @@ import {
3
3
  } from "./chunk-HEZZ74SI.js";
4
4
 
5
5
  // src/server/core/utils.ts
6
+ function validateAddress(address, paramName = "address") {
7
+ if (!address) {
8
+ throw new Error(`${paramName} is required`);
9
+ }
10
+ if (typeof address !== "string") {
11
+ throw new Error(`${paramName} must be a string, got ${typeof address}`);
12
+ }
13
+ if (!address.startsWith("0x")) {
14
+ const preview = address.length > 10 ? `${address.substring(0, 10)}...` : address;
15
+ throw new Error(
16
+ `${paramName} must start with "0x", got: ${preview}`
17
+ );
18
+ }
19
+ if (address.length !== 42) {
20
+ throw new Error(
21
+ `${paramName} must be 42 characters (0x + 40 hex), got ${address.length} characters`
22
+ );
23
+ }
24
+ const hexPart = address.slice(2);
25
+ if (!/^[0-9a-fA-F]{40}$/.test(hexPart)) {
26
+ throw new Error(
27
+ `${paramName} must contain only hexadecimal characters (0-9, a-f, A-F) after "0x"`
28
+ );
29
+ }
30
+ }
6
31
  function decodePaymentHeader(paymentHeaderBase64) {
7
32
  try {
8
33
  if (typeof Buffer !== "undefined") {
@@ -90,7 +115,7 @@ async function checkPayment(input) {
90
115
  telemetry,
91
116
  onPaymentSettled
92
117
  } = input;
93
- if (!paymentHeader) {
118
+ if (!paymentHeader || paymentHeader.trim() === "") {
94
119
  return {
95
120
  status: "require_payment",
96
121
  statusCode: 402,
@@ -202,6 +227,7 @@ async function checkPayment(input) {
202
227
  }
203
228
 
204
229
  export {
230
+ validateAddress,
205
231
  decodePaymentHeader,
206
232
  buildRouteKey,
207
233
  DEFAULT_TELEMETRY_ENDPOINT,
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  buildRouteKey,
3
- checkPayment
4
- } from "./chunk-BRGW36P7.js";
3
+ checkPayment,
4
+ validateAddress
5
+ } from "./chunk-ZLCKBFVJ.js";
5
6
  import {
6
7
  MANTLE_DEFAULTS,
7
8
  __export,
@@ -16,6 +17,7 @@ __export(web_standards_exports, {
16
17
  });
17
18
  function mantlePaywall(opts) {
18
19
  const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
20
+ validateAddress(payTo, "payTo");
19
21
  const priceUsdCents = Math.round(priceUsd * 100);
20
22
  return function(handler) {
21
23
  return async (request) => {
package/dist/index.cjs CHANGED
@@ -195,7 +195,7 @@ async function checkPayment(input) {
195
195
  telemetry,
196
196
  onPaymentSettled
197
197
  } = input;
198
- if (!paymentHeader) {
198
+ if (!paymentHeader || paymentHeader.trim() === "") {
199
199
  return {
200
200
  status: "require_payment",
201
201
  statusCode: 402,
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-PPVS3X5Z.js";
14
- import "./chunk-U73CZU3X.js";
13
+ } from "./chunk-QWQUSRLY.js";
14
+ import "./chunk-ZLCKBFVJ.js";
15
15
  import {
16
16
  MANTLE_DEFAULTS
17
17
  } from "./chunk-HEZZ74SI.js";
@@ -173,7 +173,7 @@ async function checkPayment(input) {
173
173
  telemetry,
174
174
  onPaymentSettled
175
175
  } = input;
176
- if (!paymentHeader) {
176
+ if (!paymentHeader || paymentHeader.trim() === "") {
177
177
  return {
178
178
  status: "require_payment",
179
179
  statusCode: 402,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createPaymentMiddleware,
3
3
  mantlePaywall
4
- } from "./chunk-PPVS3X5Z.js";
5
- import "./chunk-U73CZU3X.js";
4
+ } from "./chunk-QWQUSRLY.js";
5
+ import "./chunk-ZLCKBFVJ.js";
6
6
  import {
7
7
  MANTLE_DEFAULTS
8
8
  } from "./chunk-HEZZ74SI.js";
@@ -175,7 +175,7 @@ async function checkPayment(input) {
175
175
  telemetry,
176
176
  onPaymentSettled
177
177
  } = input;
178
- if (!paymentHeader) {
178
+ if (!paymentHeader || paymentHeader.trim() === "") {
179
179
  return {
180
180
  status: "require_payment",
181
181
  statusCode: 402,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mantlePaywall
3
- } from "./chunk-PCJEJYP6.js";
4
- import "./chunk-U73CZU3X.js";
3
+ } from "./chunk-CXRILT3C.js";
4
+ import "./chunk-ZLCKBFVJ.js";
5
5
  import {
6
6
  MANTLE_DEFAULTS
7
7
  } from "./chunk-HEZZ74SI.js";
@@ -172,7 +172,7 @@ async function checkPayment(input) {
172
172
  telemetry,
173
173
  onPaymentSettled
174
174
  } = input;
175
- if (!paymentHeader) {
175
+ if (!paymentHeader || paymentHeader.trim() === "") {
176
176
  return {
177
177
  status: "require_payment",
178
178
  statusCode: 402,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mantlePaywall
3
- } from "./chunk-NQWSCY44.js";
4
- import "./chunk-U73CZU3X.js";
3
+ } from "./chunk-ZROK2XOB.js";
4
+ import "./chunk-ZLCKBFVJ.js";
5
5
  import {
6
6
  MANTLE_DEFAULTS
7
7
  } from "./chunk-HEZZ74SI.js";
package/dist/server.cjs CHANGED
@@ -182,7 +182,7 @@ async function checkPayment(input) {
182
182
  telemetry,
183
183
  onPaymentSettled
184
184
  } = input;
185
- if (!paymentHeader) {
185
+ if (!paymentHeader || paymentHeader.trim() === "") {
186
186
  return {
187
187
  status: "require_payment",
188
188
  statusCode: 402,
package/dist/server.js CHANGED
@@ -3,13 +3,13 @@ import {
3
3
  createPaymentMiddleware,
4
4
  express_exports,
5
5
  mantlePaywall
6
- } from "./chunk-PPVS3X5Z.js";
6
+ } from "./chunk-QWQUSRLY.js";
7
7
  import {
8
8
  nextjs_exports
9
- } from "./chunk-PCJEJYP6.js";
9
+ } from "./chunk-CXRILT3C.js";
10
10
  import {
11
11
  web_standards_exports
12
- } from "./chunk-NQWSCY44.js";
12
+ } from "./chunk-ZROK2XOB.js";
13
13
  import {
14
14
  DEFAULT_TELEMETRY_ENDPOINT,
15
15
  buildRouteKey,
@@ -18,7 +18,7 @@ import {
18
18
  decodePaymentHeader,
19
19
  sendTelemetry,
20
20
  validateAddress
21
- } from "./chunk-U73CZU3X.js";
21
+ } from "./chunk-ZLCKBFVJ.js";
22
22
  import "./chunk-HEZZ74SI.js";
23
23
  export {
24
24
  DEFAULT_TELEMETRY_ENDPOINT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puga-labs/x402-mantle-sdk",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "x402 payments SDK for Mantle (USDC, gasless, facilitator-based)",
5
5
  "license": "MIT",
6
6
  "author": "Evgenii Pugachev <cyprus.pugamuga@gmail.com>",
@@ -108,7 +108,7 @@
108
108
  "peerDependencies": {
109
109
  "ethers": "^6.0.0",
110
110
  "express": "^4.0.0 || ^5.0.0",
111
- "next": "^14.0.0 || ^15.0.0",
111
+ "next": "^14.0.0 || ^15.0.0 || ^16.0.0",
112
112
  "react": "^18.0.0 || ^19.0.0"
113
113
  },
114
114
  "peerDependenciesMeta": {
@@ -1,274 +0,0 @@
1
- import {
2
- __require,
3
- getChainIdForNetwork
4
- } from "./chunk-XAQGMFSR.js";
5
-
6
- // src/shared/utils.ts
7
- function encodeJsonToBase64(value) {
8
- const json = JSON.stringify(value);
9
- if (typeof btoa === "function") {
10
- const bytes = new TextEncoder().encode(json);
11
- const binString = Array.from(
12
- bytes,
13
- (byte) => String.fromCodePoint(byte)
14
- ).join("");
15
- return btoa(binString);
16
- }
17
- if (typeof globalThis.Buffer !== "undefined") {
18
- return globalThis.Buffer.from(json, "utf8").toString("base64");
19
- }
20
- throw new Error("No base64 implementation found in this environment");
21
- }
22
- function randomBytes32Hex() {
23
- if (typeof crypto !== "undefined" && "getRandomValues" in crypto) {
24
- const arr = new Uint8Array(32);
25
- crypto.getRandomValues(arr);
26
- return "0x" + Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
27
- }
28
- try {
29
- const nodeCrypto = __require("crypto");
30
- const buf = nodeCrypto.randomBytes(32);
31
- return "0x" + buf.toString("hex");
32
- } catch {
33
- throw new Error(
34
- "No cryptographically secure random number generator found. This environment does not support crypto.getRandomValues or Node.js crypto module."
35
- );
36
- }
37
- }
38
-
39
- // src/client/paymentClient.ts
40
- function joinUrl(base, path) {
41
- const normalizedBase = base.replace(/\/+$/, "");
42
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
43
- return `${normalizedBase}${normalizedPath}`;
44
- }
45
- function buildTypedDataForAuthorization(authorization, paymentRequirements) {
46
- const chainId = getChainIdForNetwork(paymentRequirements.network);
47
- const verifyingContract = paymentRequirements.asset;
48
- const domain = {
49
- name: "USD Coin",
50
- version: "2",
51
- chainId,
52
- verifyingContract
53
- };
54
- const types = {
55
- TransferWithAuthorization: [
56
- { name: "from", type: "address" },
57
- { name: "to", type: "address" },
58
- { name: "value", type: "uint256" },
59
- { name: "validAfter", type: "uint256" },
60
- { name: "validBefore", type: "uint256" },
61
- { name: "nonce", type: "bytes32" }
62
- ]
63
- };
64
- return {
65
- domain,
66
- types,
67
- primaryType: "TransferWithAuthorization",
68
- message: authorization
69
- };
70
- }
71
- async function signAuthorizationWithProvider(provider, authorization, paymentRequirements) {
72
- const { BrowserProvider } = await import("ethers");
73
- const chainId = getChainIdForNetwork(paymentRequirements.network);
74
- const browserProvider = new BrowserProvider(provider, chainId);
75
- const signer = await browserProvider.getSigner();
76
- const from = await signer.getAddress();
77
- const authWithFrom = {
78
- ...authorization,
79
- from
80
- };
81
- const typedData = buildTypedDataForAuthorization(
82
- authWithFrom,
83
- paymentRequirements
84
- );
85
- const signature = await signer.signTypedData(
86
- typedData.domain,
87
- typedData.types,
88
- typedData.message
89
- );
90
- return { signature, from };
91
- }
92
- function createPaymentClient(config) {
93
- const {
94
- resourceUrl,
95
- facilitatorUrl,
96
- provider,
97
- userAddress: userAddressOverride,
98
- projectKey
99
- } = config;
100
- if (!resourceUrl) {
101
- throw new Error("resourceUrl is required");
102
- }
103
- if (!facilitatorUrl) {
104
- throw new Error("facilitatorUrl is required");
105
- }
106
- if (!provider) {
107
- throw new Error("provider is required (e.g. window.ethereum)");
108
- }
109
- return {
110
- async callWithPayment(path, options) {
111
- const method = options?.method ?? "GET";
112
- const headers = {
113
- ...options?.headers ?? {}
114
- };
115
- let body;
116
- if (options?.body !== void 0) {
117
- headers["Content-Type"] = headers["Content-Type"] ?? "application/json";
118
- body = JSON.stringify(options.body);
119
- }
120
- const initialUrl = joinUrl(resourceUrl, path);
121
- const initialRes = await fetch(initialUrl, {
122
- method,
123
- headers,
124
- body
125
- });
126
- if (initialRes.status !== 402) {
127
- const json = await initialRes.json().catch((err) => {
128
- console.error("[x402] Failed to parse initial response JSON:", err);
129
- return null;
130
- });
131
- return {
132
- response: json,
133
- txHash: void 0
134
- };
135
- }
136
- const bodyJson = await initialRes.json();
137
- const paymentRequirements = bodyJson.paymentRequirements;
138
- if (!paymentRequirements) {
139
- throw new Error(
140
- "402 response did not include paymentRequirements field"
141
- );
142
- }
143
- const nowSec = Math.floor(Date.now() / 1e3);
144
- const validAfter = "0";
145
- const validBefore = String(nowSec + 10 * 60);
146
- const nonce = randomBytes32Hex();
147
- const valueAtomic = options?.valueOverrideAtomic ?? paymentRequirements.maxAmountRequired;
148
- let authorization = {
149
- from: "0x0000000000000000000000000000000000000000",
150
- to: paymentRequirements.payTo,
151
- value: valueAtomic,
152
- validAfter,
153
- validBefore,
154
- nonce
155
- };
156
- const { signature, from } = await signAuthorizationWithProvider(
157
- provider,
158
- authorization,
159
- paymentRequirements
160
- );
161
- authorization = {
162
- ...authorization,
163
- from
164
- };
165
- if (userAddressOverride && userAddressOverride.toLowerCase() !== from.toLowerCase()) {
166
- console.warn(
167
- "[SDK WARNING] userAddress override differs from signer address",
168
- { override: userAddressOverride, signer: from }
169
- );
170
- }
171
- const paymentHeaderObject = {
172
- x402Version: 1,
173
- scheme: paymentRequirements.scheme,
174
- network: paymentRequirements.network,
175
- payload: {
176
- signature,
177
- authorization
178
- }
179
- };
180
- const paymentHeader = encodeJsonToBase64(paymentHeaderObject);
181
- const settleUrl = joinUrl(facilitatorUrl, "/settle");
182
- const settleRes = await fetch(settleUrl, {
183
- method: "POST",
184
- headers: {
185
- "Content-Type": "application/json",
186
- ...projectKey ? { "X-Project-Key": projectKey } : {}
187
- },
188
- body: JSON.stringify({
189
- x402Version: 1,
190
- paymentHeader,
191
- paymentRequirements
192
- })
193
- });
194
- if (!settleRes.ok) {
195
- const text = await settleRes.text().catch((err) => {
196
- console.error("[x402] Failed to read settle response text:", err);
197
- return "";
198
- });
199
- throw new Error(
200
- `Facilitator /settle failed with HTTP ${settleRes.status}: ${text}`
201
- );
202
- }
203
- const settleJson = await settleRes.json();
204
- if (!settleJson.success) {
205
- throw new Error(
206
- `Facilitator /settle returned error: ${settleJson.error ?? "unknown error"}`
207
- );
208
- }
209
- const txHash = settleJson.txHash ?? void 0;
210
- const retryHeaders = {
211
- ...headers,
212
- "X-PAYMENT": paymentHeader
213
- };
214
- const retryRes = await fetch(initialUrl, {
215
- method,
216
- headers: retryHeaders,
217
- body
218
- });
219
- if (!retryRes.ok) {
220
- const text = await retryRes.text().catch((err) => {
221
- console.error("[x402] Failed to read retry response text:", err);
222
- return "";
223
- });
224
- throw new Error(
225
- `Protected request with X-PAYMENT failed: HTTP ${retryRes.status} ${text}`
226
- );
227
- }
228
- const finalJson = await retryRes.json();
229
- return {
230
- response: finalJson,
231
- txHash,
232
- paymentHeader,
233
- paymentRequirements
234
- };
235
- }
236
- };
237
- }
238
-
239
- // src/client/createMantleClient.ts
240
- function createMantleClient(config) {
241
- const resourceUrl = config?.resourceUrl ?? (typeof window !== "undefined" ? window.location.origin : "");
242
- const facilitatorUrl = config?.facilitatorUrl ?? (typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_FACILITATOR_URL : void 0) ?? "http://localhost:8080";
243
- return {
244
- async postWithPayment(url, body) {
245
- const account = await config?.getAccount?.();
246
- if (!account) {
247
- throw new Error(
248
- "Wallet not connected. Please connect your wallet first."
249
- );
250
- }
251
- const provider = config?.getProvider?.();
252
- if (!provider) {
253
- throw new Error("Wallet provider not available");
254
- }
255
- const client = createPaymentClient({
256
- resourceUrl,
257
- facilitatorUrl,
258
- provider,
259
- userAddress: account,
260
- projectKey: config?.projectKey
261
- });
262
- const result = await client.callWithPayment(url, {
263
- method: "POST",
264
- body
265
- });
266
- return result;
267
- }
268
- };
269
- }
270
-
271
- export {
272
- createPaymentClient,
273
- createMantleClient
274
- };