@t402/core 2.3.1 → 2.4.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.
Files changed (48) hide show
  1. package/dist/cjs/client/index.d.ts +3 -2
  2. package/dist/cjs/client/index.js +70 -2
  3. package/dist/cjs/client/index.js.map +1 -1
  4. package/dist/cjs/facilitator/index.d.ts +2 -1
  5. package/dist/cjs/http/index.d.ts +13 -6
  6. package/dist/cjs/http/index.js +73 -3
  7. package/dist/cjs/http/index.js.map +1 -1
  8. package/dist/cjs/mechanisms-C7yK91d4.d.ts +1126 -0
  9. package/dist/cjs/server/index.d.ts +3 -2
  10. package/dist/cjs/server/index.js +67 -1
  11. package/dist/cjs/server/index.js.map +1 -1
  12. package/dist/cjs/{t402HTTPClient-GIweW6nh.d.ts → t402HTTPClient-DmkFydNG.d.ts} +1 -1
  13. package/dist/cjs/{t402HTTPResourceServer-CcpZF3af.d.ts → t402HTTPResourceServer-CybruqCk.d.ts} +1 -1
  14. package/dist/cjs/types/index.d.ts +2 -1
  15. package/dist/cjs/types/index.js +469 -2
  16. package/dist/cjs/types/index.js.map +1 -1
  17. package/dist/cjs/types/v1/index.d.ts +2 -1
  18. package/dist/cjs/utils/index.d.ts +29 -2
  19. package/dist/cjs/utils/index.js +53 -0
  20. package/dist/cjs/utils/index.js.map +1 -1
  21. package/dist/esm/chunk-KPNYZYDS.mjs +100 -0
  22. package/dist/esm/chunk-KPNYZYDS.mjs.map +1 -0
  23. package/dist/esm/{chunk-3IUBYRYG.mjs → chunk-LJ4M5Z5U.mjs} +51 -1
  24. package/dist/esm/chunk-LJ4M5Z5U.mjs.map +1 -0
  25. package/dist/esm/{chunk-773TNE2Y.mjs → chunk-REMGOG6C.mjs} +16 -5
  26. package/dist/esm/{chunk-773TNE2Y.mjs.map → chunk-REMGOG6C.mjs.map} +1 -1
  27. package/dist/esm/client/index.d.mts +3 -2
  28. package/dist/esm/client/index.mjs +3 -2
  29. package/dist/esm/client/index.mjs.map +1 -1
  30. package/dist/esm/facilitator/index.d.mts +2 -1
  31. package/dist/esm/http/index.d.mts +13 -6
  32. package/dist/esm/http/index.mjs +3 -2
  33. package/dist/esm/mechanisms-C7yK91d4.d.mts +1126 -0
  34. package/dist/esm/server/index.d.mts +3 -2
  35. package/dist/esm/server/index.mjs +3 -2
  36. package/dist/esm/server/index.mjs.map +1 -1
  37. package/dist/esm/{t402HTTPClient-DbZqiMSO.d.mts → t402HTTPClient-Bgjn3TRU.d.mts} +1 -1
  38. package/dist/esm/{t402HTTPResourceServer-BbQ6HVBC.d.mts → t402HTTPResourceServer-DuZIzhRI.d.mts} +1 -1
  39. package/dist/esm/types/index.d.mts +2 -1
  40. package/dist/esm/types/index.mjs +304 -1
  41. package/dist/esm/types/index.mjs.map +1 -1
  42. package/dist/esm/types/v1/index.d.mts +2 -1
  43. package/dist/esm/utils/index.d.mts +29 -2
  44. package/dist/esm/utils/index.mjs +7 -1
  45. package/package.json +3 -3
  46. package/dist/cjs/mechanisms-B-vz5yOj.d.ts +0 -443
  47. package/dist/esm/chunk-3IUBYRYG.mjs.map +0 -1
  48. package/dist/esm/mechanisms-B-vz5yOj.d.mts +0 -443
@@ -21,6 +21,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var utils_exports = {};
22
22
  __export(utils_exports, {
23
23
  Base64EncodedRegex: () => Base64EncodedRegex,
24
+ cryptoRandomBigInt: () => cryptoRandomBigInt,
25
+ cryptoRandomHex: () => cryptoRandomHex,
26
+ cryptoRandomInt: () => cryptoRandomInt,
24
27
  deepEqual: () => deepEqual,
25
28
  findByNetworkAndScheme: () => findByNetworkAndScheme,
26
29
  findFacilitatorBySchemeAndNetwork: () => findFacilitatorBySchemeAndNetwork,
@@ -29,6 +32,53 @@ __export(utils_exports, {
29
32
  safeBase64Encode: () => safeBase64Encode
30
33
  });
31
34
  module.exports = __toCommonJS(utils_exports);
35
+ function getCrypto() {
36
+ const cryptoObj = globalThis.crypto;
37
+ if (!cryptoObj || typeof cryptoObj.getRandomValues !== "function") {
38
+ throw new Error(
39
+ "Crypto API not available. Node.js 19+ or a browser with Web Crypto API is required."
40
+ );
41
+ }
42
+ return cryptoObj;
43
+ }
44
+ function cryptoRandomInt(max) {
45
+ if (max <= 0 || max > 4294967295 || !Number.isInteger(max)) {
46
+ throw new Error(`Invalid max value: ${max}. Must be positive integer <= 2^32`);
47
+ }
48
+ const crypto = getCrypto();
49
+ const array = new Uint32Array(1);
50
+ const limit = Math.floor(4294967295 / max) * max;
51
+ let value;
52
+ do {
53
+ crypto.getRandomValues(array);
54
+ value = array[0];
55
+ } while (value >= limit);
56
+ return value % max;
57
+ }
58
+ function cryptoRandomBigInt(bits = 64) {
59
+ if (bits <= 0 || bits > 256) {
60
+ throw new Error(`Invalid bits value: ${bits}. Must be 1-256`);
61
+ }
62
+ const crypto = getCrypto();
63
+ const bytes = Math.ceil(bits / 8);
64
+ const array = new Uint8Array(bytes);
65
+ crypto.getRandomValues(array);
66
+ let result = 0n;
67
+ for (let i = 0; i < bytes; i++) {
68
+ result = result << 8n | BigInt(array[i]);
69
+ }
70
+ const mask = (1n << BigInt(bits)) - 1n;
71
+ return result & mask;
72
+ }
73
+ function cryptoRandomHex(bytes = 16) {
74
+ if (bytes <= 0 || bytes > 128) {
75
+ throw new Error(`Invalid bytes value: ${bytes}. Must be 1-128`);
76
+ }
77
+ const crypto = getCrypto();
78
+ const array = new Uint8Array(bytes);
79
+ crypto.getRandomValues(array);
80
+ return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
81
+ }
32
82
  var findSchemesByNetwork = (map, network) => {
33
83
  let implementationsByScheme = map.get(network);
34
84
  if (!implementationsByScheme) {
@@ -98,6 +148,9 @@ function deepEqual(obj1, obj2) {
98
148
  // Annotate the CommonJS export names for ESM import in node:
99
149
  0 && (module.exports = {
100
150
  Base64EncodedRegex,
151
+ cryptoRandomBigInt,
152
+ cryptoRandomHex,
153
+ cryptoRandomInt,
101
154
  deepEqual,
102
155
  findByNetworkAndScheme,
103
156
  findFacilitatorBySchemeAndNetwork,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/index.ts"],"sourcesContent":["import { Network } from \"../types\";\n\n/**\n * Scheme data structure for facilitator storage\n */\nexport interface SchemeData<T> {\n facilitator: T;\n networks: Set<Network>;\n pattern: Network;\n}\n\nexport const findSchemesByNetwork = <T>(\n map: Map<string, Map<string, T>>,\n network: Network,\n): Map<string, T> | undefined => {\n // Direct match first\n let implementationsByScheme = map.get(network);\n\n if (!implementationsByScheme) {\n // Try pattern matching for registered network patterns\n for (const [registeredNetworkPattern, implementations] of map.entries()) {\n // Convert the registered network pattern to a regex\n // e.g., \"eip155:*\" becomes /^eip155:.*$/\n const pattern = registeredNetworkPattern\n .replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\") // Escape special regex chars except *\n .replace(/\\\\\\*/g, \".*\"); // Replace escaped * with .*\n\n const regex = new RegExp(`^${pattern}$`);\n\n if (regex.test(network)) {\n implementationsByScheme = implementations;\n break;\n }\n }\n }\n\n return implementationsByScheme;\n};\n\nexport const findByNetworkAndScheme = <T>(\n map: Map<string, Map<string, T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n return findSchemesByNetwork(map, network)?.get(scheme);\n};\n\n/**\n * Finds a facilitator by scheme and network using pattern matching.\n * Works with new SchemeData storage structure.\n *\n * @param schemeMap - Map of scheme names to SchemeData\n * @param scheme - The scheme to find\n * @param network - The network to match against\n * @returns The facilitator if found, undefined otherwise\n */\nexport const findFacilitatorBySchemeAndNetwork = <T>(\n schemeMap: Map<string, SchemeData<T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n const schemeData = schemeMap.get(scheme);\n if (!schemeData) return undefined;\n\n // Check if network is in the stored networks set\n if (schemeData.networks.has(network)) {\n return schemeData.facilitator;\n }\n\n // Try pattern matching\n const patternRegex = new RegExp(\"^\" + schemeData.pattern.replace(\"*\", \".*\") + \"$\");\n if (patternRegex.test(network)) {\n return schemeData.facilitator;\n }\n\n return undefined;\n};\n\nexport const Base64EncodedRegex = /^[A-Za-z0-9+/]*={0,2}$/;\n\n/**\n * Encodes a string to base64 format\n *\n * @param data - The string to be encoded to base64\n * @returns The base64 encoded string\n */\nexport function safeBase64Encode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.btoa === \"function\") {\n return globalThis.btoa(data);\n }\n return Buffer.from(data).toString(\"base64\");\n}\n\n/**\n * Decodes a base64 string back to its original format\n *\n * @param data - The base64 encoded string to be decoded\n * @returns The decoded string in UTF-8 format\n */\nexport function safeBase64Decode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.atob === \"function\") {\n return globalThis.atob(data);\n }\n return Buffer.from(data, \"base64\").toString(\"utf-8\");\n}\n\n/**\n * Deep equality comparison for payment requirements\n * Uses a normalized JSON.stringify for consistent comparison\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are deeply equal\n */\nexport function deepEqual(obj1: unknown, obj2: unknown): boolean {\n // Normalize and stringify both objects for comparison\n // This handles nested objects, arrays, and different property orders\n const normalize = (obj: unknown): string => {\n // Handle primitives and null/undefined\n if (obj === null || obj === undefined) return JSON.stringify(obj);\n if (typeof obj !== \"object\") return JSON.stringify(obj);\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return JSON.stringify(\n obj.map(item =>\n typeof item === \"object\" && item !== null ? JSON.parse(normalize(item)) : item,\n ),\n );\n }\n\n // Handle objects - sort keys and recursively normalize values\n const sorted: Record<string, unknown> = {};\n Object.keys(obj as Record<string, unknown>)\n .sort()\n .forEach(key => {\n const value = (obj as Record<string, unknown>)[key];\n sorted[key] =\n typeof value === \"object\" && value !== null ? JSON.parse(normalize(value)) : value;\n });\n return JSON.stringify(sorted);\n };\n\n try {\n return normalize(obj1) === normalize(obj2);\n } catch {\n // Fallback to simple comparison if normalization fails\n return JSON.stringify(obj1) === JSON.stringify(obj2);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,IAAM,uBAAuB,CAClC,KACA,YAC+B;AAE/B,MAAI,0BAA0B,IAAI,IAAI,OAAO;AAE7C,MAAI,CAAC,yBAAyB;AAE5B,eAAW,CAAC,0BAA0B,eAAe,KAAK,IAAI,QAAQ,GAAG;AAGvE,YAAM,UAAU,yBACb,QAAQ,uBAAuB,MAAM,EACrC,QAAQ,SAAS,IAAI;AAExB,YAAM,QAAQ,IAAI,OAAO,IAAI,OAAO,GAAG;AAEvC,UAAI,MAAM,KAAK,OAAO,GAAG;AACvB,kCAA0B;AAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,yBAAyB,CACpC,KACA,QACA,YACkB;AAClB,SAAO,qBAAqB,KAAK,OAAO,GAAG,IAAI,MAAM;AACvD;AAWO,IAAM,oCAAoC,CAC/C,WACA,QACA,YACkB;AAClB,QAAM,aAAa,UAAU,IAAI,MAAM;AACvC,MAAI,CAAC,WAAY,QAAO;AAGxB,MAAI,WAAW,SAAS,IAAI,OAAO,GAAG;AACpC,WAAO,WAAW;AAAA,EACpB;AAGA,QAAM,eAAe,IAAI,OAAO,MAAM,WAAW,QAAQ,QAAQ,KAAK,IAAI,IAAI,GAAG;AACjF,MAAI,aAAa,KAAK,OAAO,GAAG;AAC9B,WAAO,WAAW;AAAA,EACpB;AAEA,SAAO;AACT;AAEO,IAAM,qBAAqB;AAQ3B,SAAS,iBAAiB,MAAsB;AACrD,MAAI,OAAO,eAAe,eAAe,OAAO,WAAW,SAAS,YAAY;AAC9E,WAAO,WAAW,KAAK,IAAI;AAAA,EAC7B;AACA,SAAO,OAAO,KAAK,IAAI,EAAE,SAAS,QAAQ;AAC5C;AAQO,SAAS,iBAAiB,MAAsB;AACrD,MAAI,OAAO,eAAe,eAAe,OAAO,WAAW,SAAS,YAAY;AAC9E,WAAO,WAAW,KAAK,IAAI;AAAA,EAC7B;AACA,SAAO,OAAO,KAAK,MAAM,QAAQ,EAAE,SAAS,OAAO;AACrD;AAUO,SAAS,UAAU,MAAe,MAAwB;AAG/D,QAAM,YAAY,CAAC,QAAyB;AAE1C,QAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO,KAAK,UAAU,GAAG;AAChE,QAAI,OAAO,QAAQ,SAAU,QAAO,KAAK,UAAU,GAAG;AAGtD,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,UAAI,UACN,OAAO,SAAS,YAAY,SAAS,OAAO,KAAK,MAAM,UAAU,IAAI,CAAC,IAAI;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAkC,CAAC;AACzC,WAAO,KAAK,GAA8B,EACvC,KAAK,EACL,QAAQ,SAAO;AACd,YAAM,QAAS,IAAgC,GAAG;AAClD,aAAO,GAAG,IACR,OAAO,UAAU,YAAY,UAAU,OAAO,KAAK,MAAM,UAAU,KAAK,CAAC,IAAI;AAAA,IACjF,CAAC;AACH,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAEA,MAAI;AACF,WAAO,UAAU,IAAI,MAAM,UAAU,IAAI;AAAA,EAC3C,QAAQ;AAEN,WAAO,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,IAAI;AAAA,EACrD;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/index.ts"],"sourcesContent":["import { Network } from \"../types\";\n\n// ============================================================================\n// Cryptographically Secure Random Utilities\n// ============================================================================\n\n/**\n * Get the crypto object, works in both browser and Node.js (19+)\n *\n * @returns The crypto object\n * @throws Error if crypto API is not available\n */\nfunction getCrypto(): Crypto {\n const cryptoObj = globalThis.crypto;\n\n if (!cryptoObj || typeof cryptoObj.getRandomValues !== \"function\") {\n throw new Error(\n \"Crypto API not available. \" + \"Node.js 19+ or a browser with Web Crypto API is required.\",\n );\n }\n\n return cryptoObj;\n}\n\n/**\n * Generate a cryptographically secure random integer in range [0, max)\n *\n * Uses rejection sampling to ensure uniform distribution.\n *\n * @param max - Exclusive upper bound (must be > 0 and <= 2^32)\n * @returns Random integer in [0, max)\n * @throws Error if max is invalid or crypto unavailable\n */\nexport function cryptoRandomInt(max: number): number {\n if (max <= 0 || max > 0xffffffff || !Number.isInteger(max)) {\n throw new Error(`Invalid max value: ${max}. Must be positive integer <= 2^32`);\n }\n\n const crypto = getCrypto();\n const array = new Uint32Array(1);\n\n // Rejection sampling to avoid modulo bias\n const limit = Math.floor(0xffffffff / max) * max;\n let value: number;\n\n do {\n crypto.getRandomValues(array);\n value = array[0];\n } while (value >= limit);\n\n return value % max;\n}\n\n/**\n * Generate a cryptographically secure random BigInt\n *\n * @param bits - Number of bits (default 64, max 256)\n * @returns Random BigInt with specified number of bits\n * @throws Error if bits is invalid or crypto unavailable\n */\nexport function cryptoRandomBigInt(bits: number = 64): bigint {\n if (bits <= 0 || bits > 256) {\n throw new Error(`Invalid bits value: ${bits}. Must be 1-256`);\n }\n\n const crypto = getCrypto();\n const bytes = Math.ceil(bits / 8);\n const array = new Uint8Array(bytes);\n crypto.getRandomValues(array);\n\n // Convert bytes to BigInt\n let result = 0n;\n for (let i = 0; i < bytes; i++) {\n result = (result << 8n) | BigInt(array[i]);\n }\n\n // Mask to exact bit count\n const mask = (1n << BigInt(bits)) - 1n;\n return result & mask;\n}\n\n/**\n * Generate a cryptographically secure random hex string\n *\n * @param bytes - Number of random bytes (default 16)\n * @returns Hex-encoded random string\n * @throws Error if bytes is invalid or crypto unavailable\n */\nexport function cryptoRandomHex(bytes: number = 16): string {\n if (bytes <= 0 || bytes > 128) {\n throw new Error(`Invalid bytes value: ${bytes}. Must be 1-128`);\n }\n\n const crypto = getCrypto();\n const array = new Uint8Array(bytes);\n crypto.getRandomValues(array);\n\n return Array.from(array)\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ============================================================================\n// Network and Scheme Utilities\n// ============================================================================\n\n/**\n * Scheme data structure for facilitator storage\n */\nexport interface SchemeData<T> {\n facilitator: T;\n networks: Set<Network>;\n pattern: Network;\n}\n\nexport const findSchemesByNetwork = <T>(\n map: Map<string, Map<string, T>>,\n network: Network,\n): Map<string, T> | undefined => {\n // Direct match first\n let implementationsByScheme = map.get(network);\n\n if (!implementationsByScheme) {\n // Try pattern matching for registered network patterns\n for (const [registeredNetworkPattern, implementations] of map.entries()) {\n // Convert the registered network pattern to a regex\n // e.g., \"eip155:*\" becomes /^eip155:.*$/\n const pattern = registeredNetworkPattern\n .replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\") // Escape special regex chars except *\n .replace(/\\\\\\*/g, \".*\"); // Replace escaped * with .*\n\n const regex = new RegExp(`^${pattern}$`);\n\n if (regex.test(network)) {\n implementationsByScheme = implementations;\n break;\n }\n }\n }\n\n return implementationsByScheme;\n};\n\nexport const findByNetworkAndScheme = <T>(\n map: Map<string, Map<string, T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n return findSchemesByNetwork(map, network)?.get(scheme);\n};\n\n/**\n * Finds a facilitator by scheme and network using pattern matching.\n * Works with new SchemeData storage structure.\n *\n * @param schemeMap - Map of scheme names to SchemeData\n * @param scheme - The scheme to find\n * @param network - The network to match against\n * @returns The facilitator if found, undefined otherwise\n */\nexport const findFacilitatorBySchemeAndNetwork = <T>(\n schemeMap: Map<string, SchemeData<T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n const schemeData = schemeMap.get(scheme);\n if (!schemeData) return undefined;\n\n // Check if network is in the stored networks set\n if (schemeData.networks.has(network)) {\n return schemeData.facilitator;\n }\n\n // Try pattern matching\n const patternRegex = new RegExp(\"^\" + schemeData.pattern.replace(\"*\", \".*\") + \"$\");\n if (patternRegex.test(network)) {\n return schemeData.facilitator;\n }\n\n return undefined;\n};\n\nexport const Base64EncodedRegex = /^[A-Za-z0-9+/]*={0,2}$/;\n\n/**\n * Encodes a string to base64 format\n *\n * @param data - The string to be encoded to base64\n * @returns The base64 encoded string\n */\nexport function safeBase64Encode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.btoa === \"function\") {\n return globalThis.btoa(data);\n }\n return Buffer.from(data).toString(\"base64\");\n}\n\n/**\n * Decodes a base64 string back to its original format\n *\n * @param data - The base64 encoded string to be decoded\n * @returns The decoded string in UTF-8 format\n */\nexport function safeBase64Decode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.atob === \"function\") {\n return globalThis.atob(data);\n }\n return Buffer.from(data, \"base64\").toString(\"utf-8\");\n}\n\n/**\n * Deep equality comparison for payment requirements\n * Uses a normalized JSON.stringify for consistent comparison\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are deeply equal\n */\nexport function deepEqual(obj1: unknown, obj2: unknown): boolean {\n // Normalize and stringify both objects for comparison\n // This handles nested objects, arrays, and different property orders\n const normalize = (obj: unknown): string => {\n // Handle primitives and null/undefined\n if (obj === null || obj === undefined) return JSON.stringify(obj);\n if (typeof obj !== \"object\") return JSON.stringify(obj);\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return JSON.stringify(\n obj.map(item =>\n typeof item === \"object\" && item !== null ? JSON.parse(normalize(item)) : item,\n ),\n );\n }\n\n // Handle objects - sort keys and recursively normalize values\n const sorted: Record<string, unknown> = {};\n Object.keys(obj as Record<string, unknown>)\n .sort()\n .forEach(key => {\n const value = (obj as Record<string, unknown>)[key];\n sorted[key] =\n typeof value === \"object\" && value !== null ? JSON.parse(normalize(value)) : value;\n });\n return JSON.stringify(sorted);\n };\n\n try {\n return normalize(obj1) === normalize(obj2);\n } catch {\n // Fallback to simple comparison if normalization fails\n return JSON.stringify(obj1) === JSON.stringify(obj2);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,100 @@
1
+ // src/types/schemas.ts
2
+ import { z } from "zod";
3
+ var NetworkSchema = z.string().regex(/^[a-z0-9-]+:[a-zA-Z0-9-]+$/, {
4
+ message: "Network must be in CAIP-2 format (e.g., 'eip155:1', 'solana:mainnet')"
5
+ });
6
+ var ResourceInfoSchema = z.object({
7
+ url: z.string().url({ message: "Resource URL must be a valid URL" }),
8
+ description: z.string().optional(),
9
+ mimeType: z.string().optional()
10
+ });
11
+ var PaymentRequirementsSchema = z.object({
12
+ scheme: z.string().min(1, { message: "Scheme is required" }),
13
+ network: NetworkSchema,
14
+ asset: z.string().min(1, { message: "Asset address is required" }),
15
+ amount: z.string().regex(/^\d+$/, { message: "Amount must be a non-negative integer string" }),
16
+ payTo: z.string().min(1, { message: "PayTo address is required" }),
17
+ maxTimeoutSeconds: z.number().int().positive({ message: "maxTimeoutSeconds must be a positive integer" }),
18
+ extra: z.record(z.unknown())
19
+ });
20
+ var PaymentRequiredSchema = z.object({
21
+ t402Version: z.literal(2, {
22
+ errorMap: () => ({ message: "t402Version must be 2 for V2 protocol" })
23
+ }),
24
+ error: z.string().optional(),
25
+ resource: ResourceInfoSchema,
26
+ accepts: z.array(PaymentRequirementsSchema).min(1, { message: "At least one payment option is required" }),
27
+ extensions: z.record(z.unknown()).optional()
28
+ });
29
+ var PaymentPayloadSchema = z.object({
30
+ t402Version: z.literal(2, {
31
+ errorMap: () => ({ message: "t402Version must be 2 for V2 protocol" })
32
+ }),
33
+ resource: ResourceInfoSchema.optional(),
34
+ accepted: PaymentRequirementsSchema,
35
+ payload: z.record(z.unknown()),
36
+ extensions: z.record(z.unknown()).optional()
37
+ });
38
+ var VerifyResponseSchema = z.object({
39
+ isValid: z.boolean(),
40
+ invalidReason: z.string().optional(),
41
+ payer: z.string().optional()
42
+ });
43
+ var SettleResponseSchema = z.object({
44
+ success: z.boolean(),
45
+ transaction: z.string(),
46
+ network: NetworkSchema,
47
+ errorReason: z.string().optional(),
48
+ payer: z.string().optional()
49
+ });
50
+ var PaymentRequirementsV1Schema = z.object({
51
+ scheme: z.string().min(1),
52
+ network: z.string().min(1),
53
+ asset: z.string().min(1),
54
+ amount: z.string().regex(/^\d+$/),
55
+ payTo: z.string().min(1),
56
+ maxTimeoutSeconds: z.number().int().positive(),
57
+ extra: z.record(z.unknown()).optional()
58
+ });
59
+ var PaymentPayloadV1Schema = z.object({
60
+ t402Version: z.literal(1).optional(),
61
+ accepted: PaymentRequirementsV1Schema,
62
+ payload: z.record(z.unknown())
63
+ });
64
+ function parsePaymentPayload(data) {
65
+ return PaymentPayloadSchema.parse(data);
66
+ }
67
+ function parsePaymentRequired(data) {
68
+ return PaymentRequiredSchema.parse(data);
69
+ }
70
+ function parsePaymentRequirements(data) {
71
+ return PaymentRequirementsSchema.parse(data);
72
+ }
73
+ function safeParsePaymentPayload(data) {
74
+ return PaymentPayloadSchema.safeParse(data);
75
+ }
76
+ function safeParsePaymentRequired(data) {
77
+ return PaymentRequiredSchema.safeParse(data);
78
+ }
79
+ function safeParsePaymentRequirements(data) {
80
+ return PaymentRequirementsSchema.safeParse(data);
81
+ }
82
+
83
+ export {
84
+ NetworkSchema,
85
+ ResourceInfoSchema,
86
+ PaymentRequirementsSchema,
87
+ PaymentRequiredSchema,
88
+ PaymentPayloadSchema,
89
+ VerifyResponseSchema,
90
+ SettleResponseSchema,
91
+ PaymentRequirementsV1Schema,
92
+ PaymentPayloadV1Schema,
93
+ parsePaymentPayload,
94
+ parsePaymentRequired,
95
+ parsePaymentRequirements,
96
+ safeParsePaymentPayload,
97
+ safeParsePaymentRequired,
98
+ safeParsePaymentRequirements
99
+ };
100
+ //# sourceMappingURL=chunk-KPNYZYDS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/schemas.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Zod schemas for T402 protocol types.\n * Used for runtime validation of incoming data.\n */\n\n// Network format: \"namespace:reference\" (CAIP-2)\nexport const NetworkSchema = z.string().regex(/^[a-z0-9-]+:[a-zA-Z0-9-]+$/, {\n message: \"Network must be in CAIP-2 format (e.g., 'eip155:1', 'solana:mainnet')\",\n});\n\n// Resource info for V2 protocol\nexport const ResourceInfoSchema = z.object({\n url: z.string().url({ message: \"Resource URL must be a valid URL\" }),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n});\n\n// Payment requirements (what the server needs)\nexport const PaymentRequirementsSchema = z.object({\n scheme: z.string().min(1, { message: \"Scheme is required\" }),\n network: NetworkSchema,\n asset: z.string().min(1, { message: \"Asset address is required\" }),\n amount: z.string().regex(/^\\d+$/, { message: \"Amount must be a non-negative integer string\" }),\n payTo: z.string().min(1, { message: \"PayTo address is required\" }),\n maxTimeoutSeconds: z\n .number()\n .int()\n .positive({ message: \"maxTimeoutSeconds must be a positive integer\" }),\n extra: z.record(z.unknown()),\n});\n\n// Payment required response (402 response)\nexport const PaymentRequiredSchema = z.object({\n t402Version: z.literal(2, {\n errorMap: () => ({ message: \"t402Version must be 2 for V2 protocol\" }),\n }),\n error: z.string().optional(),\n resource: ResourceInfoSchema,\n accepts: z\n .array(PaymentRequirementsSchema)\n .min(1, { message: \"At least one payment option is required\" }),\n extensions: z.record(z.unknown()).optional(),\n});\n\n// Payment payload (client's signed payment)\nexport const PaymentPayloadSchema = z.object({\n t402Version: z.literal(2, {\n errorMap: () => ({ message: \"t402Version must be 2 for V2 protocol\" }),\n }),\n resource: ResourceInfoSchema.optional(),\n accepted: PaymentRequirementsSchema,\n payload: z.record(z.unknown()),\n extensions: z.record(z.unknown()).optional(),\n});\n\n// Verify response from facilitator\nexport const VerifyResponseSchema = z.object({\n isValid: z.boolean(),\n invalidReason: z.string().optional(),\n payer: z.string().optional(),\n});\n\n// Settle response from facilitator\nexport const SettleResponseSchema = z.object({\n success: z.boolean(),\n transaction: z.string(),\n network: NetworkSchema,\n errorReason: z.string().optional(),\n payer: z.string().optional(),\n});\n\n// V1 schemas for backward compatibility\nexport const PaymentRequirementsV1Schema = z.object({\n scheme: z.string().min(1),\n network: z.string().min(1),\n asset: z.string().min(1),\n amount: z.string().regex(/^\\d+$/),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().int().positive(),\n extra: z.record(z.unknown()).optional(),\n});\n\nexport const PaymentPayloadV1Schema = z.object({\n t402Version: z.literal(1).optional(),\n accepted: PaymentRequirementsV1Schema,\n payload: z.record(z.unknown()),\n});\n\n// Type inference helpers\nexport type ValidatedPaymentPayload = z.infer<typeof PaymentPayloadSchema>;\nexport type ValidatedPaymentRequired = z.infer<typeof PaymentRequiredSchema>;\nexport type ValidatedPaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\nexport type ValidatedVerifyResponse = z.infer<typeof VerifyResponseSchema>;\nexport type ValidatedSettleResponse = z.infer<typeof SettleResponseSchema>;\n\n/**\n * Parse and validate a PaymentPayload.\n *\n * @param data - The data to parse\n * @returns The validated payment payload\n * @throws ZodError if validation fails\n */\nexport function parsePaymentPayload(data: unknown): ValidatedPaymentPayload {\n return PaymentPayloadSchema.parse(data);\n}\n\n/**\n * Parse and validate a PaymentRequired response.\n *\n * @param data - The data to parse\n * @returns The validated payment required response\n * @throws ZodError if validation fails\n */\nexport function parsePaymentRequired(data: unknown): ValidatedPaymentRequired {\n return PaymentRequiredSchema.parse(data);\n}\n\n/**\n * Parse and validate PaymentRequirements.\n *\n * @param data - The data to parse\n * @returns The validated payment requirements\n * @throws ZodError if validation fails\n */\nexport function parsePaymentRequirements(data: unknown): ValidatedPaymentRequirements {\n return PaymentRequirementsSchema.parse(data);\n}\n\n/**\n * Safely parse a PaymentPayload, returning a result object.\n *\n * @param data - The data to parse\n * @returns The safe parse result\n */\nexport function safeParsePaymentPayload(\n data: unknown,\n): z.SafeParseReturnType<unknown, ValidatedPaymentPayload> {\n return PaymentPayloadSchema.safeParse(data);\n}\n\n/**\n * Safely parse a PaymentRequired response, returning a result object.\n *\n * @param data - The data to parse\n * @returns The safe parse result\n */\nexport function safeParsePaymentRequired(\n data: unknown,\n): z.SafeParseReturnType<unknown, ValidatedPaymentRequired> {\n return PaymentRequiredSchema.safeParse(data);\n}\n\n/**\n * Safely parse PaymentRequirements, returning a result object.\n *\n * @param data - The data to parse\n * @returns The safe parse result\n */\nexport function safeParsePaymentRequirements(\n data: unknown,\n): z.SafeParseReturnType<unknown, ValidatedPaymentRequirements> {\n return PaymentRequirementsSchema.safeParse(data);\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,51 @@
1
1
  // src/utils/index.ts
2
+ function getCrypto() {
3
+ const cryptoObj = globalThis.crypto;
4
+ if (!cryptoObj || typeof cryptoObj.getRandomValues !== "function") {
5
+ throw new Error(
6
+ "Crypto API not available. Node.js 19+ or a browser with Web Crypto API is required."
7
+ );
8
+ }
9
+ return cryptoObj;
10
+ }
11
+ function cryptoRandomInt(max) {
12
+ if (max <= 0 || max > 4294967295 || !Number.isInteger(max)) {
13
+ throw new Error(`Invalid max value: ${max}. Must be positive integer <= 2^32`);
14
+ }
15
+ const crypto = getCrypto();
16
+ const array = new Uint32Array(1);
17
+ const limit = Math.floor(4294967295 / max) * max;
18
+ let value;
19
+ do {
20
+ crypto.getRandomValues(array);
21
+ value = array[0];
22
+ } while (value >= limit);
23
+ return value % max;
24
+ }
25
+ function cryptoRandomBigInt(bits = 64) {
26
+ if (bits <= 0 || bits > 256) {
27
+ throw new Error(`Invalid bits value: ${bits}. Must be 1-256`);
28
+ }
29
+ const crypto = getCrypto();
30
+ const bytes = Math.ceil(bits / 8);
31
+ const array = new Uint8Array(bytes);
32
+ crypto.getRandomValues(array);
33
+ let result = 0n;
34
+ for (let i = 0; i < bytes; i++) {
35
+ result = result << 8n | BigInt(array[i]);
36
+ }
37
+ const mask = (1n << BigInt(bits)) - 1n;
38
+ return result & mask;
39
+ }
40
+ function cryptoRandomHex(bytes = 16) {
41
+ if (bytes <= 0 || bytes > 128) {
42
+ throw new Error(`Invalid bytes value: ${bytes}. Must be 1-128`);
43
+ }
44
+ const crypto = getCrypto();
45
+ const array = new Uint8Array(bytes);
46
+ crypto.getRandomValues(array);
47
+ return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
48
+ }
2
49
  var findSchemesByNetwork = (map, network) => {
3
50
  let implementationsByScheme = map.get(network);
4
51
  if (!implementationsByScheme) {
@@ -67,6 +114,9 @@ function deepEqual(obj1, obj2) {
67
114
  }
68
115
 
69
116
  export {
117
+ cryptoRandomInt,
118
+ cryptoRandomBigInt,
119
+ cryptoRandomHex,
70
120
  findSchemesByNetwork,
71
121
  findByNetworkAndScheme,
72
122
  findFacilitatorBySchemeAndNetwork,
@@ -75,4 +125,4 @@ export {
75
125
  safeBase64Decode,
76
126
  deepEqual
77
127
  };
78
- //# sourceMappingURL=chunk-3IUBYRYG.mjs.map
128
+ //# sourceMappingURL=chunk-LJ4M5Z5U.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["import { Network } from \"../types\";\n\n// ============================================================================\n// Cryptographically Secure Random Utilities\n// ============================================================================\n\n/**\n * Get the crypto object, works in both browser and Node.js (19+)\n *\n * @returns The crypto object\n * @throws Error if crypto API is not available\n */\nfunction getCrypto(): Crypto {\n const cryptoObj = globalThis.crypto;\n\n if (!cryptoObj || typeof cryptoObj.getRandomValues !== \"function\") {\n throw new Error(\n \"Crypto API not available. \" + \"Node.js 19+ or a browser with Web Crypto API is required.\",\n );\n }\n\n return cryptoObj;\n}\n\n/**\n * Generate a cryptographically secure random integer in range [0, max)\n *\n * Uses rejection sampling to ensure uniform distribution.\n *\n * @param max - Exclusive upper bound (must be > 0 and <= 2^32)\n * @returns Random integer in [0, max)\n * @throws Error if max is invalid or crypto unavailable\n */\nexport function cryptoRandomInt(max: number): number {\n if (max <= 0 || max > 0xffffffff || !Number.isInteger(max)) {\n throw new Error(`Invalid max value: ${max}. Must be positive integer <= 2^32`);\n }\n\n const crypto = getCrypto();\n const array = new Uint32Array(1);\n\n // Rejection sampling to avoid modulo bias\n const limit = Math.floor(0xffffffff / max) * max;\n let value: number;\n\n do {\n crypto.getRandomValues(array);\n value = array[0];\n } while (value >= limit);\n\n return value % max;\n}\n\n/**\n * Generate a cryptographically secure random BigInt\n *\n * @param bits - Number of bits (default 64, max 256)\n * @returns Random BigInt with specified number of bits\n * @throws Error if bits is invalid or crypto unavailable\n */\nexport function cryptoRandomBigInt(bits: number = 64): bigint {\n if (bits <= 0 || bits > 256) {\n throw new Error(`Invalid bits value: ${bits}. Must be 1-256`);\n }\n\n const crypto = getCrypto();\n const bytes = Math.ceil(bits / 8);\n const array = new Uint8Array(bytes);\n crypto.getRandomValues(array);\n\n // Convert bytes to BigInt\n let result = 0n;\n for (let i = 0; i < bytes; i++) {\n result = (result << 8n) | BigInt(array[i]);\n }\n\n // Mask to exact bit count\n const mask = (1n << BigInt(bits)) - 1n;\n return result & mask;\n}\n\n/**\n * Generate a cryptographically secure random hex string\n *\n * @param bytes - Number of random bytes (default 16)\n * @returns Hex-encoded random string\n * @throws Error if bytes is invalid or crypto unavailable\n */\nexport function cryptoRandomHex(bytes: number = 16): string {\n if (bytes <= 0 || bytes > 128) {\n throw new Error(`Invalid bytes value: ${bytes}. Must be 1-128`);\n }\n\n const crypto = getCrypto();\n const array = new Uint8Array(bytes);\n crypto.getRandomValues(array);\n\n return Array.from(array)\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ============================================================================\n// Network and Scheme Utilities\n// ============================================================================\n\n/**\n * Scheme data structure for facilitator storage\n */\nexport interface SchemeData<T> {\n facilitator: T;\n networks: Set<Network>;\n pattern: Network;\n}\n\nexport const findSchemesByNetwork = <T>(\n map: Map<string, Map<string, T>>,\n network: Network,\n): Map<string, T> | undefined => {\n // Direct match first\n let implementationsByScheme = map.get(network);\n\n if (!implementationsByScheme) {\n // Try pattern matching for registered network patterns\n for (const [registeredNetworkPattern, implementations] of map.entries()) {\n // Convert the registered network pattern to a regex\n // e.g., \"eip155:*\" becomes /^eip155:.*$/\n const pattern = registeredNetworkPattern\n .replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\") // Escape special regex chars except *\n .replace(/\\\\\\*/g, \".*\"); // Replace escaped * with .*\n\n const regex = new RegExp(`^${pattern}$`);\n\n if (regex.test(network)) {\n implementationsByScheme = implementations;\n break;\n }\n }\n }\n\n return implementationsByScheme;\n};\n\nexport const findByNetworkAndScheme = <T>(\n map: Map<string, Map<string, T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n return findSchemesByNetwork(map, network)?.get(scheme);\n};\n\n/**\n * Finds a facilitator by scheme and network using pattern matching.\n * Works with new SchemeData storage structure.\n *\n * @param schemeMap - Map of scheme names to SchemeData\n * @param scheme - The scheme to find\n * @param network - The network to match against\n * @returns The facilitator if found, undefined otherwise\n */\nexport const findFacilitatorBySchemeAndNetwork = <T>(\n schemeMap: Map<string, SchemeData<T>>,\n scheme: string,\n network: Network,\n): T | undefined => {\n const schemeData = schemeMap.get(scheme);\n if (!schemeData) return undefined;\n\n // Check if network is in the stored networks set\n if (schemeData.networks.has(network)) {\n return schemeData.facilitator;\n }\n\n // Try pattern matching\n const patternRegex = new RegExp(\"^\" + schemeData.pattern.replace(\"*\", \".*\") + \"$\");\n if (patternRegex.test(network)) {\n return schemeData.facilitator;\n }\n\n return undefined;\n};\n\nexport const Base64EncodedRegex = /^[A-Za-z0-9+/]*={0,2}$/;\n\n/**\n * Encodes a string to base64 format\n *\n * @param data - The string to be encoded to base64\n * @returns The base64 encoded string\n */\nexport function safeBase64Encode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.btoa === \"function\") {\n return globalThis.btoa(data);\n }\n return Buffer.from(data).toString(\"base64\");\n}\n\n/**\n * Decodes a base64 string back to its original format\n *\n * @param data - The base64 encoded string to be decoded\n * @returns The decoded string in UTF-8 format\n */\nexport function safeBase64Decode(data: string): string {\n if (typeof globalThis !== \"undefined\" && typeof globalThis.atob === \"function\") {\n return globalThis.atob(data);\n }\n return Buffer.from(data, \"base64\").toString(\"utf-8\");\n}\n\n/**\n * Deep equality comparison for payment requirements\n * Uses a normalized JSON.stringify for consistent comparison\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are deeply equal\n */\nexport function deepEqual(obj1: unknown, obj2: unknown): boolean {\n // Normalize and stringify both objects for comparison\n // This handles nested objects, arrays, and different property orders\n const normalize = (obj: unknown): string => {\n // Handle primitives and null/undefined\n if (obj === null || obj === undefined) return JSON.stringify(obj);\n if (typeof obj !== \"object\") return JSON.stringify(obj);\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return JSON.stringify(\n obj.map(item =>\n typeof item === \"object\" && item !== null ? JSON.parse(normalize(item)) : item,\n ),\n );\n }\n\n // Handle objects - sort keys and recursively normalize values\n const sorted: Record<string, unknown> = {};\n Object.keys(obj as Record<string, unknown>)\n .sort()\n .forEach(key => {\n const value = (obj as Record<string, unknown>)[key];\n sorted[key] =\n typeof value === \"object\" && value !== null ? JSON.parse(normalize(value)) : value;\n });\n return JSON.stringify(sorted);\n };\n\n try {\n return normalize(obj1) === normalize(obj2);\n } catch {\n // Fallback to simple comparison if normalization fails\n return JSON.stringify(obj1) === JSON.stringify(obj2);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +1,16 @@
1
1
  import {
2
2
  t402Version
3
3
  } from "./chunk-3VTYR43U.mjs";
4
+ import {
5
+ PaymentPayloadSchema,
6
+ PaymentRequiredSchema,
7
+ SettleResponseSchema
8
+ } from "./chunk-KPNYZYDS.mjs";
4
9
  import {
5
10
  Base64EncodedRegex,
6
11
  safeBase64Decode,
7
12
  safeBase64Encode
8
- } from "./chunk-3IUBYRYG.mjs";
13
+ } from "./chunk-LJ4M5Z5U.mjs";
9
14
  import {
10
15
  __publicField,
11
16
  __require
@@ -694,7 +699,9 @@ function decodePaymentSignatureHeader(paymentSignatureHeader) {
694
699
  if (!Base64EncodedRegex.test(paymentSignatureHeader)) {
695
700
  throw new Error("Invalid payment signature header");
696
701
  }
697
- return JSON.parse(safeBase64Decode(paymentSignatureHeader));
702
+ const parsed = JSON.parse(safeBase64Decode(paymentSignatureHeader));
703
+ PaymentPayloadSchema.parse(parsed);
704
+ return parsed;
698
705
  }
699
706
  function encodePaymentRequiredHeader(paymentRequired) {
700
707
  return safeBase64Encode(JSON.stringify(paymentRequired));
@@ -703,7 +710,9 @@ function decodePaymentRequiredHeader(paymentRequiredHeader) {
703
710
  if (!Base64EncodedRegex.test(paymentRequiredHeader)) {
704
711
  throw new Error("Invalid payment required header");
705
712
  }
706
- return JSON.parse(safeBase64Decode(paymentRequiredHeader));
713
+ const parsed = JSON.parse(safeBase64Decode(paymentRequiredHeader));
714
+ PaymentRequiredSchema.parse(parsed);
715
+ return parsed;
707
716
  }
708
717
  function encodePaymentResponseHeader(paymentResponse) {
709
718
  return safeBase64Encode(JSON.stringify(paymentResponse));
@@ -712,7 +721,9 @@ function decodePaymentResponseHeader(paymentResponseHeader) {
712
721
  if (!Base64EncodedRegex.test(paymentResponseHeader)) {
713
722
  throw new Error("Invalid payment response header");
714
723
  }
715
- return JSON.parse(safeBase64Decode(paymentResponseHeader));
724
+ const parsed = JSON.parse(safeBase64Decode(paymentResponseHeader));
725
+ SettleResponseSchema.parse(parsed);
726
+ return parsed;
716
727
  }
717
728
 
718
729
  export {
@@ -727,4 +738,4 @@ export {
727
738
  decodePaymentResponseHeader,
728
739
  t402HTTPClient
729
740
  };
730
- //# sourceMappingURL=chunk-773TNE2Y.mjs.map
741
+ //# sourceMappingURL=chunk-REMGOG6C.mjs.map