fix: WebLN QR fallback for anon users (#1858)
* fix: WebLN QR fallback for anon users * wip: clear zap color on payment fail * reverse clearItemMeAnonSats * webln-specific retry bypass * cleanup * send WebLN payment when user is Anon AND on QR * skip wallet checking on anon * Use WalletError for all errors in webln.sendPayment --------- Co-authored-by: ekzyis <ek@stacker.news> Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
This commit is contained in:
parent
5e7fd693f1
commit
f72af08882
@ -1,8 +1,9 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import Invoice from '@/components/invoice'
|
import Invoice from '@/components/invoice'
|
||||||
import { InvoiceCanceledError, InvoiceExpiredError } from '@/wallets/errors'
|
import { InvoiceCanceledError, InvoiceExpiredError, AnonWalletError } from '@/wallets/errors'
|
||||||
import { useShowModal } from '@/components/modal'
|
import { useShowModal } from '@/components/modal'
|
||||||
import useInvoice from '@/components/use-invoice'
|
import useInvoice from '@/components/use-invoice'
|
||||||
|
import { sendPayment } from '@/wallets/webln/client'
|
||||||
|
|
||||||
export default function useQrPayment () {
|
export default function useQrPayment () {
|
||||||
const invoice = useInvoice()
|
const invoice = useInvoice()
|
||||||
@ -16,6 +17,10 @@ export default function useQrPayment () {
|
|||||||
waitFor = inv => inv?.satsReceived > 0
|
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) => {
|
return await new Promise((resolve, reject) => {
|
||||||
let paid
|
let paid
|
||||||
const cancelAndReject = async (onClose) => {
|
const cancelAndReject = async (onClose) => {
|
||||||
|
@ -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 {
|
export class WalletAggregateError extends WalletError {
|
||||||
constructor (errors, invoice) {
|
constructor (errors, invoice) {
|
||||||
super('WalletAggregateError')
|
super('WalletAggregateError')
|
||||||
|
@ -4,23 +4,30 @@ import { formatSats } from '@/lib/format'
|
|||||||
import useInvoice from '@/components/use-invoice'
|
import useInvoice from '@/components/use-invoice'
|
||||||
import { FAST_POLL_INTERVAL, WALLET_SEND_PAYMENT_TIMEOUT_MS } from '@/lib/constants'
|
import { FAST_POLL_INTERVAL, WALLET_SEND_PAYMENT_TIMEOUT_MS } from '@/lib/constants'
|
||||||
import {
|
import {
|
||||||
WalletsNotAvailableError, WalletSenderError, WalletAggregateError, WalletPaymentAggregateError,
|
AnonWalletError, WalletsNotAvailableError, WalletSenderError, WalletAggregateError, WalletPaymentAggregateError,
|
||||||
WalletNotEnabledError, WalletSendNotConfiguredError, WalletPaymentError, WalletError, WalletReceiverError
|
WalletNotEnabledError, WalletSendNotConfiguredError, WalletPaymentError, WalletError, WalletReceiverError
|
||||||
} from '@/wallets/errors'
|
} from '@/wallets/errors'
|
||||||
import { canSend } from './common'
|
import { canSend } from './common'
|
||||||
import { useWalletLoggerFactory } from './logger'
|
import { useWalletLoggerFactory } from './logger'
|
||||||
import { timeoutSignal, withTimeout } from '@/lib/time'
|
import { timeoutSignal, withTimeout } from '@/lib/time'
|
||||||
|
import { useMe } from '@/components/me'
|
||||||
|
|
||||||
export function useWalletPayment () {
|
export function useWalletPayment () {
|
||||||
const wallets = useSendWallets()
|
const wallets = useSendWallets()
|
||||||
const sendPayment = useSendPayment()
|
const sendPayment = useSendPayment()
|
||||||
const loggerFactory = useWalletLoggerFactory()
|
const loggerFactory = useWalletLoggerFactory()
|
||||||
const invoiceHelper = useInvoice()
|
const invoiceHelper = useInvoice()
|
||||||
|
const { me } = useMe()
|
||||||
|
|
||||||
return useCallback(async (invoice, { waitFor, updateOnFallback } = {}) => {
|
return useCallback(async (invoice, { waitFor, updateOnFallback } = {}) => {
|
||||||
let aggregateError = new WalletAggregateError([])
|
let aggregateError = new WalletAggregateError([])
|
||||||
let latestInvoice = invoice
|
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
|
// throw a special error that caller can handle separately if no payment was attempted
|
||||||
if (wallets.length === 0) {
|
if (wallets.length === 0) {
|
||||||
throw new WalletsNotAvailableError()
|
throw new WalletsNotAvailableError()
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { SSR } from '@/lib/constants'
|
import { SSR } from '@/lib/constants'
|
||||||
|
import { WalletError } from '../errors'
|
||||||
export * from '@/wallets/webln'
|
export * from '@/wallets/webln'
|
||||||
|
|
||||||
export const sendPayment = async (bolt11) => {
|
export const sendPayment = async (bolt11) => {
|
||||||
if (typeof window.webln === 'undefined') {
|
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
|
// this will prompt the user to unlock the wallet if it's locked
|
||||||
|
try {
|
||||||
await window.webln.enable()
|
await window.webln.enable()
|
||||||
|
} catch (err) {
|
||||||
|
throw new WalletError(err.message)
|
||||||
|
}
|
||||||
|
|
||||||
// this will prompt for payment if no budget is set
|
// this will prompt for payment if no budget is set
|
||||||
const response = await window.webln.sendPayment(bolt11)
|
const response = await window.webln.sendPayment(bolt11)
|
||||||
@ -16,7 +21,7 @@ export const sendPayment = async (bolt11) => {
|
|||||||
// sendPayment returns nothing if WebLN was enabled
|
// sendPayment returns nothing if WebLN was enabled
|
||||||
// but browser extension that provides WebLN was then disabled
|
// but browser extension that provides WebLN was then disabled
|
||||||
// without reloading the page
|
// without reloading the page
|
||||||
throw new Error('sendPayment returned no response')
|
throw new WalletError('sendPayment returned no response')
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.preimage
|
return response.preimage
|
||||||
|
Loading…
x
Reference in New Issue
Block a user