@parallel-protocol/x402 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,51 @@
1
- import { z } from 'zod';
1
+ import { X402_ERROR_CODES, X402RuntimeError, X402ConfigError, isPriceRejection } from './chunk-AFRDHGDT.js';
2
2
  import { getTokenDecimals as getTokenDecimals$1 } from '@parallel-protocol/chains';
3
+ import { z } from 'zod';
3
4
 
4
- // src/errors.ts
5
- var X402_ERROR_CODES = {
6
- FACILITATOR_UNAVAILABLE: "FACILITATOR_UNAVAILABLE",
7
- FACILITATOR_INVALID_RESPONSE: "FACILITATOR_INVALID_RESPONSE",
8
- INVALID_PAYMENT: "INVALID_PAYMENT"
9
- };
10
- var X402ConfigError = class extends Error {
11
- constructor(message, cause) {
12
- super(message);
13
- this.name = "X402ConfigError";
14
- this.cause = cause;
15
- }
16
- };
17
- var X402RuntimeError = class extends Error {
18
- constructor(code) {
19
- super(code);
20
- this.code = code;
21
- this.name = "X402RuntimeError";
5
+ var PARALLEL_TOKENS = {
6
+ ethereum: {
7
+ usdp: "0x9B3a8f7CEC208e247d97dEE13313690977e24459",
8
+ susdp: "0xd3a452B305C8285c0Dd7b8537665c734d3D279eF",
9
+ usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
10
+ frxUSD: "0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29",
11
+ sfrxUSD: "0xcf62F905562626CfcDD2261162a51fd02Fc9c5b6",
12
+ USDe: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3",
13
+ sUSDe: "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497"
14
+ },
15
+ base: {
16
+ usdp: "0x76A9A0062ec6712b99B4f63bD2b4270185759dd5",
17
+ susdp: "0x472eD57b376fE400259FB28e5C46eB53f0E3e7E7",
18
+ usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
19
+ USDS: "0x820C137fa70C8691f0e44Dc420a5e53c168921Dc",
20
+ sUSDS: "0x5875eEE11Cf8398102FdAd704C9E96607675467a"
21
+ },
22
+ avalanche: {
23
+ usdp: "0x9eE1963f05553eF838604Dd39403be21ceF26AA4",
24
+ susdp: "0x9d92c21205383651610f90722131655a5b8ed3e0",
25
+ usdc: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
26
+ ygamiUSDC: "0x9fD32FD5e32C6B95483d36C5E724C5C5250Ce010"
27
+ },
28
+ hyperevm: {
29
+ usdp: "0xBE65F0F410A72BeC163dC65d46c83699e957D588",
30
+ susdp: "0x9B3a8f7CEC208e247d97dEE13313690977e24459",
31
+ usdc: "0xb88339cb7199b77e23db6e890353e22632ba630f",
32
+ USDe: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
33
+ sUSDe: "0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2"
22
34
  }
23
- code;
24
35
  };
36
+ function getDefaultAcceptedTokens(network) {
37
+ const entry = PARALLEL_TOKENS[network];
38
+ if (!entry) return void 0;
39
+ return [entry.usdp, entry.usdc, entry.susdp];
40
+ }
41
+ function getMeteredAcceptedTokens(network) {
42
+ const entry = PARALLEL_TOKENS[network];
43
+ if (!entry) return void 0;
44
+ return [entry.usdp];
45
+ }
46
+ function getTokenDecimals(network, address) {
47
+ return getTokenDecimals$1(network, address);
48
+ }
25
49
 
26
50
  // src/utils.ts
27
51
  var EIP155_NETWORKS = {
@@ -45,6 +69,28 @@ function parsePrice(price, decimals = 18) {
45
69
  `Invalid price format: "${price}". Expected "0.01" or a bigint.`
46
70
  );
47
71
  }
72
+ function isJsonContentType(contentType) {
73
+ return /^application\/(?:[\w.-]+\+)?json(?:\s*;.*)?$/i.test(
74
+ contentType?.trim() ?? ""
75
+ );
76
+ }
77
+ function parseJsonBody(contentType, text) {
78
+ if (text === void 0 || !isJsonContentType(contentType)) return void 0;
79
+ try {
80
+ return JSON.parse(text);
81
+ } catch {
82
+ return void 0;
83
+ }
84
+ }
85
+ async function jsonFromResponse(res) {
86
+ const contentType = res.headers.get("content-type") ?? void 0;
87
+ if (!isJsonContentType(contentType)) return void 0;
88
+ try {
89
+ return parseJsonBody(contentType, await res.clone().text());
90
+ } catch {
91
+ return void 0;
92
+ }
93
+ }
48
94
  function validateAddress(address) {
49
95
  return /^0x[0-9a-fA-F]{40}$/.test(address);
50
96
  }
@@ -74,7 +120,12 @@ var ethereumAddressSchema = z.string().regex(/^0x[0-9a-fA-F]{40}$/, "Invalid Eth
74
120
  var txHashSchema = z.string().regex(/^0x[0-9a-fA-F]{64}$/);
75
121
  var priceSchema = z.union([
76
122
  z.bigint().positive("Price must be greater than 0"),
77
- z.string().regex(/^\d+(?:\.\d+)?$/, 'Price must be in format "0.01"').refine((price) => Number(price) > 0, "Price must be greater than 0")
123
+ z.string().regex(/^\d+(?:\.\d+)?$/, 'Price must be in format "0.01"').refine((price) => Number(price) > 0, "Price must be greater than 0"),
124
+ // A per-request price function; its return value is checked per request.
125
+ z.custom(
126
+ (value) => typeof value === "function",
127
+ "Price must be a string, a bigint or a function of the request"
128
+ )
78
129
  ]);
79
130
  var facilitatorConfigSchema = z.object({
80
131
  url: z.string().refine((v) => URL.canParse(v), "Invalid facilitator URL"),
@@ -88,11 +139,25 @@ var routeConfigSchema = z.object({
88
139
  acceptedTokens: z.array(ethereumAddressSchema).optional(),
89
140
  description: z.string().optional(),
90
141
  scheme: z.enum(["exact", "upto"]).optional(),
91
- maxTimeoutSeconds: z.number().int().positive().optional()
142
+ maxTimeoutSeconds: z.number().int().positive().optional(),
143
+ meter: z.custom(
144
+ (value) => typeof value === "function",
145
+ "meter must be a function of the response"
146
+ ).optional()
92
147
  }).refine(
148
+ (route) => route.meter === void 0 || route.scheme === "upto",
149
+ "meter only applies to upto routes"
150
+ ).refine(
93
151
  (route) => route.scheme !== "upto" || (route.maxTimeoutSeconds ?? 300) <= UPTO_MAX_TIMEOUT_SECONDS,
94
152
  `maxTimeoutSeconds must be at most ${UPTO_MAX_TIMEOUT_SECONDS} on an upto route`
95
- );
153
+ ).refine((route) => {
154
+ if (route.scheme !== "upto" || !route.acceptedTokens?.length) return true;
155
+ const usdp = PARALLEL_TOKENS[route.network]?.usdp;
156
+ if (!usdp) return true;
157
+ return route.acceptedTokens.every(
158
+ (token) => token.toLowerCase() === usdp.toLowerCase()
159
+ );
160
+ }, "acceptedTokens on an upto route may only list the network's USDp");
96
161
  var paymentMiddlewareConfigSchema = z.object({
97
162
  facilitator: facilitatorConfigSchema,
98
163
  routes: z.record(z.string(), routeConfigSchema).refine((r) => Object.keys(r).length > 0, "At least one route is required")
@@ -277,47 +342,41 @@ async function raceTimeout(promise, ms = HANDLER_TIMEOUT_MS) {
277
342
  clearTimeout(timer);
278
343
  }
279
344
  }
280
- var PARALLEL_TOKENS = {
281
- ethereum: {
282
- usdp: "0x9B3a8f7CEC208e247d97dEE13313690977e24459",
283
- susdp: "0xd3a452B305C8285c0Dd7b8537665c734d3D279eF",
284
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
285
- frxUSD: "0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29",
286
- sfrxUSD: "0xcf62F905562626CfcDD2261162a51fd02Fc9c5b6",
287
- USDe: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3",
288
- sUSDe: "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497"
289
- },
290
- base: {
291
- usdp: "0x76A9A0062ec6712b99B4f63bD2b4270185759dd5",
292
- susdp: "0x472eD57b376fE400259FB28e5C46eB53f0E3e7E7",
293
- usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
294
- USDS: "0x820C137fa70C8691f0e44Dc420a5e53c168921Dc",
295
- sUSDS: "0x5875eEE11Cf8398102FdAd704C9E96607675467a"
296
- },
297
- avalanche: {
298
- usdp: "0x9eE1963f05553eF838604Dd39403be21ceF26AA4",
299
- susdp: "0x9d92c21205383651610f90722131655a5b8ed3e0",
300
- usdc: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
301
- ygamiUSDC: "0x9fD32FD5e32C6B95483d36C5E724C5C5250Ce010"
302
- },
303
- hyperevm: {
304
- usdp: "0xBE65F0F410A72BeC163dC65d46c83699e957D588",
305
- susdp: "0x9B3a8f7CEC208e247d97dEE13313690977e24459",
306
- usdc: "0xb88339cb7199b77e23db6e890353e22632ba630f",
307
- USDe: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34",
308
- sUSDe: "0x211Cc4DD073734dA055fbF44a2b4667d5E5fE5d2"
309
- }
310
- };
311
- function getDefaultAcceptedTokens(network) {
312
- const entry = PARALLEL_TOKENS[network];
313
- if (!entry) return void 0;
314
- return [entry.usdp, entry.usdc, entry.susdp];
315
- }
316
- function getTokenDecimals(network, address) {
317
- return getTokenDecimals$1(network, address);
318
- }
319
345
 
320
346
  // src/middleware.ts
347
+ var PRICE_FORMAT = /^\d+(?:\.\d+)?$/;
348
+ async function requestContext(adapter) {
349
+ return {
350
+ method: adapter.getMethod(),
351
+ path: adapter.getPath(),
352
+ url: adapter.getUrl(),
353
+ header: (name) => adapter.getHeader(name),
354
+ body: adapter.getBody ? await adapter.getBody() : void 0
355
+ };
356
+ }
357
+ async function resolvePrice(config, ctx) {
358
+ if (typeof config.price !== "function") return config.price;
359
+ if (!ctx) throw new X402ConfigError("A price function needs the request");
360
+ let price;
361
+ try {
362
+ price = await config.price(ctx);
363
+ } catch (cause) {
364
+ if (isPriceRejection(cause)) throw cause;
365
+ throw new X402ConfigError(
366
+ `The price function of route "${config.network}${ctx.path}" threw`,
367
+ cause
368
+ );
369
+ }
370
+ const valid = typeof price === "bigint" ? price > 0n : typeof price === "string" && PRICE_FORMAT.test(price) && Number(price) > 0;
371
+ if (!valid) {
372
+ throw new X402ConfigError(
373
+ `The price function of route "${config.network}${ctx.path}" returned ${JSON.stringify(
374
+ typeof price === "bigint" ? price.toString() : price
375
+ )} \u2014 expected a positive amount like "0.01" or a bigint`
376
+ );
377
+ }
378
+ return price;
379
+ }
321
380
  var SETTLE_AMOUNT_HEADER = "payment-settle-amount";
322
381
  var DEFAULT_MAX_TIMEOUT_SECONDS = 300;
323
382
  function handlerTimeoutFor(config) {
@@ -346,11 +405,67 @@ var INVALID_SETTLE_AMOUNT_RESPONSE = {
346
405
  error: "INVALID_SETTLE_AMOUNT",
347
406
  message: `The handler set an invalid ${SETTLE_AMOUNT_HEADER} header \u2014 expected a decimal amount in token units, formatted like the route price and within the token's precision, at most the route price.`
348
407
  };
408
+ var INVALID_METER_RESPONSE = {
409
+ error: "INVALID_SETTLE_AMOUNT",
410
+ message: "The route's meter function failed or returned something that is not an amount; the response was discarded and nothing was charged."
411
+ };
412
+ function invalidSettleAmountResponse(reason) {
413
+ return reason === "meter" ? INVALID_METER_RESPONSE : INVALID_SETTLE_AMOUNT_RESPONSE;
414
+ }
415
+ var AMOUNT_FORMAT = /^\d+(?:\.\d+)?$/;
416
+ async function resolveCharge(verified, settleHeader, response) {
417
+ if (verified.meter) {
418
+ if (!verified.request) {
419
+ throw new X402ConfigError(
420
+ "A metered payment carries a meter but no request context"
421
+ );
422
+ }
423
+ let result;
424
+ try {
425
+ const body = await raceTimeout(
426
+ response.body(),
427
+ verified.handlerTimeoutMs
428
+ );
429
+ if (body === HANDLER_TIMEOUT) return { kind: "invalid", reason: "meter" };
430
+ result = await verified.meter({
431
+ status: response.status,
432
+ header: response.header,
433
+ body,
434
+ request: verified.request
435
+ });
436
+ } catch {
437
+ return { kind: "invalid", reason: "meter" };
438
+ }
439
+ if (result != null) {
440
+ let amount;
441
+ if (typeof result === "bigint") {
442
+ if (result < 0n) return { kind: "invalid", reason: "meter" };
443
+ amount = result;
444
+ } else if (typeof result === "string" && AMOUNT_FORMAT.test(result)) {
445
+ const fraction = result.split(".")[1] ?? "";
446
+ if (fraction.length > verified.decimals) {
447
+ return { kind: "invalid", reason: "meter" };
448
+ }
449
+ amount = parsePrice(result, verified.decimals);
450
+ } else {
451
+ return { kind: "invalid", reason: "meter" };
452
+ }
453
+ if (amount === 0n) return { kind: "skip" };
454
+ if (amount > verified.maxAmount) amount = verified.maxAmount;
455
+ return { kind: "settle", amount: amount.toString() };
456
+ }
457
+ }
458
+ return resolveSettleAmount(
459
+ settleHeader,
460
+ verified.maxAmount,
461
+ verified.decimals
462
+ );
463
+ }
349
464
  function resolveAcceptedTokens(config) {
350
465
  if (config.acceptedTokens?.length) {
351
466
  return config.acceptedTokens;
352
467
  }
353
- const defaults = getDefaultAcceptedTokens(config.network);
468
+ const defaults = config.scheme === "upto" ? getMeteredAcceptedTokens(config.network) : getDefaultAcceptedTokens(config.network);
354
469
  if (defaults) return defaults;
355
470
  throw new X402ConfigError(
356
471
  `acceptedTokens is required for network "${config.network}" \u2014 no defaults available for this chain`
@@ -365,7 +480,16 @@ function resolveDecimals(config, asset) {
365
480
  }
366
481
  return decimals;
367
482
  }
368
- function buildPaymentRequired(url, config, resolvedTokens) {
483
+ function priceInUnits(price, decimals, asset) {
484
+ const units = parsePrice(price, decimals);
485
+ if (units === 0n) {
486
+ throw new X402ConfigError(
487
+ `Price ${typeof price === "bigint" ? price.toString() : `"${price}"`} is below the precision of token ${asset} (${decimals} decimals)`
488
+ );
489
+ }
490
+ return units.toString();
491
+ }
492
+ function buildPaymentRequired(url, config, resolvedTokens, price) {
369
493
  const network = toEip155Network(config.network);
370
494
  const accepts = resolvedTokens.map((asset) => {
371
495
  const decimals = resolveDecimals(config, asset);
@@ -373,7 +497,7 @@ function buildPaymentRequired(url, config, resolvedTokens) {
373
497
  scheme: config.scheme ?? "exact",
374
498
  network,
375
499
  asset,
376
- amount: parsePrice(config.price, decimals).toString(),
500
+ amount: priceInUnits(price, decimals, asset),
377
501
  payTo: config.payTo,
378
502
  maxTimeoutSeconds: config.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS,
379
503
  extra: { decimals }
@@ -419,11 +543,11 @@ function resolveDeliveredAsset(header, config, resolvedTokens) {
419
543
  const lower = target?.toLowerCase();
420
544
  return resolvedTokens.find((token) => token.toLowerCase() === lower) ?? resolvedTokens[0];
421
545
  }
422
- function buildFacilitatorRequirements(config, asset) {
546
+ function buildFacilitatorRequirements(config, asset, price) {
423
547
  const decimals = resolveDecimals(config, asset);
424
548
  const scheme = config.scheme ?? "exact";
425
549
  return {
426
- maxAmountRequired: parsePrice(config.price, decimals).toString(),
550
+ maxAmountRequired: priceInUnits(price, decimals, asset),
427
551
  asset,
428
552
  payTo: config.payTo,
429
553
  network: config.network,
@@ -434,8 +558,13 @@ function buildFacilitatorRequirements(config, asset) {
434
558
  }
435
559
  };
436
560
  }
437
- function paymentRequiredResponse(url, config, resolvedTokens, error) {
438
- const paymentRequired = buildPaymentRequired(url, config, resolvedTokens);
561
+ function paymentRequiredResponse(url, config, resolvedTokens, price, error) {
562
+ const paymentRequired = buildPaymentRequired(
563
+ url,
564
+ config,
565
+ resolvedTokens,
566
+ price
567
+ );
439
568
  if (error) paymentRequired.error = error;
440
569
  return {
441
570
  status: 402,
@@ -463,6 +592,22 @@ function createPaymentGate(config) {
463
592
  const routeConfig = matchRoute(adapter.getPath(), config.routes);
464
593
  if (!routeConfig) return { type: "pass" };
465
594
  const resolvedTokens = resolveAcceptedTokens(routeConfig);
595
+ let request = typeof routeConfig.price === "function" ? await requestContext(adapter) : void 0;
596
+ let price;
597
+ try {
598
+ price = await resolvePrice(routeConfig, request);
599
+ } catch (err) {
600
+ if (!isPriceRejection(err)) throw err;
601
+ const status = Number.isInteger(err.status) && err.status >= 400 && err.status <= 599 ? err.status : 400;
602
+ return {
603
+ type: "error",
604
+ result: {
605
+ status,
606
+ headers: { "Content-Type": "application/json" },
607
+ body: { error: err.code, message: err.message }
608
+ }
609
+ };
610
+ }
466
611
  const paymentHeader = adapter.getHeader("payment-signature") ?? adapter.getHeader("x-payment");
467
612
  if (!paymentHeader) {
468
613
  return {
@@ -470,7 +615,8 @@ function createPaymentGate(config) {
470
615
  result: paymentRequiredResponse(
471
616
  adapter.getUrl(),
472
617
  routeConfig,
473
- resolvedTokens
618
+ resolvedTokens,
619
+ price
474
620
  )
475
621
  };
476
622
  }
@@ -479,7 +625,11 @@ function createPaymentGate(config) {
479
625
  routeConfig,
480
626
  resolvedTokens
481
627
  );
482
- const requirements = buildFacilitatorRequirements(routeConfig, asset);
628
+ const requirements = buildFacilitatorRequirements(
629
+ routeConfig,
630
+ asset,
631
+ price
632
+ );
483
633
  try {
484
634
  await client.verify(paymentHeader, requirements);
485
635
  } catch (e) {
@@ -490,10 +640,12 @@ function createPaymentGate(config) {
490
640
  adapter.getUrl(),
491
641
  routeConfig,
492
642
  resolvedTokens,
643
+ price,
493
644
  code
494
645
  )
495
646
  };
496
647
  }
648
+ if (routeConfig.meter && !request) request = await requestContext(adapter);
497
649
  return {
498
650
  type: "verified",
499
651
  scheme: routeConfig.scheme ?? "exact",
@@ -501,7 +653,8 @@ function createPaymentGate(config) {
501
653
  decimals: resolveDecimals(routeConfig, asset),
502
654
  handlerTimeoutMs: handlerTimeoutFor(routeConfig),
503
655
  // Exact routes keep the historical two-argument client call.
504
- settle: (options) => options ? client.settle(paymentHeader, requirements, options) : client.settle(paymentHeader, requirements)
656
+ settle: (options) => options ? client.settle(paymentHeader, requirements, options) : client.settle(paymentHeader, requirements),
657
+ ...routeConfig.meter && { meter: routeConfig.meter, request }
505
658
  };
506
659
  };
507
660
  }
@@ -527,17 +680,17 @@ function createPaymentMiddleware(config) {
527
680
  if (handlerResult.status >= 200 && handlerResult.status < 300) {
528
681
  let settleOptions;
529
682
  if (gateResult.scheme === "upto") {
530
- const resolved = resolveSettleAmount(
531
- raw,
532
- gateResult.maxAmount,
533
- gateResult.decimals
534
- );
683
+ const resolved = await resolveCharge(gateResult, raw, {
684
+ status: handlerResult.status,
685
+ header: (name) => handlerResult.getResponseHeader?.(name),
686
+ body: async () => handlerResult.getResponseBody?.()
687
+ });
535
688
  if (resolved.kind === "invalid") {
536
689
  handlerResult.discardResponse();
537
690
  return {
538
691
  status: 402,
539
692
  headers: { "Content-Type": "application/json" },
540
- body: INVALID_SETTLE_AMOUNT_RESPONSE
693
+ body: invalidSettleAmountResponse(resolved.reason)
541
694
  };
542
695
  }
543
696
  if (resolved.kind === "skip") {
@@ -579,4 +732,4 @@ function createPaymentMiddleware(config) {
579
732
  };
580
733
  }
581
734
 
582
- export { FacilitatorClient, HANDLER_TIMEOUT, INVALID_SETTLE_AMOUNT_RESPONSE, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, X402ConfigError, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, raceTimeout, resolveSettleAmount, toEip155Network, validateAddress };
735
+ export { FacilitatorClient, HANDLER_TIMEOUT, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, invalidSettleAmountResponse, isJsonContentType, jsonFromResponse, matchRoute, parseJsonBody, parsePrice, raceTimeout, resolveCharge, resolveSettleAmount, toEip155Network, validateAddress };
@@ -0,0 +1,36 @@
1
+ // src/errors.ts
2
+ var X402_ERROR_CODES = {
3
+ FACILITATOR_UNAVAILABLE: "FACILITATOR_UNAVAILABLE",
4
+ FACILITATOR_INVALID_RESPONSE: "FACILITATOR_INVALID_RESPONSE",
5
+ INVALID_PAYMENT: "INVALID_PAYMENT"
6
+ };
7
+ var X402ConfigError = class extends Error {
8
+ constructor(message, cause) {
9
+ super(message);
10
+ this.name = "X402ConfigError";
11
+ this.cause = cause;
12
+ }
13
+ };
14
+ var X402RuntimeError = class extends Error {
15
+ constructor(code) {
16
+ super(code);
17
+ this.code = code;
18
+ this.name = "X402RuntimeError";
19
+ }
20
+ code;
21
+ };
22
+ var X402PriceRejectedError = class extends Error {
23
+ constructor(code, message, status = 400) {
24
+ super(message);
25
+ this.code = code;
26
+ this.status = status;
27
+ this.name = "X402PriceRejectedError";
28
+ }
29
+ code;
30
+ status;
31
+ };
32
+ function isPriceRejection(error) {
33
+ return error instanceof Error && error.name === "X402PriceRejectedError" && typeof error.code === "string";
34
+ }
35
+
36
+ export { X402ConfigError, X402PriceRejectedError, X402RuntimeError, X402_ERROR_CODES, isPriceRejection };
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ // src/errors.ts
4
+ var X402_ERROR_CODES = {
5
+ FACILITATOR_UNAVAILABLE: "FACILITATOR_UNAVAILABLE",
6
+ FACILITATOR_INVALID_RESPONSE: "FACILITATOR_INVALID_RESPONSE",
7
+ INVALID_PAYMENT: "INVALID_PAYMENT"
8
+ };
9
+ var X402ConfigError = class extends Error {
10
+ constructor(message, cause) {
11
+ super(message);
12
+ this.name = "X402ConfigError";
13
+ this.cause = cause;
14
+ }
15
+ };
16
+ var X402RuntimeError = class extends Error {
17
+ constructor(code) {
18
+ super(code);
19
+ this.code = code;
20
+ this.name = "X402RuntimeError";
21
+ }
22
+ code;
23
+ };
24
+ var X402PriceRejectedError = class extends Error {
25
+ constructor(code, message, status = 400) {
26
+ super(message);
27
+ this.code = code;
28
+ this.status = status;
29
+ this.name = "X402PriceRejectedError";
30
+ }
31
+ code;
32
+ status;
33
+ };
34
+ function isPriceRejection(error) {
35
+ return error instanceof Error && error.name === "X402PriceRejectedError" && typeof error.code === "string";
36
+ }
37
+
38
+ exports.X402ConfigError = X402ConfigError;
39
+ exports.X402PriceRejectedError = X402PriceRejectedError;
40
+ exports.X402RuntimeError = X402RuntimeError;
41
+ exports.X402_ERROR_CODES = X402_ERROR_CODES;
42
+ exports.isPriceRejection = isPriceRejection;