extract error messages
This commit is contained in:
parent
a564dfc4e8
commit
3040dd46fa
@ -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;
|
if (zapping || e.isPropagationStopped()) return;
|
||||||
|
|
||||||
const lnurl = author?.lud16 || author?.lud06;
|
const lnurl = author?.lud16 || author?.lud06;
|
||||||
@ -149,7 +149,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
if (service) {
|
if (service) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`reaction-pill ${didZap ? "reacted" : ""}`} {...longPress()} onClick={e => zapClick(e)}>
|
<div className={`reaction-pill ${didZap ? "reacted" : ""}`} {...longPress()} onClick={e => fastZap(e)}>
|
||||||
<div className="reaction-pill-icon">{zapping ? <Spinner /> : webln?.enabled ? <ZapFast /> : <Zap />}</div>
|
<div className="reaction-pill-icon">{zapping ? <Spinner /> : webln?.enabled ? <ZapFast /> : <Zap />}</div>
|
||||||
{zapTotal > 0 && <div className="reaction-pill-number">{formatShort(zapTotal)}</div>}
|
{zapTotal > 0 && <div className="reaction-pill-number">{formatShort(zapTotal)}</div>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@ import Copy from "Element/Copy";
|
|||||||
import useWebln from "Hooks/useWebln";
|
import useWebln from "Hooks/useWebln";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
import { LNURL, LNURLInvoice, LNURLSuccessAction } from "LNURL";
|
import { LNURL, LNURLError, LNURLErrorCode, LNURLInvoice, LNURLSuccessAction } from "LNURL";
|
||||||
|
|
||||||
enum ZapType {
|
enum ZapType {
|
||||||
PublicZap = 1,
|
PublicZap = 1,
|
||||||
@ -96,7 +96,7 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
try {
|
try {
|
||||||
const h = new LNURL(props.lnurl);
|
const h = new LNURL(props.lnurl);
|
||||||
setHandler(h);
|
setHandler(h);
|
||||||
h.load().catch(e => setError((e as Error).message));
|
h.load().catch(e => handleLNURLError(e, formatMessage(messages.InvoiceFail)));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) {
|
if (e instanceof Error) {
|
||||||
setError(e.message);
|
setError(e.message);
|
||||||
@ -147,10 +147,26 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
await payWebLNIfEnabled(rsp);
|
await payWebLNIfEnabled(rsp);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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() {
|
function custom() {
|
||||||
if (!handler) return null;
|
if (!handler) return null;
|
||||||
const min = handler.min / 1000;
|
const min = handler.min / 1000;
|
||||||
|
@ -60,6 +60,7 @@ export default defineMessages({
|
|||||||
Milliseconds: { defaultMessage: "{n} ms" },
|
Milliseconds: { defaultMessage: "{n} ms" },
|
||||||
ShowLatest: { defaultMessage: "Show latest {n} notes" },
|
ShowLatest: { defaultMessage: "Show latest {n} notes" },
|
||||||
LNURLFail: { defaultMessage: "Failed to load LNURL service" },
|
LNURLFail: { defaultMessage: "Failed to load LNURL service" },
|
||||||
|
InvalidLNURL: { defaultMessage: "Invalid LNURL" },
|
||||||
InvoiceFail: { defaultMessage: "Failed to load invoice" },
|
InvoiceFail: { defaultMessage: "Failed to load invoice" },
|
||||||
Custom: { defaultMessage: "Custom" },
|
Custom: { defaultMessage: "Custom" },
|
||||||
Confirm: { defaultMessage: "Confirm" },
|
Confirm: { defaultMessage: "Confirm" },
|
||||||
|
@ -4,25 +4,47 @@ import { bech32ToText, unwrap } from "Util";
|
|||||||
|
|
||||||
const PayServiceTag = "payRequest";
|
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 {
|
export class LNURL {
|
||||||
#url: URL;
|
#url: URL;
|
||||||
#service?: LNURLService;
|
#service?: LNURLService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup LNURL service
|
||||||
|
* @param lnurl bech32 lnurl / lightning address / https url
|
||||||
|
*/
|
||||||
constructor(lnurl: string) {
|
constructor(lnurl: string) {
|
||||||
lnurl = lnurl.toLowerCase().trim();
|
lnurl = lnurl.toLowerCase().trim();
|
||||||
if (lnurl.startsWith("lnurl")) {
|
if (lnurl.startsWith("lnurl")) {
|
||||||
const decoded = bech32ToText(lnurl);
|
const decoded = bech32ToText(lnurl);
|
||||||
if (!decoded.startsWith("http")) {
|
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);
|
this.#url = new URL(decoded);
|
||||||
} else if (lnurl.match(EmailRegex)) {
|
} else if (lnurl.match(EmailRegex)) {
|
||||||
const [handle, domain] = lnurl.split("@");
|
const [handle, domain] = lnurl.split("@");
|
||||||
this.#url = new URL(`https://${domain}/.well-known/lnurlp/${handle}`);
|
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);
|
this.#url = new URL(lnurl);
|
||||||
|
} else if (lnurl.startsWith("lnurlp:")) {
|
||||||
|
const tmp = new URL(lnurl);
|
||||||
|
tmp.protocol = "https:";
|
||||||
|
this.#url = tmp;
|
||||||
} else {
|
} 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;
|
return data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Failed to fetch invoice (${rsp.statusText})`);
|
throw new LNURLError(LNURLErrorCode.ServiceUnavailable, `Failed to fetch invoice (${rsp.statusText})`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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() {
|
#validateService() {
|
||||||
if (this.#service?.tag !== PayServiceTag) {
|
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) {
|
if (!this.#service?.callback) {
|
||||||
throw new Error("Invalid service: no callback url");
|
throw new LNURLError(LNURLErrorCode.InvalidLNURL, "No callback url");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
"0BUTMv": {
|
"0BUTMv": {
|
||||||
"defaultMessage": "Search..."
|
"defaultMessage": "Search..."
|
||||||
},
|
},
|
||||||
|
"0jOEtS": {
|
||||||
|
"defaultMessage": "Invalid LNURL"
|
||||||
|
},
|
||||||
"0mch2Y": {
|
"0mch2Y": {
|
||||||
"defaultMessage": "name has disallowed characters"
|
"defaultMessage": "name has disallowed characters"
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"/d6vEc": "Make your profile easier to find and share",
|
"/d6vEc": "Make your profile easier to find and share",
|
||||||
"/n5KSF": "{n} ms",
|
"/n5KSF": "{n} ms",
|
||||||
"0BUTMv": "Search...",
|
"0BUTMv": "Search...",
|
||||||
|
"0jOEtS": "Invalid LNURL",
|
||||||
"0mch2Y": "name has disallowed characters",
|
"0mch2Y": "name has disallowed characters",
|
||||||
"0yO7wF": "{n} secs",
|
"0yO7wF": "{n} secs",
|
||||||
"1A7TZk": "What is Snort and how does it work?",
|
"1A7TZk": "What is Snort and how does it work?",
|
||||||
|
Loading…
Reference in New Issue
Block a user