From 0bf630c39fe290ea2718eab7a0759d978c736ef9 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 26 Nov 2024 13:08:08 -0800 Subject: bip21 and socket fixes --- src/lib/bip21.ts | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/lib/bip21.ts (limited to 'src/lib/bip21.ts') diff --git a/src/lib/bip21.ts b/src/lib/bip21.ts new file mode 100644 index 00000000..2642afab --- /dev/null +++ b/src/lib/bip21.ts @@ -0,0 +1,48 @@ +export function decode(uri, allowedSchemes = ["bitcoin", "liquidnetwork"]) { + // Determine the scheme from the URI + const split = uri.indexOf(":"); + if (split === -1) { + throw new Error("Invalid URI: Missing scheme"); + } + + const urnScheme = uri.slice(0, split).toLowerCase(); + if (!allowedSchemes.includes(urnScheme)) { + throw new Error(`Invalid scheme: ${urnScheme}`); + } + + // Extract address and query string + const queryStart = uri.indexOf("?"); + const address = uri.slice( + split + 1, + queryStart === -1 ? undefined : queryStart, + ); + const query = queryStart === -1 ? "" : uri.slice(queryStart + 1); + const options = Object.fromEntries(new URLSearchParams(query)); + + const n = Number(options?.amount); + if (!Number.isFinite(n)) throw new Error("Invalid amount"); + if (n < 0) throw new Error("Invalid amount"); + + return { scheme: urnScheme, address, options }; +} + +export function encode( + address, + options = { amount: "" }, + urnScheme = "bitcoin", +) { + if (!address || typeof address !== "string") { + throw new TypeError("Invalid address"); + } + + if (!["bitcoin", "liquidnetwork"].includes(urnScheme)) { + throw new Error(`Unsupported scheme: ${urnScheme}`); + } + + const n = Number(options?.amount); + if (!Number.isFinite(n)) throw new Error("Invalid amount"); + if (n < 0) throw new Error("Invalid amount"); + + const query = new URLSearchParams(options).toString(); + return `${urnScheme}:${address}${query ? `?${query}` : ""}`; +} -- cgit v1.2.3