optimize api calls, remove useless effects

This commit is contained in:
Riccardo Balbo 2024-10-15 23:00:01 +02:00 committed by k00b
parent aded5ac422
commit 2ef7651421
5 changed files with 89 additions and 78 deletions

View File

@ -195,13 +195,17 @@ const resolvers = {
} else if (includeSenders) { } else if (includeSenders) {
filter.canSend = true filter.canSend = true
} }
if (onlyEnabled) {
filter.enabled = true
}
return await models.wallet.findMany({ const out = await models.wallet.findMany({
where: filter, where: filter,
orderBy: { orderBy: {
priority: 'asc' priority: 'asc'
} }
}) })
return out
}, },
withdrawl: getWithdrawl, withdrawl: getWithdrawl,
numBolt11s: async (parent, args, { me, models, lnd }) => { numBolt11s: async (parent, args, { me, models, lnd }) => {

View File

@ -86,6 +86,7 @@ const typeDefs = `
type Wallet implements VaultOwner { type Wallet implements VaultOwner {
id: ID! id: ID!
createdAt: Date! createdAt: Date!
updatedAt: Date!
type: String! type: String!
enabled: Boolean! enabled: Boolean!
priority: Int! priority: Int!

View File

@ -204,6 +204,7 @@ export const BEST_SEND_WALLETS = gql`
id id
priority priority
type type
updatedAt
} }
} }
` `

View File

@ -105,13 +105,13 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
<PlausibleProvider domain='stacker.news' trackOutboundLinks> <PlausibleProvider domain='stacker.news' trackOutboundLinks>
<ApolloProvider client={client}> <ApolloProvider client={client}>
<MeProvider me={me}> <MeProvider me={me}>
<HasNewNotesProvider> <WalletProvider>
<LoggerProvider> <HasNewNotesProvider>
<WebLnProvider> <LoggerProvider>
<ServiceWorkerProvider> <WebLnProvider>
<AccountProvider> <ServiceWorkerProvider>
<PriceProvider price={price}> <AccountProvider>
<WalletProvider> <PriceProvider price={price}>
<LightningProvider> <LightningProvider>
<ToastProvider> <ToastProvider>
<ShowModalProvider> <ShowModalProvider>
@ -126,13 +126,13 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
</ShowModalProvider> </ShowModalProvider>
</ToastProvider> </ToastProvider>
</LightningProvider> </LightningProvider>
</WalletProvider> </PriceProvider>
</PriceProvider> </AccountProvider>
</AccountProvider> </ServiceWorkerProvider>
</ServiceWorkerProvider> </WebLnProvider>
</WebLnProvider> </LoggerProvider>
</LoggerProvider> </HasNewNotesProvider>
</HasNewNotesProvider> </WalletProvider>
</MeProvider> </MeProvider>
</ApolloProvider> </ApolloProvider>
</PlausibleProvider> </PlausibleProvider>

View File

@ -1,4 +1,4 @@
import { useCallback, useState, useEffect, useRef, useMemo } from 'react' import { createContext, useContext, useCallback, useState, useEffect, useRef } from 'react'
import { useMe } from '@/components/me' import { useMe } from '@/components/me'
import { openVault } from '@/components/use-vault' import { openVault } from '@/components/use-vault'
import { useWalletLogger } from '@/components/wallet-logger' import { useWalletLogger } from '@/components/wallet-logger'
@ -12,7 +12,8 @@ import { useShowModal } from '@/components/modal'
import { useToast } from '../components/toast' import { useToast } from '../components/toast'
import { generateResolverName, isConfigured, isClientField, isServerField } from '@/lib/wallet' import { generateResolverName, isConfigured, isClientField, isServerField } from '@/lib/wallet'
import { walletValidate } from '@/lib/validate' import { walletValidate } from '@/lib/validate'
import { SSR } from '@/lib/constants' import { SSR, FAST_POLL_INTERVAL as POLL_INTERVAL } from '@/lib/constants'
export const Status = { export const Status = {
Initialized: 'Initialized', Initialized: 'Initialized',
Enabled: 'Enabled', Enabled: 'Enabled',
@ -20,27 +21,30 @@ export const Status = {
Error: 'Error' Error: 'Error'
} }
const WalletContext = createContext({
wallets: [],
sendWallets: []
})
export function useWallet (name) { export function useWallet (name) {
const context = useContext(WalletContext)
const bestSendWalletList = context.sendWallets
if (!name) {
// find best wallet in list
const highestWalletDef = bestSendWalletList?.map(w => getWalletByType(w.type))
.filter(w => !w.isAvailable || w.isAvailable())
name = highestWalletDef?.[0]?.name
}
const wallet = context.wallets.find(w => w.def.name === name)
return wallet
}
function useWalletInner (name) {
const { me } = useMe() const { me } = useMe()
const showModal = useShowModal() const showModal = useShowModal()
const toaster = useToast() const toaster = useToast()
const [disableFreebies] = useMutation(gql`mutation { disableFreebies }`) const [disableFreebies] = useMutation(gql`mutation { disableFreebies }`)
const { data: bestSendWalletList } = useQuery(BEST_SEND_WALLETS)
if (!name) {
// find best wallet in list
const highestWalletDef = bestSendWalletList?.wallets
// .filter(w => w.enabled && w.canSend)// filtered by the server
// .sort((a, b) => b.priority - a.priority) // already priority sorted by the server
.map(w => getWalletByType(w.type))
const highestAvailableWalletDef = highestWalletDef?.filter(w => !w.isAvailable || w.isAvailable())
// console.log('Wallets priority', bestAvailableWallet.map(w => w.name))
// console.log('Available wallets priority', bestAvailableWallet.map(w => w.name))
name = highestAvailableWalletDef?.[0]?.name
}
const walletDef = getWalletByName(name) const walletDef = getWalletByName(name)
const { logger, deleteLogs } = useWalletLogger(walletDef) const { logger, deleteLogs } = useWalletLogger(walletDef)
@ -51,7 +55,6 @@ export function useWallet (name) {
const enabled = status === Status.Enabled const enabled = status === Status.Enabled
const priority = config?.priority const priority = config?.priority
const hasConfig = walletDef?.fields?.length > 0 const hasConfig = walletDef?.fields?.length > 0
const _isConfigured = useCallback(() => { const _isConfigured = useCallback(() => {
return isConfigured({ ...walletDef, config }) return isConfigured({ ...walletDef, config })
}, [walletDef, config]) }, [walletDef, config])
@ -78,7 +81,7 @@ export function useWallet (name) {
logger.error('payment failed:', `payment_hash=${hash}`, message) logger.error('payment failed:', `payment_hash=${hash}`, message)
throw err throw err
} }
}, [me, walletDef, config, status]) }, [me, walletDef, config])
const setPriority = useCallback(async (priority) => { const setPriority = useCallback(async (priority) => {
if (_isConfigured() && priority !== config.priority) { if (_isConfigured() && priority !== config.priority) {
@ -115,33 +118,28 @@ export function useWallet (name) {
return await deleteLogs(options) return await deleteLogs(options)
}, [deleteLogs]) }, [deleteLogs])
const wallet = useMemo(() => { if (!walletDef) return null
if (!walletDef) {
return undefined const wallet = { ...walletDef }
}
const wallet = { wallet.isConfigured = _isConfigured()
...walletDef wallet.enablePayments = enablePayments
} wallet.disablePayments = disablePayments
wallet.isConfigured = _isConfigured() wallet.canSend = config.canSend && available
wallet.enablePayments = enablePayments wallet.canReceive = config.canReceive
wallet.disablePayments = disablePayments wallet.config = config
wallet.canSend = config.canSend && available wallet.save = save
wallet.canReceive = config.canReceive wallet.delete = delete_
wallet.config = config wallet.deleteLogs = deleteLogs_
wallet.save = save wallet.setPriority = setPriority
wallet.delete = delete_ wallet.hasConfig = hasConfig
wallet.deleteLogs = deleteLogs_ wallet.status = status
wallet.setPriority = setPriority wallet.enabled = enabled
wallet.hasConfig = hasConfig wallet.available = available
wallet.status = status wallet.priority = priority
wallet.enabled = enabled wallet.logger = logger
wallet.available = available wallet.sendPayment = sendPayment
wallet.priority = priority wallet.def = walletDef
wallet.logger = logger
wallet.sendPayment = sendPayment
wallet.def = walletDef
return wallet
}, [walletDef, config, status, enabled, priority, logger, enablePayments, disablePayments, save, delete_, deleteLogs_, setPriority, hasConfig])
return wallet return wallet
} }
@ -219,9 +217,7 @@ function useConfig (walletDef) {
// fetch client config // fetch client config
let clientConfig = {} let clientConfig = {}
if (serverConfig?.data?.walletByType) { if (serverConfig?.data?.walletByType) {
if (clientVault.current) { if (clientVault.current) clientVault.current.close()
clientVault.current.close()
}
const newClientVault = openVault(client, me, serverConfig.data.walletByType) const newClientVault = openVault(client, me, serverConfig.data.walletByType)
clientVault.current = newClientVault clientVault.current = newClientVault
clientConfig = await newClientVault.get(walletDef.name, {}) clientConfig = await newClientVault.get(walletDef.name, {})
@ -443,13 +439,7 @@ export function walletPrioritySort (w1, w2) {
} }
export function useWallets () { export function useWallets () {
const wallets = walletDefs.map(def => useWallet(def.name)) const { wallets } = useContext(WalletContext)
const [walletsReady, setWalletsReady] = useState([])
useEffect(() => {
setWalletsReady(wallets.filter(w => w))
}, wallets)
const resetClient = useCallback(async (wallet) => { const resetClient = useCallback(async (wallet) => {
for (const w of wallets) { for (const w of wallets) {
if (w.canSend) { if (w.canSend) {
@ -457,17 +447,28 @@ export function useWallets () {
} }
await w.deleteLogs({ clientOnly: true }) await w.deleteLogs({ clientOnly: true })
} }
}, wallets) }, [wallets])
return { wallets: walletsReady, resetClient } return { wallets, resetClient }
} }
export function WalletProvider ({ children }) { export function WalletProvider ({ children }) {
if (SSR) return children
const { me } = useMe() const { me } = useMe()
const wallets = walletDefs.map(def => useWalletInner(def.name)).filter(w => w)
const migrationRan = useRef(false) const migrationRan = useRef(false)
const migratableKeys = !migrationRan.current && !SSR ? Object.keys(window.localStorage).filter(k => k.startsWith('wallet:')) : undefined const migratableKeys = !migrationRan.current && !SSR ? Object.keys(window.localStorage).filter(k => k.startsWith('wallet:')) : undefined
const { wallets } = useWallets()
const { data: bestSendWalletListData } = useQuery(BEST_SEND_WALLETS, {
pollInterval: POLL_INTERVAL,
nextFetchPolicy: 'network-only',
fetchPolicy: 'network-only'
})
const [bestSendWalletList, setBestSendWalletList] = useState(bestSendWalletListData?.wallets ?? [])
useEffect(() => {
setBestSendWalletList(bestSendWalletListData?.wallets)
}, [bestSendWalletListData])
// migration // migration
useEffect(() => { useEffect(() => {
@ -495,7 +496,11 @@ export function WalletProvider ({ children }) {
} }
} }
})() })()
}, [me, wallets]) }, [])
return children return (
<WalletContext.Provider value={{ wallets, sendWallets: bestSendWalletList }}>
{children}
</WalletContext.Provider>
)
} }