diff --git a/lib/lnurl.js b/lib/lnurl.js index 930568d6..8f3c3090 100644 --- a/lib/lnurl.js +++ b/lib/lnurl.js @@ -3,6 +3,7 @@ import { bech32 } from 'bech32' import { lnAddrSchema } from './validate' import { FetchTimeoutError } from '@/lib/fetch' import { WALLET_CREATE_INVOICE_TIMEOUT_MS } from './constants' +import { assertContentTypeJson, assertResponseOk, ResponseAssertError } from '@/lib/url' export function encodeLNUrl (url) { const words = bech32.toWords(Buffer.from(url.toString(), 'utf8')) @@ -35,25 +36,33 @@ export async function lnAddrOptions (addr, { signal } = {}) { // support HTTP and HTTPS during development protocol = process.env.NEXT_PUBLIC_URL.split('://')[0] } - const unexpectedErrorMessage = `An unexpected error occurred fetching the Lightning Address metadata for ${addr}. Check the address and try again.` - let res + + const unexpectedErrorMessage = 'Lightning address validation failed. Make sure you entered the correct address.' + let body const url = `${protocol}://${domain}/.well-known/lnurlp/${name}` try { - const req = await fetch(url, { signal }) - res = await req.json() + const res = await fetch(url, { signal }) + assertResponseOk(res) + assertContentTypeJson(res) + body = await res.json() } catch (err) { - console.log('Error fetching lnurlp', err) + console.log('Error fetching lnurlp:', err) + if (err instanceof ResponseAssertError) { + throw err + } if (err.name === 'TimeoutError') { throw new FetchTimeoutError('GET', url, WALLET_CREATE_INVOICE_TIMEOUT_MS) } - // If `fetch` fails, or if `req.json` fails, catch it here and surface a reasonable error + if (err.name === 'SyntaxError') { + throw new Error(`GET ${url}: invalid JSON`) + } throw new Error(unexpectedErrorMessage) } - if (res.status === 'ERROR') { + if (body.status === 'ERROR') { // if the response doesn't adhere to spec by providing a `reason` entry, returns a default error message - throw new Error(res.reason ?? unexpectedErrorMessage) + throw new Error(body.reason ?? unexpectedErrorMessage) } - const { minSendable, maxSendable, ...leftOver } = res + const { minSendable, maxSendable, ...leftOver } = body return { min: minSendable / 1000, max: maxSendable / 1000, ...leftOver } } diff --git a/lib/url.js b/lib/url.js index 2fffe90b..3d636cd9 100644 --- a/lib/url.js +++ b/lib/url.js @@ -213,7 +213,7 @@ export function parseNwcUrl (walletConnectUrl) { return params } -class ResponseAssertError extends Error { +export class ResponseAssertError extends Error { constructor (res, { method } = {}) { if (method) { super(`${method} ${res.url}: ${res.status} ${res.statusText}`)