diff --git a/src/components/selectors/VariableRate.tsx b/src/components/selectors/VariableRate.tsx
index f80639eb3..1542c77ab 100644
--- a/src/components/selectors/VariableRate.tsx
+++ b/src/components/selectors/VariableRate.tsx
@@ -4,6 +4,7 @@ import styled from 'styled-components';
import { UserContext } from '../../contexts/UserContext';
import { SettingsContext } from '../../contexts/SettingsContext';
import YieldMark from '../logos/YieldMark';
+import SkeletonWrap from '../wraps/SkeletonWrap';
const StyledBox = styled(Box)`
-webkit-transition: transform 0.3s ease-in-out;
@@ -68,7 +69,7 @@ const ShineyBox = styled(Box)`
}
`;
-const VariableRate = () => {
+const VariableRate = ({ rate }: { rate?: string }) => {
const {
settingsState: { darkMode },
} = useContext(SettingsContext);
@@ -139,9 +140,13 @@ const VariableRate = () => {
-
- {2.7} % {'APR'}
-
+ {rate ? (
+
+ {parseFloat(rate).toFixed(2)} % {'APR'}
+
+ ) : (
+
+ )}
diff --git a/src/components/views/Borrow.tsx b/src/components/views/Borrow.tsx
index 8e96f4196..691286951 100644
--- a/src/components/views/Borrow.tsx
+++ b/src/components/views/Borrow.tsx
@@ -25,6 +25,7 @@ import InfoBite from '../InfoBite';
import NextButton from '../buttons/NextButton';
import TransactButton from '../buttons/TransactButton';
import { useApr } from '../../hooks/useApr';
+import { useAprVR } from '../../hooks/useAprVR';
import PositionAvatar from '../PositionAvatar';
import VaultDropSelector from '../selectors/VaultDropSelector';
import { useInputValidation } from '../../hooks/useInputValidation';
@@ -89,6 +90,8 @@ const Borrow = () => {
const borrow = useBorrow();
const { apr } = useApr(borrowInput, ActionType.BORROW, selectedSeries);
+ const { apr: aprVR } = useAprVR(borrowInput, ActionType.BORROW);
+
const { data: assetPair } = useAssetPair(selectedBase?.id, selectedIlk?.id);
const { data: basesVR } = useBasesVR();
const { data: vaultsVR } = useVaultsVR();
@@ -168,6 +171,7 @@ const Borrow = () => {
const handleMaxAction = (actionCode: ActionCodes) => {
actionCode === ActionCodes.ADD_COLLATERAL && setCollatInput(maxCollateral!);
actionCode === ActionCodes.BORROW && selectedSeries && setBorrowInput(selectedSeries.sharesReserves_!);
+ actionCode === ActionCodes.BORROW && selectedVR && setBorrowInput(maxDebtVR_!);
logAnalyticsEvent(GA_Event.max_clicked, {
view: GA_View.BORROW,
action_code: actionCode,
@@ -340,7 +344,9 @@ const Borrow = () => {
placeholder="Enter amount"
value={borrowInput}
onChange={(event: any) =>
- setBorrowInput(cleanValue(event.target.value, selectedSeries?.decimals))
+ setBorrowInput(
+ cleanValue(event.target.value, selectedSeries?.decimals || selectedBase?.decimals)
+ )
}
autoFocus={!mobile}
/>
@@ -370,7 +376,7 @@ const Borrow = () => {
{basesVR?.length && basesVR.includes(selectedBase?.id!) ? (
-
+
) : null}
diff --git a/src/components/views/Lend.tsx b/src/components/views/Lend.tsx
index aa631d2b6..879e40086 100644
--- a/src/components/views/Lend.tsx
+++ b/src/components/views/Lend.tsx
@@ -48,6 +48,7 @@ import { useLendHelpersFR } from '../../hooks/viewHelperHooks/useLendHelpers/use
import { useLendHelpersVR } from '../../hooks/viewHelperHooks/useLendHelpers/useLendHelpersVR';
import useVYTokens from '../../hooks/entities/useVYTokens';
import useBasesVR from '../../hooks/views/useBasesVR';
+import { useAprVR } from '../../hooks/useAprVR';
const Lend = () => {
const mobile: boolean = useContext(ResponsiveContext) === 'small';
@@ -65,6 +66,8 @@ const Lend = () => {
const [stepPosition, setStepPosition] = useState(0);
const [stepDisabled, setStepDisabled] = useState(true);
+ const { apr: aprVR } = useAprVR(lendInput, ActionType.LEND);
+
/* HOOK FNS */
const {
maxLend_: maxLendFR_,
@@ -214,7 +217,7 @@ const Lend = () => {
{basesVR?.length && basesVR.includes(selectedBase?.id!) ? (
-
+
) : null}
diff --git a/src/components/views/LendPosition.tsx b/src/components/views/LendPosition.tsx
index 97fbbfa3a..52007eac6 100644
--- a/src/components/views/LendPosition.tsx
+++ b/src/components/views/LendPosition.tsx
@@ -307,7 +307,7 @@ const LendPosition = () => {
/>
} />
diff --git a/src/contracts/VRInterestRateOracle.d.ts b/src/contracts/VRInterestRateOracle.d.ts
index c0654009a..6006030a4 100644
--- a/src/contracts/VRInterestRateOracle.d.ts
+++ b/src/contracts/VRInterestRateOracle.d.ts
@@ -171,6 +171,7 @@ interface VRInterestRateOracleInterface extends ethers.utils.Interface {
): Result;
events: {
+ "AccumulationUpdated(bytes6,bytes6,uint256,uint256,uint256)": EventFragment;
"InterestRateParamSet(bytes6,bytes6,uint256,uint256,uint256,uint256,address)": EventFragment;
"InterestRateParamUpdated(bytes6,bytes6,uint256,uint256,uint256,uint256,address)": EventFragment;
"RoleAdminChanged(bytes4,bytes4)": EventFragment;
@@ -178,6 +179,7 @@ interface VRInterestRateOracleInterface extends ethers.utils.Interface {
"RoleRevoked(bytes4,address,address)": EventFragment;
};
+ getEvent(nameOrSignatureOrTopic: "AccumulationUpdated"): EventFragment;
getEvent(nameOrSignatureOrTopic: "InterestRateParamSet"): EventFragment;
getEvent(nameOrSignatureOrTopic: "InterestRateParamUpdated"): EventFragment;
getEvent(nameOrSignatureOrTopic: "RoleAdminChanged"): EventFragment;
@@ -185,6 +187,16 @@ interface VRInterestRateOracleInterface extends ethers.utils.Interface {
getEvent(nameOrSignatureOrTopic: "RoleRevoked"): EventFragment;
}
+export type AccumulationUpdatedEvent = TypedEvent<
+ [string, string, BigNumber, BigNumber, BigNumber] & {
+ baseId: string;
+ kind: string;
+ accumulated: BigNumber;
+ lastUpdateTimestamp: BigNumber;
+ utilizationRate: BigNumber;
+ }
+>;
+
export type InterestRateParamSetEvent = TypedEvent<
[string, string, BigNumber, BigNumber, BigNumber, BigNumber, string] & {
baseId: string;
@@ -637,6 +649,40 @@ export class VRInterestRateOracle extends BaseContract {
};
filters: {
+ "AccumulationUpdated(bytes6,bytes6,uint256,uint256,uint256)"(
+ baseId?: BytesLike | null,
+ kind?: BytesLike | null,
+ accumulated?: null,
+ lastUpdateTimestamp?: null,
+ utilizationRate?: null
+ ): TypedEventFilter<
+ [string, string, BigNumber, BigNumber, BigNumber],
+ {
+ baseId: string;
+ kind: string;
+ accumulated: BigNumber;
+ lastUpdateTimestamp: BigNumber;
+ utilizationRate: BigNumber;
+ }
+ >;
+
+ AccumulationUpdated(
+ baseId?: BytesLike | null,
+ kind?: BytesLike | null,
+ accumulated?: null,
+ lastUpdateTimestamp?: null,
+ utilizationRate?: null
+ ): TypedEventFilter<
+ [string, string, BigNumber, BigNumber, BigNumber],
+ {
+ baseId: string;
+ kind: string;
+ accumulated: BigNumber;
+ lastUpdateTimestamp: BigNumber;
+ utilizationRate: BigNumber;
+ }
+ >;
+
"InterestRateParamSet(bytes6,bytes6,uint256,uint256,uint256,uint256,address)"(
baseId?: BytesLike | null,
kind?: BytesLike | null,
diff --git a/src/contracts/abis/VRInterestRateOracle.json b/src/contracts/abis/VRInterestRateOracle.json
index 996dca2a1..92c4dece7 100644
--- a/src/contracts/abis/VRInterestRateOracle.json
+++ b/src/contracts/abis/VRInterestRateOracle.json
@@ -7,6 +7,18 @@
"stateMutability": "nonpayable",
"type": "constructor"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ { "indexed": true, "internalType": "bytes6", "name": "baseId", "type": "bytes6" },
+ { "indexed": true, "internalType": "bytes6", "name": "kind", "type": "bytes6" },
+ { "indexed": false, "internalType": "uint256", "name": "accumulated", "type": "uint256" },
+ { "indexed": false, "internalType": "uint256", "name": "lastUpdateTimestamp", "type": "uint256" },
+ { "indexed": false, "internalType": "uint256", "name": "utilizationRate", "type": "uint256" }
+ ],
+ "name": "AccumulationUpdated",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
diff --git a/src/contracts/factories/VRInterestRateOracle__factory.ts b/src/contracts/factories/VRInterestRateOracle__factory.ts
index b821eab0b..7911e3a60 100644
--- a/src/contracts/factories/VRInterestRateOracle__factory.ts
+++ b/src/contracts/factories/VRInterestRateOracle__factory.ts
@@ -26,6 +26,43 @@ const _abi = [
stateMutability: "nonpayable",
type: "constructor",
},
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: "bytes6",
+ name: "baseId",
+ type: "bytes6",
+ },
+ {
+ indexed: true,
+ internalType: "bytes6",
+ name: "kind",
+ type: "bytes6",
+ },
+ {
+ indexed: false,
+ internalType: "uint256",
+ name: "accumulated",
+ type: "uint256",
+ },
+ {
+ indexed: false,
+ internalType: "uint256",
+ name: "lastUpdateTimestamp",
+ type: "uint256",
+ },
+ {
+ indexed: false,
+ internalType: "uint256",
+ name: "utilizationRate",
+ type: "uint256",
+ },
+ ],
+ name: "AccumulationUpdated",
+ type: "event",
+ },
{
anonymous: false,
inputs: [
diff --git a/src/hooks/entities/useVYTokens.ts b/src/hooks/entities/useVYTokens.ts
index 0f4d1c4a6..36fa5e5ad 100644
--- a/src/hooks/entities/useVYTokens.ts
+++ b/src/hooks/entities/useVYTokens.ts
@@ -9,8 +9,6 @@ import { BigNumber, ethers } from 'ethers';
import { formatUnits } from 'ethers/lib/utils.js';
import { ChainContext } from '../../contexts/ChainContext';
import { MulticallContext } from '../../contexts/MutlicallContext';
-import { useApr } from '../useApr';
-import { ActionType } from '../../types';
export interface IVYToken extends ISignable {
id: string; // vyToken address
@@ -32,7 +30,6 @@ const useVYTokens = () => {
const { address: account } = useAccountPlus();
const { useForkedEnv, provider: forkProvider, forkUrl } = useFork();
const provider = useDefaultProvider();
- const { apr } = useApr(undefined, ActionType.LEND, null);
const {
chainState: { assetRootMap },
@@ -42,7 +39,6 @@ const useVYTokens = () => {
const multicall = useForkedEnv ? forkMulticall : _multicall;
const get = useCallback(async () => {
- console.log('getting vyToken data');
return await Array.from(assetRootMap.values())
.map((a) => [a.VYTokenProxyAddress, a.VYTokenAddress]) // get asset's vyTokenProxy addr
.reduce(async (vyTokens, [proxyAddress, address]) => {
@@ -65,11 +61,14 @@ const useVYTokens = () => {
let vyTokenBaseVal = balance;
try {
- vyTokenBaseVal = await proxy.previewRedeem(balance);
+ vyTokenBaseVal = await proxy.callStatic.previewRedeem(balance);
} catch (e) {
console.log('Error getting vyTokenBaseVal', e);
}
+ const accumulatedInterestInBase = vyTokenBaseVal.sub(balance);
+ const accumulatedInterestInBase_ = formatUnits(accumulatedInterestInBase, decimals);
+
const addr = address.toLowerCase();
const data: IVYToken = {
id: addr,
@@ -87,7 +86,7 @@ const useVYTokens = () => {
vyTokenBaseVal,
vyTokenBaseVal_: formatUnits(vyTokenBaseVal, decimals),
proxyAddress: proxyAddress.toLowerCase(),
- accumulatedInterestInBase_: '0.0',
+ accumulatedInterestInBase_,
};
return (await vyTokens).set(addr, data);
diff --git a/src/hooks/useApr.ts b/src/hooks/useApr.ts
index 0de033737..dfeb57891 100644
--- a/src/hooks/useApr.ts
+++ b/src/hooks/useApr.ts
@@ -1,22 +1,11 @@
-import { ethers, BigNumber } from 'ethers';
+import { ethers } from 'ethers';
import { useContext, useEffect, useState } from 'react';
-import { sellBase, buyBase, calculateAPR, bytesToBytes32 } from '@yield-protocol/ui-math';
-
+import { sellBase, buyBase, calculateAPR } from '@yield-protocol/ui-math';
import { ETH_BASED_ASSETS } from '../config/assets';
import { UserContext } from '../contexts/UserContext';
import { ActionType, ISeries } from '../types';
import { cleanValue } from '../utils/appUtils';
import useTimeTillMaturity from './useTimeTillMaturity';
-import { useProvider } from 'wagmi';
-import * as contractTypes from '../contracts';
-
-import { VRInterestRateOracle__factory } from '../contracts';
-import useContracts from './useContracts';
-import { ContractNames } from '../config/contracts';
-import { RATE, ZERO_BN, CHI } from '../utils/constants';
-import { useConvertValue } from './useConvertValue';
-import useFork from './useFork';
-import { formatUnits } from 'ethers/lib/utils.js';
/* APR hook calculatess APR, min and max aprs for selected series and BORROW or LEND type */
export const useApr = (input: string | undefined, actionType: ActionType, series: ISeries | null) => {
@@ -26,9 +15,6 @@ export const useApr = (input: string | undefined, actionType: ActionType, series
/* HOOKS */
const { getTimeTillMaturity, isMature } = useTimeTillMaturity();
- const provider = useProvider();
- const contracts = useContracts();
- const { useForkedEnv, forkStartBlock } = useFork();
const _selectedSeries = series || selectedSeries;
/* Make sure there won't be an underflow */
@@ -73,53 +59,7 @@ export const useApr = (input: string | undefined, actionType: ActionType, series
// figure out what to do with negative apr on borrow for tv series
const _apr = calculateAPR(baseAmount, preview, _selectedSeries.maturity);
_apr ? setApr(cleanValue(_apr, 2)) : setApr(_selectedSeries.apr);
- } else if (selectedBase) {
- /* logic for VR */
- const cleanedInput = cleanValue(_input || _fallbackInput, selectedBase.decimals);
- const baseAmount = ethers.utils.parseUnits(cleanedInput, selectedBase.decimals);
-
- const now = Date.now() + 20000;
- // trying to call interest rate oracle
- // const interestRateOracleAddr = '0xa60eb553b65284e3a221b958c9115d8e558289bf';
-
- const getAPY = async () => {
- try {
- const VRCauldron = contracts?.get(ContractNames.VR_CAULDRON) as contractTypes.VRCauldron;
- const interestRateOracleAddr = await VRCauldron.rateOracles(selectedBase.id);
- const interestRateOracle = VRInterestRateOracle__factory.connect(interestRateOracleAddr, provider);
- const joinAddress = selectedBase.joinAddressVR;
- // console.log('INTEREST RATE ORACLE', interestRateOracleAddr, interestRateOracle);
-
- let rate: any = ethers.constants.Zero; // TODO - fix this type
-
- if (actionType === 'LEND') {
- rate = await interestRateOracle.peek(bytesToBytes32(selectedBase.id, 6), RATE, '0');
- }
-
- if (actionType === 'BORROW') {
- rate = await interestRateOracle.peek(
- bytesToBytes32(selectedBase.id, 6),
- bytesToBytes32('0x434849000000', 6), // TODO - make this a constant
- '0'
- );
- }
-
- // console.log('rate in useAPR', rate);
-
- return rate;
- } catch (e) {
- console.log(`Error getting APY for ${selectedBase.symbol}:`, e);
- return ethers.constants.Zero;
- }
- };
-
- getAPY().then((res) => {
- const rate = res.accumulated
- ? formatUnits(BigNumber.from(res.accumulated.toHexString()), selectedBase.decimals)
- : ethers.constants.Zero;
-
- setApr(rate.toString());
- });
+ console.log('baseAmount FR', baseAmount, baseAmount.toString(), _fallbackInput, _input);
}
}, [_selectedSeries, _input, actionType, _fallbackInput, getTimeTillMaturity]);
diff --git a/src/hooks/viewHelperHooks/useLendHelpers/useLendHelpersVR.ts b/src/hooks/viewHelperHooks/useLendHelpers/useLendHelpersVR.ts
index a54c1e29d..ade596140 100644
--- a/src/hooks/viewHelperHooks/useLendHelpers/useLendHelpersVR.ts
+++ b/src/hooks/viewHelperHooks/useLendHelpers/useLendHelpersVR.ts
@@ -2,6 +2,7 @@ import { useContext, useMemo } from 'react';
import { UserContext } from '../../../contexts/UserContext';
import { ActionType } from '../../../types';
import { useApr } from '../../useApr';
+import { useAprVR } from '../../useAprVR';
import { Address, useBalance } from 'wagmi';
import { WETH } from '../../../config/assets';
import useAccountPlus from '../../useAccountPlus';
@@ -24,7 +25,7 @@ export const useLendHelpersVR = (vyTokenAddress: string | undefined, input?: str
const { data: vyTokens } = useVYTokens();
const vyToken = vyTokens?.get(vyTokenAddress!);
- const { apr: apy } = useApr(input, ActionType.LEND, null); // TODO - handle vr apy's
+ const { apr: apy } = useAprVR(input ? input : vyToken?.balance_, ActionType.LEND); // TODO - handle vr apy's
return {
maxLend: baseBal?.value,