From f30a9075a229503204a50bca9088ecc40f49ca41 Mon Sep 17 00:00:00 2001 From: Kieran Date: Tue, 28 Feb 2023 19:25:10 +0000 Subject: [PATCH] bug: prevent multiple parallel WebLN calls --- packages/app/src/Feed/EventPublisher.ts | 8 +-- packages/app/src/Hooks/useWebln.ts | 75 ++++++++++++++++++++++--- packages/app/src/Util.ts | 6 ++ 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/packages/app/src/Feed/EventPublisher.ts b/packages/app/src/Feed/EventPublisher.ts index f0b8174..7234e33 100644 --- a/packages/app/src/Feed/EventPublisher.ts +++ b/packages/app/src/Feed/EventPublisher.ts @@ -5,7 +5,7 @@ import { TaggedRawEvent } from "@snort/nostr"; import { EventKind, Tag, Event as NEvent, RelaySettings } from "@snort/nostr"; import { RootState } from "State/Store"; import { HexKey, RawEvent, u256, UserMetadata, Lists } from "@snort/nostr"; -import { bech32ToHex, unwrap } from "Util"; +import { bech32ToHex, delay, unwrap } from "Util"; import { DefaultRelays, HashtagRegex } from "Const"; import { System } from "System"; @@ -398,12 +398,6 @@ export default function useEventPublisher() { let isNip07Busy = false; -const delay = (t: number) => { - return new Promise(resolve => { - setTimeout(resolve, t); - }); -}; - export const barrierNip07 = async (then: () => Promise): Promise => { while (isNip07Busy) { await delay(10); diff --git a/packages/app/src/Hooks/useWebln.ts b/packages/app/src/Hooks/useWebln.ts index e5d0b33..b7b5717 100644 --- a/packages/app/src/Hooks/useWebln.ts +++ b/packages/app/src/Hooks/useWebln.ts @@ -1,25 +1,82 @@ import { useEffect } from "react"; +import { delay, unwrap } from "Util"; -interface WebLNPaymentResponse { - paymentHash: string; +let isWebLnBusy = false; +export const barrierWebLn = async (then: () => Promise): Promise => { + while (isWebLnBusy) { + await delay(10); + } + isWebLnBusy = true; + try { + return await then(); + } finally { + isWebLnBusy = false; + } +}; + +interface SendPaymentResponse { + paymentHash?: string; preimage: string; - route: { + route?: { total_amt: number; total_fees: number; }; } + +interface RequestInvoiceArgs { + amount?: string | number; + defaultAmount?: string | number; + minimumAmount?: string | number; + maximumAmount?: string | number; + defaultMemo?: string; +} + +interface RequestInvoiceResponse { + paymentRequest: string; +} + +interface GetInfoResponse { + node: { + alias: string; + pubkey: string; + color?: string; + }; +} + +interface SignMessageResponse { + message: string; + signature: string; +} + +interface WebLN { + enabled: boolean; + getInfo(): Promise; + enable: () => Promise; + makeInvoice(args: RequestInvoiceArgs): Promise; + signMessage(message: string): Promise; + verifyMessage(signature: string, message: string): Promise; + sendPayment: (pr: string) => Promise; +} + declare global { interface Window { - webln?: { - enabled: boolean; - enable: () => Promise; - sendPayment: (pr: string) => Promise; - }; + webln?: WebLN; } } export default function useWebln(enable = true) { - const maybeWebLn = "webln" in window ? window.webln : null; + const maybeWebLn = + "webln" in window && window.webln + ? ({ + enabled: unwrap(window.webln).enabled, + getInfo: () => barrierWebLn(() => unwrap(window.webln).getInfo()), + enable: () => barrierWebLn(() => unwrap(window.webln).enable()), + makeInvoice: args => barrierWebLn(() => unwrap(window.webln).makeInvoice(args)), + signMessage: msg => barrierWebLn(() => unwrap(window.webln).signMessage(msg)), + verifyMessage: (sig, msg) => barrierWebLn(() => unwrap(window.webln).verifyMessage(sig, msg)), + sendPayment: pr => barrierWebLn(() => unwrap(window.webln).sendPayment(pr)), + } as WebLN) + : null; useEffect(() => { if (maybeWebLn && !maybeWebLn.enabled && enable) { diff --git a/packages/app/src/Util.ts b/packages/app/src/Util.ts index 4ee046a..c5fdab6 100644 --- a/packages/app/src/Util.ts +++ b/packages/app/src/Util.ts @@ -229,3 +229,9 @@ export function splitByUrl(str: string) { return str.split(urlRegex); } + +export const delay = (t: number) => { + return new Promise(resolve => { + setTimeout(resolve, t); + }); +};