Skip to content

Commit

Permalink
send WebLN payment when user is Anon AND on QR
Browse files Browse the repository at this point in the history
  • Loading branch information
Soxasora committed Feb 10, 2025
1 parent b71e518 commit ed59dd3
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 16 deletions.
9 changes: 2 additions & 7 deletions components/use-paid-mutation.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,10 @@ export function usePaidMutation (mutation,
throw err
}
}

const paymentAttempted = walletError instanceof WalletPaymentError
if (paymentAttempted) {
try {
walletInvoice = await invoiceHelper.retry(walletInvoice, { update: updateOnFallback })
} catch (err) {
if (walletError.wallet === 'webln') { // show QR code for WebLN errors
throw err
}
}
walletInvoice = await invoiceHelper.retry(walletInvoice, { update: updateOnFallback })
}
return await waitForQrPayment(walletInvoice, walletError, { persistOnNavigate, waitFor })
}, [waitForWalletPayment, waitForQrPayment, invoiceHelper])
Expand Down
9 changes: 8 additions & 1 deletion components/use-qr-payment.js
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -16,6 +17,12 @@ 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(err => {
console.error('WebLN payment failed:', err)
})
}
return await new Promise((resolve, reject) => {
let paid
const cancelAndReject = async (onClose) => {
Expand Down
6 changes: 6 additions & 0 deletions wallets/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ 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')
Expand Down
17 changes: 10 additions & 7 deletions wallets/payment.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ 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([])
Expand All @@ -26,6 +28,11 @@ export function useWalletPayment () {
throw new WalletsNotAvailableError()
}

// anon user cannot pay with wallets
if (!me) {
throw new AnonWalletError()
}

for (let i = 0; i < wallets.length; i++) {
const wallet = wallets[i]
const logger = loggerFactory(wallet)
Expand Down Expand Up @@ -78,12 +85,8 @@ export function useWalletPayment () {
}

if (paymentError instanceof WalletPaymentError) {
// only cancel the invoice if we're not dealing with a WebLN error
// as WebLN failures need to fall back to QR code and anonymous users can't retry
if (paymentError.wallet !== 'webln') {
// if a payment was attempted, cancel invoice to make sure it cannot be paid later and create new invoice to retry.
await invoiceHelper.cancel(latestInvoice)
}
// if a payment was attempted, cancel invoice to make sure it cannot be paid later and create new invoice to retry.
await invoiceHelper.cancel(latestInvoice)
}

// only create a new invoice if we will try to pay with a wallet again
Expand Down
2 changes: 1 addition & 1 deletion wallets/webln/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const sendPayment = async (bolt11) => {
try {
await window.webln.enable()
} catch (err) {
throw new WalletError('cannot re-enable wallet')
throw new WalletError(err.message)
}

// this will prompt for payment if no budget is set
Expand Down

0 comments on commit ed59dd3

Please sign in to comment.