Skip to content

Commit

Permalink
perceived finality (#1649)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Sinclair <[email protected]>
  • Loading branch information
derHowie and DanielSinclair authored Aug 19, 2024
1 parent b2e0bb7 commit f9b793d
Show file tree
Hide file tree
Showing 8 changed files with 453 additions and 152 deletions.
12 changes: 10 additions & 2 deletions src/core/raps/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,18 @@ export const walletExecuteRap = async (
parameters: RapSwapActionParameters<
'swap' | 'crosschainSwap' | 'claimBridge'
>,
): Promise<{ nonce: number | undefined; errorMessage: string | null }> => {
): Promise<{
nonce: number | undefined;
errorMessage: string | null;
hash?: string | null;
}> => {
const rap: Rap = await createSwapRapByType(type, parameters);

const { actions } = rap;
const rapName = getRapFullName(rap.actions);
let nonce = parameters?.nonce;
let errorMessage = null;
let txHash = null;
if (actions.length) {
const firstAction = actions[0];
const actionParams = {
Expand Down Expand Up @@ -177,11 +182,14 @@ export const walletExecuteRap = async (
};
const { hash } = await executeAction(actionParams);
hash && (await waitForNodeAck(hash, wallet.provider));
if (index === actions.length - 1) {
txHash = hash;
}
}
nonce = baseNonce + actions.length - 1;
} else {
errorMessage = error;
}
}
return { nonce, errorMessage };
return { nonce, errorMessage, hash: txHash };
};
43 changes: 33 additions & 10 deletions src/core/resources/assets/userAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { SupportedCurrencyKey } from '~/core/references';
import { supportedAssetsChainIds } from '~/core/references/chains';
import { useTestnetModeStore } from '~/core/state/currentSettings/testnetMode';
import { staleBalancesStore } from '~/core/state/staleBalances';
import { ParsedAssetsDictByChain, ParsedUserAsset } from '~/core/types/assets';
import { ChainId } from '~/core/types/chains';
import { AddressAssetsReceivedMessage } from '~/core/types/refraction';
Expand Down Expand Up @@ -78,7 +79,11 @@ export const userAssetsFetchQuery = ({
testnetMode,
}: FetchUserAssetsArgs) => {
queryClient.fetchQuery({
queryKey: userAssetsQueryKey({ address, currency, testnetMode }),
queryKey: userAssetsQueryKey({
address,
currency,
testnetMode,
}),
queryFn: userAssetsQueryFunction,
});
};
Expand Down Expand Up @@ -114,20 +119,26 @@ async function userAssetsQueryFunction({
}: QueryFunctionArgs<typeof userAssetsQueryKey>) {
const cache = queryClient.getQueryCache();
const cachedUserAssets = (cache.find({
queryKey: userAssetsQueryKey({ address, currency, testnetMode }),
queryKey: userAssetsQueryKey({
address,
currency,
testnetMode,
}),
})?.state?.data || {}) as ParsedAssetsDictByChain;
try {
const supportedChainIds = getSupportedChains({
testnets: testnetMode,
})
.map(({ id }) => id)
.filter((id) => supportedAssetsChainIds.includes(id));

const url = `/${supportedChainIds.join(',')}/${address}/assets`;
staleBalancesStore.getState().clearExpiredData(address as Address);
const staleBalancesParam = staleBalancesStore
.getState()
.getStaleBalancesQueryParam(address as Address);
const url = `/${supportedChainIds.join(
',',
)}/${address}/assets/?currency=${currency.toLowerCase()}${staleBalancesParam}`;
const res = await addysHttp.get<AddressAssetsReceivedMessage>(url, {
params: {
currency: currency.toLowerCase(),
},
timeout: USER_ASSETS_TIMEOUT_DURATION,
});
const chainIdsInResponse = res?.data?.meta?.chain_ids || [];
Expand Down Expand Up @@ -183,7 +194,11 @@ async function userAssetsQueryFunctionRetryByChain({
const cache = queryClient.getQueryCache();
const cachedUserAssets =
(cache.find({
queryKey: userAssetsQueryKey({ address, currency, testnetMode }),
queryKey: userAssetsQueryKey({
address,
currency,
testnetMode,
}),
})?.state?.data as ParsedAssetsDictByChain) || {};
const retries = [];
for (const chainIdWithError of chainIds) {
Expand All @@ -206,7 +221,11 @@ async function userAssetsQueryFunctionRetryByChain({
}
}
queryClient.setQueryData(
userAssetsQueryKey({ address, currency, testnetMode }),
userAssetsQueryKey({
address,
currency,
testnetMode,
}),
cachedUserAssets,
);
} catch (e) {
Expand All @@ -230,7 +249,11 @@ export function useUserAssets<TSelectResult = UserAssetsResult>(
) {
const { testnetMode } = useTestnetModeStore();
return useQuery({
queryKey: userAssetsQueryKey({ address, currency, testnetMode }),
queryKey: userAssetsQueryKey({
address,
currency,
testnetMode,
}),
queryFn: userAssetsQueryFunction,
...config,
refetchInterval: USER_ASSETS_REFETCH_INTERVAL,
Expand Down
170 changes: 170 additions & 0 deletions src/core/state/staleBalances/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { Address } from 'viem';
import { expect, test } from 'vitest';

import { DAI_ADDRESS, ETH_ADDRESS, OP_ADDRESS } from '~/core/references';
import { ChainId } from '~/core/types/chains';
import { TEST_ADDRESS_1, TEST_ADDRESS_2 } from '~/test/utils';

import { staleBalancesStore } from '.';

const THEN = Date.now() - 700000;
const WHEN = Date.now() + 60000;

test('should be able to add asset information to the staleBalances object', async () => {
const { addStaleBalance, staleBalances } = staleBalancesStore.getState();
expect(staleBalances).toStrictEqual({});
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.mainnet,
info: {
address: DAI_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: THEN,
},
});
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.mainnet,
info: {
address: ETH_ADDRESS as Address,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
});
const newStaleBalances = staleBalancesStore.getState().staleBalances;
expect(newStaleBalances).toStrictEqual({
[TEST_ADDRESS_1]: {
[ChainId.mainnet]: {
[DAI_ADDRESS]: {
address: DAI_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: THEN,
},
[ETH_ADDRESS]: {
address: ETH_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
},
},
});
});

test('should generate accurate stale balance query params and clear expired data - case #1', async () => {
const { getStaleBalancesQueryParam, clearExpiredData } =
staleBalancesStore.getState();
clearExpiredData(TEST_ADDRESS_1);
const queryParam = getStaleBalancesQueryParam(TEST_ADDRESS_1);
expect(queryParam).toStrictEqual(`&token=${ChainId.mainnet}.${ETH_ADDRESS}`);
});

test('should be able to remove expired stale balance and preserve unexpired data', async () => {
const { addStaleBalance, clearExpiredData } = staleBalancesStore.getState();
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.mainnet,
info: {
address: DAI_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: THEN,
},
});
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.mainnet,
info: {
address: ETH_ADDRESS as Address,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
});
clearExpiredData(TEST_ADDRESS_1);
const newStaleBalances = staleBalancesStore.getState().staleBalances;
expect(newStaleBalances).toStrictEqual({
[TEST_ADDRESS_1]: {
[ChainId.mainnet]: {
[ETH_ADDRESS]: {
address: ETH_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
},
},
});
});

test('should preserve data from other addresses when clearing expired data', async () => {
const { addStaleBalance, clearExpiredData } = staleBalancesStore.getState();
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.mainnet,
info: {
address: DAI_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: THEN,
},
});
addStaleBalance({
address: TEST_ADDRESS_2,
chainId: ChainId.mainnet,
info: {
address: ETH_ADDRESS as Address,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
});
clearExpiredData(TEST_ADDRESS_1);
const newStaleBalances = staleBalancesStore.getState().staleBalances;
expect(newStaleBalances).toStrictEqual({
[TEST_ADDRESS_1]: {
[ChainId.mainnet]: {
[ETH_ADDRESS]: {
address: ETH_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
},
},
[TEST_ADDRESS_2]: {
[ChainId.mainnet]: {
[ETH_ADDRESS]: {
address: ETH_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
},
},
});
});

test('should generate accurate stale balance query params and clear expired data - case #2', async () => {
const { getStaleBalancesQueryParam, clearExpiredData } =
staleBalancesStore.getState();
clearExpiredData(TEST_ADDRESS_2);
const queryParam = getStaleBalancesQueryParam(TEST_ADDRESS_2);
expect(queryParam).toStrictEqual(`&token=${ChainId.mainnet}.${ETH_ADDRESS}`);
});

test('should generate accurate stale balance query params and clear expired data - case #3', async () => {
const { addStaleBalance, getStaleBalancesQueryParam, clearExpiredData } =
staleBalancesStore.getState();
addStaleBalance({
address: TEST_ADDRESS_1,
chainId: ChainId.optimism,
info: {
address: OP_ADDRESS,
transactionHash: '0xFOOBAR',
expirationTime: WHEN,
},
});

clearExpiredData(TEST_ADDRESS_1);
const queryParam = getStaleBalancesQueryParam(TEST_ADDRESS_1);
expect(queryParam).toStrictEqual(
`&token=${ChainId.mainnet}.${ETH_ADDRESS}&token=${ChainId.optimism}.${OP_ADDRESS}`,
);

clearExpiredData(TEST_ADDRESS_2);
const queryParam2 = getStaleBalancesQueryParam(TEST_ADDRESS_2);
expect(queryParam2).toStrictEqual(`&token=${ChainId.mainnet}.${ETH_ADDRESS}`);
});
Loading

0 comments on commit f9b793d

Please sign in to comment.