@puga-labs/x402-mantle-sdk 0.2.1 → 0.3.2

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 (95) hide show
  1. package/dist/chunk-23QNUJIB.js +136 -0
  2. package/dist/chunk-6GLR5EBK.js +96 -0
  3. package/dist/chunk-BRGW36P7.js +211 -0
  4. package/dist/chunk-CTI5CRDY.js +274 -0
  5. package/dist/chunk-DA6ZBXNO.js +275 -0
  6. package/dist/chunk-E46A7I6B.js +274 -0
  7. package/dist/chunk-FD4HG7KR.js +135 -0
  8. package/dist/chunk-FHU6CFHF.js +0 -0
  9. package/dist/chunk-GHUWTX7J.js +66 -0
  10. package/dist/chunk-GWVWPS3R.js +277 -0
  11. package/dist/chunk-HEZZ74SI.js +62 -0
  12. package/dist/chunk-HTZ3QFY4.js +135 -0
  13. package/dist/chunk-MQALBRGV.js +135 -0
  14. package/dist/chunk-NQWSCY44.js +70 -0
  15. package/dist/chunk-PCJEJYP6.js +68 -0
  16. package/dist/chunk-PPVS3X5Z.js +99 -0
  17. package/dist/chunk-PYIYE3HI.js +135 -0
  18. package/dist/chunk-Q6SPMEIW.js +235 -0
  19. package/dist/chunk-RNKXSBT7.js +135 -0
  20. package/dist/chunk-SPCXFN7C.js +284 -0
  21. package/dist/chunk-T5DRYLNB.js +135 -0
  22. package/dist/chunk-TSEE5NSJ.js +297 -0
  23. package/dist/chunk-U73CZU3X.js +237 -0
  24. package/dist/chunk-WAKJRVUP.js +135 -0
  25. package/dist/chunk-WELDWRDX.js +307 -0
  26. package/dist/chunk-WFUDGBKK.js +68 -0
  27. package/dist/chunk-WO2MYZXT.js +0 -0
  28. package/dist/chunk-XAQGMFSR.js +56 -0
  29. package/dist/client.cjs +328 -0
  30. package/dist/client.d.cts +17 -0
  31. package/dist/client.d.ts +17 -0
  32. package/dist/client.js +12 -0
  33. package/dist/constants-0ncqvV_O.d.ts +17 -0
  34. package/dist/constants-C7aY8u5b.d.cts +77 -0
  35. package/dist/constants-C7aY8u5b.d.ts +77 -0
  36. package/dist/constants-CVFF0ray.d.ts +17 -0
  37. package/dist/constants-CsIL25uQ.d.cts +17 -0
  38. package/dist/constants-DzCGK0Q3.d.cts +17 -0
  39. package/dist/createMantleClient-CO0uWPb-.d.cts +87 -0
  40. package/dist/createMantleClient-CuiPsTa6.d.ts +87 -0
  41. package/dist/createMantleClient-DS1Ghqrz.d.cts +51 -0
  42. package/dist/createMantleClient-DS1Ghqrz.d.ts +51 -0
  43. package/dist/createMantleClient-DVFkbBfS.d.ts +87 -0
  44. package/dist/createMantleClient-NN0Nitp9.d.cts +87 -0
  45. package/dist/express-Ck7eryef.d.cts +66 -0
  46. package/dist/express-CmEg5hR3.d.ts +66 -0
  47. package/dist/express-D8EwEcOL.d.ts +66 -0
  48. package/dist/express-eQOPxfnI.d.cts +66 -0
  49. package/dist/index.cjs +342 -155
  50. package/dist/index.d.cts +10 -290
  51. package/dist/index.d.ts +10 -290
  52. package/dist/index.js +18 -567
  53. package/dist/nextjs-Bp8DxYDN.d.ts +45 -0
  54. package/dist/nextjs-CliiaTPe.d.cts +45 -0
  55. package/dist/nextjs-D7t-BC4N.d.ts +45 -0
  56. package/dist/nextjs-Duecps0q.d.cts +45 -0
  57. package/dist/nextjs-TFhFiQuL.d.ts +45 -0
  58. package/dist/nextjs-ZO2J9mdo.d.cts +45 -0
  59. package/dist/react.cjs +454 -0
  60. package/dist/react.d.cts +93 -0
  61. package/dist/react.d.ts +93 -0
  62. package/dist/react.js +10 -0
  63. package/dist/server-express.cjs +368 -0
  64. package/dist/server-express.d.cts +5 -0
  65. package/dist/server-express.d.ts +5 -0
  66. package/dist/server-express.js +13 -0
  67. package/dist/server-nextjs.cjs +339 -0
  68. package/dist/server-nextjs.d.cts +5 -0
  69. package/dist/server-nextjs.d.ts +5 -0
  70. package/dist/server-nextjs.js +11 -0
  71. package/dist/server-web.cjs +339 -0
  72. package/dist/server-web.d.cts +4 -0
  73. package/dist/server-web.d.ts +4 -0
  74. package/dist/server-web.js +11 -0
  75. package/dist/server.cjs +497 -0
  76. package/dist/server.d.cts +79 -0
  77. package/dist/server.d.ts +79 -0
  78. package/dist/server.js +36 -0
  79. package/dist/types-2zqbJvcz.d.cts +63 -0
  80. package/dist/types-2zqbJvcz.d.ts +63 -0
  81. package/dist/types-BFUqKBBO.d.cts +63 -0
  82. package/dist/types-BFUqKBBO.d.ts +63 -0
  83. package/dist/types-C7EPJ6Hd.d.ts +85 -0
  84. package/dist/types-CEttmr1U.d.cts +97 -0
  85. package/dist/types-CoOdbZSp.d.cts +97 -0
  86. package/dist/types-CqQ6OgRi.d.ts +85 -0
  87. package/dist/types-CrOsOHcX.d.cts +85 -0
  88. package/dist/types-D20K36pc.d.ts +97 -0
  89. package/dist/types-DTzov_EE.d.ts +97 -0
  90. package/dist/types-xkNm0uzE.d.cts +85 -0
  91. package/dist/web-standards-BNQyWzBC.d.cts +77 -0
  92. package/dist/web-standards-C3D2vdTg.d.ts +77 -0
  93. package/dist/web-standards-D8j1kZxd.d.ts +77 -0
  94. package/dist/web-standards-DOYp0UDT.d.cts +77 -0
  95. package/package.json +80 -8
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -25,6 +35,7 @@ __export(index_exports, {
25
35
  createPaymentClient: () => createPaymentClient,
26
36
  createPaymentMiddleware: () => createPaymentMiddleware,
27
37
  mantlePaywall: () => mantlePaywall,
38
+ useEthersWallet: () => useEthersWallet,
28
39
  useMantleX402: () => useMantleX402
29
40
  });
30
41
  module.exports = __toCommonJS(index_exports);
@@ -71,6 +82,54 @@ function usdCentsToAtomic(cents, decimals) {
71
82
  return BigInt(cents) * base;
72
83
  }
73
84
 
85
+ // src/server/core/utils.ts
86
+ function validateAddress(address, paramName = "address") {
87
+ if (!address) {
88
+ throw new Error(`${paramName} is required`);
89
+ }
90
+ if (typeof address !== "string") {
91
+ throw new Error(`${paramName} must be a string, got ${typeof address}`);
92
+ }
93
+ if (!address.startsWith("0x")) {
94
+ const preview = address.length > 10 ? `${address.substring(0, 10)}...` : address;
95
+ throw new Error(
96
+ `${paramName} must start with "0x", got: ${preview}`
97
+ );
98
+ }
99
+ if (address.length !== 42) {
100
+ throw new Error(
101
+ `${paramName} must be 42 characters (0x + 40 hex), got ${address.length} characters`
102
+ );
103
+ }
104
+ const hexPart = address.slice(2);
105
+ if (!/^[0-9a-fA-F]{40}$/.test(hexPart)) {
106
+ throw new Error(
107
+ `${paramName} must contain only hexadecimal characters (0-9, a-f, A-F) after "0x"`
108
+ );
109
+ }
110
+ }
111
+ function decodePaymentHeader(paymentHeaderBase64) {
112
+ try {
113
+ if (typeof Buffer !== "undefined") {
114
+ const json = Buffer.from(paymentHeaderBase64, "base64").toString("utf8");
115
+ return JSON.parse(json);
116
+ }
117
+ if (typeof atob === "function") {
118
+ const json = atob(paymentHeaderBase64);
119
+ return JSON.parse(json);
120
+ }
121
+ throw new Error("No base64 decoding available in this environment");
122
+ } catch (err) {
123
+ const msg = err instanceof Error ? err.message : "Unknown error";
124
+ throw new Error(`Failed to decode paymentHeader: ${msg}`);
125
+ }
126
+ }
127
+ function buildRouteKey(method, path) {
128
+ const normalizedMethod = (method || "GET").toUpperCase();
129
+ const normalizedPath = path || "/";
130
+ return `${normalizedMethod} ${normalizedPath}`;
131
+ }
132
+
74
133
  // src/server/constants.ts
75
134
  var DEFAULT_TELEMETRY_ENDPOINT = void 0;
76
135
 
@@ -124,28 +183,130 @@ async function sendTelemetry(event, endpoint) {
124
183
  }
125
184
  }
126
185
 
127
- // src/server/paymentMiddleware.ts
128
- function getRouteKey(req) {
129
- const method = (req.method || "GET").toUpperCase();
130
- const path = req.path || "/";
131
- return `${method} ${path}`;
132
- }
133
- function decodePaymentHeader(paymentHeaderBase64) {
186
+ // src/server/core/verifyPayment.ts
187
+ async function checkPayment(input) {
188
+ const {
189
+ paymentHeader,
190
+ paymentRequirements,
191
+ facilitatorUrl,
192
+ routeKey,
193
+ network,
194
+ asset,
195
+ telemetry,
196
+ onPaymentSettled
197
+ } = input;
198
+ if (!paymentHeader) {
199
+ return {
200
+ status: "require_payment",
201
+ statusCode: 402,
202
+ responseBody: {
203
+ error: "Payment Required",
204
+ paymentRequirements,
205
+ paymentHeader: null
206
+ },
207
+ isValid: false
208
+ };
209
+ }
134
210
  try {
135
- if (typeof Buffer !== "undefined") {
136
- const json = Buffer.from(paymentHeaderBase64, "base64").toString("utf8");
137
- return JSON.parse(json);
211
+ const verifyUrl = `${facilitatorUrl.replace(/\/+$/, "")}/verify`;
212
+ const verifyRes = await fetch(verifyUrl, {
213
+ method: "POST",
214
+ headers: {
215
+ "Content-Type": "application/json"
216
+ },
217
+ body: JSON.stringify({
218
+ x402Version: 1,
219
+ paymentHeader,
220
+ paymentRequirements
221
+ })
222
+ });
223
+ if (!verifyRes.ok) {
224
+ const text = await verifyRes.text().catch(() => "");
225
+ console.error(
226
+ "[x402-mantle-sdk] Facilitator /verify returned non-OK:",
227
+ verifyRes.status,
228
+ text
229
+ );
230
+ return {
231
+ status: "verification_error",
232
+ statusCode: 500,
233
+ responseBody: {
234
+ error: "Payment verification error",
235
+ details: `Facilitator responded with HTTP ${verifyRes.status}`
236
+ },
237
+ isValid: false
238
+ };
138
239
  }
139
- if (typeof atob === "function") {
140
- const json = atob(paymentHeaderBase64);
141
- return JSON.parse(json);
240
+ const verifyJson = await verifyRes.json();
241
+ if (!verifyJson.isValid) {
242
+ return {
243
+ status: "invalid_payment",
244
+ statusCode: 402,
245
+ responseBody: {
246
+ error: "Payment verification failed",
247
+ invalidReason: verifyJson.invalidReason ?? null,
248
+ paymentRequirements,
249
+ paymentHeader: null
250
+ },
251
+ isValid: false
252
+ };
142
253
  }
143
- throw new Error("No base64 decoding available in this environment");
254
+ if (onPaymentSettled) {
255
+ try {
256
+ const headerObj = decodePaymentHeader(paymentHeader);
257
+ const { authorization } = headerObj.payload;
258
+ const assetConfig = getDefaultAssetForNetwork(network);
259
+ const logEntry = {
260
+ id: authorization.nonce,
261
+ from: authorization.from,
262
+ to: authorization.to,
263
+ valueAtomic: authorization.value,
264
+ network,
265
+ asset,
266
+ route: routeKey,
267
+ timestamp: Date.now(),
268
+ facilitatorUrl,
269
+ paymentRequirements
270
+ };
271
+ onPaymentSettled(logEntry);
272
+ if (telemetry) {
273
+ const event = createTelemetryEvent(logEntry, telemetry);
274
+ sendTelemetry(event, telemetry.endpoint).catch(
275
+ (err) => console.error("[x402-telemetry] Async send failed:", err)
276
+ );
277
+ }
278
+ } catch (err) {
279
+ console.error(
280
+ "[x402-mantle-sdk] Error calling onPaymentSettled hook:",
281
+ err
282
+ );
283
+ }
284
+ }
285
+ return {
286
+ status: "verified",
287
+ statusCode: 200,
288
+ responseBody: null,
289
+ isValid: true
290
+ };
144
291
  } catch (err) {
145
- const msg = err instanceof Error ? err.message : "Unknown error";
146
- throw new Error(`Failed to decode paymentHeader: ${msg}`);
292
+ console.error(
293
+ "[x402-mantle-sdk] Error while calling facilitator /verify:",
294
+ err
295
+ );
296
+ const message = err instanceof Error ? err.message : "Unknown verification error";
297
+ return {
298
+ status: "verification_error",
299
+ statusCode: 500,
300
+ responseBody: {
301
+ error: "Payment verification error",
302
+ details: message
303
+ },
304
+ isValid: false
305
+ };
147
306
  }
148
307
  }
308
+
309
+ // src/server/adapters/express.ts
149
310
  function createPaymentMiddleware(config) {
150
311
  const { facilitatorUrl, receiverAddress, routes, onPaymentSettled, telemetry } = config;
151
312
  if (!facilitatorUrl) {
@@ -154,11 +315,12 @@ function createPaymentMiddleware(config) {
154
315
  if (!receiverAddress) {
155
316
  throw new Error("receiverAddress is required");
156
317
  }
318
+ validateAddress(receiverAddress, "receiverAddress");
157
319
  if (!routes || Object.keys(routes).length === 0) {
158
320
  throw new Error("routes config must not be empty");
159
321
  }
160
322
  return async function paymentMiddleware(req, res, next) {
161
- const routeKey = getRouteKey(req);
323
+ const routeKey = buildRouteKey(req.method, req.path);
162
324
  const routeConfig = routes[routeKey];
163
325
  if (!routeConfig) {
164
326
  next();
@@ -179,104 +341,29 @@ function createPaymentMiddleware(config) {
179
341
  price: `$${(priceUsdCents / 100).toFixed(2)}`,
180
342
  currency: "USD"
181
343
  };
182
- const paymentHeader = req.header("X-PAYMENT") ?? req.header("x-payment");
183
- if (!paymentHeader) {
184
- res.status(402).json({
185
- error: "Payment Required",
186
- paymentRequirements,
187
- paymentHeader: null
188
- });
189
- return;
190
- }
191
- try {
192
- const verifyUrl = `${facilitatorUrl.replace(/\/+$/, "")}/verify`;
193
- const verifyRes = await fetch(verifyUrl, {
194
- method: "POST",
195
- headers: {
196
- "Content-Type": "application/json"
197
- },
198
- body: JSON.stringify({
199
- x402Version: 1,
200
- paymentHeader,
201
- paymentRequirements
202
- })
203
- });
204
- if (!verifyRes.ok) {
205
- const text = await verifyRes.text().catch(() => "");
206
- console.error(
207
- "[x402-mantle-sdk] Facilitator /verify returned non-OK:",
208
- verifyRes.status,
209
- text
210
- );
211
- res.status(500).json({
212
- error: "Payment verification error",
213
- details: `Facilitator responded with HTTP ${verifyRes.status}`
214
- });
215
- return;
216
- }
217
- const verifyJson = await verifyRes.json();
218
- if (!verifyJson.isValid) {
219
- res.status(402).json({
220
- error: "Payment verification failed",
221
- invalidReason: verifyJson.invalidReason ?? null,
222
- paymentRequirements,
223
- paymentHeader: null
224
- });
225
- return;
226
- }
227
- if (onPaymentSettled) {
228
- try {
229
- const headerObj = decodePaymentHeader(paymentHeader);
230
- const { authorization } = headerObj.payload;
231
- const logEntry = {
232
- id: authorization.nonce,
233
- from: authorization.from,
234
- to: authorization.to,
235
- valueAtomic: authorization.value,
236
- network,
237
- asset: assetConfig.address,
238
- route: routeKey,
239
- timestamp: Date.now(),
240
- facilitatorUrl,
241
- // Pass from config closure
242
- paymentRequirements
243
- };
244
- onPaymentSettled(logEntry);
245
- if (telemetry) {
246
- const event = createTelemetryEvent(logEntry, telemetry);
247
- sendTelemetry(event, telemetry.endpoint).catch(
248
- (err) => console.error("[x402-telemetry] Async send failed:", err)
249
- );
250
- }
251
- } catch (err) {
252
- console.error(
253
- "[x402-mantle-sdk] Error calling onPaymentSettled hook:",
254
- err
255
- );
256
- }
257
- }
258
- next();
259
- return;
260
- } catch (err) {
261
- console.error(
262
- "[x402-mantle-sdk] Error while calling facilitator /verify:",
263
- err
264
- );
265
- const message = err instanceof Error ? err.message : "Unknown verification error";
266
- res.status(500).json({
267
- error: "Payment verification error",
268
- details: message
269
- });
344
+ const paymentHeader = req.header("X-PAYMENT") || req.header("x-payment") || null;
345
+ const result = await checkPayment({
346
+ paymentHeader,
347
+ paymentRequirements,
348
+ facilitatorUrl,
349
+ routeKey,
350
+ network,
351
+ asset: assetConfig.address,
352
+ telemetry,
353
+ onPaymentSettled
354
+ });
355
+ if (!result.isValid) {
356
+ res.status(result.statusCode).json(result.responseBody);
270
357
  return;
271
358
  }
359
+ next();
272
360
  };
273
361
  }
274
-
275
- // src/server/mantlePaywall.ts
276
362
  function mantlePaywall(opts) {
277
363
  const { priceUsd, payTo, facilitatorUrl, telemetry, onPaymentSettled } = opts;
364
+ validateAddress(payTo, "payTo");
278
365
  const priceUsdCents = Math.round(priceUsd * 100);
279
- return (req, res, next) => {
366
+ return async (req, res, next) => {
280
367
  const method = (req.method || "GET").toUpperCase();
281
368
  const path = req.path || "/";
282
369
  const routeKey = `${method} ${path}`;
@@ -335,19 +422,6 @@ function joinUrl(base, path) {
335
422
  const normalizedPath = path.startsWith("/") ? path : `/${path}`;
336
423
  return `${normalizedBase}${normalizedPath}`;
337
424
  }
338
- async function getUserAddressFromProvider(provider) {
339
- const p = provider;
340
- if (!p || typeof p.request !== "function") {
341
- throw new Error("provider must implement EIP-1193 request()");
342
- }
343
- const accounts = await p.request({
344
- method: "eth_requestAccounts"
345
- });
346
- if (!accounts || accounts.length === 0) {
347
- throw new Error("No accounts returned from provider");
348
- }
349
- return accounts[0];
350
- }
351
425
  function buildTypedDataForAuthorization(authorization, paymentRequirements) {
352
426
  const chainId = getChainIdForNetwork(paymentRequirements.network);
353
427
  const verifyingContract = paymentRequirements.asset;
@@ -374,24 +448,26 @@ function buildTypedDataForAuthorization(authorization, paymentRequirements) {
374
448
  message: authorization
375
449
  };
376
450
  }
377
- async function signAuthorizationWithProvider(provider, address, authorization, paymentRequirements) {
378
- const p = provider;
379
- if (!p || typeof p.request !== "function") {
380
- throw new Error("provider must implement EIP-1193 request()");
381
- }
451
+ async function signAuthorizationWithProvider(provider, authorization, paymentRequirements) {
452
+ const { BrowserProvider } = await import("ethers");
453
+ const chainId = getChainIdForNetwork(paymentRequirements.network);
454
+ const browserProvider = new BrowserProvider(provider, chainId);
455
+ const signer = await browserProvider.getSigner();
456
+ const from = await signer.getAddress();
457
+ const authWithFrom = {
458
+ ...authorization,
459
+ from
460
+ };
382
461
  const typedData = buildTypedDataForAuthorization(
383
- authorization,
462
+ authWithFrom,
384
463
  paymentRequirements
385
464
  );
386
- const params = [address, JSON.stringify(typedData)];
387
- const signature = await p.request({
388
- method: "eth_signTypedData_v4",
389
- params
390
- });
391
- if (typeof signature !== "string" || !signature.startsWith("0x")) {
392
- throw new Error("Invalid signature returned from provider");
393
- }
394
- return signature;
465
+ const signature = await signer.signTypedData(
466
+ typedData.domain,
467
+ typedData.types,
468
+ typedData.message
469
+ );
470
+ return { signature, from };
395
471
  }
396
472
  function createPaymentClient(config) {
397
473
  const {
@@ -434,14 +510,6 @@ function createPaymentClient(config) {
434
510
  });
435
511
  return {
436
512
  response: json,
437
- paymentHeader: "",
438
- paymentRequirements: {
439
- scheme: "exact",
440
- network: "mantle-mainnet",
441
- asset: "",
442
- maxAmountRequired: "0",
443
- payTo: ""
444
- },
445
513
  txHash: void 0
446
514
  };
447
515
  }
@@ -452,26 +520,34 @@ function createPaymentClient(config) {
452
520
  "402 response did not include paymentRequirements field"
453
521
  );
454
522
  }
455
- const fromAddress = userAddressOverride ?? await getUserAddressFromProvider(provider);
456
523
  const nowSec = Math.floor(Date.now() / 1e3);
457
524
  const validAfter = "0";
458
525
  const validBefore = String(nowSec + 10 * 60);
459
526
  const nonce = randomBytes32Hex();
460
527
  const valueAtomic = options?.valueOverrideAtomic ?? paymentRequirements.maxAmountRequired;
461
- const authorization = {
462
- from: fromAddress,
528
+ let authorization = {
529
+ from: "0x0000000000000000000000000000000000000000",
463
530
  to: paymentRequirements.payTo,
464
531
  value: valueAtomic,
465
532
  validAfter,
466
533
  validBefore,
467
534
  nonce
468
535
  };
469
- const signature = await signAuthorizationWithProvider(
536
+ const { signature, from } = await signAuthorizationWithProvider(
470
537
  provider,
471
- fromAddress,
472
538
  authorization,
473
539
  paymentRequirements
474
540
  );
541
+ authorization = {
542
+ ...authorization,
543
+ from
544
+ };
545
+ if (userAddressOverride && userAddressOverride.toLowerCase() !== from.toLowerCase()) {
546
+ console.warn(
547
+ "[SDK WARNING] userAddress override differs from signer address",
548
+ { override: userAddressOverride, signer: from }
549
+ );
550
+ }
475
551
  const paymentHeaderObject = {
476
552
  x402Version: 1,
477
553
  scheme: paymentRequirements.scheme,
@@ -545,7 +621,7 @@ function createMantleClient(config) {
545
621
  const resourceUrl = config?.resourceUrl ?? (typeof window !== "undefined" ? window.location.origin : "");
546
622
  const facilitatorUrl = config?.facilitatorUrl ?? (typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_FACILITATOR_URL : void 0) ?? "http://localhost:8080";
547
623
  return {
548
- async post(url, body) {
624
+ async postWithPayment(url, body) {
549
625
  const account = await config?.getAccount?.();
550
626
  if (!account) {
551
627
  throw new Error(
@@ -567,16 +643,121 @@ function createMantleClient(config) {
567
643
  method: "POST",
568
644
  body
569
645
  });
570
- return result.response;
646
+ return result;
571
647
  }
572
648
  };
573
649
  }
574
650
 
651
+ // src/client/react/useEthersWallet.ts
652
+ var import_react = require("react");
653
+ var import_ethers = require("ethers");
654
+ function useEthersWallet(options) {
655
+ const [address, setAddress] = (0, import_react.useState)(void 0);
656
+ const [isConnected, setIsConnected] = (0, import_react.useState)(false);
657
+ const [provider, setProvider] = (0, import_react.useState)(
658
+ void 0
659
+ );
660
+ const [chainId, setChainId] = (0, import_react.useState)(void 0);
661
+ const [error, setError] = (0, import_react.useState)(void 0);
662
+ const connect = (0, import_react.useCallback)(async () => {
663
+ try {
664
+ setError(void 0);
665
+ if (typeof window === "undefined" || !window.ethereum) {
666
+ throw new Error(
667
+ "No Ethereum wallet detected. Please install MetaMask or another wallet."
668
+ );
669
+ }
670
+ const browserProvider = new import_ethers.ethers.BrowserProvider(
671
+ window.ethereum
672
+ );
673
+ setProvider(browserProvider);
674
+ const accounts = await window.ethereum.request({
675
+ method: "eth_requestAccounts"
676
+ });
677
+ if (!accounts || accounts.length === 0) {
678
+ throw new Error("No accounts returned from wallet");
679
+ }
680
+ const userAddress = accounts[0];
681
+ setAddress(userAddress);
682
+ setIsConnected(true);
683
+ const network = await browserProvider.getNetwork();
684
+ setChainId(Number(network.chainId));
685
+ } catch (err) {
686
+ const errorObj = err instanceof Error ? err : new Error(String(err));
687
+ setError(errorObj);
688
+ setIsConnected(false);
689
+ setAddress(void 0);
690
+ setChainId(void 0);
691
+ throw errorObj;
692
+ }
693
+ }, []);
694
+ const disconnect = (0, import_react.useCallback)(() => {
695
+ setAddress(void 0);
696
+ setIsConnected(false);
697
+ setChainId(void 0);
698
+ setError(void 0);
699
+ }, []);
700
+ (0, import_react.useEffect)(() => {
701
+ if (typeof window === "undefined" || !window.ethereum) return;
702
+ const ethereum = window.ethereum;
703
+ const handleAccountsChanged = (accounts) => {
704
+ const accountsArray = accounts;
705
+ if (!accountsArray || accountsArray.length === 0) {
706
+ disconnect();
707
+ } else {
708
+ setAddress(accountsArray[0]);
709
+ setIsConnected(true);
710
+ }
711
+ };
712
+ if (ethereum.on) {
713
+ ethereum.on("accountsChanged", handleAccountsChanged);
714
+ }
715
+ return () => {
716
+ if (ethereum.removeListener) {
717
+ ethereum.removeListener("accountsChanged", handleAccountsChanged);
718
+ }
719
+ };
720
+ }, [disconnect]);
721
+ (0, import_react.useEffect)(() => {
722
+ if (typeof window === "undefined" || !window.ethereum) return;
723
+ const ethereum = window.ethereum;
724
+ const handleChainChanged = (chainIdHex) => {
725
+ const newChainId = parseInt(chainIdHex, 16);
726
+ setChainId(newChainId);
727
+ };
728
+ if (ethereum.on) {
729
+ ethereum.on("chainChanged", handleChainChanged);
730
+ }
731
+ return () => {
732
+ if (ethereum.removeListener) {
733
+ ethereum.removeListener("chainChanged", handleChainChanged);
734
+ }
735
+ };
736
+ }, []);
737
+ const shouldAutoConnect = options?.autoConnect !== false;
738
+ (0, import_react.useEffect)(() => {
739
+ if (shouldAutoConnect) {
740
+ connect().catch((err) => {
741
+ console.warn("[useEthersWallet] Auto-connect failed:", err);
742
+ });
743
+ }
744
+ }, [shouldAutoConnect, connect]);
745
+ return {
746
+ address,
747
+ isConnected,
748
+ provider,
749
+ chainId,
750
+ connect,
751
+ disconnect,
752
+ error
753
+ };
754
+ }
755
+
575
756
  // src/client/react/useMantleX402.ts
576
- var import_wagmi = require("wagmi");
577
757
  function useMantleX402(opts) {
578
- const { address, isConnected } = (0, import_wagmi.useAccount)();
579
- const { data: walletClient } = (0, import_wagmi.useWalletClient)();
758
+ const { address, isConnected } = useEthersWallet({
759
+ autoConnect: opts?.autoConnect ?? false
760
+ });
580
761
  const client = createMantleClient({
581
762
  facilitatorUrl: opts?.facilitatorUrl,
582
763
  resourceUrl: opts?.resourceUrl,
@@ -585,7 +766,12 @@ function useMantleX402(opts) {
585
766
  if (!isConnected || !address) return void 0;
586
767
  return address;
587
768
  },
588
- getProvider: () => walletClient
769
+ getProvider: () => {
770
+ if (typeof window !== "undefined" && window.ethereum) {
771
+ return window.ethereum;
772
+ }
773
+ return void 0;
774
+ }
589
775
  });
590
776
  return client;
591
777
  }
@@ -596,5 +782,6 @@ function useMantleX402(opts) {
596
782
  createPaymentClient,
597
783
  createPaymentMiddleware,
598
784
  mantlePaywall,
785
+ useEthersWallet,
599
786
  useMantleX402
600
787
  });