diff --git a/components/use-qr-payment.js b/components/use-qr-payment.js index dddc53e9..8fbc9cf0 100644 --- a/components/use-qr-payment.js +++ b/components/use-qr-payment.js @@ -1,8 +1,9 @@ import { useCallback } from 'react' import Invoice from '@/components/invoice' -import { InvoiceCanceledError, InvoiceExpiredError } from '@/wallets/errors' +import { InvoiceCanceledError, InvoiceExpiredError, AnonWalletError } from '@/wallets/errors' import { useShowModal } from '@/components/modal' import useInvoice from '@/components/use-invoice' +import { sendPayment } from '@/wallets/webln/client' export default function useQrPayment () { const invoice = useInvoice() @@ -16,6 +17,10 @@ export default function useQrPayment () { waitFor = inv => inv?.satsReceived > 0 } = {} ) => { + // if anon user and webln is available, try to pay with webln + if (typeof window.webln !== 'undefined' && (walletError instanceof AnonWalletError)) { + sendPayment(inv.bolt11).catch(e => { console.error('WebLN payment failed:', e) }) + } return await new Promise((resolve, reject) => { let paid const cancelAndReject = async (onClose) => { diff --git a/wallets/errors.js b/wallets/errors.js index 13c9ca18..11a9d7be 100644 --- a/wallets/errors.js +++ b/wallets/errors.js @@ -62,6 +62,13 @@ export class WalletsNotAvailableError extends WalletConfigurationError { } } +export class AnonWalletError extends WalletConfigurationError { + constructor () { + super('anon cannot pay with wallets') + this.name = 'AnonWalletError' + } +} + export class WalletAggregateError extends WalletError { constructor (errors, invoice) { super('WalletAggregateError') diff --git a/wallets/payment.js b/wallets/payment.js index 7cb0bec6..6b21f20d 100644 --- a/wallets/payment.js +++ b/wallets/payment.js @@ -4,23 +4,30 @@ import { formatSats } from '@/lib/format' import useInvoice from '@/components/use-invoice' import { FAST_POLL_INTERVAL, WALLET_SEND_PAYMENT_TIMEOUT_MS } from '@/lib/constants' import { - WalletsNotAvailableError, WalletSenderError, WalletAggregateError, WalletPaymentAggregateError, + AnonWalletError, WalletsNotAvailableError, WalletSenderError, WalletAggregateError, WalletPaymentAggregateError, WalletNotEnabledError, WalletSendNotConfiguredError, WalletPaymentError, WalletError, WalletReceiverError } from '@/wallets/errors' import { canSend } from './common' import { useWalletLoggerFactory } from './logger' import { timeoutSignal, withTimeout } from '@/lib/time' +import { useMe } from '@/components/me' export function useWalletPayment () { const wallets = useSendWallets() const sendPayment = useSendPayment() const loggerFactory = useWalletLoggerFactory() const invoiceHelper = useInvoice() + const { me } = useMe() return useCallback(async (invoice, { waitFor, updateOnFallback } = {}) => { let aggregateError = new WalletAggregateError([]) let latestInvoice = invoice + // anon user cannot pay with wallets + if (!me) { + throw new AnonWalletError() + } + // throw a special error that caller can handle separately if no payment was attempted if (wallets.length === 0) { throw new WalletsNotAvailableError() diff --git a/wallets/webln/client.js b/wallets/webln/client.js index 630b2bf5..a54df4b3 100644 --- a/wallets/webln/client.js +++ b/wallets/webln/client.js @@ -1,14 +1,19 @@ import { useEffect } from 'react' import { SSR } from '@/lib/constants' +import { WalletError } from '../errors' export * from '@/wallets/webln' export const sendPayment = async (bolt11) => { if (typeof window.webln === 'undefined') { - throw new Error('WebLN provider not found') + throw new WalletError('WebLN provider not found') } // this will prompt the user to unlock the wallet if it's locked - await window.webln.enable() + try { + await window.webln.enable() + } catch (err) { + throw new WalletError(err.message) + } // this will prompt for payment if no budget is set const response = await window.webln.sendPayment(bolt11) @@ -16,7 +21,7 @@ export const sendPayment = async (bolt11) => { // sendPayment returns nothing if WebLN was enabled // but browser extension that provides WebLN was then disabled // without reloading the page - throw new Error('sendPayment returned no response') + throw new WalletError('sendPayment returned no response') } return response.preimage