UNPKG

@x402-hpke/node

Version:

Provider-agnostic HPKE envelope library for x402 (Node) — cross-language interop with Python

67 lines (66 loc) 2.45 kB
export function isXPayment(obj) { return obj && typeof obj === "object" && obj.payload && typeof obj.payload.signature === "string" && obj.authorization === undefined; } export function isXPaymentResponse(obj) { return obj && typeof obj === "object" && obj.payload && typeof obj.payload === "object" && obj.payload.signature === undefined; } export function normalizePaymentLike(input) { // Minimal structural checks; leave deep validation to integrators for now if (!input || typeof input !== "object") throw new Error("X_PAYMENT_SCHEMA"); if (input.x402Version !== 1) throw new Error("X_PAYMENT_VERSION"); if (!input.scheme || typeof input.scheme !== "string") throw new Error("X_PAYMENT_SCHEMA"); if (!input.network || typeof input.network !== "string") throw new Error("X_PAYMENT_SCHEMA"); if (!input.payload || typeof input.payload !== "object") throw new Error("X_PAYMENT_SCHEMA"); return input; } function deepCanonicalize(obj) { if (obj === null || typeof obj !== "object") return obj; if (Array.isArray(obj)) return obj.map(deepCanonicalize); const keys = Object.keys(obj).sort(); const out = {}; for (const k of keys) out[k] = deepCanonicalize(obj[k]); return out; } export function synthesizePaymentHeaderValue(p) { // Emit compact, stable JSON string (header value is JSON per x402 examples) return JSON.stringify(deepCanonicalize(p)); } export function parsePaymentHeaderValue(s) { // Accept either raw JSON or base64-encoded JSON (be liberal in what we accept) try { const j = JSON.parse(s); return normalizePaymentLike(j); } catch (_) { try { const dec = Buffer.from(s, "base64").toString("utf8"); const j2 = JSON.parse(dec); return normalizePaymentLike(j2); } catch { return null; } } } export function deriveExtendedAppFromPayment(p) { const a = p.payload.authorization; return { paymentScheme: String(p.scheme), paymentNetwork: String(p.network), paymentFrom: String(a.from), paymentTo: String(a.to), paymentValue: String(a.value), paymentValidAfter: String(a.validAfter), paymentValidBefore: String(a.validBefore), paymentNonce: String(a.nonce), paymentSignature: String(p.payload.signature), }; }