Skip to content

Commit

Permalink
perf: optimize api request (#846)
Browse files Browse the repository at this point in the history
* dev: react strict mode in dev mode

* perf: load display data only if necessary

* chore: 'force' reload on wallet unlock

* ui(earn): validate minsize on mount of form
  • Loading branch information
theborakompanioni authored Sep 19, 2024
1 parent 343d40e commit 2c33a88
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 25 deletions.
14 changes: 7 additions & 7 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ export default function App() {
}, [clearCurrentWallet])

const reloadWalletInfo = useCallback(
(delay: Milliseconds) => {
({ delay, force }: { delay: Milliseconds; force: boolean }) => {
setReloadingWalletInfoCounter((current) => current + 1)
console.info('Reloading wallet info...')
return new Promise<WalletInfo>((resolve, reject) =>
setTimeout(() => {
const reload = force ? reloadCurrentWalletInfo.reloadAllForce : reloadCurrentWalletInfo.reloadAll
const abortCtrl = new AbortController()
reloadCurrentWalletInfo
.reloadAll({ signal: abortCtrl.signal })
reload({ signal: abortCtrl.signal })
.then((result) => resolve(result))
.catch((error) => reject(error))
.finally(() => {
Expand Down Expand Up @@ -286,7 +286,7 @@ const MAX_RECURSIVE_WALLET_INFO_RELOADS = 10

interface WalletInfoAutoReloadProps {
currentWallet: CurrentWallet | null
reloadWalletInfo: (delay: Milliseconds) => Promise<WalletInfo>
reloadWalletInfo: ({ delay, force }: { delay: Milliseconds; force: boolean }) => Promise<WalletInfo>
}

/**
Expand Down Expand Up @@ -316,7 +316,7 @@ const WalletInfoAutoReload = ({ currentWallet, reloadWalletInfo }: WalletInfoAut
function reloadAfterUnlock() {
if (!currentWallet) return

reloadWalletInfo(RELOAD_WALLET_INFO_DELAY.AFTER_UNLOCK).catch((err) => console.error(err))
reloadWalletInfo({ delay: RELOAD_WALLET_INFO_DELAY.AFTER_UNLOCK, force: true }).catch((err) => console.error(err))
},
[currentWallet, reloadWalletInfo],
)
Expand All @@ -335,14 +335,14 @@ const WalletInfoAutoReload = ({ currentWallet, reloadWalletInfo }: WalletInfoAut
callCounter: number = 0,
) => {
if (callCounter >= maxCalls) return
const info = await reloadWalletInfo(delay)
const info = await reloadWalletInfo({ delay, force: false })
const newBalance = info.balanceSummary.calculatedTotalBalanceInSats
if (newBalance > currentBalance) {
await reloadWhileBalanceChangesRecursively(newBalance, delay, maxCalls, callCounter++)
}
}

reloadWalletInfo(RELOAD_WALLET_INFO_DELAY.AFTER_RESCAN)
reloadWalletInfo({ delay: RELOAD_WALLET_INFO_DELAY.AFTER_RESCAN, force: false })
.then((info) =>
reloadWhileBalanceChangesRecursively(
info.balanceSummary.calculatedTotalBalanceInSats,
Expand Down
10 changes: 9 additions & 1 deletion src/components/Earn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,15 @@ const EarnForm = ({
}

return (
<Formik initialValues={initialValues} validate={validate} onSubmit={onSubmit}>
<Formik
initialValues={initialValues}
validate={validate}
onSubmit={onSubmit}
validateOnMount={true}
initialTouched={{
minsize: true,
}}
>
{(props) => {
const { handleSubmit, setFieldValue, handleBlur, values, touched, errors, isSubmitting } = props
const minsizeField = props.getFieldProps<AmountValue>('minsize')
Expand Down
41 changes: 37 additions & 4 deletions src/context/WalletContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useEffect, useCallback, useState, useContext, PropsWithChildren, useMemo } from 'react'
import { createContext, useEffect, useCallback, useState, useContext, PropsWithChildren, useMemo, useRef } from 'react'
import { getSession, setSession } from '../session'
import * as fb from '../components/fb/utils'
import * as Api from '../libs/JmWalletApi'
Expand Down Expand Up @@ -143,6 +143,7 @@ interface WalletContextEntry<T extends CurrentWallet> {
currentWalletInfo: WalletInfo | undefined
reloadCurrentWalletInfo: {
reloadAll: ({ signal }: { signal: AbortSignal }) => Promise<WalletInfo>
reloadAllForce: ({ signal }: { signal: AbortSignal }) => Promise<WalletInfo>
reloadUtxos: ({ signal }: { signal: AbortSignal }) => Promise<UtxosResponse>
}
}
Expand Down Expand Up @@ -280,7 +281,7 @@ const WalletProvider = ({ children }: PropsWithChildren<any>) => {
[fetchDisplay],
)

const reloadAll = useCallback(
const reloadAllForce = useCallback(
({ signal }: { signal: AbortSignal }): Promise<WalletInfo> =>
Promise.all([reloadUtxos({ signal }), reloadDisplay({ signal })])
.then((data) => toCombinedRawData(data[0], data[1]))
Expand All @@ -298,12 +299,44 @@ const WalletProvider = ({ children }: PropsWithChildren<any>) => {
return toWalletInfo(combinedRawData)
}, [combinedRawData])

const currentWalletInfoRef = useRef(currentWalletInfo)

useEffect(() => {
currentWalletInfoRef.current = currentWalletInfo
}, [currentWalletInfoRef, currentWalletInfo])

const reloadAllIfNecessary = useCallback(
({ signal }: { signal: AbortSignal }): Promise<WalletInfo> =>
reloadUtxos({ signal }).then((utxoResponse) => {
const needsDisplayReload =
currentWalletInfoRef.current === undefined ||
!!utxoResponse.utxos.find(
(utxo) =>
// reload "display" data if:
// no address summary could be found for a returned UTXO...
currentWalletInfoRef.current!.addressSummary[utxo.address] === undefined ||
// ...or if the address is still considered "new"
currentWalletInfoRef.current!.addressSummary[utxo.address].status === 'new',
)

if (!needsDisplayReload) {
return currentWalletInfoRef.current!
}

return reloadDisplay({ signal })
.then((displayResponse) => toCombinedRawData(utxoResponse, displayResponse))
.then((raw) => toWalletInfo(raw))
}),
[currentWalletInfoRef, reloadUtxos, reloadDisplay],
)

const reloadCurrentWalletInfo = useMemo(
() => ({
reloadAll,
reloadAll: reloadAllIfNecessary,
reloadAllForce,
reloadUtxos,
}),
[reloadAll, reloadUtxos],
[reloadAllIfNecessary, reloadUtxos, reloadAllForce],
)

useEffect(() => {
Expand Down
33 changes: 20 additions & 13 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@ import { WebsocketProvider } from './context/WebsocketContext'
import { ServiceInfoProvider } from './context/ServiceInfoContext'
import { WalletProvider } from './context/WalletContext'
import { ServiceConfigProvider } from './context/ServiceConfigContext'
import { isDevMode } from './constants/debugFeatures'

import 'bootstrap/dist/css/bootstrap.min.css'
import './index.css'
import './i18n/config'

const ENBALE_STRICT_MODE = isDevMode()

const container = document.getElementById('root')
const root = createRoot(container!)
root.render(
<StrictMode>
<SettingsProvider>
<WalletProvider>
<ServiceConfigProvider>
<WebsocketProvider>
<ServiceInfoProvider>
<App />
</ServiceInfoProvider>
</WebsocketProvider>
</ServiceConfigProvider>
</WalletProvider>
</SettingsProvider>
</StrictMode>,
(() => {
const children = (
<SettingsProvider>
<WalletProvider>
<ServiceConfigProvider>
<WebsocketProvider>
<ServiceInfoProvider>
<App />
</ServiceInfoProvider>
</WebsocketProvider>
</ServiceConfigProvider>
</WalletProvider>
</SettingsProvider>
)

return ENBALE_STRICT_MODE ? <StrictMode>{children}</StrictMode> : children
})(),
)

0 comments on commit 2c33a88

Please sign in to comment.