ZapProvider.tsx raw

   1  import lightningService from '@/services/lightning.service'
   2  import storage, { dispatchSettingsChanged } from '@/services/local-storage.service'
   3  import { onConnected, onDisconnected } from '@getalby/bitcoin-connect-react'
   4  import { GetInfoResponse, WebLNProvider } from '@webbtc/webln-types'
   5  import { createContext, useContext, useEffect, useState } from 'react'
   6  
   7  type TZapContext = {
   8    isWalletConnected: boolean
   9    provider: WebLNProvider | null
  10    walletInfo: GetInfoResponse | null
  11    defaultZapSats: number
  12    updateDefaultSats: (sats: number) => void
  13    defaultZapComment: string
  14    updateDefaultComment: (comment: string) => void
  15    quickZap: boolean
  16    updateQuickZap: (quickZap: boolean) => void
  17  }
  18  
  19  const ZapContext = createContext<TZapContext | undefined>(undefined)
  20  
  21  export const useZap = () => {
  22    const context = useContext(ZapContext)
  23    if (!context) {
  24      throw new Error('useZap must be used within a ZapProvider')
  25    }
  26    return context
  27  }
  28  
  29  export function ZapProvider({ children }: { children: React.ReactNode }) {
  30    const [defaultZapSats, setDefaultZapSats] = useState<number>(storage.getDefaultZapSats())
  31    const [defaultZapComment, setDefaultZapComment] = useState<string>(storage.getDefaultZapComment())
  32    const [quickZap, setQuickZap] = useState<boolean>(storage.getQuickZap())
  33    const [isWalletConnected, setIsWalletConnected] = useState(false)
  34    const [provider, setProvider] = useState<WebLNProvider | null>(null)
  35    const [walletInfo, setWalletInfo] = useState<GetInfoResponse | null>(null)
  36  
  37    useEffect(() => {
  38      // Set up listeners FIRST
  39      const unSubOnConnected = onConnected((provider) => {
  40        setIsWalletConnected(true)
  41        setWalletInfo(null)
  42        setProvider(provider)
  43        lightningService.provider = provider
  44        provider.getInfo().then(setWalletInfo)
  45      })
  46      const unSubOnDisconnected = onDisconnected(() => {
  47        setIsWalletConnected(false)
  48        setProvider(null)
  49        lightningService.provider = null
  50      })
  51  
  52      // THEN initialize bitcoin-connect (this triggers auto-reconnect which fires onConnected)
  53      lightningService.initBitcoinConnect()
  54  
  55      return () => {
  56        unSubOnConnected()
  57        unSubOnDisconnected()
  58      }
  59    }, [])
  60  
  61    const updateDefaultSats = (sats: number) => {
  62      storage.setDefaultZapSats(sats)
  63      setDefaultZapSats(sats)
  64      dispatchSettingsChanged()
  65    }
  66  
  67    const updateDefaultComment = (comment: string) => {
  68      storage.setDefaultZapComment(comment)
  69      setDefaultZapComment(comment)
  70      dispatchSettingsChanged()
  71    }
  72  
  73    const updateQuickZap = (quickZap: boolean) => {
  74      storage.setQuickZap(quickZap)
  75      setQuickZap(quickZap)
  76      dispatchSettingsChanged()
  77    }
  78  
  79    return (
  80      <ZapContext.Provider
  81        value={{
  82          isWalletConnected,
  83          provider,
  84          walletInfo,
  85          defaultZapSats,
  86          updateDefaultSats,
  87          defaultZapComment,
  88          updateDefaultComment,
  89          quickZap,
  90          updateQuickZap
  91        }}
  92      >
  93        {children}
  94      </ZapContext.Provider>
  95    )
  96  }
  97