Skip to content

Commit

Permalink
feat: some useAsyncEffect
Browse files Browse the repository at this point in the history
  • Loading branch information
Majorfi committed Oct 16, 2023
1 parent dd15821 commit 9ae42f8
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 53 deletions.
17 changes: 17 additions & 0 deletions apps/common/hooks/useAsyncEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {useCallback, useEffect} from 'react';

import type {DependencyList} from 'react';

function useAsyncEffect(effect: () => Promise<void>, deps?: DependencyList): () => Promise<void> {
const asyncEffectInCallback = useCallback(async (): Promise<void> => {
effect();
}, [effect, deps]);

useEffect((): void => {
asyncEffectInCallback();
}, [asyncEffectInCallback]);

return asyncEffectInCallback;
}

export {useAsyncEffect};
20 changes: 9 additions & 11 deletions apps/common/hooks/useMultichainBalances.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {useCallback, useMemo, useRef, useState} from 'react';
import {erc20ABI, useChainId} from 'wagmi';
import {deserialize, multicall, serialize} from '@wagmi/core';
import {useUI} from '@yearn-finance/web-lib/contexts/useUI';
Expand All @@ -12,6 +12,8 @@ import {isEth} from '@yearn-finance/web-lib/utils/isEth';
import {isZero} from '@yearn-finance/web-lib/utils/isZero';
import {getNetwork} from '@yearn-finance/web-lib/utils/wagmi/utils';

import {useAsyncEffect} from './useAsyncEffect';

import type {DependencyList} from 'react';
import type {ContractFunctionConfig} from 'viem';
import type {Connector} from 'wagmi';
Expand Down Expand Up @@ -380,7 +382,12 @@ export function useBalances(props?: TUseBalancesReq): TUseBalancesRes {
[props?.prices]
);

const asyncUseEffect = useCallback(async (): Promise<void> => {
/* 🔵 - Yearn Finance ******************************************************
** Everytime the stringifiedTokens change, we need to update the balances.
** This is the main hook and is optimized for performance, using a worker
** to fetch the balances, preventing the UI to freeze.
**************************************************************************/
useAsyncEffect(async (): Promise<void> => {
if (!isActive || !userAddress || !provider) {
return;
}
Expand Down Expand Up @@ -422,15 +429,6 @@ export function useBalances(props?: TUseBalancesReq): TUseBalancesRes {
set_status({...defaultStatus, isSuccess: true, isFetched: true});
}, [stringifiedTokens, isActive, userAddress, provider, onLoadStart, chainID, updateBalancesCall, onLoadDone]);

/* 🔵 - Yearn Finance ******************************************************
** Everytime the stringifiedTokens change, we need to update the balances.
** This is the main hook and is optimized for performance, using a worker
** to fetch the balances, preventing the UI to freeze.
**************************************************************************/
useEffect((): void => {
asyncUseEffect();
}, [asyncUseEffect]);

const contextValue = useMemo(
(): TUseBalancesRes => ({
data: assignPrices(balances || {}),
Expand Down
16 changes: 8 additions & 8 deletions apps/vaults/components/details/actions/QuickActionsButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {useCallback, useEffect, useState} from 'react';
import {useAsync} from '@react-hookz/web';
import {useCallback, useState} from 'react';
import {useActionFlow} from '@vaults/contexts/useActionFlow';
import {useSolver} from '@vaults/contexts/useSolver';
import {useStakingRewards} from '@vaults/contexts/useStakingRewards';
Expand All @@ -14,6 +13,7 @@ import {isZero} from '@yearn-finance/web-lib/utils/isZero';
import {defaultTxStatus} from '@yearn-finance/web-lib/utils/web3/transaction';
import {useWallet} from '@common/contexts/useWallet';
import {useYearn} from '@common/contexts/useYearn';
import {useAsyncEffect} from '@common/hooks/useAsyncEffect';
import {Solver} from '@common/schemas/yDaemonTokenListBalances';

import type {ReactElement} from 'react';
Expand All @@ -29,6 +29,7 @@ export function VaultDetailsQuickActionsButtons({currentVault}: {currentVault: T
const [txStatusApprove, set_txStatusApprove] = useState(defaultTxStatus);
const [txStatusExecuteDeposit, set_txStatusExecuteDeposit] = useState(defaultTxStatus);
const [txStatusExecuteWithdraw, set_txStatusExecuteWithdraw] = useState(defaultTxStatus);
const [allowanceFrom, set_allowanceFrom] = useState<TNormalizedBN>(toNormalizedBN(0));
const {actionParams, onChangeAmount, maxDepositPossible, isDepositing} = useActionFlow();
const {onApprove, onExecuteDeposit, onExecuteWithdraw, onRetrieveAllowance, currentSolver, expectedOut, isLoadingExpectedOut, hash} = useSolver();
const isWithdrawing = !isDepositing;
Expand All @@ -37,10 +38,9 @@ export function VaultDetailsQuickActionsButtons({currentVault}: {currentVault: T
** SWR hook to get the expected out for a given in/out pair with a specific amount. This hook is
** called when amount/in or out changes. Calls the allowanceFetcher callback.
**********************************************************************************************/
const [{result: allowanceFrom, status}, actions] = useAsync(async (): Promise<TNormalizedBN> => onRetrieveAllowance(true), toNormalizedBN(0));
useEffect((): void => {
actions.execute();
}, [actions, provider, address, onRetrieveAllowance, hash]);
const triggerRetrieveAllowance = useAsyncEffect(async (): Promise<void> => {
set_allowanceFrom(await onRetrieveAllowance(true));
}, [address, onRetrieveAllowance, hash]);

const onSuccess = useCallback(async (): Promise<void> => {
onChangeAmount(toNormalizedBN(0));
Expand Down Expand Up @@ -110,9 +110,9 @@ export function VaultDetailsQuickActionsButtons({currentVault}: {currentVault: T
const onApproveFrom = useCallback(async (): Promise<void> => {
const shouldApproveInfinite = currentSolver === Solver.enum.PartnerContract || currentSolver === Solver.enum.Vanilla || currentSolver === Solver.enum.InternalMigration;
onApprove(shouldApproveInfinite ? MAX_UINT_256 : actionParams?.amount.raw, set_txStatusApprove, async (): Promise<void> => {
await actions.execute();
await triggerRetrieveAllowance();
});
}, [actionParams?.amount.raw, actions, currentSolver, onApprove]);
}, [actionParams?.amount.raw, triggerRetrieveAllowance, currentSolver, onApprove]);

const isButtonDisabled =
(!address && !provider) || isZero(actionParams.amount.raw) || toBigInt(actionParams.amount.raw) > toBigInt(maxDepositPossible.raw) || isLoadingExpectedOut;
Expand Down
19 changes: 5 additions & 14 deletions apps/vaults/contexts/useStakingRewards.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {createContext, memo, useCallback, useContext, useEffect, useMemo, useState} from 'react';
import {createContext, memo, useCallback, useContext, useMemo, useState} from 'react';
import {OPT_STAKING_REWARD_SUPPORTED_NETWORK} from '@vaults/constants';
import {STACKING_TO_VAULT, VAULT_TO_STACKING} from '@vaults/constants/optRewards';
import {STAKING_REWARDS_ABI} from '@vaults/utils/abi/stakingRewards.abi';
Expand All @@ -8,6 +8,7 @@ import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {toAddress} from '@yearn-finance/web-lib/utils/address';
import {STAKING_REWARDS_REGISTRY_ADDRESS} from '@yearn-finance/web-lib/utils/constants';
import {decodeAsBigInt, decodeAsString} from '@yearn-finance/web-lib/utils/decoder';
import {useAsyncEffect} from '@common/hooks/useAsyncEffect';
import {keyBy} from '@common/utils';

import type {ReactElement} from 'react';
Expand Down Expand Up @@ -43,7 +44,7 @@ export const StakingRewardsContextApp = memo(function StakingRewardsContextApp({
const [stakingRewards, set_stakingRewards] = useState<TStakingRewards[]>([]);
const [positions, set_positions] = useState<TStakePosition[]>([]);

const stakingRewardsFetcher = useCallback(async (): Promise<TStakingRewards[]> => {
const stakingRewardsFetcher = useAsyncEffect(async (): Promise<void> => {
const stakingPoolCalls = [];
const stackingAddresses = Object.values(VAULT_TO_STACKING);
for (const stackingAddress of stackingAddresses) {
Expand Down Expand Up @@ -94,16 +95,11 @@ export const StakingRewardsContextApp = memo(function StakingRewardsContextApp({
}

set_stakingRewards(_stackingRewards);
return _stackingRewards;
}, []);

useEffect((): void => {
stakingRewardsFetcher();
}, [stakingRewardsFetcher]);

const positionsFetcher = useCallback(async (): Promise<TStakePosition[]> => {
const positionsFetcher = useAsyncEffect(async (): Promise<void> => {
if (!stakingRewards || !isActive || !userAddress) {
return [];
return;
}
/* 🔵 - Yearn Finance **********************************************************************
** Retrieve the number of tokens in the registry, and for each token retrieve it's address
Expand Down Expand Up @@ -138,13 +134,8 @@ export const StakingRewardsContextApp = memo(function StakingRewardsContextApp({
}

set_positions(positionPromises);
return positionPromises;
}, [stakingRewards, isActive, userAddress, OPT_STAKING_REWARD_SUPPORTED_NETWORK]);

useEffect((): void => {
positionsFetcher();
}, [positionsFetcher]);

const positionsMap = useMemo((): TDict<TStakePosition | undefined> => {
return keyBy(positions ?? [], 'address');
}, [positions]);
Expand Down
9 changes: 3 additions & 6 deletions apps/veyfi/contexts/useGauge.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {createContext, memo, useCallback, useContext, useEffect, useMemo} from 'react';
import React, {createContext, memo, useCallback, useContext, useMemo} from 'react';
import {FixedNumber} from 'ethers';
import {useContractRead} from 'wagmi';
import {useAsync} from '@react-hookz/web';
Expand All @@ -9,6 +9,7 @@ import {VEYFI_REGISTRY_ADDRESS} from '@veYFI/utils/constants';
import {erc20ABI, getContract, multicall} from '@wagmi/core';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {allowanceKey} from '@yearn-finance/web-lib/utils/address';
import {useAsyncEffect} from '@common/hooks/useAsyncEffect';

import type {ReactElement} from 'react';
import type {TAddress, TDict} from '@yearn-finance/web-lib/types';
Expand Down Expand Up @@ -142,16 +143,12 @@ export const GaugeContextApp = memo(function GaugeContextApp({children}: {childr
return gaugesFetcher();
}, []);

const refresh = useCallback((): void => {
const refresh = useAsyncEffect(async (): Promise<void> => {
refreshVotingEscrow();
refreshPositions();
refreshAllowances();
}, [refreshAllowances, refreshPositions, refreshVotingEscrow]);

useEffect((): void => {
refresh();
}, [refresh]);

const positionsFetcher = useCallback(async (): Promise<TGaugePosition[]> => {
if (!gauges || !isActive || !userAddress) {
return [];
Expand Down
9 changes: 3 additions & 6 deletions apps/veyfi/contexts/useOption.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {createContext, memo, useCallback, useContext, useEffect, useMemo} from 'react';
import React, {createContext, memo, useCallback, useContext, useMemo} from 'react';
import {ethers} from 'ethers';
import {useAsync} from '@react-hookz/web';
import {VEYFI_OPTIONS_ABI} from '@veYFI/utils/abi/veYFIOptions.abi';
Expand All @@ -9,6 +9,7 @@ import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {allowanceKey} from '@yearn-finance/web-lib/utils/address';
import {BIG_ZERO, ETH_TOKEN_ADDRESS, YFI_ADDRESS} from '@yearn-finance/web-lib/utils/constants';
import {toBigInt, toNormalizedValue} from '@yearn-finance/web-lib/utils/format.bigNumber';
import {useAsyncEffect} from '@common/hooks/useAsyncEffect';
import {useTokenPrice} from '@common/hooks/useTokenPrice';

import type {ReactElement} from 'react';
Expand Down Expand Up @@ -66,16 +67,12 @@ export const OptionContextApp = memo(function OptionContextApp({children}: {chil
return allowancesFetcher();
}, {});

const refresh = useCallback((): void => {
const refresh = useAsyncEffect(async (): Promise<void> => {
refreshPrice();
refreshPositions();
refreshAllowances();
}, [refreshPrice, refreshPositions, refreshAllowances]);

useEffect((): void => {
refresh();
}, [refresh]);

const getRequiredEth = useCallback(async (amount: bigint): Promise<bigint> => {
// TODO: update once abi is available
return readContract({
Expand Down
12 changes: 4 additions & 8 deletions apps/ybribe/contexts/useBribes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {toBigInt} from '@yearn-finance/web-lib/utils/format.bigNumber';
import {isZero} from '@yearn-finance/web-lib/utils/isZero';
import {performBatchedUpdates} from '@yearn-finance/web-lib/utils/performBatchedUpdates';
import {useCurve} from '@common/contexts/useCurve';
import {useAsyncEffect} from '@common/hooks/useAsyncEffect';
import {YBRIBE_SUPPORTED_NETWORK} from '@yBribe/constants';
import {getLastThursday, getNextThursday} from '@yBribe/utils';
import {CURVE_BRIBE_V3_ABI} from '@yBribe/utils/abi/curveBribeV3.abi';
Expand Down Expand Up @@ -66,10 +67,8 @@ export const BribesContextApp = ({children}: {children: React.ReactElement}): Re
** Bribe contracts, not related to the user.
***************************************************************************/
useEffect((): void => {
performBatchedUpdates((): void => {
set_currentPeriod(Number(_currentPeriod));
set_nextPeriod(Number(_currentPeriod) + 86400 * 7);
});
set_currentPeriod(Number(_currentPeriod));
set_nextPeriod(Number(_currentPeriod) + 86400 * 7);
}, [_currentPeriod]);

/* 🔵 - Yearn Finance ******************************************************
Expand Down Expand Up @@ -267,7 +266,7 @@ export const BribesContextApp = ({children}: {children: React.ReactElement}): Re
/* 🔵 - Yearn Finance ******************************************************
** getBribes will start the process to retrieve the bribe information.
***************************************************************************/
const getBribes = useCallback(async (): Promise<void> => {
const getBribes = useAsyncEffect(async (): Promise<void> => {
const rewardsPerGauges = await getRewardsPerGauges();
const [rewardsPerUser, nextPeriodRewards] = await Promise.all([getRewardsPerUser(rewardsPerGauges), getNextPeriodRewards(rewardsPerGauges)]);

Expand All @@ -277,9 +276,6 @@ export const BribesContextApp = ({children}: {children: React.ReactElement}): Re
});
return;
}, [getRewardsPerGauges, getRewardsPerUser, getNextPeriodRewards, assignBribes, assignNextRewards]);
useEffect((): void => {
getBribes();
}, [getBribes]);

const onRefresh = useCallback(async (): Promise<void> => {
await getBribes();
Expand Down

0 comments on commit 9ae42f8

Please sign in to comment.