Skip to content

Commit

Permalink
build: bump
Browse files Browse the repository at this point in the history
  • Loading branch information
Majorfi committed Mar 12, 2024
1 parent 93d10e5 commit be95529
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 30 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yearn-finance/web-lib",
"version": "3.0.180",
"version": "3.0.181",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
"files": [
Expand Down
156 changes: 156 additions & 0 deletions src/contexts/useYearn.helper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import {useCallback, useMemo} from 'react';
import {useBalances} from '@builtbymom/web3/hooks/useBalances.multichains';
import {toAddress} from '@builtbymom/web3/utils';
import {useDeepCompareMemo} from '@react-hookz/web';

import {
CRV_TOKEN_ADDRESS,
CVXCRV_TOKEN_ADDRESS,
ETH_TOKEN_ADDRESS,
LPYCRV_TOKEN_ADDRESS,
LPYCRV_V2_TOKEN_ADDRESS,
YCRV_CURVE_POOL_V2_ADDRESS,
YCRV_TOKEN_ADDRESS,
YVBOOST_TOKEN_ADDRESS,
YVECRV_TOKEN_ADDRESS
} from '../utils/constants';
import {useYearn} from './useYearn';

import type {TUseBalancesTokens} from '@builtbymom/web3/hooks/useBalances.multichains';
import type {TDict} from '@builtbymom/web3/types';
import type {TYChainTokens} from '../types';
import type {TYDaemonVault} from '../utils/schemas/yDaemonVaultsSchemas';

export function useYearnTokens({shouldUseForknetBalances}: {shouldUseForknetBalances: boolean}): TUseBalancesTokens[] {
const {vaults, vaultsMigrations, vaultsRetired, isLoadingVaultList} = useYearn();

const availableTokens = useMemo((): TUseBalancesTokens[] => {
if (isLoadingVaultList) {
return [];
}
const tokens: TUseBalancesTokens[] = [];
const tokensExists: TDict<boolean> = {};
const extraTokens: TUseBalancesTokens[] = [];
extraTokens.push(
...[
{chainID: 1, address: ETH_TOKEN_ADDRESS},
{chainID: 10, address: ETH_TOKEN_ADDRESS},
{chainID: 137, address: ETH_TOKEN_ADDRESS},
{chainID: 250, address: ETH_TOKEN_ADDRESS},
{chainID: 8453, address: ETH_TOKEN_ADDRESS},
{chainID: 42161, address: ETH_TOKEN_ADDRESS},
{chainID: 1, address: YCRV_TOKEN_ADDRESS},
{chainID: 1, address: LPYCRV_TOKEN_ADDRESS},
{chainID: 1, address: CRV_TOKEN_ADDRESS},
{chainID: 1, address: YVBOOST_TOKEN_ADDRESS},
{chainID: 1, address: YVECRV_TOKEN_ADDRESS},
{chainID: 1, address: CVXCRV_TOKEN_ADDRESS},
{chainID: 1, address: YCRV_CURVE_POOL_V2_ADDRESS},
{chainID: 1, address: LPYCRV_V2_TOKEN_ADDRESS}
]
);

for (const token of extraTokens) {
tokensExists[token.address] = true;
tokens.push(token);
}

Object.values(vaults || {}).forEach((vault?: TYDaemonVault): void => {
if (!vault) {
return;
}
if (vault?.address && !tokensExists[toAddress(vault?.address)]) {
tokens.push({address: vault.address, chainID: vault.chainID});
tokensExists[vault.address] = true;
}
if (vault?.token?.address && !tokensExists[toAddress(vault?.token?.address)]) {
tokens.push({address: vault.token.address, chainID: vault.chainID});
tokensExists[vault.token.address] = true;
}
if (vault?.staking?.available && !tokensExists[toAddress(vault?.staking?.address)]) {
tokens.push({
address: vault?.staking?.address,
chainID: vault.chainID,
symbol: vault.symbol,
decimals: vault.decimals,
name: vault.name
});
tokensExists[vault?.staking?.address] = true;
}
});

return tokens;
}, [isLoadingVaultList, vaults]);

//List all vaults with a possible migration
const migratableTokens = useMemo((): TUseBalancesTokens[] => {
const tokens: TUseBalancesTokens[] = [];
Object.values(vaultsMigrations || {}).forEach((vault?: TYDaemonVault): void => {
if (!vault) {
return;
}
tokens.push({address: vault.address, chainID: vault.chainID});
});
return tokens;
}, [vaultsMigrations]);

const retiredTokens = useMemo((): TUseBalancesTokens[] => {
const tokens: TUseBalancesTokens[] = [];
Object.values(vaultsRetired || {}).forEach((vault?: TYDaemonVault): void => {
if (!vault) {
return;
}
tokens.push({address: vault.address, chainID: vault.chainID});
});
return tokens;
}, [vaultsRetired]);

const allTokens = useMemo((): TUseBalancesTokens[] => {
const tokens = [...availableTokens, ...migratableTokens, ...retiredTokens];
if (!shouldUseForknetBalances) {
return tokens;
}
for (const token of tokens) {
if (token.chainID === 1) {
//remove it
tokens.push({...token, chainID: 1337});
}
}
return tokens;
}, [availableTokens, migratableTokens, retiredTokens, shouldUseForknetBalances]);

return allTokens;
}

export function useYearnBalances({shouldUseForknetBalances}: {shouldUseForknetBalances: boolean}): {
tokens: TYChainTokens;
isLoading: boolean;
onRefresh: (tokenToUpdate?: TUseBalancesTokens[]) => Promise<TYChainTokens>;
} {
const {prices} = useYearn();
const allTokens = useYearnTokens({shouldUseForknetBalances});
const {data: tokensRaw, onUpdate, onUpdateSome, isLoading} = useBalances({tokens: allTokens, prices});

const tokens = useDeepCompareMemo((): TYChainTokens => {
const _tokens = {...tokensRaw};
if (shouldUseForknetBalances) {
_tokens[1] = _tokens[1337]; // eslint-disable-line prefer-destructuring
}

return _tokens as TYChainTokens;
}, [tokensRaw, shouldUseForknetBalances]);

const onRefresh = useCallback(
async (tokenToUpdate?: TUseBalancesTokens[]): Promise<TYChainTokens> => {
if (tokenToUpdate) {
const updatedBalances = await onUpdateSome(tokenToUpdate);
return updatedBalances as TYChainTokens;
}
const updatedBalances = await onUpdate();
return updatedBalances as TYChainTokens;
},
[onUpdate, onUpdateSome]
);

return {tokens, isLoading, onRefresh};
}
125 changes: 118 additions & 7 deletions src/contexts/useYearn.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import {createContext, memo, useContext, useEffect} from 'react';
import {createContext, memo, useCallback, useContext, useEffect, useMemo, useState} from 'react';
import {deserialize, serialize} from 'wagmi';
import {toAddress} from '@builtbymom/web3/utils';
import {useWeb3} from '@builtbymom/web3/contexts/useWeb3';
import {isZeroAddress, toAddress, toNormalizedBN, zeroNormalizedBN} from '@builtbymom/web3/utils';
import {useLocalStorageValue} from '@react-hookz/web';

import {useFetchYearnEarnedForUser} from '../hooks/useFetchYearnEarnedForUser';
import {useFetchYearnPrices} from '../hooks/useFetchYearnPrices';
import {useFetchYearnTokens} from '../hooks/useFetchYearnTokens';
import {useFetchYearnVaults} from '../hooks/useFetchYearnVaults';
import {Solver} from '../utils/schemas/yDaemonTokenListBalances';
import {useYearnWallet} from './useYearnWallet';
import {useYearnBalances} from './useYearn.helper';

import type {ReactElement} from 'react';
import type {KeyedMutator} from 'swr';
import type {TUseBalancesTokens} from '@builtbymom/web3/hooks/useBalances.multichains';
import type {TAddress, TDict} from '@builtbymom/web3/types';
import type {TAddress, TDict, TNormalizedBN} from '@builtbymom/web3/types';
import type {TYChainTokens, TYToken} from '../types';
import type {TYDaemonEarned} from '../utils/schemas/yDaemonEarnedSchema';
import type {TYDaemonPricesChain} from '../utils/schemas/yDaemonPricesSchema';
import type {TSolver} from '../utils/schemas/yDaemonTokenListBalances';
Expand All @@ -23,6 +25,7 @@ import type {TYDaemonVault, TYDaemonVaults} from '../utils/schemas/yDaemonVaults
export const DEFAULT_SLIPPAGE = 0.5;
export const DEFAULT_MAX_LOSS = 1n;

type TTokenAndChain = {address: TAddress; chainID: number};
export type TYearnContext = {
currentPartner: TAddress;
earned?: TYDaemonEarned;
Expand All @@ -41,6 +44,31 @@ export type TYearnContext = {
set_zapSlippage: (value: number) => void;
set_zapProvider: (value: TSolver) => void;
set_isStakingOpBoostedVaults: (value: boolean) => void;
//
//Yearn wallet context
getToken: ({address, chainID}: TTokenAndChain) => TYToken;
getBalance: ({address, chainID}: TTokenAndChain) => TNormalizedBN;
getPrice: ({address, chainID}: TTokenAndChain) => TNormalizedBN;
balances: TYChainTokens;
cumulatedValueInV2Vaults: number;
cumulatedValueInV3Vaults: number;
isLoading: boolean;
shouldUseForknetBalances: boolean;
onRefresh: (tokenList?: TUseBalancesTokens[]) => Promise<TYChainTokens>;
triggerForknetBalances: () => void;
};

const defaultToken: TYToken = {
address: toAddress(''),
name: '',
symbol: '',
decimals: 18,
chainID: 1,
value: 0,
stakingValue: 0,
price: zeroNormalizedBN,
balance: zeroNormalizedBN,
supportedZaps: []
};

const YearnContext = createContext<TYearnContext>({
Expand All @@ -65,11 +93,24 @@ const YearnContext = createContext<TYearnContext>({
set_maxLoss: (): void => undefined,
set_zapSlippage: (): void => undefined,
set_zapProvider: (): void => undefined,
set_isStakingOpBoostedVaults: (): void => undefined
set_isStakingOpBoostedVaults: (): void => undefined,
//
//Yearn wallet context
getToken: (): TYToken => defaultToken,
getBalance: (): TNormalizedBN => zeroNormalizedBN,
getPrice: (): TNormalizedBN => zeroNormalizedBN,
balances: {},
cumulatedValueInV2Vaults: 0,
cumulatedValueInV3Vaults: 0,
isLoading: true,
shouldUseForknetBalances: false,
onRefresh: async (): Promise<TYChainTokens> => ({}),
triggerForknetBalances: (): void => {}
});

export const YearnContextApp = memo(function YearnContextApp({children}: {children: ReactElement}): ReactElement {
const {onRefresh} = useYearnWallet();
const {address: userAddress} = useWeb3();
const [shouldUseForknetBalances, set_shouldUseForknetBalances] = useState<boolean>(false);
const {value: maxLoss, set: set_maxLoss} = useLocalStorageValue<bigint>('yearn.fi/max-loss', {
defaultValue: DEFAULT_MAX_LOSS,
parse: (str, fallback): bigint => (str ? deserialize(str) : fallback ?? DEFAULT_MAX_LOSS),
Expand All @@ -92,6 +133,7 @@ export const YearnContextApp = memo(function YearnContextApp({children}: {childr
const tokens = useFetchYearnTokens();
const earned = useFetchYearnEarnedForUser();
const {vaults, vaultsMigrations, vaultsRetired, isLoading, mutate} = useFetchYearnVaults();
const {tokens: balances, isLoading: isLoadingBalances, onRefresh} = useYearnBalances({shouldUseForknetBalances});

useEffect(() => {
const tokensToRefresh: TUseBalancesTokens[] = [];
Expand All @@ -108,6 +150,57 @@ export const YearnContextApp = memo(function YearnContextApp({children}: {childr
onRefresh(tokensToRefresh);
}, [tokens, onRefresh]);

const [cumulatedValueInV2Vaults, cumulatedValueInV3Vaults] = useMemo((): [number, number] => {
let cumulatedValueInV2Vaults = 0;
let cumulatedValueInV3Vaults = 0;
for (const [, perChain] of Object.entries(balances)) {
for (const [tokenAddress, tokenData] of Object.entries(perChain)) {
if (tokenData.value + tokenData.stakingValue === 0) {
continue;
}
if (vaults?.[toAddress(tokenAddress)]) {
if (vaults[toAddress(tokenAddress)].version.split('.')?.[0] === '3') {
cumulatedValueInV3Vaults += tokenData.value + tokenData.stakingValue;
} else {
cumulatedValueInV2Vaults += tokenData.value + tokenData.stakingValue;
}
} else if (vaultsMigrations?.[toAddress(tokenAddress)]) {
if (vaultsMigrations[toAddress(tokenAddress)].version.split('.')?.[0] === '3') {
cumulatedValueInV3Vaults += tokenData.value + tokenData.stakingValue;
} else {
cumulatedValueInV2Vaults += tokenData.value + tokenData.stakingValue;
}
}
}
}
return [cumulatedValueInV2Vaults, cumulatedValueInV3Vaults];
}, [vaults, vaultsMigrations, balances]);

const getToken = useCallback(
({address, chainID}: TTokenAndChain): TYToken => balances?.[chainID || 1]?.[address] || defaultToken,
[balances]
);
const getBalance = useCallback(
({address, chainID}: TTokenAndChain): TNormalizedBN => {
if (isZeroAddress(userAddress)) {
return zeroNormalizedBN;
}
return balances?.[chainID || 1]?.[address]?.balance || zeroNormalizedBN;
},
[balances, userAddress]
);

const getPrice = useCallback(
({address, chainID}: TTokenAndChain): TNormalizedBN => {
const price = balances?.[chainID || 1]?.[address]?.price;
if (!price) {
return toNormalizedBN(prices?.[chainID]?.[address] || 0, 6) || zeroNormalizedBN;
}
return price;
},
[prices, balances]
);

return (
<YearnContext.Provider
value={{
Expand All @@ -127,7 +220,25 @@ export const YearnContextApp = memo(function YearnContextApp({children}: {childr
vaultsMigrations,
vaultsRetired,
isLoadingVaultList: isLoading,
mutateVaultList: mutate
mutateVaultList: mutate,
getToken,
getBalance,
getPrice,
balances: balances,
cumulatedValueInV2Vaults,
cumulatedValueInV3Vaults,
isLoading: isLoadingBalances || false,
shouldUseForknetBalances,
onRefresh,
triggerForknetBalances: (): void =>
set_shouldUseForknetBalances((s): boolean => {
const isEnabled = !s;
if (!(window as any).ethereum) {
(window as any).ethereum = {};
}
(window as any).ethereum.useForknetForMainnet = isEnabled;
return isEnabled;
})
}}>
{children}
</YearnContext.Provider>
Expand Down

0 comments on commit be95529

Please sign in to comment.