Skip to content

Commit

Permalink
Improve loading speed (by a lot)
Browse files Browse the repository at this point in the history
  • Loading branch information
nop33 committed Jan 30, 2024
1 parent 7884e32 commit 0dbc4f9
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 99 deletions.
63 changes: 31 additions & 32 deletions apps/desktop-wallet/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { AddressHash } from '@alephium/shared'
import { ALPH } from '@alephium/token-list'
import { AnimatePresence } from 'framer-motion'
import { difference } from 'lodash'
import { usePostHog } from 'posthog-js/react'
Expand All @@ -37,18 +36,18 @@ import UpdateWalletModal from '@/modals/UpdateWalletModal'
import Router from '@/routes'
import { syncAddressesAlphHistoricBalances, syncAddressesData } from '@/storage/addresses/addressesActions'
import {
makeSelectAddressesKnownFungibleTokens,
makeSelectAddressesUnknownTokens,
makeSelectAllAddressVerifiedFungibleTokenSymbols,
selectAddressIds
} from '@/storage/addresses/addressesSelectors'
import { syncNetworkTokensInfo, syncUnknownTokensInfo } from '@/storage/assets/assetsActions'
import { syncUnknownTokensInfo, syncVerifiedFungibleTokens } from '@/storage/assets/assetsActions'
import { selectIsFungibleTokensUninitialized } from '@/storage/assets/assetsSelectors'
import {
devModeShortcutDetected,
localStorageDataMigrated,
localStorageDataMigrationFailed
} from '@/storage/global/globalActions'
import { syncTokenPrices, syncTokenPricesHistory } from '@/storage/prices/pricesActions'
import { syncTokenCurrentPrices, syncTokenPriceHistories } from '@/storage/prices/pricesActions'
import { apiClientInitFailed, apiClientInitSucceeded } from '@/storage/settings/networkActions'
import { systemLanguageMatchFailed, systemLanguageMatchSucceeded } from '@/storage/settings/settingsActions'
import { makeSelectAddressesHashesWithPendingTransactions } from '@/storage/transactions/transactionsSelectors'
Expand Down Expand Up @@ -81,14 +80,11 @@ const App = () => {
const addressesStatus = useAppSelector((s) => s.addresses.status)
const isSyncingAddressData = useAppSelector((s) => s.addresses.syncingAddressData)
const isFungibleTokensUninitialized = useAppSelector(selectIsFungibleTokensUninitialized)
const isLoadingFungibleTokens = useAppSelector((s) => s.fungibleTokens.loading)
const isLoadingAddressesTokensBalances = useAppSelector((s) => s.addresses.loadingTokensBalances)
const isLoadingVerifiedFungibleTokens = useAppSelector((s) => s.fungibleTokens.loadingVerified)
const isLoadingUnverifiedFungibleTokens = useAppSelector((s) => s.fungibleTokens.loadingUnverified)

const selectAddressesKnownTokens = useMemo(makeSelectAddressesKnownFungibleTokens, [])
const knownTokens = useAppSelector(selectAddressesKnownTokens)
const knownTokenSymbols = knownTokens
.map((token) => token.symbol)
.filter((symbol): symbol is string => symbol !== undefined)
const selectAddressesVerifiedFungibleTokenSymbols = useMemo(makeSelectAllAddressVerifiedFungibleTokenSymbols, [])
const verifiedFungibleTokenSymbols = useAppSelector(selectAddressesVerifiedFungibleTokenSymbols)

const selectAddressesUnknownTokens = useMemo(makeSelectAddressesUnknownTokens, [])
const unknownTokens = useAppSelector(selectAddressesUnknownTokens)
Expand Down Expand Up @@ -188,10 +184,6 @@ const App = () => {

useEffect(() => {
if (network.status === 'online') {
if (fungibleTokens.status === 'uninitialized' && !isLoadingFungibleTokens) {
dispatch(syncNetworkTokensInfo())
}

if (addressesStatus === 'uninitialized') {
if (!isSyncingAddressData && addressHashes.length > 0) {
const storedPendingTxs = getStoredPendingTransactions()
Expand All @@ -207,33 +199,40 @@ const App = () => {
dispatch(syncAddressesAlphHistoricBalances())
}
} else if (addressesStatus === 'initialized') {
if (!isFungibleTokensUninitialized && !isLoadingFungibleTokens) {
if (newUnknownTokens.length > 0) {
dispatch(syncUnknownTokensInfo(newUnknownTokens))
}

if (!isLoadingAddressesTokensBalances) {
dispatch(syncTokenPrices({ knownTokenSymbols, currency: settings.fiatCurrency }))
dispatch(syncTokenPricesHistory({ tokenSymbol: ALPH.symbol, currency: settings.fiatCurrency })) // Needs to be here so that currency change triggers it
// TODO: Get history of known tokens
}
if (!isFungibleTokensUninitialized && !isLoadingUnverifiedFungibleTokens && newUnknownTokens.length > 0) {
dispatch(syncUnknownTokensInfo(newUnknownTokens))
}
}
}
}, [
addressHashes.length,
addressesStatus,
fungibleTokens.status,
dispatch,
isSyncingAddressData,
isLoadingAddressesTokensBalances,
isLoadingFungibleTokens,
fungibleTokens.status,
isFungibleTokensUninitialized,
isLoadingUnverifiedFungibleTokens,
isLoadingVerifiedFungibleTokens,
isSyncingAddressData,
network.status,
newUnknownTokens
])

useEffect(() => {
if (network.status === 'online' && !isLoadingVerifiedFungibleTokens) {
if (fungibleTokens.status === 'uninitialized') {
dispatch(syncVerifiedFungibleTokens())
} else {
dispatch(syncTokenCurrentPrices({ verifiedFungibleTokenSymbols, currency: settings.fiatCurrency }))
dispatch(syncTokenPriceHistories({ verifiedFungibleTokenSymbols, currency: settings.fiatCurrency }))
}
}
}, [
dispatch,
fungibleTokens.status,
isLoadingVerifiedFungibleTokens,
network.status,
newUnknownTokens,
knownTokens,
settings.fiatCurrency,
knownTokenSymbols
verifiedFungibleTokenSymbols
])

const refreshAddressesData = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ const TokensList = ({ className, addressHashes, isExpanded, onExpand }: AssetsLi
const selectAddressesKnownFungibleTokens = useMemo(makeSelectAddressesKnownFungibleTokens, [])
const knownFungibleTokens = useAppSelector((s) => selectAddressesKnownFungibleTokens(s, addressHashes))
const stateUninitialized = useAppSelector(selectIsStateUninitialized)
const isLoadingFungibleTokens = useAppSelector((s) => s.fungibleTokens.loading)
const isLoadingFungibleTokens = useAppSelector(
(s) => s.fungibleTokens.loadingUnverified || s.fungibleTokens.loadingVerified
)

return (
<>
Expand Down Expand Up @@ -236,12 +238,12 @@ const NFTsList = ({ className, addressHashes, isExpanded, onExpand }: AssetsList
const selectAddressesNFTs = useMemo(makeSelectAddressesNFTs, [])
const nfts = useAppSelector((s) => selectAddressesNFTs(s, addressHashes))
const stateUninitialized = useAppSelector(selectIsStateUninitialized)
const isLoadingFungibleTokens = useAppSelector((s) => s.fungibleTokens.loading)
const isLoadingNFTs = useAppSelector((s) => s.nfts.loading)

return (
<>
<motion.div {...fadeIn} className={className}>
{isLoadingFungibleTokens || stateUninitialized ? (
{isLoadingNFTs || stateUninitialized ? (
<NFTList>
<SkeletonLoader height="205px" />
<SkeletonLoader height="205px" />
Expand Down
18 changes: 16 additions & 2 deletions apps/desktop-wallet/src/storage/addresses/addressesSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ You should have received a copy of the GNU Lesser General Public License
along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { AddressHash, Asset, NFT, TokenDisplayBalances } from '@alephium/shared'
import {
AddressFungibleToken,
AddressHash,
Asset,
NFT,
TokenDisplayBalances,
VerifiedAddressFungibleToken
} from '@alephium/shared'
import { ALPH } from '@alephium/token-list'
import { AddressGroup } from '@alephium/walletconnect-provider'
import { createSelector } from '@reduxjs/toolkit'
Expand Down Expand Up @@ -101,7 +108,14 @@ export const makeSelectAddressesTokens = () =>
)

export const makeSelectAddressesKnownFungibleTokens = () =>
createSelector([makeSelectAddressesTokens()], (tokens): Asset[] => tokens.filter((token) => !!token?.symbol))
createSelector([makeSelectAddressesTokens()], (tokens): AddressFungibleToken[] =>
tokens.filter((token): token is AddressFungibleToken => !!token.symbol)
)

export const makeSelectAllAddressVerifiedFungibleTokenSymbols = () =>
createSelector([makeSelectAddressesTokens()], (tokens): VerifiedAddressFungibleToken['symbol'][] =>
tokens.filter((token): token is VerifiedAddressFungibleToken => !!token.symbol).map((token) => token.symbol)
)

export const makeSelectAddressesUnknownTokens = () =>
createSelector(
Expand Down
6 changes: 3 additions & 3 deletions apps/desktop-wallet/src/storage/assets/assetsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import client from '@/api/client'
import { exponentialBackoffFetchRetry } from '@/api/fetchRetry'
import { RootState } from '@/storage/store'

export const syncNetworkTokensInfo = createAsyncThunk(
'assets/syncNetworkTokensInfo',
export const syncVerifiedFungibleTokens = createAsyncThunk(
'assets/syncVerifiedFungibleTokens',
async (_, { getState, dispatch }) => {
const state = getState() as RootState

Expand Down Expand Up @@ -58,7 +58,7 @@ export const syncNetworkTokensInfo = createAsyncThunk(

export const syncUnknownTokensInfo = createAsyncThunk(
'assets/syncUnknownTokensInfo',
async (unknownTokenIds: Asset['id'][], { dispatch }): Promise<SyncUnknownTokensInfoResult> => {
async (unknownTokenIds: Asset['id'][]): Promise<SyncUnknownTokensInfoResult> => {
const results = {
tokens: [],
nfts: []
Expand Down
26 changes: 15 additions & 11 deletions apps/desktop-wallet/src/storage/assets/fungibleTokensSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,23 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.

import { FungibleToken } from '@alephium/shared'
import { ALPH } from '@alephium/token-list'
import { createSlice, EntityState, isAnyOf } from '@reduxjs/toolkit'
import { createSlice, EntityState } from '@reduxjs/toolkit'

import { syncNetworkTokensInfo, syncUnknownTokensInfo } from '@/storage/assets/assetsActions'
import { syncUnknownTokensInfo, syncVerifiedFungibleTokens } from '@/storage/assets/assetsActions'
import { fungibleTokensAdapter } from '@/storage/assets/assetsAdapter'
import { customNetworkSettingsSaved, networkPresetSwitched } from '@/storage/settings/networkActions'

interface FungibleTokensState extends EntityState<FungibleToken> {
loading: boolean
loadingVerified: boolean
loadingUnverified: boolean
status: 'initialized' | 'uninitialized'
checkedUnknownTokenIds: FungibleToken['id'][]
}

const initialState: FungibleTokensState = fungibleTokensAdapter.addOne(
fungibleTokensAdapter.getInitialState({
loading: false,
loadingVerified: false,
loadingUnverified: false,
status: 'uninitialized',
checkedUnknownTokenIds: []
}),
Expand All @@ -48,7 +50,10 @@ const fungibleTokensSlice = createSlice({
reducers: {},
extraReducers(builder) {
builder
.addCase(syncNetworkTokensInfo.fulfilled, (state, action) => {
.addCase(syncVerifiedFungibleTokens.pending, (state) => {
state.loadingVerified = true
})
.addCase(syncVerifiedFungibleTokens.fulfilled, (state, action) => {
const metadata = action.payload

if (metadata) {
Expand All @@ -60,9 +65,12 @@ const fungibleTokensSlice = createSlice({
}))
)
state.status = 'initialized'
state.loading = false
state.loadingVerified = false
}
})
.addCase(syncUnknownTokensInfo.pending, (state) => {
state.loadingUnverified = true
})
.addCase(syncUnknownTokensInfo.fulfilled, (state, action) => {
const metadata = action.payload.tokens
const initiallyUnknownTokenIds = action.meta.arg
Expand All @@ -79,14 +87,10 @@ const fungibleTokensSlice = createSlice({
)
}

state.loading = false
state.loadingUnverified = false
})
.addCase(networkPresetSwitched, resetState)
.addCase(customNetworkSettingsSaved, resetState)

builder.addMatcher(isAnyOf(syncNetworkTokensInfo.pending, syncUnknownTokensInfo.pending), (state) => {
state.loading = true
})
}
})

Expand Down
15 changes: 13 additions & 2 deletions apps/desktop-wallet/src/storage/assets/nftsSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,31 @@ import { syncUnknownTokensInfo } from '@/storage/assets/assetsActions'
import { nftsAdapter } from '@/storage/assets/assetsAdapter'
import { customNetworkSettingsSaved, networkPresetSwitched } from '@/storage/settings/networkActions'

type NFTsState = EntityState<NFT>
interface NFTsState extends EntityState<NFT> {
loading: boolean
}

const initialState: NFTsState = nftsAdapter.getInitialState()
const initialState: NFTsState = nftsAdapter.getInitialState({
loading: false
})

const nftsSlice = createSlice({
name: 'nfts',
initialState,
reducers: {},
extraReducers(builder) {
builder
.addCase(syncUnknownTokensInfo.pending, (state) => {
state.loading = true
})
.addCase(syncUnknownTokensInfo.fulfilled, (state, action) => {
const nfts = action.payload.nfts

nftsAdapter.upsertMany(state, nfts)
state.loading = false
})
.addCase(syncUnknownTokensInfo.rejected, (state) => {
state.loading = false
})
.addCase(networkPresetSwitched, resetState)
.addCase(customNetworkSettingsSaved, resetState)
Expand Down
Loading

0 comments on commit 0dbc4f9

Please sign in to comment.