Skip to content

Commit

Permalink
feat: Migrate useGauge to wagmi
Browse files Browse the repository at this point in the history
  • Loading branch information
karelianpie committed Jun 21, 2023
1 parent ad2d3b8 commit 56a7042
Showing 1 changed file with 75 additions and 38 deletions.
113 changes: 75 additions & 38 deletions apps/veyfi/contexts/useGauge.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, {createContext, memo, useCallback, useContext, useMemo} from 'react';
import {Contract} from 'ethcall';
import {Contract} from 'ethcall'; // TODO: Remove this import
import {FixedNumber} from 'ethers';
import {useContractRead} from 'wagmi';
import useSWR from 'swr';
import {keyBy} from '@veYFI/utils';
import VEYFI_GAUGE_ABI from '@veYFI/utils/abi/veYFIGauge.abi';
import VEYFI_REGISTRY_ABI from '@veYFI/utils/abi/veYFIRegistry.abi';
import {VEYFI_REGISTRY_ADDRESS} from '@veYFI/utils/constants';
import {getContract, multicall} from '@wagmi/core';
import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import {useChainID} from '@yearn-finance/web-lib/hooks/useChainID';
import ERC20_ABI from '@yearn-finance/web-lib/utils/abi/erc20.abi';
import {allowanceKey} from '@yearn-finance/web-lib/utils/address';
import {getProvider, newEthCallProvider} from '@yearn-finance/web-lib/utils/web3/providers';

import type {Call} from 'ethcall';
import type {Call} from 'ethcall'; // TODO: Remove this import
import type {ReactElement} from 'react';
import type {TAddress, TDict} from '@yearn-finance/web-lib/types';

Expand Down Expand Up @@ -56,30 +58,57 @@ const defaultProps: TGaugeContext = {

const GaugeContext = createContext<TGaugeContext>(defaultProps);
export const GaugeContextApp = memo(function GaugeContextApp({children}: {children: ReactElement}): ReactElement {
const {provider, address: userAddress, isActive} = useWeb3();
const {address: userAddress, isActive} = useWeb3();
const {chainID} = useChainID();
const veYFIRegistryContract = useMemo((): {address: TAddress, abi: typeof VEYFI_REGISTRY_ABI} => ({
address: VEYFI_REGISTRY_ADDRESS,
abi: VEYFI_REGISTRY_ABI
}), []);
const {data: vaultAddresses} = useContractRead({
...veYFIRegistryContract,
functionName: 'getVaults',
chainId: chainID
});

const gaugesFetcher = useCallback(async (): Promise<TGauge[]> => {
const currentProvider = getProvider(1);
const ethcallProvider = await newEthCallProvider(currentProvider);
const veYFIRegistryContract = new Contract(VEYFI_REGISTRY_ADDRESS, VEYFI_REGISTRY_ABI); // todo: update once abi is available
const [vaultAddresses] = await ethcallProvider.tryAll([veYFIRegistryContract.getVaults()]) as [TAddress[]];
const gaugeAddressCalls = vaultAddresses.map((address): Call => veYFIRegistryContract.gauges(address));
const gaugeAddresses = await ethcallProvider.tryAll(gaugeAddressCalls) as TAddress[];
if (!isActive || !userAddress) {
return [];
}

const gaugeAddressCalls = [];
for (const vaultAddress of vaultAddresses as TAddress[]) {
gaugeAddressCalls.push({
...veYFIRegistryContract,
functionName: 'gauges',
args: [vaultAddress]
});
}

// TODO: Types of property 'abi' are incompatible.
const gaugeAddressesResults = await multicall({contracts: gaugeAddressCalls, chainId: chainID});

const gaugeAddresses = gaugeAddressesResults.map(({result}): unknown => result) as TAddress[];
const gaugePromises = gaugeAddresses.map(async (address): Promise<TGauge> => {
const veYFIGaugeContract = new Contract(address, VEYFI_GAUGE_ABI); // todo: update once abi is available
const [
asset,
name,
symbol,
decimals,
totalAssets
] = await ethcallProvider.tryAll([
veYFIGaugeContract.asset(),
veYFIGaugeContract.name(),
veYFIGaugeContract.symbol(),
veYFIGaugeContract.decimals(),
veYFIGaugeContract.totalAssets()
]) as [TAddress, string, string, number, bigint];
// todo: update once abi is available
const veYFIGaugeContract = getContract({
address,
abi: VEYFI_GAUGE_ABI
});


// TODO: These should be migrated to wagmi
const results = await multicall({
contracts: [
veYFIGaugeContract.asset(),
veYFIGaugeContract.name(),
veYFIGaugeContract.symbol(),
veYFIGaugeContract.decimals(),
veYFIGaugeContract.totalAssets()
],
chainId: chainID
});

const [asset, name, symbol, decimals, totalAssets] = results.map(({result}): unknown => result) as [TAddress, string, string, number, bigint];

return ({
address,
Expand All @@ -98,16 +127,20 @@ export const GaugeContextApp = memo(function GaugeContextApp({children}: {childr
if (!gauges|| !isActive|| !userAddress) {
return [];
}
const currentProvider = getProvider(1);
const ethcallProvider = await newEthCallProvider(currentProvider);

const positionPromises = gauges.map(async ({address}): Promise<TGaugePosition> => {
const veYFIGaugeContract = new Contract(address, VEYFI_GAUGE_ABI); // todo: update once abi is available
const [balance, earned, boostedBalance] = await ethcallProvider.tryAll([
veYFIGaugeContract.balanceOf(userAddress),
veYFIGaugeContract.earned(userAddress),
veYFIGaugeContract.nextBoostedBalanceOf(userAddress)
]) as bigint[];

const results = await multicall({
contracts: [
veYFIGaugeContract.balanceOf(userAddress),
veYFIGaugeContract.earned(userAddress),
veYFIGaugeContract.nextBoostedBalanceOf(userAddress)
],
chainId: chainID
});

const [balance, earned, boostedBalance] = results.map(({result}): unknown => result) as bigint[];

const depositPosition: TPosition = {
balance,
Expand All @@ -132,29 +165,33 @@ export const GaugeContextApp = memo(function GaugeContextApp({children}: {childr
};
});
return Promise.all(positionPromises);
}, [gauges, isActive, userAddress]);
const {data: positions, mutate: refreshPositions, isLoading: isLoadingPositions} = useSWR(gauges && isActive && provider ? 'gaugePositions' : null, positionsFetcher, {shouldRetryOnError: false});
}, [chainID, gauges, isActive, userAddress]);
const {data: positions, mutate: refreshPositions, isLoading: isLoadingPositions} = useSWR(gauges && isActive ? 'gaugePositions' : null, positionsFetcher, {shouldRetryOnError: false});

const allowancesFetcher = useCallback(async (): Promise<TDict<bigint>> => {
if (!gauges || !isActive || !userAddress) {
return {};
}
const currentProvider = getProvider(1);
const ethcallProvider = await newEthCallProvider(currentProvider);

const allowanceCalls = gauges.map(({address, vaultAddress}): Call => {
const erc20Contract = new Contract(vaultAddress, ERC20_ABI);
return erc20Contract.allowance(userAddress, address);
});
const allowances = await ethcallProvider.tryAll(allowanceCalls) as bigint[];

const results = await multicall({
contracts: allowanceCalls,
chainId: chainID
});
const allowances = results.map(({result}): unknown => result) as bigint[];

const allowancesMap: TDict<bigint> = {};
gauges.forEach(({address, vaultAddress}, index): void => {
allowancesMap[allowanceKey(1, vaultAddress, address, userAddress)] = allowances[index];
});

return allowancesMap;
}, [gauges, isActive, userAddress]);
const {data: allowancesMap, mutate: refreshAllowances, isLoading: isLoadingAllowances} = useSWR(gauges && isActive && provider ? 'gaugeAllowances' : null, allowancesFetcher, {shouldRetryOnError: false});
}, [chainID, gauges, isActive, userAddress]);
const {data: allowancesMap, mutate: refreshAllowances, isLoading: isLoadingAllowances} = useSWR(gauges && isActive ? 'gaugeAllowances' : null, allowancesFetcher, {shouldRetryOnError: false});

const refresh = useCallback((): void => {
refreshVotingEscrow();
Expand Down

0 comments on commit 56a7042

Please sign in to comment.