From 3040dd46fa1d8900c635dd500b89cd304cc0abaa Mon Sep 17 00:00:00 2001 From: Kieran Date: Mon, 27 Feb 2023 19:15:39 +0000 Subject: [PATCH] extract error messages --- packages/app/src/Element/NoteFooter.tsx | 4 +-- packages/app/src/Element/SendSats.tsx | 22 ++++++++++++--- packages/app/src/Element/messages.ts | 1 + packages/app/src/LNURL.ts | 36 ++++++++++++++++++++----- packages/app/src/lang.json | 3 +++ packages/app/src/translations/en.json | 3 ++- 6 files changed, 56 insertions(+), 13 deletions(-) diff --git a/packages/app/src/Element/NoteFooter.tsx b/packages/app/src/Element/NoteFooter.tsx index d8e69449..0fa03cb9 100644 --- a/packages/app/src/Element/NoteFooter.tsx +++ b/packages/app/src/Element/NoteFooter.tsx @@ -118,7 +118,7 @@ export default function NoteFooter(props: NoteFooterProps) { } } - async function zapClick(e: React.MouseEvent) { + async function fastZap(e: React.MouseEvent) { if (zapping || e.isPropagationStopped()) return; const lnurl = author?.lud16 || author?.lud06; @@ -149,7 +149,7 @@ export default function NoteFooter(props: NoteFooterProps) { if (service) { return ( <> -
zapClick(e)}> +
fastZap(e)}>
{zapping ? : webln?.enabled ? : }
{zapTotal > 0 &&
{formatShort(zapTotal)}
}
diff --git a/packages/app/src/Element/SendSats.tsx b/packages/app/src/Element/SendSats.tsx index 593289d4..cdb9cd24 100644 --- a/packages/app/src/Element/SendSats.tsx +++ b/packages/app/src/Element/SendSats.tsx @@ -17,7 +17,7 @@ import Copy from "Element/Copy"; import useWebln from "Hooks/useWebln"; import messages from "./messages"; -import { LNURL, LNURLInvoice, LNURLSuccessAction } from "LNURL"; +import { LNURL, LNURLError, LNURLErrorCode, LNURLInvoice, LNURLSuccessAction } from "LNURL"; enum ZapType { PublicZap = 1, @@ -96,7 +96,7 @@ export default function SendSats(props: SendSatsProps) { try { const h = new LNURL(props.lnurl); setHandler(h); - h.load().catch(e => setError((e as Error).message)); + h.load().catch(e => handleLNURLError(e, formatMessage(messages.InvoiceFail))); } catch (e) { if (e instanceof Error) { setError(e.message); @@ -147,10 +147,26 @@ export default function SendSats(props: SendSatsProps) { await payWebLNIfEnabled(rsp); } } catch (e) { - setError(formatMessage(messages.InvoiceFail)); + handleLNURLError(e, formatMessage(messages.InvoiceFail)); } } + function handleLNURLError(e: unknown, fallback: string) { + if (e instanceof LNURLError) { + switch (e.code) { + case LNURLErrorCode.ServiceUnavailable: { + setError(formatMessage(messages.LNURLFail)); + return; + } + case LNURLErrorCode.InvalidLNURL: { + setError(formatMessage(messages.InvalidLNURL)); + return; + } + } + } + setError(fallback); + } + function custom() { if (!handler) return null; const min = handler.min / 1000; diff --git a/packages/app/src/Element/messages.ts b/packages/app/src/Element/messages.ts index 0eb77170..eeee0682 100644 --- a/packages/app/src/Element/messages.ts +++ b/packages/app/src/Element/messages.ts @@ -60,6 +60,7 @@ export default defineMessages({ Milliseconds: { defaultMessage: "{n} ms" }, ShowLatest: { defaultMessage: "Show latest {n} notes" }, LNURLFail: { defaultMessage: "Failed to load LNURL service" }, + InvalidLNURL: { defaultMessage: "Invalid LNURL" }, InvoiceFail: { defaultMessage: "Failed to load invoice" }, Custom: { defaultMessage: "Custom" }, Confirm: { defaultMessage: "Confirm" }, diff --git a/packages/app/src/LNURL.ts b/packages/app/src/LNURL.ts index c7c4cf8f..8184af72 100644 --- a/packages/app/src/LNURL.ts +++ b/packages/app/src/LNURL.ts @@ -4,25 +4,47 @@ import { bech32ToText, unwrap } from "Util"; const PayServiceTag = "payRequest"; +export enum LNURLErrorCode { + ServiceUnavailable = 1, + InvalidLNURL = 2, +} + +export class LNURLError extends Error { + code: LNURLErrorCode; + + constructor(code: LNURLErrorCode, msg: string) { + super(msg); + this.code = code; + } +} + export class LNURL { #url: URL; #service?: LNURLService; + /** + * Setup LNURL service + * @param lnurl bech32 lnurl / lightning address / https url + */ constructor(lnurl: string) { lnurl = lnurl.toLowerCase().trim(); if (lnurl.startsWith("lnurl")) { const decoded = bech32ToText(lnurl); if (!decoded.startsWith("http")) { - throw new Error("Invalid LNURL: not a url"); + throw new LNURLError(LNURLErrorCode.InvalidLNURL, "Not a url"); } this.#url = new URL(decoded); } else if (lnurl.match(EmailRegex)) { const [handle, domain] = lnurl.split("@"); this.#url = new URL(`https://${domain}/.well-known/lnurlp/${handle}`); - } else if (lnurl.startsWith("http")) { + } else if (lnurl.startsWith("https:")) { this.#url = new URL(lnurl); + } else if (lnurl.startsWith("lnurlp:")) { + const tmp = new URL(lnurl); + tmp.protocol = "https:"; + this.#url = tmp; } else { - throw new Error("Invalid LNURL: could not determine service url"); + throw new LNURLError(LNURLErrorCode.InvalidLNURL, "Could not determine service url"); } } @@ -75,10 +97,10 @@ export class LNURL { return data; } } else { - throw new Error(`Failed to fetch invoice (${rsp.statusText})`); + throw new LNURLError(LNURLErrorCode.ServiceUnavailable, `Failed to fetch invoice (${rsp.statusText})`); } } catch (e) { - throw new Error("Failed to load callback"); + throw new LNURLError(LNURLErrorCode.ServiceUnavailable, "Failed to load callback"); } } @@ -112,10 +134,10 @@ export class LNURL { #validateService() { if (this.#service?.tag !== PayServiceTag) { - throw new Error("Invalid service: only lnurlp is supported"); + throw new LNURLError(LNURLErrorCode.InvalidLNURL, "Only LNURLp is supported"); } if (!this.#service?.callback) { - throw new Error("Invalid service: no callback url"); + throw new LNURLError(LNURLErrorCode.InvalidLNURL, "No callback url"); } } } diff --git a/packages/app/src/lang.json b/packages/app/src/lang.json index a4b877c0..4b3d6257 100644 --- a/packages/app/src/lang.json +++ b/packages/app/src/lang.json @@ -30,6 +30,9 @@ "0BUTMv": { "defaultMessage": "Search..." }, + "0jOEtS": { + "defaultMessage": "Invalid LNURL" + }, "0mch2Y": { "defaultMessage": "name has disallowed characters" }, diff --git a/packages/app/src/translations/en.json b/packages/app/src/translations/en.json index 9c8ef3d6..4c149f1a 100644 --- a/packages/app/src/translations/en.json +++ b/packages/app/src/translations/en.json @@ -9,6 +9,7 @@ "/d6vEc": "Make your profile easier to find and share", "/n5KSF": "{n} ms", "0BUTMv": "Search...", + "0jOEtS": "Invalid LNURL", "0mch2Y": "name has disallowed characters", "0yO7wF": "{n} secs", "1A7TZk": "What is Snort and how does it work?", @@ -268,4 +269,4 @@ "zjJZBd": "You're ready!", "zonsdq": "Failed to load LNURL service", "zvCDao": "Automatically show latest notes" -} +} \ No newline at end of file