import { getUnixTime } from 'date-fns' import React, { useEffect, useState } from 'react' import SInfo from 'react-native-sensitive-info' import type WalletAction from '../lib/Lightning' import LnBits, { type LnBitsConfig } from '../lib/Lightning/LnBits' import LndHub, { type LndHubConfig } from '../lib/Lightning/LndHub' export interface WalletContextProps { type?: string setType: (type: string) => void updatedAt?: string lndHub?: LndHubConfig | LnBitsConfig balance?: number transactions: WalletAction[] invoices: WalletAction[] updateWallet: () => Promise refreshWallet: (params?: object, type?: string) => void payInvoice: (invoice: string) => Promise logoutWallet: () => void } export interface WalletContextProviderProps { children: React.ReactNode } export const initialWalletContext: WalletContextProps = { transactions: [], invoices: [], setType: () => {}, updateWallet: async () => {}, refreshWallet: () => {}, payInvoice: async () => false, logoutWallet: () => {}, } export const WalletContextProvider = ({ children }: WalletContextProviderProps): JSX.Element => { const [type, setType] = React.useState() const [config, setConfig] = useState() const [balance, setBalance] = useState() const [updatedAt, setUpdatedAt] = useState() const [transactions, setTransactions] = useState( initialWalletContext.transactions, ) const [invoices, setInvoices] = useState(initialWalletContext.invoices) useEffect(() => { SInfo.getItem('lndHub', {}).then((value) => { if (value) { setConfig(JSON.parse(value)) setType('lndHub') } }) SInfo.getItem('lnBits', {}).then((value) => { if (value) { setConfig(JSON.parse(value)) setType('lnBits') } }) }, []) useEffect(() => { if (config && type) updateWallet() }, [config, type]) const getClient: (params?: any, clientType?: string) => LndHub | LnBits | undefined = ( params, clientType, ) => { const kind = clientType ?? type let client if (kind === 'lndHub') { client = new LndHub(params ?? config) } else if (kind === 'lnBits') { client = new LnBits(params ?? config) } return client } const refreshWallet: (params?: any, clientType?: string) => void = (params, clientType) => { setConfig(undefined) if (clientType) { setType(clientType) const client = getClient(params, clientType) if (client) { client.refresh(params).then((response) => { if (response?.status === 200) setConfig(response.config) }) } } } const updateWallet: () => Promise = async () => { if (!config || !type) return const client = getClient() if (client) { client.getBalance().then((response) => { if (response?.status === 200) { setUpdatedAt(`${getUnixTime(new Date())}-balance`) setBalance(response.balance) SInfo.setItem(type, JSON.stringify(client.config), {}) } else if (response?.status === 401) { refreshWallet() } }) client.getMovements(setTransactions, setInvoices, setUpdatedAt) } } useEffect(() => { if (config) updateWallet() }, [config]) const payInvoice: (invoice: string) => Promise = async (invoice) => { if (type && config) { const client = new LndHub(config as LndHubConfig) const response = await client.payInvoice(invoice) if (response?.status === 200) { updateWallet() return true } else if (response?.status === 401) { refreshWallet() return true } } return false } const logoutWallet: () => void = () => { SInfo.deleteItem('lndHub', {}) SInfo.deleteItem('lnBits', {}) setType(undefined) setConfig(undefined) setBalance(undefined) setUpdatedAt(undefined) setTransactions([]) setInvoices([]) } return ( {children} ) } export const WalletContext = React.createContext(initialWalletContext)