diff --git a/hooks/__tests__/useHandleLinking.ts b/hooks/__tests__/useHandleLinking.ts index 6319176..f957fbe 100644 --- a/hooks/__tests__/useHandleLinking.ts +++ b/hooks/__tests__/useHandleLinking.ts @@ -33,38 +33,51 @@ jest.mock("../../lib/lnurl", () => { const testVectors: Record = { // Lightning Addresses "lightning:hello@getalby.com": { - url: "lightning:hello@getalby.com", + url: "hello@getalby.com", path: "/send", }, "lightning://hello@getalby.com": { - url: "lightning:hello@getalby.com", + url: "hello@getalby.com", path: "/send", }, "LIGHTNING://hello@getalby.com": { - url: "lightning:hello@getalby.com", + url: "hello@getalby.com", path: "/send", }, "LIGHTNING:hello@getalby.com": { - url: "lightning:hello@getalby.com", + url: "hello@getalby.com", path: "/send", }, // Lightning invoices - "lightning:lnbc1": { url: "lightning:lnbc1", path: "/send" }, - "lightning://lnbc1": { url: "lightning:lnbc1", path: "/send" }, + "lightning:lnbc123": { + url: "lnbc123", + path: "/send", + }, + "lightning://lnbc123": { + url: "lnbc123", + path: "/send", + }, // BIP21 - "bitcoin:bitcoinaddress?lightning=invoice": { - url: "bitcoin:bitcoinaddress?lightning=invoice", + "bitcoin:bitcoinaddress?lightning=lnbc123": { + url: "lnbc123", path: "/send", }, - "BITCOIN:bitcoinaddress?lightning=invoice": { - url: "bitcoin:bitcoinaddress?lightning=invoice", + "BITCOIN:bitcoinaddress?lightning=lnbc123": { + url: "lnbc123", path: "/send", }, // LNURL-withdraw - "lightning:lnurlw123": { url: "lightning:lnurlw123", path: "/withdraw" }, + "lightning:lnurlw123": { + url: "lnurlw123", + path: "/withdraw", + }, + "lightning://lnurlw123": { + url: "lnurlw123", + path: "/withdraw", + }, }; describe("handleLink", () => { diff --git a/lib/constants.ts b/lib/constants.ts index f9674ee..47d735a 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -40,3 +40,5 @@ export const REQUIRED_CAPABILITIES: Nip47Capability[] = [ export const SATS_REGEX = /^\d*$/; export const FIAT_REGEX = /^\d*(\.\d{0,2})?$/; + +export const BOLT11_REGEX = /.*?((lnbcrt|lntb|lnbc)([0-9]{1,}[a-z0-9]+){1})/; diff --git a/lib/link.ts b/lib/link.ts index 7a498c6..aa5db1f 100644 --- a/lib/link.ts +++ b/lib/link.ts @@ -1,5 +1,6 @@ import { router } from "expo-router"; -import { lnurl } from "./lnurl"; +import { BOLT11_REGEX } from "./constants"; +import { lnurl as lnurlLib } from "./lnurl"; const SUPPORTED_SCHEMES = ["lightning:", "bitcoin:", "alby:"]; @@ -44,27 +45,48 @@ export const handleLink = async (url: string) => { console.info("Navigating to", fullUrl); - const lnurlValue = lnurl.findLnurl(fullUrl); - if (lnurlValue) { - const lnurlDetails = await lnurl.getDetails(lnurlValue); + const schemePattern = new RegExp( + `^(${SUPPORTED_SCHEMES.map((s) => s.replace(":", "")).join("|")}):`, + ); + const trimmedUrl = fullUrl.replace(schemePattern, ""); + + // Check for LNURLs + const lnurl = lnurlLib.findLnurl(trimmedUrl); + if (lnurl) { + const lnurlDetails = await lnurlLib.getDetails(lnurl); if (lnurlDetails.tag === "withdrawRequest") { router.push({ pathname: "/withdraw", params: { - url: fullUrl, + url: lnurl, + }, + }); + return; + } + + if (lnurlDetails.tag === "payRequest") { + router.push({ + pathname: "/send", + params: { + url: lnurl, }, }); return; } } - router.push({ - pathname: "/send", - params: { - url: fullUrl, - }, - }); + // Check for BOLT-11 invoices (including BIP-21 unified QRs) + const bolt11Match = trimmedUrl.match(BOLT11_REGEX); + if (bolt11Match) { + const bolt11 = bolt11Match[1]; + router.push({ + pathname: "/send", + params: { + url: bolt11, + }, + }); + } } else { // Redirect the user to the home screen // if no match was found