// Copyright (C) 2026 Whiterun LLC, // This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later. // A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html /** * Serialization helpers for converting between native libauth types and the * relay-safe JSON format used by the WizardConnect protocol. * * The relay transmits messages as JSON, which cannot represent BigInt or * Uint8Array natively. This module provides the canonical encoding: * * - Uint8Array → hex string (or `` extended format) * - BigInt → `` string * * Both dapps and wallets should use these helpers to ensure interoperability. */ import { hexToBin } from "@bitauth/libauth"; // --------------------------------------------------------------------------- // Deserialization (relay JSON → native types) // --------------------------------------------------------------------------- const BIGINT_RE = /^[0-9]*)n>$/; const UINT8_RE = /^[0-9a-f]*)>$/u; /** * Parse a full JSON string that may contain extended-format values. * Handles both `` and `` formats. */ export function parseExtendedJson(jsonString: string): any { return JSON.parse(jsonString, (_key, value) => { if (typeof value === "string") { const bigintMatch = value.match(BIGINT_RE); if (bigintMatch) return BigInt(bigintMatch[1]); const uint8Match = value.match(UINT8_RE); if (uint8Match) return hexToBin(uint8Match[1]); } return value; }); } /** * Check if a string contains extended JSON markers. */ export function isExtendedJsonFormat(str: string): boolean { return UINT8_RE.test(str) || BIGINT_RE.test(str); } /** * Parse a single extended JSON value string to its native type. * Returns the original string if it doesn't match any known format. */ export function parseExtendedJsonValue( value: string, ): Uint8Array | bigint | string { const bigintMatch = value.match(BIGINT_RE); if (bigintMatch) return BigInt(bigintMatch[1]); const uint8Match = value.match(UINT8_RE); if (uint8Match) return hexToBin(uint8Match[1]); return value; } /** * Convert a value to Uint8Array. Accepts: * - Uint8Array (returned as-is) * - hex string * - extended JSON format string (``) */ export function toUint8Array(value: string | Uint8Array): Uint8Array { if (value instanceof Uint8Array) return value; if (isExtendedJsonFormat(value)) return parseExtendedJsonValue(value) as Uint8Array; return hexToBin(value); } /** * Convert a value to bigint. Accepts: * - bigint (returned as-is) * - number * - numeric string * - extended JSON format string (``) */ export function toBigInt(value: string | number | bigint): bigint { if (typeof value === "bigint") return value; if (typeof value === "string") { if (isExtendedJsonFormat(value)) return parseExtendedJsonValue(value) as bigint; return BigInt(value); } return BigInt(value); }