@peac/rails-x402 0.15.0 → 0.15.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.
package/dist/helpers.d.ts CHANGED
@@ -75,7 +75,8 @@ export declare function getHeaders(dialect: 'v1' | 'v2'): typeof X402_HEADERS_V1
75
75
  */
76
76
  export declare function isTestnet(networkId: string): boolean;
77
77
  /**
78
- * Clear warned networks set (for testing)
78
+ * Clear warned networks set (for testing).
79
+ * @internal Package-internal test hook; not part of the public API.
79
80
  */
80
81
  export declare function _resetWarnedNetworks(): void;
81
82
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,EAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAO3C;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAKhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAiB3E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,WAAW,EACpB,eAAe,EAAE,WAAW,GAC3B,IAAI,GAAG,IAAI,CAUb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,eAAe,GAAG,OAAO,eAAe,CAEhG;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,EAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAO3C;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAKhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAiB3E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,WAAW,EACpB,eAAe,EAAE,WAAW,GAC3B,IAAI,GAAG,IAAI,CAUb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,eAAe,GAAG,OAAO,eAAe,CAEhG;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
package/dist/index.cjs CHANGED
@@ -68,9 +68,6 @@ function getHeaders(dialect) {
68
68
  function isTestnet(networkId) {
69
69
  return CAIP2_REGISTRY[networkId]?.env === "testnet";
70
70
  }
71
- function _resetWarnedNetworks() {
72
- warnedNetworks.clear();
73
- }
74
71
 
75
72
  // src/payment-headers.ts
76
73
  function hasGetMethod(headers) {
@@ -287,7 +284,6 @@ exports.CAIP2_REGISTRY = CAIP2_REGISTRY;
287
284
  exports.X402_HEADERS_V1 = X402_HEADERS_V1;
288
285
  exports.X402_HEADERS_V2 = X402_HEADERS_V2;
289
286
  exports.X402_V1_DEFAULT_NETWORK = X402_V1_DEFAULT_NETWORK;
290
- exports._resetWarnedNetworks = _resetWarnedNetworks;
291
287
  exports.detectDialect = detectDialect;
292
288
  exports.detectPaymentRequired = detectPaymentRequired;
293
289
  exports.extractPaymentReference = extractPaymentReference;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/helpers.ts","../src/payment-headers.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * x402 protocol constants and types\n *\n * Supports both x402 v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n * Default behavior is auto-detection with v1 fallback.\n */\n\n/**\n * x402 protocol dialect\n *\n * - 'v1': Legacy X-PAYMENT-* headers (pre-Dec 2025)\n * - 'v2': New Payment-* headers (Dec 2025+)\n * - 'auto': Auto-detect from response headers (default)\n */\nexport type X402Dialect = 'v1' | 'v2' | 'auto';\n\n/**\n * x402 v1 header names (legacy, pre-Dec 2025)\n */\nexport const X402_HEADERS_V1 = {\n paymentRequired: 'X-PAYMENT',\n paymentResponse: 'X-PAYMENT-RESPONSE',\n} as const;\n\n/**\n * x402 v2 header names (Dec 2025+)\n */\nexport const X402_HEADERS_V2 = {\n paymentRequired: 'Payment-Required',\n paymentSignature: 'Payment-Signature',\n paymentResponse: 'Payment-Response',\n} as const;\n\n/**\n * CAIP-2 network registry\n *\n * Maps canonical CAIP-2 identifiers to human-readable labels and environment.\n * Used for validation/logging only - network IDs are passed through unchanged.\n *\n * Reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_REGISTRY: Record<string, { label: string; env: 'mainnet' | 'testnet' }> = {\n // EVM chains\n 'eip155:8453': { label: 'Base', env: 'mainnet' },\n 'eip155:84532': { label: 'Base Sepolia', env: 'testnet' },\n 'eip155:43114': { label: 'Avalanche', env: 'mainnet' },\n 'eip155:43113': { label: 'Avalanche Fuji', env: 'testnet' },\n // Solana\n 'solana:mainnet': { label: 'Solana', env: 'mainnet' },\n 'solana:devnet': { label: 'Solana Devnet', env: 'testnet' },\n // Lightning (v1 default)\n lightning: { label: 'Lightning', env: 'mainnet' },\n};\n\n/**\n * Default network for v1 x402 (Lightning)\n */\nexport const X402_V1_DEFAULT_NETWORK = 'lightning';\n","/**\n * x402 helper functions\n *\n * Detection, normalization, and logging utilities for x402 v1/v2 support.\n */\n\nimport {\n type X402Dialect,\n X402_HEADERS_V1,\n X402_HEADERS_V2,\n CAIP2_REGISTRY,\n X402_V1_DEFAULT_NETWORK,\n} from './constants';\nimport type { X402Invoice } from './types';\n\n/**\n * Track warned networks to avoid log spam (one warning per network per process)\n */\nconst warnedNetworks = new Set<string>();\n\n/**\n * Log warning for unknown CAIP-2 network (once per network per process)\n *\n * Message is calm and informative. Does not throw.\n */\nexport function logUnknownNetworkWarning(networkId: string): void {\n if (warnedNetworks.has(networkId)) return;\n warnedNetworks.add(networkId);\n\n console.warn(`[peac:x402] Unknown CAIP-2 network \"${networkId}\", passing through as-is.`);\n}\n\n/**\n * Detect x402 dialect from HTTP response headers\n *\n * Priority: v2 headers first (case-insensitive), then v1 fallback.\n *\n * Detection rules:\n * 1. If any v2 header present (Payment-Required, Payment-Signature, Payment-Response) -> v2\n * 2. If only v1 headers present (X-PAYMENT-*) -> v1\n * 3. If no headers provided -> v1 (safe default)\n *\n * @param headers - HTTP response headers (optional)\n * @returns Detected dialect ('v1' or 'v2')\n */\nexport function detectDialect(headers?: Record<string, string>): 'v1' | 'v2' {\n if (!headers) return 'v1';\n\n const lowerHeaders = Object.keys(headers).map((k) => k.toLowerCase());\n\n // Check for v2 headers first\n const v2Headers = [\n X402_HEADERS_V2.paymentRequired.toLowerCase(),\n X402_HEADERS_V2.paymentSignature.toLowerCase(),\n X402_HEADERS_V2.paymentResponse.toLowerCase(),\n ];\n\n if (v2Headers.some((h) => lowerHeaders.includes(h))) {\n return 'v2';\n }\n\n return 'v1';\n}\n\n/**\n * Resolve dialect for invoice processing (no headers available)\n *\n * Heuristics:\n * 1. If explicit dialect is specified (not 'auto') -> use it\n * 2. If invoice.network is a CAIP-2 string (contains ':') -> v2\n * 3. If invoice.payTo is present -> v2\n * 4. Otherwise -> v1\n *\n * @param invoice - x402 invoice\n * @param explicitDialect - Explicit dialect from config\n * @returns Resolved dialect ('v1' or 'v2')\n */\nexport function resolveDialectFromInvoice(\n invoice: X402Invoice,\n explicitDialect: X402Dialect\n): 'v1' | 'v2' {\n if (explicitDialect !== 'auto') {\n return explicitDialect;\n }\n\n // v2 indicators\n if (invoice.network && invoice.network.includes(':')) return 'v2';\n if (invoice.payTo) return 'v2';\n\n return 'v1';\n}\n\n/**\n * Normalize network ID (returns canonical ID, not label)\n *\n * Behavior:\n * - Missing input -> \"lightning\" (v1 default)\n * - Known CAIP-2 -> return as-is\n * - Unknown -> log warning, return as-is (no throw)\n *\n * Key rule: NO lossy mapping. The canonical ID is always preserved.\n *\n * @param caip2 - CAIP-2 network identifier (optional)\n * @returns Canonical network ID\n */\nexport function normalizeNetworkId(caip2: string | undefined): string {\n if (!caip2) return X402_V1_DEFAULT_NETWORK;\n\n if (!(caip2 in CAIP2_REGISTRY)) {\n logUnknownNetworkWarning(caip2);\n }\n\n return caip2; // Always return the canonical ID unchanged\n}\n\n/**\n * Get human-readable label for network (for evidence.network_label)\n *\n * @param caip2 - CAIP-2 network identifier\n * @returns Human-readable label, or undefined for unknown networks\n */\nexport function getNetworkLabel(caip2: string): string | undefined {\n return CAIP2_REGISTRY[caip2]?.label;\n}\n\n/**\n * Get header names for a specific dialect\n *\n * @param dialect - 'v1' or 'v2'\n * @returns Header name mapping\n */\nexport function getHeaders(dialect: 'v1' | 'v2'): typeof X402_HEADERS_V1 | typeof X402_HEADERS_V2 {\n return dialect === 'v2' ? X402_HEADERS_V2 : X402_HEADERS_V1;\n}\n\n/**\n * Check if a network ID indicates testnet environment\n *\n * @param networkId - CAIP-2 network identifier\n * @returns true if testnet, false otherwise\n */\nexport function isTestnet(networkId: string): boolean {\n return CAIP2_REGISTRY[networkId]?.env === 'testnet';\n}\n\n/**\n * Clear warned networks set (for testing)\n */\nexport function _resetWarnedNetworks(): void {\n warnedNetworks.clear();\n}\n","/**\n * x402 Payment Header Detection (Headers-Only)\n *\n * Provides minimal headers-only detection and extraction for x402 payment flow.\n * No Response objects, no body parsing.\n *\n * x402 Header Names (per Coinbase x402 spec):\n * - PAYMENT-REQUIRED: Server challenge with payment details\n * - PAYMENT-SIGNATURE: Client payment proof\n * - PAYMENT-RESPONSE: Server success response\n */\n\n/**\n * Headers-like object with .get() method.\n * Compatible with native Headers, node-fetch, undici, etc.\n */\nexport interface HeadersWithGet {\n get(name: string): string | null;\n}\n\n/**\n * Plain header object (Node.js/Express IncomingHttpHeaders style).\n * Values can be string, string[], or undefined.\n */\nexport type HeadersPlainObject = Record<string, string | string[] | undefined>;\n\n/**\n * Union type accepting both Headers-like objects and plain objects.\n * Works with:\n * - Native Headers (browser, Cloudflare Workers, Deno)\n * - node-fetch, undici Headers\n * - Express/Node.js req.headers (IncomingHttpHeaders)\n * - Plain objects\n */\nexport type HeadersLike = HeadersWithGet | HeadersPlainObject;\n\n/**\n * Check if headers object has a .get() method.\n */\nfunction hasGetMethod(headers: HeadersLike): headers is HeadersWithGet {\n return typeof (headers as HeadersWithGet).get === 'function';\n}\n\n/**\n * Get header value from plain object, handling case-insensitivity and arrays.\n * Node.js lowercases all header names, so we check multiple casings.\n */\nfunction getFromPlainObject(headers: HeadersPlainObject, name: string): string | null {\n // Common casings to try\n const casings = [\n name.toLowerCase(),\n name.toUpperCase(),\n name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-'),\n ];\n\n for (const key of casings) {\n const value = headers[key];\n if (value !== undefined) {\n // Handle array values (take first element)\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n\n // Also try exact match and iterate all keys for case-insensitive match\n const lowerName = name.toLowerCase();\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lowerName) {\n const value = headers[key];\n if (value !== undefined) {\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Case-insensitive header getter helper.\n * Handles both Headers-like objects (.get() method) and plain objects.\n *\n * @param headers - Headers object or plain object to query\n * @param name - Header name to look up\n * @returns Header value or null if not found\n */\nfunction getHeaderCaseInsensitive(headers: HeadersLike, name: string): string | null {\n if (hasGetMethod(headers)) {\n // Use .get() method - most Headers implementations are case-insensitive\n // but we try multiple casings for implementations that aren't\n const lower = headers.get(name.toLowerCase());\n if (lower !== null) return lower;\n\n const titleCase = name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-');\n const title = headers.get(titleCase);\n if (title !== null) return title;\n\n const upper = headers.get(name.toUpperCase());\n if (upper !== null) return upper;\n\n return null;\n }\n\n // Plain object path\n return getFromPlainObject(headers, name);\n}\n\n/**\n * Detect payment-required mode from HTTP headers.\n * Uses case-insensitive lookup and trims whitespace.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns true if PAYMENT-REQUIRED header is present and non-empty\n */\nexport function detectPaymentRequired(headers: HeadersLike): boolean {\n const paymentRequired = getHeaderCaseInsensitive(headers, 'payment-required');\n return paymentRequired !== null && paymentRequired.trim().length > 0;\n}\n\n/**\n * Extract payment reference from HTTP headers.\n * Returns the PAYMENT-REQUIRED header value (contains payment details).\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-REQUIRED header value, or undefined if not present/empty\n */\nexport function extractPaymentReference(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-required');\n return value?.trim() || undefined;\n}\n\n/**\n * Extract payment response from success headers.\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-RESPONSE header value, or undefined if not present/empty\n */\nexport function extractPaymentResponse(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-response');\n return value?.trim() || undefined;\n}\n","/**\n * x402 payment rail adapter\n *\n * Normalizes x402 invoices/settlements to PEAC PaymentEvidence.\n * Supports both v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n *\n * Default behavior is auto-detection with v1 fallback for backwards compatibility.\n */\n\nimport type { JsonObject } from '@peac/kernel';\nimport type { PaymentEvidence, PaymentSplit } from '@peac/schema';\n\n// Re-export types and constants for consumers\nexport * from './constants';\nexport * from './types';\nexport * from './helpers';\nexport * from './payment-headers';\n\nimport type { X402Dialect } from './constants';\nimport type { X402Invoice, X402Settlement, X402WebhookEvent } from './types';\nimport {\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n} from './helpers';\n\n/**\n * Build aggregator and splits from x402 invoice metadata\n *\n * Mapping rules:\n * - aggregator: Set when invoice has platform/aggregator in metadata\n * - Pattern: \"x402:{serviceName}\" (e.g., \"x402:load\", \"x402:tollbit\")\n * - splits: Mapped from explicit split data, or single merchant split if aggregator known\n * - If no split data and no aggregator -> undefined\n *\n * @param invoice - x402 invoice\n * @param resolvedDialect - Resolved dialect\n * @returns Object with optional aggregator and splits\n */\nfunction buildAggregatorAndSplits(\n invoice: X402Invoice,\n resolvedDialect: 'v1' | 'v2'\n): { aggregator?: string; splits?: PaymentSplit[] } {\n // Only attempt aggregator/splits for v2 (v1 has no such concept)\n if (resolvedDialect === 'v1') {\n return {};\n }\n\n let aggregator: string | undefined;\n let splits: PaymentSplit[] | undefined;\n\n // Detect aggregator from invoice metadata or known patterns\n const meta = invoice.metadata;\n if (meta?.aggregator && typeof meta.aggregator === 'string') {\n aggregator = `x402:${meta.aggregator}`;\n } else if (meta?.platform && typeof meta.platform === 'string') {\n aggregator = `x402:${meta.platform}`;\n }\n\n // Build splits if we have explicit split data\n if (meta?.splits && Array.isArray(meta.splits)) {\n const rawSplits = meta.splits as Array<Record<string, unknown>>;\n splits = rawSplits\n .map((s) => {\n const party = s.party as string | undefined;\n const amount = s.amount as number | undefined;\n const share = s.share as number | undefined;\n\n // Validate: party required, at least one of amount/share\n if (!party || (amount === undefined && share === undefined)) {\n return null;\n }\n\n const split: PaymentSplit = { party };\n if (amount !== undefined) split.amount = amount;\n if (share !== undefined) split.share = share;\n if (s.currency) split.currency = s.currency as string;\n if (s.rail) split.rail = s.rail as string;\n if (s.account_ref) split.account_ref = s.account_ref as string;\n\n return split;\n })\n .filter((s): s is PaymentSplit => s !== null);\n\n // If no valid splits after filtering, set to undefined\n if (splits.length === 0) {\n splits = undefined;\n }\n } else if (aggregator) {\n // Single split for merchant when aggregator is known but no explicit splits\n splits = [{ party: 'merchant', share: 1.0 }];\n }\n\n return { aggregator, splits };\n}\n\n/**\n * Map x402 payTo.mode to PaymentEvidence.routing\n *\n * @param payToMode - x402 payTo mode value\n * @returns Valid routing value or undefined\n */\nfunction mapRouting(payToMode: string | undefined): 'direct' | 'callback' | 'role' | undefined {\n if (payToMode === 'direct' || payToMode === 'callback' || payToMode === 'role') {\n return payToMode;\n }\n return undefined;\n}\n\n/**\n * Normalize x402 invoice to PEAC PaymentEvidence\n *\n * Supports both v1 and v2 x402 formats. Default is auto-detection.\n *\n * @param invoice - x402 invoice object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromInvoice(\n invoice: X402Invoice,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!invoice.id) {\n throw new Error('x402 invoice missing id');\n }\n if (typeof invoice.amount !== 'number' || invoice.amount < 0) {\n throw new Error('x402 invoice invalid amount');\n }\n if (!invoice.currency || !/^[A-Z]{3}$/.test(invoice.currency)) {\n throw new Error('x402 invoice invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect\n const resolvedDialect = resolveDialectFromInvoice(invoice, dialect);\n\n // Normalize network (canonical ID, not label)\n const network = normalizeNetworkId(invoice.network);\n\n // Build x402-specific evidence as JsonObject (typed internally as X402Evidence structure)\n const evidence: JsonObject = {\n invoice_id: invoice.id,\n dialect: resolvedDialect,\n };\n\n // Add network label for human readability\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (invoice.session_id) {\n evidence.session_id = invoice.session_id;\n }\n if (invoice.invoice_url) {\n evidence.invoice_url = invoice.invoice_url;\n }\n if (invoice.memo) {\n evidence.memo = invoice.memo;\n }\n if (invoice.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = invoice.metadata as JsonObject;\n }\n\n // v2: Add payTo if present\n if (invoice.payTo) {\n const payTo: JsonObject = {};\n if (invoice.payTo.mode) payTo.mode = invoice.payTo.mode;\n if (invoice.payTo.callback_url) payTo.callback_url = invoice.payTo.callback_url;\n if (invoice.payTo.role) payTo.role = invoice.payTo.role;\n evidence.pay_to = payTo;\n }\n\n // Build aggregator and splits (v2 only)\n const { aggregator, splits } = buildAggregatorAndSplits(invoice, resolvedDialect);\n\n // Map routing from payTo.mode\n const routing = mapRouting(invoice.payTo?.mode);\n\n // Build PaymentEvidence\n const result: PaymentEvidence = {\n rail: 'x402',\n reference: invoice.id,\n amount: invoice.amount,\n currency: invoice.currency,\n asset: invoice.currency,\n env,\n network,\n evidence,\n };\n\n // Add optional top-level fields\n if (aggregator) {\n result.aggregator = aggregator;\n }\n if (splits) {\n result.splits = splits;\n }\n if (routing) {\n result.routing = routing;\n }\n\n return result;\n}\n\n/**\n * Normalize x402 settlement to PEAC PaymentEvidence\n *\n * @param settlement - x402 settlement object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromSettlement(\n settlement: X402Settlement,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!settlement.id) {\n throw new Error('x402 settlement missing id');\n }\n if (!settlement.invoice_id) {\n throw new Error('x402 settlement missing invoice_id');\n }\n if (typeof settlement.amount !== 'number' || settlement.amount < 0) {\n throw new Error('x402 settlement invalid amount');\n }\n if (!settlement.currency || !/^[A-Z]{3}$/.test(settlement.currency)) {\n throw new Error('x402 settlement invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect (simplified for settlements - check network field)\n const resolvedDialect =\n dialect !== 'auto' ? dialect : settlement.network?.includes(':') ? 'v2' : 'v1';\n\n // Normalize network\n const network = normalizeNetworkId(settlement.network);\n\n // Build x402-specific evidence as JsonObject\n const evidence: JsonObject = {\n invoice_id: settlement.invoice_id,\n settlement_id: settlement.id,\n dialect: resolvedDialect,\n };\n\n // Add network label\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (settlement.settled_at) {\n evidence.settled_at = settlement.settled_at;\n }\n if (settlement.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = settlement.metadata as JsonObject;\n }\n\n return {\n rail: 'x402',\n reference: settlement.invoice_id,\n amount: settlement.amount,\n currency: settlement.currency,\n asset: settlement.currency,\n env,\n network,\n evidence,\n };\n}\n\n/**\n * Normalize x402 webhook event to PEAC PaymentEvidence\n *\n * Supports:\n * - invoice.paid\n * - settlement.completed\n *\n * Dialect is auto-detected from headers if provided.\n *\n * @param event - x402 webhook event\n * @param env - Environment ('live' or 'test')\n * @param headers - HTTP response headers (optional, for dialect detection)\n * @returns Normalized PaymentEvidence\n */\nexport function fromWebhookEvent(\n event: X402WebhookEvent,\n env: 'live' | 'test' = 'live',\n headers?: Record<string, string>\n): PaymentEvidence {\n const obj = event.data.object;\n\n // Detect dialect from headers if provided\n const dialect: X402Dialect = headers ? detectDialect(headers) : 'auto';\n\n // Determine object type by presence of fields\n if ('invoice_id' in obj && ('settled_at' in obj || 'settlement_id' in (obj as X402Settlement))) {\n // Settlement\n return fromSettlement(obj as X402Settlement, env, dialect);\n } else if ('amount' in obj && 'id' in obj) {\n // Invoice\n return fromInvoice(obj as X402Invoice, env, dialect);\n }\n\n throw new Error(`Unsupported x402 webhook event type: ${event.type}`);\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/helpers.ts","../src/payment-headers.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * x402 protocol constants and types\n *\n * Supports both x402 v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n * Default behavior is auto-detection with v1 fallback.\n */\n\n/**\n * x402 protocol dialect\n *\n * - 'v1': Legacy X-PAYMENT-* headers (pre-Dec 2025)\n * - 'v2': New Payment-* headers (Dec 2025+)\n * - 'auto': Auto-detect from response headers (default)\n */\nexport type X402Dialect = 'v1' | 'v2' | 'auto';\n\n/**\n * x402 v1 header names (legacy, pre-Dec 2025)\n */\nexport const X402_HEADERS_V1 = {\n paymentRequired: 'X-PAYMENT',\n paymentResponse: 'X-PAYMENT-RESPONSE',\n} as const;\n\n/**\n * x402 v2 header names (Dec 2025+)\n */\nexport const X402_HEADERS_V2 = {\n paymentRequired: 'Payment-Required',\n paymentSignature: 'Payment-Signature',\n paymentResponse: 'Payment-Response',\n} as const;\n\n/**\n * CAIP-2 network registry\n *\n * Maps canonical CAIP-2 identifiers to human-readable labels and environment.\n * Used for validation/logging only - network IDs are passed through unchanged.\n *\n * Reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_REGISTRY: Record<string, { label: string; env: 'mainnet' | 'testnet' }> = {\n // EVM chains\n 'eip155:8453': { label: 'Base', env: 'mainnet' },\n 'eip155:84532': { label: 'Base Sepolia', env: 'testnet' },\n 'eip155:43114': { label: 'Avalanche', env: 'mainnet' },\n 'eip155:43113': { label: 'Avalanche Fuji', env: 'testnet' },\n // Solana\n 'solana:mainnet': { label: 'Solana', env: 'mainnet' },\n 'solana:devnet': { label: 'Solana Devnet', env: 'testnet' },\n // Lightning (v1 default)\n lightning: { label: 'Lightning', env: 'mainnet' },\n};\n\n/**\n * Default network for v1 x402 (Lightning)\n */\nexport const X402_V1_DEFAULT_NETWORK = 'lightning';\n","/**\n * x402 helper functions\n *\n * Detection, normalization, and logging utilities for x402 v1/v2 support.\n */\n\nimport {\n type X402Dialect,\n X402_HEADERS_V1,\n X402_HEADERS_V2,\n CAIP2_REGISTRY,\n X402_V1_DEFAULT_NETWORK,\n} from './constants';\nimport type { X402Invoice } from './types';\n\n/**\n * Track warned networks to avoid log spam (one warning per network per process)\n */\nconst warnedNetworks = new Set<string>();\n\n/**\n * Log warning for unknown CAIP-2 network (once per network per process)\n *\n * Message is calm and informative. Does not throw.\n */\nexport function logUnknownNetworkWarning(networkId: string): void {\n if (warnedNetworks.has(networkId)) return;\n warnedNetworks.add(networkId);\n\n console.warn(`[peac:x402] Unknown CAIP-2 network \"${networkId}\", passing through as-is.`);\n}\n\n/**\n * Detect x402 dialect from HTTP response headers\n *\n * Priority: v2 headers first (case-insensitive), then v1 fallback.\n *\n * Detection rules:\n * 1. If any v2 header present (Payment-Required, Payment-Signature, Payment-Response) -> v2\n * 2. If only v1 headers present (X-PAYMENT-*) -> v1\n * 3. If no headers provided -> v1 (safe default)\n *\n * @param headers - HTTP response headers (optional)\n * @returns Detected dialect ('v1' or 'v2')\n */\nexport function detectDialect(headers?: Record<string, string>): 'v1' | 'v2' {\n if (!headers) return 'v1';\n\n const lowerHeaders = Object.keys(headers).map((k) => k.toLowerCase());\n\n // Check for v2 headers first\n const v2Headers = [\n X402_HEADERS_V2.paymentRequired.toLowerCase(),\n X402_HEADERS_V2.paymentSignature.toLowerCase(),\n X402_HEADERS_V2.paymentResponse.toLowerCase(),\n ];\n\n if (v2Headers.some((h) => lowerHeaders.includes(h))) {\n return 'v2';\n }\n\n return 'v1';\n}\n\n/**\n * Resolve dialect for invoice processing (no headers available)\n *\n * Heuristics:\n * 1. If explicit dialect is specified (not 'auto') -> use it\n * 2. If invoice.network is a CAIP-2 string (contains ':') -> v2\n * 3. If invoice.payTo is present -> v2\n * 4. Otherwise -> v1\n *\n * @param invoice - x402 invoice\n * @param explicitDialect - Explicit dialect from config\n * @returns Resolved dialect ('v1' or 'v2')\n */\nexport function resolveDialectFromInvoice(\n invoice: X402Invoice,\n explicitDialect: X402Dialect\n): 'v1' | 'v2' {\n if (explicitDialect !== 'auto') {\n return explicitDialect;\n }\n\n // v2 indicators\n if (invoice.network && invoice.network.includes(':')) return 'v2';\n if (invoice.payTo) return 'v2';\n\n return 'v1';\n}\n\n/**\n * Normalize network ID (returns canonical ID, not label)\n *\n * Behavior:\n * - Missing input -> \"lightning\" (v1 default)\n * - Known CAIP-2 -> return as-is\n * - Unknown -> log warning, return as-is (no throw)\n *\n * Key rule: NO lossy mapping. The canonical ID is always preserved.\n *\n * @param caip2 - CAIP-2 network identifier (optional)\n * @returns Canonical network ID\n */\nexport function normalizeNetworkId(caip2: string | undefined): string {\n if (!caip2) return X402_V1_DEFAULT_NETWORK;\n\n if (!(caip2 in CAIP2_REGISTRY)) {\n logUnknownNetworkWarning(caip2);\n }\n\n return caip2; // Always return the canonical ID unchanged\n}\n\n/**\n * Get human-readable label for network (for evidence.network_label)\n *\n * @param caip2 - CAIP-2 network identifier\n * @returns Human-readable label, or undefined for unknown networks\n */\nexport function getNetworkLabel(caip2: string): string | undefined {\n return CAIP2_REGISTRY[caip2]?.label;\n}\n\n/**\n * Get header names for a specific dialect\n *\n * @param dialect - 'v1' or 'v2'\n * @returns Header name mapping\n */\nexport function getHeaders(dialect: 'v1' | 'v2'): typeof X402_HEADERS_V1 | typeof X402_HEADERS_V2 {\n return dialect === 'v2' ? X402_HEADERS_V2 : X402_HEADERS_V1;\n}\n\n/**\n * Check if a network ID indicates testnet environment\n *\n * @param networkId - CAIP-2 network identifier\n * @returns true if testnet, false otherwise\n */\nexport function isTestnet(networkId: string): boolean {\n return CAIP2_REGISTRY[networkId]?.env === 'testnet';\n}\n\n/**\n * Clear warned networks set (for testing).\n * @internal Package-internal test hook; not part of the public API.\n */\nexport function _resetWarnedNetworks(): void {\n warnedNetworks.clear();\n}\n","/**\n * x402 Payment Header Detection (Headers-Only)\n *\n * Provides minimal headers-only detection and extraction for x402 payment flow.\n * No Response objects, no body parsing.\n *\n * x402 Header Names (per Coinbase x402 spec):\n * - PAYMENT-REQUIRED: Server challenge with payment details\n * - PAYMENT-SIGNATURE: Client payment proof\n * - PAYMENT-RESPONSE: Server success response\n */\n\n/**\n * Headers-like object with .get() method.\n * Compatible with native Headers, node-fetch, undici, etc.\n */\nexport interface HeadersWithGet {\n get(name: string): string | null;\n}\n\n/**\n * Plain header object (Node.js/Express IncomingHttpHeaders style).\n * Values can be string, string[], or undefined.\n */\nexport type HeadersPlainObject = Record<string, string | string[] | undefined>;\n\n/**\n * Union type accepting both Headers-like objects and plain objects.\n * Works with:\n * - Native Headers (browser, Cloudflare Workers, Deno)\n * - node-fetch, undici Headers\n * - Express/Node.js req.headers (IncomingHttpHeaders)\n * - Plain objects\n */\nexport type HeadersLike = HeadersWithGet | HeadersPlainObject;\n\n/**\n * Check if headers object has a .get() method.\n */\nfunction hasGetMethod(headers: HeadersLike): headers is HeadersWithGet {\n return typeof (headers as HeadersWithGet).get === 'function';\n}\n\n/**\n * Get header value from plain object, handling case-insensitivity and arrays.\n * Node.js lowercases all header names, so we check multiple casings.\n */\nfunction getFromPlainObject(headers: HeadersPlainObject, name: string): string | null {\n // Common casings to try\n const casings = [\n name.toLowerCase(),\n name.toUpperCase(),\n name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-'),\n ];\n\n for (const key of casings) {\n const value = headers[key];\n if (value !== undefined) {\n // Handle array values (take first element)\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n\n // Also try exact match and iterate all keys for case-insensitive match\n const lowerName = name.toLowerCase();\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lowerName) {\n const value = headers[key];\n if (value !== undefined) {\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Case-insensitive header getter helper.\n * Handles both Headers-like objects (.get() method) and plain objects.\n *\n * @param headers - Headers object or plain object to query\n * @param name - Header name to look up\n * @returns Header value or null if not found\n */\nfunction getHeaderCaseInsensitive(headers: HeadersLike, name: string): string | null {\n if (hasGetMethod(headers)) {\n // Use .get() method - most Headers implementations are case-insensitive\n // but we try multiple casings for implementations that aren't\n const lower = headers.get(name.toLowerCase());\n if (lower !== null) return lower;\n\n const titleCase = name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-');\n const title = headers.get(titleCase);\n if (title !== null) return title;\n\n const upper = headers.get(name.toUpperCase());\n if (upper !== null) return upper;\n\n return null;\n }\n\n // Plain object path\n return getFromPlainObject(headers, name);\n}\n\n/**\n * Detect payment-required mode from HTTP headers.\n * Uses case-insensitive lookup and trims whitespace.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns true if PAYMENT-REQUIRED header is present and non-empty\n */\nexport function detectPaymentRequired(headers: HeadersLike): boolean {\n const paymentRequired = getHeaderCaseInsensitive(headers, 'payment-required');\n return paymentRequired !== null && paymentRequired.trim().length > 0;\n}\n\n/**\n * Extract payment reference from HTTP headers.\n * Returns the PAYMENT-REQUIRED header value (contains payment details).\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-REQUIRED header value, or undefined if not present/empty\n */\nexport function extractPaymentReference(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-required');\n return value?.trim() || undefined;\n}\n\n/**\n * Extract payment response from success headers.\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-RESPONSE header value, or undefined if not present/empty\n */\nexport function extractPaymentResponse(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-response');\n return value?.trim() || undefined;\n}\n","/**\n * x402 payment rail adapter\n *\n * Normalizes x402 invoices/settlements to PEAC PaymentEvidence.\n * Supports both v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n *\n * Default behavior is auto-detection with v1 fallback for backwards compatibility.\n */\n\nimport type { JsonObject } from '@peac/kernel';\nimport type { PaymentEvidence, PaymentSplit } from '@peac/schema';\n\n// Re-export types and constants for consumers\nexport * from './constants';\nexport * from './types';\n// Re-export the public helpers explicitly; the internal test reset hook\n// (_resetWarnedNetworks) is intentionally NOT part of the public API\n// (import it from './helpers' inside the package's own tests).\nexport {\n logUnknownNetworkWarning,\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n getHeaders,\n isTestnet,\n} from './helpers';\nexport * from './payment-headers';\n\nimport type { X402Dialect } from './constants';\nimport type { X402Invoice, X402Settlement, X402WebhookEvent } from './types';\nimport {\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n} from './helpers';\n\n/**\n * Build aggregator and splits from x402 invoice metadata\n *\n * Mapping rules:\n * - aggregator: Set when invoice has platform/aggregator in metadata\n * - Pattern: \"x402:{serviceName}\" (e.g., \"x402:load\", \"x402:tollbit\")\n * - splits: Mapped from explicit split data, or single merchant split if aggregator known\n * - If no split data and no aggregator -> undefined\n *\n * @param invoice - x402 invoice\n * @param resolvedDialect - Resolved dialect\n * @returns Object with optional aggregator and splits\n */\nfunction buildAggregatorAndSplits(\n invoice: X402Invoice,\n resolvedDialect: 'v1' | 'v2'\n): { aggregator?: string; splits?: PaymentSplit[] } {\n // Only attempt aggregator/splits for v2 (v1 has no such concept)\n if (resolvedDialect === 'v1') {\n return {};\n }\n\n let aggregator: string | undefined;\n let splits: PaymentSplit[] | undefined;\n\n // Detect aggregator from invoice metadata or known patterns\n const meta = invoice.metadata;\n if (meta?.aggregator && typeof meta.aggregator === 'string') {\n aggregator = `x402:${meta.aggregator}`;\n } else if (meta?.platform && typeof meta.platform === 'string') {\n aggregator = `x402:${meta.platform}`;\n }\n\n // Build splits if we have explicit split data\n if (meta?.splits && Array.isArray(meta.splits)) {\n const rawSplits = meta.splits as Array<Record<string, unknown>>;\n splits = rawSplits\n .map((s) => {\n const party = s.party as string | undefined;\n const amount = s.amount as number | undefined;\n const share = s.share as number | undefined;\n\n // Validate: party required, at least one of amount/share\n if (!party || (amount === undefined && share === undefined)) {\n return null;\n }\n\n const split: PaymentSplit = { party };\n if (amount !== undefined) split.amount = amount;\n if (share !== undefined) split.share = share;\n if (s.currency) split.currency = s.currency as string;\n if (s.rail) split.rail = s.rail as string;\n if (s.account_ref) split.account_ref = s.account_ref as string;\n\n return split;\n })\n .filter((s): s is PaymentSplit => s !== null);\n\n // If no valid splits after filtering, set to undefined\n if (splits.length === 0) {\n splits = undefined;\n }\n } else if (aggregator) {\n // Single split for merchant when aggregator is known but no explicit splits\n splits = [{ party: 'merchant', share: 1.0 }];\n }\n\n return { aggregator, splits };\n}\n\n/**\n * Map x402 payTo.mode to PaymentEvidence.routing\n *\n * @param payToMode - x402 payTo mode value\n * @returns Valid routing value or undefined\n */\nfunction mapRouting(payToMode: string | undefined): 'direct' | 'callback' | 'role' | undefined {\n if (payToMode === 'direct' || payToMode === 'callback' || payToMode === 'role') {\n return payToMode;\n }\n return undefined;\n}\n\n/**\n * Normalize x402 invoice to PEAC PaymentEvidence\n *\n * Supports both v1 and v2 x402 formats. Default is auto-detection.\n *\n * @param invoice - x402 invoice object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromInvoice(\n invoice: X402Invoice,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!invoice.id) {\n throw new Error('x402 invoice missing id');\n }\n if (typeof invoice.amount !== 'number' || invoice.amount < 0) {\n throw new Error('x402 invoice invalid amount');\n }\n if (!invoice.currency || !/^[A-Z]{3}$/.test(invoice.currency)) {\n throw new Error('x402 invoice invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect\n const resolvedDialect = resolveDialectFromInvoice(invoice, dialect);\n\n // Normalize network (canonical ID, not label)\n const network = normalizeNetworkId(invoice.network);\n\n // Build x402-specific evidence as JsonObject (typed internally as X402Evidence structure)\n const evidence: JsonObject = {\n invoice_id: invoice.id,\n dialect: resolvedDialect,\n };\n\n // Add network label for human readability\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (invoice.session_id) {\n evidence.session_id = invoice.session_id;\n }\n if (invoice.invoice_url) {\n evidence.invoice_url = invoice.invoice_url;\n }\n if (invoice.memo) {\n evidence.memo = invoice.memo;\n }\n if (invoice.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = invoice.metadata as JsonObject;\n }\n\n // v2: Add payTo if present\n if (invoice.payTo) {\n const payTo: JsonObject = {};\n if (invoice.payTo.mode) payTo.mode = invoice.payTo.mode;\n if (invoice.payTo.callback_url) payTo.callback_url = invoice.payTo.callback_url;\n if (invoice.payTo.role) payTo.role = invoice.payTo.role;\n evidence.pay_to = payTo;\n }\n\n // Build aggregator and splits (v2 only)\n const { aggregator, splits } = buildAggregatorAndSplits(invoice, resolvedDialect);\n\n // Map routing from payTo.mode\n const routing = mapRouting(invoice.payTo?.mode);\n\n // Build PaymentEvidence\n const result: PaymentEvidence = {\n rail: 'x402',\n reference: invoice.id,\n amount: invoice.amount,\n currency: invoice.currency,\n asset: invoice.currency,\n env,\n network,\n evidence,\n };\n\n // Add optional top-level fields\n if (aggregator) {\n result.aggregator = aggregator;\n }\n if (splits) {\n result.splits = splits;\n }\n if (routing) {\n result.routing = routing;\n }\n\n return result;\n}\n\n/**\n * Normalize x402 settlement to PEAC PaymentEvidence\n *\n * @param settlement - x402 settlement object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromSettlement(\n settlement: X402Settlement,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!settlement.id) {\n throw new Error('x402 settlement missing id');\n }\n if (!settlement.invoice_id) {\n throw new Error('x402 settlement missing invoice_id');\n }\n if (typeof settlement.amount !== 'number' || settlement.amount < 0) {\n throw new Error('x402 settlement invalid amount');\n }\n if (!settlement.currency || !/^[A-Z]{3}$/.test(settlement.currency)) {\n throw new Error('x402 settlement invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect (simplified for settlements - check network field)\n const resolvedDialect =\n dialect !== 'auto' ? dialect : settlement.network?.includes(':') ? 'v2' : 'v1';\n\n // Normalize network\n const network = normalizeNetworkId(settlement.network);\n\n // Build x402-specific evidence as JsonObject\n const evidence: JsonObject = {\n invoice_id: settlement.invoice_id,\n settlement_id: settlement.id,\n dialect: resolvedDialect,\n };\n\n // Add network label\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (settlement.settled_at) {\n evidence.settled_at = settlement.settled_at;\n }\n if (settlement.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = settlement.metadata as JsonObject;\n }\n\n return {\n rail: 'x402',\n reference: settlement.invoice_id,\n amount: settlement.amount,\n currency: settlement.currency,\n asset: settlement.currency,\n env,\n network,\n evidence,\n };\n}\n\n/**\n * Normalize x402 webhook event to PEAC PaymentEvidence\n *\n * Supports:\n * - invoice.paid\n * - settlement.completed\n *\n * Dialect is auto-detected from headers if provided.\n *\n * @param event - x402 webhook event\n * @param env - Environment ('live' or 'test')\n * @param headers - HTTP response headers (optional, for dialect detection)\n * @returns Normalized PaymentEvidence\n */\nexport function fromWebhookEvent(\n event: X402WebhookEvent,\n env: 'live' | 'test' = 'live',\n headers?: Record<string, string>\n): PaymentEvidence {\n const obj = event.data.object;\n\n // Detect dialect from headers if provided\n const dialect: X402Dialect = headers ? detectDialect(headers) : 'auto';\n\n // Determine object type by presence of fields\n if ('invoice_id' in obj && ('settled_at' in obj || 'settlement_id' in (obj as X402Settlement))) {\n // Settlement\n return fromSettlement(obj as X402Settlement, env, dialect);\n } else if ('amount' in obj && 'id' in obj) {\n // Invoice\n return fromInvoice(obj as X402Invoice, env, dialect);\n }\n\n throw new Error(`Unsupported x402 webhook event type: ${event.type}`);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  import type { PaymentEvidence } from '@peac/schema';
10
10
  export * from './constants';
11
11
  export * from './types';
12
- export * from './helpers';
12
+ export { logUnknownNetworkWarning, detectDialect, resolveDialectFromInvoice, normalizeNetworkId, getNetworkLabel, getHeaders, isTestnet, } from './helpers';
13
13
  export * from './payment-headers';
14
14
  import type { X402Dialect } from './constants';
15
15
  import type { X402Invoice, X402Settlement, X402WebhookEvent } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,cAAc,CAAC;AAGlE,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA2F7E;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,GAAE,WAAoB,GAC5B,eAAe,CAoFjB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,cAAc,EAC1B,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,GAAE,WAAoB,GAC5B,eAAe,CAsDjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,gBAAgB,EACvB,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,eAAe,CAgBjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,cAAc,CAAC;AAGlE,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AAIxB,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,yBAAyB,EACzB,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,cAAc,mBAAmB,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA2F7E;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,GAAE,WAAoB,GAC5B,eAAe,CAoFjB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,cAAc,EAC1B,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,GAAE,WAAoB,GAC5B,eAAe,CAsDjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,gBAAgB,EACvB,GAAG,GAAE,MAAM,GAAG,MAAe,EAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,eAAe,CAgBjB"}
package/dist/index.mjs CHANGED
@@ -66,9 +66,6 @@ function getHeaders(dialect) {
66
66
  function isTestnet(networkId) {
67
67
  return CAIP2_REGISTRY[networkId]?.env === "testnet";
68
68
  }
69
- function _resetWarnedNetworks() {
70
- warnedNetworks.clear();
71
- }
72
69
 
73
70
  // src/payment-headers.ts
74
71
  function hasGetMethod(headers) {
@@ -281,6 +278,6 @@ function fromWebhookEvent(event, env = "live", headers) {
281
278
  throw new Error(`Unsupported x402 webhook event type: ${event.type}`);
282
279
  }
283
280
 
284
- export { CAIP2_REGISTRY, X402_HEADERS_V1, X402_HEADERS_V2, X402_V1_DEFAULT_NETWORK, _resetWarnedNetworks, detectDialect, detectPaymentRequired, extractPaymentReference, extractPaymentResponse, fromInvoice, fromSettlement, fromWebhookEvent, getHeaders, getNetworkLabel, isTestnet, logUnknownNetworkWarning, normalizeNetworkId, resolveDialectFromInvoice };
281
+ export { CAIP2_REGISTRY, X402_HEADERS_V1, X402_HEADERS_V2, X402_V1_DEFAULT_NETWORK, detectDialect, detectPaymentRequired, extractPaymentReference, extractPaymentResponse, fromInvoice, fromSettlement, fromWebhookEvent, getHeaders, getNetworkLabel, isTestnet, logUnknownNetworkWarning, normalizeNetworkId, resolveDialectFromInvoice };
285
282
  //# sourceMappingURL=index.mjs.map
286
283
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/helpers.ts","../src/payment-headers.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * x402 protocol constants and types\n *\n * Supports both x402 v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n * Default behavior is auto-detection with v1 fallback.\n */\n\n/**\n * x402 protocol dialect\n *\n * - 'v1': Legacy X-PAYMENT-* headers (pre-Dec 2025)\n * - 'v2': New Payment-* headers (Dec 2025+)\n * - 'auto': Auto-detect from response headers (default)\n */\nexport type X402Dialect = 'v1' | 'v2' | 'auto';\n\n/**\n * x402 v1 header names (legacy, pre-Dec 2025)\n */\nexport const X402_HEADERS_V1 = {\n paymentRequired: 'X-PAYMENT',\n paymentResponse: 'X-PAYMENT-RESPONSE',\n} as const;\n\n/**\n * x402 v2 header names (Dec 2025+)\n */\nexport const X402_HEADERS_V2 = {\n paymentRequired: 'Payment-Required',\n paymentSignature: 'Payment-Signature',\n paymentResponse: 'Payment-Response',\n} as const;\n\n/**\n * CAIP-2 network registry\n *\n * Maps canonical CAIP-2 identifiers to human-readable labels and environment.\n * Used for validation/logging only - network IDs are passed through unchanged.\n *\n * Reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_REGISTRY: Record<string, { label: string; env: 'mainnet' | 'testnet' }> = {\n // EVM chains\n 'eip155:8453': { label: 'Base', env: 'mainnet' },\n 'eip155:84532': { label: 'Base Sepolia', env: 'testnet' },\n 'eip155:43114': { label: 'Avalanche', env: 'mainnet' },\n 'eip155:43113': { label: 'Avalanche Fuji', env: 'testnet' },\n // Solana\n 'solana:mainnet': { label: 'Solana', env: 'mainnet' },\n 'solana:devnet': { label: 'Solana Devnet', env: 'testnet' },\n // Lightning (v1 default)\n lightning: { label: 'Lightning', env: 'mainnet' },\n};\n\n/**\n * Default network for v1 x402 (Lightning)\n */\nexport const X402_V1_DEFAULT_NETWORK = 'lightning';\n","/**\n * x402 helper functions\n *\n * Detection, normalization, and logging utilities for x402 v1/v2 support.\n */\n\nimport {\n type X402Dialect,\n X402_HEADERS_V1,\n X402_HEADERS_V2,\n CAIP2_REGISTRY,\n X402_V1_DEFAULT_NETWORK,\n} from './constants';\nimport type { X402Invoice } from './types';\n\n/**\n * Track warned networks to avoid log spam (one warning per network per process)\n */\nconst warnedNetworks = new Set<string>();\n\n/**\n * Log warning for unknown CAIP-2 network (once per network per process)\n *\n * Message is calm and informative. Does not throw.\n */\nexport function logUnknownNetworkWarning(networkId: string): void {\n if (warnedNetworks.has(networkId)) return;\n warnedNetworks.add(networkId);\n\n console.warn(`[peac:x402] Unknown CAIP-2 network \"${networkId}\", passing through as-is.`);\n}\n\n/**\n * Detect x402 dialect from HTTP response headers\n *\n * Priority: v2 headers first (case-insensitive), then v1 fallback.\n *\n * Detection rules:\n * 1. If any v2 header present (Payment-Required, Payment-Signature, Payment-Response) -> v2\n * 2. If only v1 headers present (X-PAYMENT-*) -> v1\n * 3. If no headers provided -> v1 (safe default)\n *\n * @param headers - HTTP response headers (optional)\n * @returns Detected dialect ('v1' or 'v2')\n */\nexport function detectDialect(headers?: Record<string, string>): 'v1' | 'v2' {\n if (!headers) return 'v1';\n\n const lowerHeaders = Object.keys(headers).map((k) => k.toLowerCase());\n\n // Check for v2 headers first\n const v2Headers = [\n X402_HEADERS_V2.paymentRequired.toLowerCase(),\n X402_HEADERS_V2.paymentSignature.toLowerCase(),\n X402_HEADERS_V2.paymentResponse.toLowerCase(),\n ];\n\n if (v2Headers.some((h) => lowerHeaders.includes(h))) {\n return 'v2';\n }\n\n return 'v1';\n}\n\n/**\n * Resolve dialect for invoice processing (no headers available)\n *\n * Heuristics:\n * 1. If explicit dialect is specified (not 'auto') -> use it\n * 2. If invoice.network is a CAIP-2 string (contains ':') -> v2\n * 3. If invoice.payTo is present -> v2\n * 4. Otherwise -> v1\n *\n * @param invoice - x402 invoice\n * @param explicitDialect - Explicit dialect from config\n * @returns Resolved dialect ('v1' or 'v2')\n */\nexport function resolveDialectFromInvoice(\n invoice: X402Invoice,\n explicitDialect: X402Dialect\n): 'v1' | 'v2' {\n if (explicitDialect !== 'auto') {\n return explicitDialect;\n }\n\n // v2 indicators\n if (invoice.network && invoice.network.includes(':')) return 'v2';\n if (invoice.payTo) return 'v2';\n\n return 'v1';\n}\n\n/**\n * Normalize network ID (returns canonical ID, not label)\n *\n * Behavior:\n * - Missing input -> \"lightning\" (v1 default)\n * - Known CAIP-2 -> return as-is\n * - Unknown -> log warning, return as-is (no throw)\n *\n * Key rule: NO lossy mapping. The canonical ID is always preserved.\n *\n * @param caip2 - CAIP-2 network identifier (optional)\n * @returns Canonical network ID\n */\nexport function normalizeNetworkId(caip2: string | undefined): string {\n if (!caip2) return X402_V1_DEFAULT_NETWORK;\n\n if (!(caip2 in CAIP2_REGISTRY)) {\n logUnknownNetworkWarning(caip2);\n }\n\n return caip2; // Always return the canonical ID unchanged\n}\n\n/**\n * Get human-readable label for network (for evidence.network_label)\n *\n * @param caip2 - CAIP-2 network identifier\n * @returns Human-readable label, or undefined for unknown networks\n */\nexport function getNetworkLabel(caip2: string): string | undefined {\n return CAIP2_REGISTRY[caip2]?.label;\n}\n\n/**\n * Get header names for a specific dialect\n *\n * @param dialect - 'v1' or 'v2'\n * @returns Header name mapping\n */\nexport function getHeaders(dialect: 'v1' | 'v2'): typeof X402_HEADERS_V1 | typeof X402_HEADERS_V2 {\n return dialect === 'v2' ? X402_HEADERS_V2 : X402_HEADERS_V1;\n}\n\n/**\n * Check if a network ID indicates testnet environment\n *\n * @param networkId - CAIP-2 network identifier\n * @returns true if testnet, false otherwise\n */\nexport function isTestnet(networkId: string): boolean {\n return CAIP2_REGISTRY[networkId]?.env === 'testnet';\n}\n\n/**\n * Clear warned networks set (for testing)\n */\nexport function _resetWarnedNetworks(): void {\n warnedNetworks.clear();\n}\n","/**\n * x402 Payment Header Detection (Headers-Only)\n *\n * Provides minimal headers-only detection and extraction for x402 payment flow.\n * No Response objects, no body parsing.\n *\n * x402 Header Names (per Coinbase x402 spec):\n * - PAYMENT-REQUIRED: Server challenge with payment details\n * - PAYMENT-SIGNATURE: Client payment proof\n * - PAYMENT-RESPONSE: Server success response\n */\n\n/**\n * Headers-like object with .get() method.\n * Compatible with native Headers, node-fetch, undici, etc.\n */\nexport interface HeadersWithGet {\n get(name: string): string | null;\n}\n\n/**\n * Plain header object (Node.js/Express IncomingHttpHeaders style).\n * Values can be string, string[], or undefined.\n */\nexport type HeadersPlainObject = Record<string, string | string[] | undefined>;\n\n/**\n * Union type accepting both Headers-like objects and plain objects.\n * Works with:\n * - Native Headers (browser, Cloudflare Workers, Deno)\n * - node-fetch, undici Headers\n * - Express/Node.js req.headers (IncomingHttpHeaders)\n * - Plain objects\n */\nexport type HeadersLike = HeadersWithGet | HeadersPlainObject;\n\n/**\n * Check if headers object has a .get() method.\n */\nfunction hasGetMethod(headers: HeadersLike): headers is HeadersWithGet {\n return typeof (headers as HeadersWithGet).get === 'function';\n}\n\n/**\n * Get header value from plain object, handling case-insensitivity and arrays.\n * Node.js lowercases all header names, so we check multiple casings.\n */\nfunction getFromPlainObject(headers: HeadersPlainObject, name: string): string | null {\n // Common casings to try\n const casings = [\n name.toLowerCase(),\n name.toUpperCase(),\n name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-'),\n ];\n\n for (const key of casings) {\n const value = headers[key];\n if (value !== undefined) {\n // Handle array values (take first element)\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n\n // Also try exact match and iterate all keys for case-insensitive match\n const lowerName = name.toLowerCase();\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lowerName) {\n const value = headers[key];\n if (value !== undefined) {\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Case-insensitive header getter helper.\n * Handles both Headers-like objects (.get() method) and plain objects.\n *\n * @param headers - Headers object or plain object to query\n * @param name - Header name to look up\n * @returns Header value or null if not found\n */\nfunction getHeaderCaseInsensitive(headers: HeadersLike, name: string): string | null {\n if (hasGetMethod(headers)) {\n // Use .get() method - most Headers implementations are case-insensitive\n // but we try multiple casings for implementations that aren't\n const lower = headers.get(name.toLowerCase());\n if (lower !== null) return lower;\n\n const titleCase = name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-');\n const title = headers.get(titleCase);\n if (title !== null) return title;\n\n const upper = headers.get(name.toUpperCase());\n if (upper !== null) return upper;\n\n return null;\n }\n\n // Plain object path\n return getFromPlainObject(headers, name);\n}\n\n/**\n * Detect payment-required mode from HTTP headers.\n * Uses case-insensitive lookup and trims whitespace.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns true if PAYMENT-REQUIRED header is present and non-empty\n */\nexport function detectPaymentRequired(headers: HeadersLike): boolean {\n const paymentRequired = getHeaderCaseInsensitive(headers, 'payment-required');\n return paymentRequired !== null && paymentRequired.trim().length > 0;\n}\n\n/**\n * Extract payment reference from HTTP headers.\n * Returns the PAYMENT-REQUIRED header value (contains payment details).\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-REQUIRED header value, or undefined if not present/empty\n */\nexport function extractPaymentReference(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-required');\n return value?.trim() || undefined;\n}\n\n/**\n * Extract payment response from success headers.\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-RESPONSE header value, or undefined if not present/empty\n */\nexport function extractPaymentResponse(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-response');\n return value?.trim() || undefined;\n}\n","/**\n * x402 payment rail adapter\n *\n * Normalizes x402 invoices/settlements to PEAC PaymentEvidence.\n * Supports both v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n *\n * Default behavior is auto-detection with v1 fallback for backwards compatibility.\n */\n\nimport type { JsonObject } from '@peac/kernel';\nimport type { PaymentEvidence, PaymentSplit } from '@peac/schema';\n\n// Re-export types and constants for consumers\nexport * from './constants';\nexport * from './types';\nexport * from './helpers';\nexport * from './payment-headers';\n\nimport type { X402Dialect } from './constants';\nimport type { X402Invoice, X402Settlement, X402WebhookEvent } from './types';\nimport {\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n} from './helpers';\n\n/**\n * Build aggregator and splits from x402 invoice metadata\n *\n * Mapping rules:\n * - aggregator: Set when invoice has platform/aggregator in metadata\n * - Pattern: \"x402:{serviceName}\" (e.g., \"x402:load\", \"x402:tollbit\")\n * - splits: Mapped from explicit split data, or single merchant split if aggregator known\n * - If no split data and no aggregator -> undefined\n *\n * @param invoice - x402 invoice\n * @param resolvedDialect - Resolved dialect\n * @returns Object with optional aggregator and splits\n */\nfunction buildAggregatorAndSplits(\n invoice: X402Invoice,\n resolvedDialect: 'v1' | 'v2'\n): { aggregator?: string; splits?: PaymentSplit[] } {\n // Only attempt aggregator/splits for v2 (v1 has no such concept)\n if (resolvedDialect === 'v1') {\n return {};\n }\n\n let aggregator: string | undefined;\n let splits: PaymentSplit[] | undefined;\n\n // Detect aggregator from invoice metadata or known patterns\n const meta = invoice.metadata;\n if (meta?.aggregator && typeof meta.aggregator === 'string') {\n aggregator = `x402:${meta.aggregator}`;\n } else if (meta?.platform && typeof meta.platform === 'string') {\n aggregator = `x402:${meta.platform}`;\n }\n\n // Build splits if we have explicit split data\n if (meta?.splits && Array.isArray(meta.splits)) {\n const rawSplits = meta.splits as Array<Record<string, unknown>>;\n splits = rawSplits\n .map((s) => {\n const party = s.party as string | undefined;\n const amount = s.amount as number | undefined;\n const share = s.share as number | undefined;\n\n // Validate: party required, at least one of amount/share\n if (!party || (amount === undefined && share === undefined)) {\n return null;\n }\n\n const split: PaymentSplit = { party };\n if (amount !== undefined) split.amount = amount;\n if (share !== undefined) split.share = share;\n if (s.currency) split.currency = s.currency as string;\n if (s.rail) split.rail = s.rail as string;\n if (s.account_ref) split.account_ref = s.account_ref as string;\n\n return split;\n })\n .filter((s): s is PaymentSplit => s !== null);\n\n // If no valid splits after filtering, set to undefined\n if (splits.length === 0) {\n splits = undefined;\n }\n } else if (aggregator) {\n // Single split for merchant when aggregator is known but no explicit splits\n splits = [{ party: 'merchant', share: 1.0 }];\n }\n\n return { aggregator, splits };\n}\n\n/**\n * Map x402 payTo.mode to PaymentEvidence.routing\n *\n * @param payToMode - x402 payTo mode value\n * @returns Valid routing value or undefined\n */\nfunction mapRouting(payToMode: string | undefined): 'direct' | 'callback' | 'role' | undefined {\n if (payToMode === 'direct' || payToMode === 'callback' || payToMode === 'role') {\n return payToMode;\n }\n return undefined;\n}\n\n/**\n * Normalize x402 invoice to PEAC PaymentEvidence\n *\n * Supports both v1 and v2 x402 formats. Default is auto-detection.\n *\n * @param invoice - x402 invoice object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromInvoice(\n invoice: X402Invoice,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!invoice.id) {\n throw new Error('x402 invoice missing id');\n }\n if (typeof invoice.amount !== 'number' || invoice.amount < 0) {\n throw new Error('x402 invoice invalid amount');\n }\n if (!invoice.currency || !/^[A-Z]{3}$/.test(invoice.currency)) {\n throw new Error('x402 invoice invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect\n const resolvedDialect = resolveDialectFromInvoice(invoice, dialect);\n\n // Normalize network (canonical ID, not label)\n const network = normalizeNetworkId(invoice.network);\n\n // Build x402-specific evidence as JsonObject (typed internally as X402Evidence structure)\n const evidence: JsonObject = {\n invoice_id: invoice.id,\n dialect: resolvedDialect,\n };\n\n // Add network label for human readability\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (invoice.session_id) {\n evidence.session_id = invoice.session_id;\n }\n if (invoice.invoice_url) {\n evidence.invoice_url = invoice.invoice_url;\n }\n if (invoice.memo) {\n evidence.memo = invoice.memo;\n }\n if (invoice.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = invoice.metadata as JsonObject;\n }\n\n // v2: Add payTo if present\n if (invoice.payTo) {\n const payTo: JsonObject = {};\n if (invoice.payTo.mode) payTo.mode = invoice.payTo.mode;\n if (invoice.payTo.callback_url) payTo.callback_url = invoice.payTo.callback_url;\n if (invoice.payTo.role) payTo.role = invoice.payTo.role;\n evidence.pay_to = payTo;\n }\n\n // Build aggregator and splits (v2 only)\n const { aggregator, splits } = buildAggregatorAndSplits(invoice, resolvedDialect);\n\n // Map routing from payTo.mode\n const routing = mapRouting(invoice.payTo?.mode);\n\n // Build PaymentEvidence\n const result: PaymentEvidence = {\n rail: 'x402',\n reference: invoice.id,\n amount: invoice.amount,\n currency: invoice.currency,\n asset: invoice.currency,\n env,\n network,\n evidence,\n };\n\n // Add optional top-level fields\n if (aggregator) {\n result.aggregator = aggregator;\n }\n if (splits) {\n result.splits = splits;\n }\n if (routing) {\n result.routing = routing;\n }\n\n return result;\n}\n\n/**\n * Normalize x402 settlement to PEAC PaymentEvidence\n *\n * @param settlement - x402 settlement object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromSettlement(\n settlement: X402Settlement,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!settlement.id) {\n throw new Error('x402 settlement missing id');\n }\n if (!settlement.invoice_id) {\n throw new Error('x402 settlement missing invoice_id');\n }\n if (typeof settlement.amount !== 'number' || settlement.amount < 0) {\n throw new Error('x402 settlement invalid amount');\n }\n if (!settlement.currency || !/^[A-Z]{3}$/.test(settlement.currency)) {\n throw new Error('x402 settlement invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect (simplified for settlements - check network field)\n const resolvedDialect =\n dialect !== 'auto' ? dialect : settlement.network?.includes(':') ? 'v2' : 'v1';\n\n // Normalize network\n const network = normalizeNetworkId(settlement.network);\n\n // Build x402-specific evidence as JsonObject\n const evidence: JsonObject = {\n invoice_id: settlement.invoice_id,\n settlement_id: settlement.id,\n dialect: resolvedDialect,\n };\n\n // Add network label\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (settlement.settled_at) {\n evidence.settled_at = settlement.settled_at;\n }\n if (settlement.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = settlement.metadata as JsonObject;\n }\n\n return {\n rail: 'x402',\n reference: settlement.invoice_id,\n amount: settlement.amount,\n currency: settlement.currency,\n asset: settlement.currency,\n env,\n network,\n evidence,\n };\n}\n\n/**\n * Normalize x402 webhook event to PEAC PaymentEvidence\n *\n * Supports:\n * - invoice.paid\n * - settlement.completed\n *\n * Dialect is auto-detected from headers if provided.\n *\n * @param event - x402 webhook event\n * @param env - Environment ('live' or 'test')\n * @param headers - HTTP response headers (optional, for dialect detection)\n * @returns Normalized PaymentEvidence\n */\nexport function fromWebhookEvent(\n event: X402WebhookEvent,\n env: 'live' | 'test' = 'live',\n headers?: Record<string, string>\n): PaymentEvidence {\n const obj = event.data.object;\n\n // Detect dialect from headers if provided\n const dialect: X402Dialect = headers ? detectDialect(headers) : 'auto';\n\n // Determine object type by presence of fields\n if ('invoice_id' in obj && ('settled_at' in obj || 'settlement_id' in (obj as X402Settlement))) {\n // Settlement\n return fromSettlement(obj as X402Settlement, env, dialect);\n } else if ('amount' in obj && 'id' in obj) {\n // Invoice\n return fromInvoice(obj as X402Invoice, env, dialect);\n }\n\n throw new Error(`Unsupported x402 webhook event type: ${event.type}`);\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/helpers.ts","../src/payment-headers.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * x402 protocol constants and types\n *\n * Supports both x402 v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n * Default behavior is auto-detection with v1 fallback.\n */\n\n/**\n * x402 protocol dialect\n *\n * - 'v1': Legacy X-PAYMENT-* headers (pre-Dec 2025)\n * - 'v2': New Payment-* headers (Dec 2025+)\n * - 'auto': Auto-detect from response headers (default)\n */\nexport type X402Dialect = 'v1' | 'v2' | 'auto';\n\n/**\n * x402 v1 header names (legacy, pre-Dec 2025)\n */\nexport const X402_HEADERS_V1 = {\n paymentRequired: 'X-PAYMENT',\n paymentResponse: 'X-PAYMENT-RESPONSE',\n} as const;\n\n/**\n * x402 v2 header names (Dec 2025+)\n */\nexport const X402_HEADERS_V2 = {\n paymentRequired: 'Payment-Required',\n paymentSignature: 'Payment-Signature',\n paymentResponse: 'Payment-Response',\n} as const;\n\n/**\n * CAIP-2 network registry\n *\n * Maps canonical CAIP-2 identifiers to human-readable labels and environment.\n * Used for validation/logging only - network IDs are passed through unchanged.\n *\n * Reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_REGISTRY: Record<string, { label: string; env: 'mainnet' | 'testnet' }> = {\n // EVM chains\n 'eip155:8453': { label: 'Base', env: 'mainnet' },\n 'eip155:84532': { label: 'Base Sepolia', env: 'testnet' },\n 'eip155:43114': { label: 'Avalanche', env: 'mainnet' },\n 'eip155:43113': { label: 'Avalanche Fuji', env: 'testnet' },\n // Solana\n 'solana:mainnet': { label: 'Solana', env: 'mainnet' },\n 'solana:devnet': { label: 'Solana Devnet', env: 'testnet' },\n // Lightning (v1 default)\n lightning: { label: 'Lightning', env: 'mainnet' },\n};\n\n/**\n * Default network for v1 x402 (Lightning)\n */\nexport const X402_V1_DEFAULT_NETWORK = 'lightning';\n","/**\n * x402 helper functions\n *\n * Detection, normalization, and logging utilities for x402 v1/v2 support.\n */\n\nimport {\n type X402Dialect,\n X402_HEADERS_V1,\n X402_HEADERS_V2,\n CAIP2_REGISTRY,\n X402_V1_DEFAULT_NETWORK,\n} from './constants';\nimport type { X402Invoice } from './types';\n\n/**\n * Track warned networks to avoid log spam (one warning per network per process)\n */\nconst warnedNetworks = new Set<string>();\n\n/**\n * Log warning for unknown CAIP-2 network (once per network per process)\n *\n * Message is calm and informative. Does not throw.\n */\nexport function logUnknownNetworkWarning(networkId: string): void {\n if (warnedNetworks.has(networkId)) return;\n warnedNetworks.add(networkId);\n\n console.warn(`[peac:x402] Unknown CAIP-2 network \"${networkId}\", passing through as-is.`);\n}\n\n/**\n * Detect x402 dialect from HTTP response headers\n *\n * Priority: v2 headers first (case-insensitive), then v1 fallback.\n *\n * Detection rules:\n * 1. If any v2 header present (Payment-Required, Payment-Signature, Payment-Response) -> v2\n * 2. If only v1 headers present (X-PAYMENT-*) -> v1\n * 3. If no headers provided -> v1 (safe default)\n *\n * @param headers - HTTP response headers (optional)\n * @returns Detected dialect ('v1' or 'v2')\n */\nexport function detectDialect(headers?: Record<string, string>): 'v1' | 'v2' {\n if (!headers) return 'v1';\n\n const lowerHeaders = Object.keys(headers).map((k) => k.toLowerCase());\n\n // Check for v2 headers first\n const v2Headers = [\n X402_HEADERS_V2.paymentRequired.toLowerCase(),\n X402_HEADERS_V2.paymentSignature.toLowerCase(),\n X402_HEADERS_V2.paymentResponse.toLowerCase(),\n ];\n\n if (v2Headers.some((h) => lowerHeaders.includes(h))) {\n return 'v2';\n }\n\n return 'v1';\n}\n\n/**\n * Resolve dialect for invoice processing (no headers available)\n *\n * Heuristics:\n * 1. If explicit dialect is specified (not 'auto') -> use it\n * 2. If invoice.network is a CAIP-2 string (contains ':') -> v2\n * 3. If invoice.payTo is present -> v2\n * 4. Otherwise -> v1\n *\n * @param invoice - x402 invoice\n * @param explicitDialect - Explicit dialect from config\n * @returns Resolved dialect ('v1' or 'v2')\n */\nexport function resolveDialectFromInvoice(\n invoice: X402Invoice,\n explicitDialect: X402Dialect\n): 'v1' | 'v2' {\n if (explicitDialect !== 'auto') {\n return explicitDialect;\n }\n\n // v2 indicators\n if (invoice.network && invoice.network.includes(':')) return 'v2';\n if (invoice.payTo) return 'v2';\n\n return 'v1';\n}\n\n/**\n * Normalize network ID (returns canonical ID, not label)\n *\n * Behavior:\n * - Missing input -> \"lightning\" (v1 default)\n * - Known CAIP-2 -> return as-is\n * - Unknown -> log warning, return as-is (no throw)\n *\n * Key rule: NO lossy mapping. The canonical ID is always preserved.\n *\n * @param caip2 - CAIP-2 network identifier (optional)\n * @returns Canonical network ID\n */\nexport function normalizeNetworkId(caip2: string | undefined): string {\n if (!caip2) return X402_V1_DEFAULT_NETWORK;\n\n if (!(caip2 in CAIP2_REGISTRY)) {\n logUnknownNetworkWarning(caip2);\n }\n\n return caip2; // Always return the canonical ID unchanged\n}\n\n/**\n * Get human-readable label for network (for evidence.network_label)\n *\n * @param caip2 - CAIP-2 network identifier\n * @returns Human-readable label, or undefined for unknown networks\n */\nexport function getNetworkLabel(caip2: string): string | undefined {\n return CAIP2_REGISTRY[caip2]?.label;\n}\n\n/**\n * Get header names for a specific dialect\n *\n * @param dialect - 'v1' or 'v2'\n * @returns Header name mapping\n */\nexport function getHeaders(dialect: 'v1' | 'v2'): typeof X402_HEADERS_V1 | typeof X402_HEADERS_V2 {\n return dialect === 'v2' ? X402_HEADERS_V2 : X402_HEADERS_V1;\n}\n\n/**\n * Check if a network ID indicates testnet environment\n *\n * @param networkId - CAIP-2 network identifier\n * @returns true if testnet, false otherwise\n */\nexport function isTestnet(networkId: string): boolean {\n return CAIP2_REGISTRY[networkId]?.env === 'testnet';\n}\n\n/**\n * Clear warned networks set (for testing).\n * @internal Package-internal test hook; not part of the public API.\n */\nexport function _resetWarnedNetworks(): void {\n warnedNetworks.clear();\n}\n","/**\n * x402 Payment Header Detection (Headers-Only)\n *\n * Provides minimal headers-only detection and extraction for x402 payment flow.\n * No Response objects, no body parsing.\n *\n * x402 Header Names (per Coinbase x402 spec):\n * - PAYMENT-REQUIRED: Server challenge with payment details\n * - PAYMENT-SIGNATURE: Client payment proof\n * - PAYMENT-RESPONSE: Server success response\n */\n\n/**\n * Headers-like object with .get() method.\n * Compatible with native Headers, node-fetch, undici, etc.\n */\nexport interface HeadersWithGet {\n get(name: string): string | null;\n}\n\n/**\n * Plain header object (Node.js/Express IncomingHttpHeaders style).\n * Values can be string, string[], or undefined.\n */\nexport type HeadersPlainObject = Record<string, string | string[] | undefined>;\n\n/**\n * Union type accepting both Headers-like objects and plain objects.\n * Works with:\n * - Native Headers (browser, Cloudflare Workers, Deno)\n * - node-fetch, undici Headers\n * - Express/Node.js req.headers (IncomingHttpHeaders)\n * - Plain objects\n */\nexport type HeadersLike = HeadersWithGet | HeadersPlainObject;\n\n/**\n * Check if headers object has a .get() method.\n */\nfunction hasGetMethod(headers: HeadersLike): headers is HeadersWithGet {\n return typeof (headers as HeadersWithGet).get === 'function';\n}\n\n/**\n * Get header value from plain object, handling case-insensitivity and arrays.\n * Node.js lowercases all header names, so we check multiple casings.\n */\nfunction getFromPlainObject(headers: HeadersPlainObject, name: string): string | null {\n // Common casings to try\n const casings = [\n name.toLowerCase(),\n name.toUpperCase(),\n name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-'),\n ];\n\n for (const key of casings) {\n const value = headers[key];\n if (value !== undefined) {\n // Handle array values (take first element)\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n\n // Also try exact match and iterate all keys for case-insensitive match\n const lowerName = name.toLowerCase();\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === lowerName) {\n const value = headers[key];\n if (value !== undefined) {\n return Array.isArray(value) ? (value[0] ?? null) : value;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Case-insensitive header getter helper.\n * Handles both Headers-like objects (.get() method) and plain objects.\n *\n * @param headers - Headers object or plain object to query\n * @param name - Header name to look up\n * @returns Header value or null if not found\n */\nfunction getHeaderCaseInsensitive(headers: HeadersLike, name: string): string | null {\n if (hasGetMethod(headers)) {\n // Use .get() method - most Headers implementations are case-insensitive\n // but we try multiple casings for implementations that aren't\n const lower = headers.get(name.toLowerCase());\n if (lower !== null) return lower;\n\n const titleCase = name\n .split('-')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('-');\n const title = headers.get(titleCase);\n if (title !== null) return title;\n\n const upper = headers.get(name.toUpperCase());\n if (upper !== null) return upper;\n\n return null;\n }\n\n // Plain object path\n return getFromPlainObject(headers, name);\n}\n\n/**\n * Detect payment-required mode from HTTP headers.\n * Uses case-insensitive lookup and trims whitespace.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns true if PAYMENT-REQUIRED header is present and non-empty\n */\nexport function detectPaymentRequired(headers: HeadersLike): boolean {\n const paymentRequired = getHeaderCaseInsensitive(headers, 'payment-required');\n return paymentRequired !== null && paymentRequired.trim().length > 0;\n}\n\n/**\n * Extract payment reference from HTTP headers.\n * Returns the PAYMENT-REQUIRED header value (contains payment details).\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-REQUIRED header value, or undefined if not present/empty\n */\nexport function extractPaymentReference(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-required');\n return value?.trim() || undefined;\n}\n\n/**\n * Extract payment response from success headers.\n * Uses case-insensitive lookup.\n *\n * @param headers - HTTP headers (HeadersLike interface)\n * @returns PAYMENT-RESPONSE header value, or undefined if not present/empty\n */\nexport function extractPaymentResponse(headers: HeadersLike): string | undefined {\n const value = getHeaderCaseInsensitive(headers, 'payment-response');\n return value?.trim() || undefined;\n}\n","/**\n * x402 payment rail adapter\n *\n * Normalizes x402 invoices/settlements to PEAC PaymentEvidence.\n * Supports both v1 (legacy X-PAYMENT-* headers) and v2 (Payment-* headers).\n *\n * Default behavior is auto-detection with v1 fallback for backwards compatibility.\n */\n\nimport type { JsonObject } from '@peac/kernel';\nimport type { PaymentEvidence, PaymentSplit } from '@peac/schema';\n\n// Re-export types and constants for consumers\nexport * from './constants';\nexport * from './types';\n// Re-export the public helpers explicitly; the internal test reset hook\n// (_resetWarnedNetworks) is intentionally NOT part of the public API\n// (import it from './helpers' inside the package's own tests).\nexport {\n logUnknownNetworkWarning,\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n getHeaders,\n isTestnet,\n} from './helpers';\nexport * from './payment-headers';\n\nimport type { X402Dialect } from './constants';\nimport type { X402Invoice, X402Settlement, X402WebhookEvent } from './types';\nimport {\n detectDialect,\n resolveDialectFromInvoice,\n normalizeNetworkId,\n getNetworkLabel,\n} from './helpers';\n\n/**\n * Build aggregator and splits from x402 invoice metadata\n *\n * Mapping rules:\n * - aggregator: Set when invoice has platform/aggregator in metadata\n * - Pattern: \"x402:{serviceName}\" (e.g., \"x402:load\", \"x402:tollbit\")\n * - splits: Mapped from explicit split data, or single merchant split if aggregator known\n * - If no split data and no aggregator -> undefined\n *\n * @param invoice - x402 invoice\n * @param resolvedDialect - Resolved dialect\n * @returns Object with optional aggregator and splits\n */\nfunction buildAggregatorAndSplits(\n invoice: X402Invoice,\n resolvedDialect: 'v1' | 'v2'\n): { aggregator?: string; splits?: PaymentSplit[] } {\n // Only attempt aggregator/splits for v2 (v1 has no such concept)\n if (resolvedDialect === 'v1') {\n return {};\n }\n\n let aggregator: string | undefined;\n let splits: PaymentSplit[] | undefined;\n\n // Detect aggregator from invoice metadata or known patterns\n const meta = invoice.metadata;\n if (meta?.aggregator && typeof meta.aggregator === 'string') {\n aggregator = `x402:${meta.aggregator}`;\n } else if (meta?.platform && typeof meta.platform === 'string') {\n aggregator = `x402:${meta.platform}`;\n }\n\n // Build splits if we have explicit split data\n if (meta?.splits && Array.isArray(meta.splits)) {\n const rawSplits = meta.splits as Array<Record<string, unknown>>;\n splits = rawSplits\n .map((s) => {\n const party = s.party as string | undefined;\n const amount = s.amount as number | undefined;\n const share = s.share as number | undefined;\n\n // Validate: party required, at least one of amount/share\n if (!party || (amount === undefined && share === undefined)) {\n return null;\n }\n\n const split: PaymentSplit = { party };\n if (amount !== undefined) split.amount = amount;\n if (share !== undefined) split.share = share;\n if (s.currency) split.currency = s.currency as string;\n if (s.rail) split.rail = s.rail as string;\n if (s.account_ref) split.account_ref = s.account_ref as string;\n\n return split;\n })\n .filter((s): s is PaymentSplit => s !== null);\n\n // If no valid splits after filtering, set to undefined\n if (splits.length === 0) {\n splits = undefined;\n }\n } else if (aggregator) {\n // Single split for merchant when aggregator is known but no explicit splits\n splits = [{ party: 'merchant', share: 1.0 }];\n }\n\n return { aggregator, splits };\n}\n\n/**\n * Map x402 payTo.mode to PaymentEvidence.routing\n *\n * @param payToMode - x402 payTo mode value\n * @returns Valid routing value or undefined\n */\nfunction mapRouting(payToMode: string | undefined): 'direct' | 'callback' | 'role' | undefined {\n if (payToMode === 'direct' || payToMode === 'callback' || payToMode === 'role') {\n return payToMode;\n }\n return undefined;\n}\n\n/**\n * Normalize x402 invoice to PEAC PaymentEvidence\n *\n * Supports both v1 and v2 x402 formats. Default is auto-detection.\n *\n * @param invoice - x402 invoice object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromInvoice(\n invoice: X402Invoice,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!invoice.id) {\n throw new Error('x402 invoice missing id');\n }\n if (typeof invoice.amount !== 'number' || invoice.amount < 0) {\n throw new Error('x402 invoice invalid amount');\n }\n if (!invoice.currency || !/^[A-Z]{3}$/.test(invoice.currency)) {\n throw new Error('x402 invoice invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect\n const resolvedDialect = resolveDialectFromInvoice(invoice, dialect);\n\n // Normalize network (canonical ID, not label)\n const network = normalizeNetworkId(invoice.network);\n\n // Build x402-specific evidence as JsonObject (typed internally as X402Evidence structure)\n const evidence: JsonObject = {\n invoice_id: invoice.id,\n dialect: resolvedDialect,\n };\n\n // Add network label for human readability\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (invoice.session_id) {\n evidence.session_id = invoice.session_id;\n }\n if (invoice.invoice_url) {\n evidence.invoice_url = invoice.invoice_url;\n }\n if (invoice.memo) {\n evidence.memo = invoice.memo;\n }\n if (invoice.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = invoice.metadata as JsonObject;\n }\n\n // v2: Add payTo if present\n if (invoice.payTo) {\n const payTo: JsonObject = {};\n if (invoice.payTo.mode) payTo.mode = invoice.payTo.mode;\n if (invoice.payTo.callback_url) payTo.callback_url = invoice.payTo.callback_url;\n if (invoice.payTo.role) payTo.role = invoice.payTo.role;\n evidence.pay_to = payTo;\n }\n\n // Build aggregator and splits (v2 only)\n const { aggregator, splits } = buildAggregatorAndSplits(invoice, resolvedDialect);\n\n // Map routing from payTo.mode\n const routing = mapRouting(invoice.payTo?.mode);\n\n // Build PaymentEvidence\n const result: PaymentEvidence = {\n rail: 'x402',\n reference: invoice.id,\n amount: invoice.amount,\n currency: invoice.currency,\n asset: invoice.currency,\n env,\n network,\n evidence,\n };\n\n // Add optional top-level fields\n if (aggregator) {\n result.aggregator = aggregator;\n }\n if (splits) {\n result.splits = splits;\n }\n if (routing) {\n result.routing = routing;\n }\n\n return result;\n}\n\n/**\n * Normalize x402 settlement to PEAC PaymentEvidence\n *\n * @param settlement - x402 settlement object\n * @param env - Environment ('live' or 'test')\n * @param dialect - x402 dialect ('v1', 'v2', or 'auto')\n * @returns Normalized PaymentEvidence\n */\nexport function fromSettlement(\n settlement: X402Settlement,\n env: 'live' | 'test' = 'live',\n dialect: X402Dialect = 'auto'\n): PaymentEvidence {\n // Validate required fields\n if (!settlement.id) {\n throw new Error('x402 settlement missing id');\n }\n if (!settlement.invoice_id) {\n throw new Error('x402 settlement missing invoice_id');\n }\n if (typeof settlement.amount !== 'number' || settlement.amount < 0) {\n throw new Error('x402 settlement invalid amount');\n }\n if (!settlement.currency || !/^[A-Z]{3}$/.test(settlement.currency)) {\n throw new Error('x402 settlement invalid currency (must be uppercase ISO 4217)');\n }\n\n // Resolve dialect (simplified for settlements - check network field)\n const resolvedDialect =\n dialect !== 'auto' ? dialect : settlement.network?.includes(':') ? 'v2' : 'v1';\n\n // Normalize network\n const network = normalizeNetworkId(settlement.network);\n\n // Build x402-specific evidence as JsonObject\n const evidence: JsonObject = {\n invoice_id: settlement.invoice_id,\n settlement_id: settlement.id,\n dialect: resolvedDialect,\n };\n\n // Add network label\n const networkLabel = getNetworkLabel(network);\n if (networkLabel) {\n evidence.network_label = networkLabel;\n }\n\n // Add optional fields\n if (settlement.settled_at) {\n evidence.settled_at = settlement.settled_at;\n }\n if (settlement.metadata) {\n // Cast metadata to JsonObject (Record<string, unknown> -> JsonObject)\n evidence.metadata = settlement.metadata as JsonObject;\n }\n\n return {\n rail: 'x402',\n reference: settlement.invoice_id,\n amount: settlement.amount,\n currency: settlement.currency,\n asset: settlement.currency,\n env,\n network,\n evidence,\n };\n}\n\n/**\n * Normalize x402 webhook event to PEAC PaymentEvidence\n *\n * Supports:\n * - invoice.paid\n * - settlement.completed\n *\n * Dialect is auto-detected from headers if provided.\n *\n * @param event - x402 webhook event\n * @param env - Environment ('live' or 'test')\n * @param headers - HTTP response headers (optional, for dialect detection)\n * @returns Normalized PaymentEvidence\n */\nexport function fromWebhookEvent(\n event: X402WebhookEvent,\n env: 'live' | 'test' = 'live',\n headers?: Record<string, string>\n): PaymentEvidence {\n const obj = event.data.object;\n\n // Detect dialect from headers if provided\n const dialect: X402Dialect = headers ? detectDialect(headers) : 'auto';\n\n // Determine object type by presence of fields\n if ('invoice_id' in obj && ('settled_at' in obj || 'settlement_id' in (obj as X402Settlement))) {\n // Settlement\n return fromSettlement(obj as X402Settlement, env, dialect);\n } else if ('amount' in obj && 'id' in obj) {\n // Invoice\n return fromInvoice(obj as X402Invoice, env, dialect);\n }\n\n throw new Error(`Unsupported x402 webhook event type: ${event.type}`);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peac/rails-x402",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "x402 payment rail adapter for PEAC protocol",
5
5
  "main": "dist/index.cjs",
6
6
  "types": "dist/index.d.ts",
@@ -23,13 +23,13 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@peac/kernel": "0.15.0",
27
- "@peac/schema": "0.15.0"
26
+ "@peac/schema": "0.15.2",
27
+ "@peac/kernel": "0.15.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.19.11",
31
31
  "typescript": "^5.3.3",
32
- "vitest": "^4.0.0",
32
+ "vitest": "^4.1.0",
33
33
  "tsup": "^8.0.0"
34
34
  },
35
35
  "exports": {