Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix userAssets query enabled config #6243

Merged
merged 14 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/__swaps__/screens/Swap/resources/assets/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { useUserAssets } from './userAssets';
export type { UserAssetsArgs } from './userAssets';
export { useUserAssetsByChain } from './userAssetsByChain';
export type { UserAssetsByChainArgs } from './userAssetsByChain';
24 changes: 14 additions & 10 deletions src/__swaps__/screens/Swap/resources/assets/userAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ async function userAssetsQueryFunction({
const chainIdsWithErrorsInResponse = res?.data?.meta?.chain_ids_with_errors || [];
const assets = res?.data?.payload?.assets || [];
if (address) {
userAssetsQueryFunctionRetryByChain({
address,
chainIds: chainIdsWithErrorsInResponse,
currency,
testnetMode,
});
if (chainIdsWithErrorsInResponse.length) {
jinchung marked this conversation as resolved.
Show resolved Hide resolved
userAssetsQueryFunctionRetryByChain({
address,
chainIds: chainIdsWithErrorsInResponse,
currency,
testnetMode,
});
}
if (assets.length && chainIdsInResponse.length) {
const parsedAssetsDict = await parseUserAssets({
assets,
Expand Down Expand Up @@ -186,9 +188,11 @@ async function userAssetsQueryFunctionRetryByChain({
}
const parsedRetries = await Promise.all(retries);
for (const parsedAssets of parsedRetries) {
const values = Object.values(parsedAssets);
if (values[0]) {
cachedUserAssets[values[0].chainId] = parsedAssets;
if (parsedAssets) {
const values = Object.values(parsedAssets);
if (values[0]) {
cachedUserAssets[values[0].chainId] = parsedAssets;
}
}
}
queryClient.setQueryData(userAssetsQueryKey({ address, currency, testnetMode }), cachedUserAssets);
Expand Down Expand Up @@ -236,9 +240,9 @@ export function useUserAssets<TSelectResult = UserAssetsResult>(
config: QueryConfigWithSelect<UserAssetsResult, Error, TSelectResult, UserAssetsQueryKey> = {}
) {
const { connectedToHardhat } = useConnectedToHardhatStore();

return useQuery(userAssetsQueryKey({ address, currency, testnetMode: connectedToHardhat }), userAssetsQueryFunction, {
...config,
enabled: !!address && !!currency,
jinchung marked this conversation as resolved.
Show resolved Hide resolved
refetchInterval: USER_ASSETS_REFETCH_INTERVAL,
staleTime: process.env.IS_TESTING === 'true' ? 0 : 1000,
});
Expand Down
36 changes: 8 additions & 28 deletions src/__swaps__/screens/Swap/resources/assets/userAssetsByChain.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useQuery } from '@tanstack/react-query';
import { Address } from 'viem';

import { QueryConfigWithSelect, QueryFunctionArgs, QueryFunctionResult, createQueryKey, queryClient } from '@/react-query';
Expand All @@ -12,8 +11,6 @@ import { parseUserAssets, userAssetsQueryKey } from './userAssets';
import { RainbowFetchClient } from '@/rainbow-fetch';
import { ADDYS_API_KEY } from 'react-native-dotenv';

const USER_ASSETS_REFETCH_INTERVAL = 60000;

const addysHttp = new RainbowFetchClient({
baseURL: 'https://addys.p.rainbow.me/v3',
headers: {
Expand Down Expand Up @@ -59,15 +56,19 @@ export async function fetchUserAssetsByChain<TSelectData = UserAssetsByChainResu
// ///////////////////////////////////////////////
// Query Function

export async function userAssetsByChainQueryFunction({
async function userAssetsByChainQueryFunction({
queryKey: [{ address, chainId, currency }],
}: QueryFunctionArgs<typeof userAssetsByChainQueryKey>): Promise<Record<string, ParsedUserAsset>> {
const cache = queryClient.getQueryCache();
const cachedUserAssets = (cache.find(userAssetsQueryKey({ address, currency }))?.state?.data || {}) as ParsedAssetsDictByChain;
const cachedDataForChain = cachedUserAssets?.[chainId];
const cachedDataForChain = cachedUserAssets?.[chainId] || {};
try {
jinchung marked this conversation as resolved.
Show resolved Hide resolved
const url = `/${chainId}/${address}/assets/?currency=${currency.toLowerCase()}`;
const res = await addysHttp.get<AddressAssetsReceivedMessage>(url);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was where we were seeing the "No auth" error message on the retries - have it following the same pattern we have elsewhere now

const url = `/${chainId}/${address}/assets`;
const res = await addysHttp.get<AddressAssetsReceivedMessage>(url, {
params: {
currency: currency.toLowerCase(),
},
});
const chainIdsInResponse = res?.data?.meta?.chain_ids || [];
const assets = res?.data?.payload?.assets || [];
if (assets.length && chainIdsInResponse.length) {
Expand All @@ -90,24 +91,3 @@ export async function userAssetsByChainQueryFunction({
}

type UserAssetsByChainResult = QueryFunctionResult<typeof userAssetsByChainQueryFunction>;

// ///////////////////////////////////////////////
// Query Hook

export function useUserAssetsByChain<TSelectResult = UserAssetsByChainResult>(
{ address, chainId, currency }: UserAssetsByChainArgs,
jinchung marked this conversation as resolved.
Show resolved Hide resolved
config: QueryConfigWithSelect<UserAssetsByChainResult, Error, TSelectResult, UserAssetsByChainQueryKey> = {}
) {
return useQuery(
userAssetsByChainQueryKey({
address,
chainId,
currency,
}),
userAssetsByChainQueryFunction,
{
...config,
refetchInterval: USER_ASSETS_REFETCH_INTERVAL,
}
);
}
36 changes: 30 additions & 6 deletions src/state/assets/userAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,34 @@ export interface UserAssetsState {
setUserAssets: (userAssets: Map<UniqueId, ParsedSearchAsset> | ParsedSearchAsset[]) => void;
}

type UserAssetsStateToPersist = Omit<
Partial<UserAssetsState>,
| 'currentAbortController'
| 'inputSearchQuery'
| 'searchCache'
| 'getBalanceSortedChainList'
| 'getChainsWithBalance'
| 'getFilteredUserAssetIds'
| 'getHighestValueEth'
| 'getUserAsset'
| 'getUserAssets'
| 'selectUserAssetIds'
| 'selectUserAssets'
| 'setSearchCache'
| 'setSearchQuery'
| 'setUserAssets'
>;

// NOTE: We are serializing Map as an Array<[UniqueId, ParsedSearchAsset]>
type UserAssetsStateWithTransforms = Omit<Partial<UserAssetsState>, 'chainBalances' | 'idsByChain' | 'userAssets'> & {
type UserAssetsStateToPersistWithTransforms = Omit<UserAssetsStateToPersist, 'chainBalances' | 'idsByChain' | 'userAssets'> & {
chainBalances: Array<[ChainId, number]>;
idsByChain: Array<[UserAssetFilter, UniqueId[]]>;
userAssets: Array<[UniqueId, ParsedSearchAsset]>;
};

function serializeUserAssetsState(state: Partial<UserAssetsState>, version?: number) {
function serializeUserAssetsState(state: UserAssetsStateToPersist, version?: number) {
try {
const transformedStateToPersist: UserAssetsStateWithTransforms = {
const transformedStateToPersist: UserAssetsStateToPersistWithTransforms = {
...state,
chainBalances: state.chainBalances ? Array.from(state.chainBalances.entries()) : [],
idsByChain: state.idsByChain ? Array.from(state.idsByChain.entries()) : [],
Expand All @@ -76,7 +94,7 @@ function serializeUserAssetsState(state: Partial<UserAssetsState>, version?: num
}

function deserializeUserAssetsState(serializedState: string) {
let parsedState: { state: UserAssetsStateWithTransforms; version: number };
let parsedState: { state: UserAssetsStateToPersistWithTransforms; version: number };
try {
parsedState = JSON.parse(serializedState);
} catch (error) {
Expand Down Expand Up @@ -332,7 +350,13 @@ export const createUserAssetsStore = (address: Address | string) =>
}),
{
storageKey: `userAssets_${address}`,
version: 0,
partialize: state => ({
chainBalances: state.chainBalances,
filter: state.filter,
idsByChain: state.idsByChain,
userAssets: state.userAssets,
}),
version: 1,
serializer: serializeUserAssetsState,
deserializer: deserializeUserAssetsState,
}
Expand Down Expand Up @@ -375,6 +399,6 @@ export function useUserAssetsStore<T>(selector: (state: UserAssetsState) => T) {
return useStore(store, useCallback(selector, []));
}

function getCurrentSearchCache(): Map<string, UniqueId[]> | undefined {
function getCurrentSearchCache(): Map<string, UniqueId[]> {
return getOrCreateStore().getState().searchCache;
}
7 changes: 4 additions & 3 deletions src/state/sync/UserAssetsSync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@ import { ChainId } from '@/chains/types';

export const UserAssetsSync = function UserAssetsSync() {
const { accountAddress, nativeCurrency: currentCurrency } = useAccountSettings();

const isSwapsOpen = useSwapsStore(state => state.isSwapsOpen);
const isUserAssetsStoreMissingData = userAssetsStore.getState().getUserAssets()?.length === 0;
const enabled = (!isSwapsOpen || isUserAssetsStoreMissingData) && !!accountAddress && !!currentCurrency;

useUserAssets(
{
address: accountAddress,
currency: currentCurrency,
},
{
enabled: !isSwapsOpen,
enabled,
select: data =>
selectorFilterByUserChains({
data,
selector: selectUserAssetsList,
}),
onSuccess: data => {
if (!isSwapsOpen) {
jinchung marked this conversation as resolved.
Show resolved Hide resolved
if (!isSwapsOpen || isUserAssetsStoreMissingData) {
userAssetsStore.getState().setUserAssets(data as ParsedSearchAsset[]);

const inputAsset = userAssetsStore.getState().getHighestValueEth();
Expand Down
Loading