From 7703f36d7ffc5595c933aeaf6b8d64ff86cb06e4 Mon Sep 17 00:00:00 2001 From: michael1011 Date: Sun, 20 Oct 2024 13:26:25 +0200 Subject: [PATCH] refactor: improve invoice fetching (#699) --- e2e/submarineSwap.spec.ts | 26 +++++++++++++++++ src/components/CreateButton.tsx | 29 +++++++++++------- src/utils/invoice.ts | 52 ++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/e2e/submarineSwap.spec.ts b/e2e/submarineSwap.spec.ts index df5c72b2..5c7479c8 100644 --- a/e2e/submarineSwap.spec.ts +++ b/e2e/submarineSwap.spec.ts @@ -50,4 +50,30 @@ test.describe("Submarine swap", () => { await generateBitcoinBlock(); // TODO: verify amounts }); + + test("Create with LNURL", async ({ page }) => { + await page.goto("/"); + + await page + .locator( + "div:nth-child(3) > .asset-wrap > .asset > .asset-selection", + ) + .click(); + await page.getByTestId("select-LN").click(); + await page.locator(".asset-wrap").first().click(); + await page.getByTestId("select-L-BTC").click(); + + await page.getByTestId("invoice").click(); + await page + .getByTestId("invoice") + .fill( + "LNURL1DP68GUP69UHNZV3H9CCZUVPWXYARXVPSXQHKZURF9AKXUATJD3CQQKE2EU", + ); + + await page.getByTestId("sendAmount").fill("50 0000"); + + await page.getByTestId("create-swap-button").click(); + // When we can click that button, the swap was created + await page.getByRole("button", { name: "Skip download" }).click(); + }); }); diff --git a/src/components/CreateButton.tsx b/src/components/CreateButton.tsx index de7bc09a..4855fe7c 100644 --- a/src/components/CreateButton.tsx +++ b/src/components/CreateButton.tsx @@ -173,23 +173,30 @@ export const CreateButton = () => { resolve(res); } catch (e) { log.warn( - "Fetching invoice from LNURL failed", + "Fetching invoice for LNURL failed:", e, ); - throw e; + reject(e); } }); })(), (() => { - try { - return fetchBip353( - lnurl(), - Number(receiveAmount()), - ); - } catch (e) { - log.warn("Fetching invoice from BIP-353 failed", e); - throw e; - } + return new Promise(async (resolve, reject) => { + try { + resolve( + await fetchBip353( + lnurl(), + Number(receiveAmount()), + ), + ); + } catch (e) { + log.warn( + "Fetching invoice from BIP-353 failed:", + e, + ); + reject(e); + } + }); })(), ]); diff --git a/src/utils/invoice.ts b/src/utils/invoice.ts index 0613f617..46a938df 100644 --- a/src/utils/invoice.ts +++ b/src/utils/invoice.ts @@ -79,32 +79,29 @@ export const decodeInvoice = ( } }; -export const fetchLnurl = ( +export const fetchLnurl = async ( lnurl: string, amount_sat: number, ): Promise => { - return new Promise((resolve, reject) => { - let url: string; - const amount = Math.round(amount_sat * 1000); - - if (lnurl.includes("@")) { - // Lightning address - const urlsplit = lnurl.split("@"); - url = `https://${urlsplit[1]}/.well-known/lnurlp/${urlsplit[0]}`; - } else { - // LNURL - const { bytes } = bech32.decodeToBytes(lnurl); - url = utf8.encode(bytes); - } + let url: string; + if (lnurl.includes("@")) { + // Lightning address + const urlsplit = lnurl.split("@"); + url = `https://${urlsplit[1]}/.well-known/lnurlp/${urlsplit[0]}`; + } else { + // LNURL + const { bytes } = bech32.decodeToBytes(lnurl); + url = utf8.encode(bytes); + } - log.debug("fetching lnurl:", url); - fetch(url) - .then(checkResponse) - .then((data) => checkLnurlResponse(amount, data)) - .then((data) => fetchLnurlInvoice(amount, data)) - .then(resolve) - .catch(reject); - }); + const amount = Math.round(amount_sat * 1000); + + log.debug("Fetching LNURL:", url); + + const res = await checkResponse(await fetch(url)); + checkLnurlResponse(amount, res); + + return await fetchLnurlInvoice(amount, res); }; export const fetchBip353 = async ( @@ -132,10 +129,17 @@ export const fetchBip353 = async ( }, }); const resBody = await res.json(); + if (resBody.Answer === undefined || resBody.Answer.length === 0) { + throw "no TXT record"; + } + const paymentRequest = resBody.Answer[0].data; const offer = new URLSearchParams(paymentRequest.split("?")[1]).get("lno"); - return (await fetchBolt12Invoice(offer.replaceAll('"', ""), amountSat)) - .invoice; + const invoice = ( + await fetchBolt12Invoice(offer.replaceAll('"', ""), amountSat) + ).invoice; + log.debug(`Resolved invoice for BIP-353:`, invoice); + return invoice; }; const checkLnurlResponse = (amount: number, data: LnurlResponse) => {