Skip to content

Commit

Permalink
Use lendingPairs instead of fetching duplicate data in marketInfos
Browse files Browse the repository at this point in the history
  • Loading branch information
haydenshively committed Feb 8, 2024
1 parent a6e7992 commit 638d375
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 64 deletions.
44 changes: 4 additions & 40 deletions earn/src/components/lend/BorrowingWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { useContext, useEffect, useMemo, useState } from 'react';
import { useMemo, useState } from 'react';

import { SendTransactionResult } from '@wagmi/core';
import TokenIcon from 'shared/lib/components/common/TokenIcon';
import { Display, Text } from 'shared/lib/components/common/Typography';
import { GREY_600, GREY_700 } from 'shared/lib/data/constants/Colors';
import { GN } from 'shared/lib/data/GoodNumber';
import useSafeState from 'shared/lib/data/hooks/UseSafeState';
import { Token } from 'shared/lib/data/Token';
import { formatTokenAmount, roundPercentage } from 'shared/lib/util/Numbers';
import styled from 'styled-components';
import { useProvider } from 'wagmi';

import { ChainContext } from '../../App';
import { computeLTV } from '../../data/BalanceSheet';
import { BorrowerNftBorrower } from '../../data/BorrowerNft';
import { LendingPair, LendingPairBalancesMap } from '../../data/LendingPair';
import { fetchMarketInfos, MarketInfo } from '../../data/MarketInfo';
import { rgba } from '../../util/Colors';
import HealthGauge from '../common/HealthGauge';
import BorrowModal from './modal/BorrowModal';
Expand Down Expand Up @@ -148,7 +144,6 @@ function filterBySelection(lendingPairs: LendingPair[], selection: Token | null)
export default function BorrowingWidget(props: BorrowingWidgetProps) {
const { borrowers, lendingPairs, tokenBalances, tokenColors, setPendingTxn } = props;

const [marketInfos, setMarketInfos] = useSafeState<Map<string, MarketInfo>>(new Map());
// selection/hover state for Available Table
const [selectedCollateral, setSelectedCollateral] = useState<Token | null>(null);
const [selectedBorrows, setSelectedBorrows] = useState<Token | null>(null);
Expand All @@ -157,33 +152,6 @@ export default function BorrowingWidget(props: BorrowingWidgetProps) {
const [selectedBorrower, setSelectedBorrower] = useState<SelectedBorrower | null>(null);
const [hoveredBorrower, setHoveredBorrower] = useState<BorrowerNftBorrower | null>(null);

const { activeChain } = useContext(ChainContext);
const provider = useProvider();

// Fetch market infos for all borrowers
useEffect(() => {
(async () => {
const markets =
borrowers?.map((borrower) => {
return {
lender0: borrower.lender0,
lender1: borrower.lender1,
token0Decimals: borrower.token0.decimals,
token1Decimals: borrower.token1.decimals,
};
}) ?? [];
const uniqueMarkets = markets?.filter((market, index) => {
return markets.findIndex((m) => m.lender0 === market.lender0 && m.lender1 === market.lender1) === index;
});
const marketInfosData = await fetchMarketInfos(uniqueMarkets, activeChain.id, provider);
const marketInfosMapped = marketInfosData.reduce((acc, marketInfo) => {
acc.set(`${marketInfo.lender0.toLowerCase()}-${marketInfo.lender1.toLowerCase()}`, marketInfo);
return acc;
}, new Map<string, MarketInfo>());
setMarketInfos(marketInfosMapped);
})();
}, [borrowers, activeChain.id, provider, setMarketInfos]);

const filteredCollateralEntries = useMemo(
() => filterBySelection(lendingPairs, selectedBorrows),
[lendingPairs, selectedBorrows]
Expand Down Expand Up @@ -288,11 +256,9 @@ export default function BorrowingWidget(props: BorrowingWidgetProps) {
? account.liabilities.amount0
: account.liabilities.amount1;
const liabilityColor = tokenColors.get(liability.address);
const marketInfo = marketInfos.get(
`${account.lender0.toLowerCase()}-${account.lender1.toLowerCase()}`
);
const lendingPair = lendingPairs.find((pair) => pair.uniswapPool === account.uniswapPool);
const apr =
((isBorrowingToken0 ? marketInfo?.borrowerAPR0 : marketInfo?.borrowerAPR1) ?? 0) * 100;
(lendingPair?.[isBorrowingToken0 ? 'kitty0Info' : 'kitty1Info'].borrowAPR || 0) * 100;
const roundedApr = Math.round(apr * 100) / 100;
return (
<AvailableContainer
Expand Down Expand Up @@ -487,9 +453,7 @@ export default function BorrowingWidget(props: BorrowingWidgetProps) {
<UpdateBorrowerModal
isOpen={selectedBorrower != null}
borrower={selectedBorrower.borrower}
marketInfo={marketInfos.get(
`${selectedBorrower.borrower.lender0.toLowerCase()}-${selectedBorrower.borrower.lender1.toLowerCase()}`
)}
lendingPair={lendingPairs.find((pair) => pair.uniswapPool === selectedBorrower.borrower.uniswapPool)}
setIsOpen={() => {
setSelectedBorrower(null);
}}
Expand Down
8 changes: 4 additions & 4 deletions earn/src/components/lend/modal/UpdateBorrowerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { GREY_700 } from 'shared/lib/data/constants/Colors';
import styled from 'styled-components';

import { BorrowerNftBorrower } from '../../../data/BorrowerNft';
import { MarketInfo } from '../../../data/MarketInfo';
import { LendingPair } from '../../../data/LendingPair';
import BorrowModalContent from './content/BorrowModalContent';
import RepayModalContent from './content/RepayModalContent';

Expand Down Expand Up @@ -50,13 +50,13 @@ const TabButton = styled.button`
export type UpdateBorrowerModalProps = {
isOpen: boolean;
borrower: BorrowerNftBorrower;
marketInfo?: MarketInfo;
lendingPair?: LendingPair;
setIsOpen: (isOpen: boolean) => void;
setPendingTxn: (pendingTxn: SendTransactionResult | null) => void;
};

export default function UpdateBorrowerModal(props: UpdateBorrowerModalProps) {
const { isOpen, borrower, marketInfo, setIsOpen, setPendingTxn } = props;
const { isOpen, borrower, lendingPair, setIsOpen, setPendingTxn } = props;
const [confirmationType, setConfirmationType] = useState<ConfirmationType>(ConfirmationType.BORROW);

return (
Expand Down Expand Up @@ -86,7 +86,7 @@ export default function UpdateBorrowerModal(props: UpdateBorrowerModalProps) {
<BorrowModalContent
borrower={borrower}
setIsOpen={setIsOpen}
marketInfo={marketInfo}
lendingPair={lendingPair}
setPendingTxnResult={setPendingTxn}
/>
</Tab.Panel>
Expand Down
35 changes: 15 additions & 20 deletions earn/src/components/lend/modal/content/BorrowModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import { useAccount, useBalance, useContractRead, useContractWrite, usePrepareCo
import { ChainContext } from '../../../../App';
import { isHealthy, maxBorrowAndWithdraw } from '../../../../data/BalanceSheet';
import { BorrowerNftBorrower } from '../../../../data/BorrowerNft';
import { LendingPair } from '../../../../data/LendingPair';
import { Liabilities } from '../../../../data/MarginAccount';
import { MarketInfo } from '../../../../data/MarketInfo';
import { RateModel, yieldPerSecondToAPR } from '../../../../data/RateModel';
import HealthBar from '../../../borrow/HealthBar';

Expand Down Expand Up @@ -169,13 +169,13 @@ function ConfirmButton(props: ConfirmButtonProps) {

export type BorrowModalContentProps = {
borrower: BorrowerNftBorrower;
marketInfo?: MarketInfo;
lendingPair?: LendingPair;
setIsOpen: (isOpen: boolean) => void;
setPendingTxnResult: (result: SendTransactionResult | null) => void;
};

export default function BorrowModalContent(props: BorrowModalContentProps) {
const { borrower, marketInfo, setIsOpen, setPendingTxnResult } = props;
const { borrower, lendingPair, setIsOpen, setPendingTxnResult } = props;

const [additionalBorrowAmountStr, setAdditionalBorrowAmountStr] = useState('');

Expand Down Expand Up @@ -219,9 +219,15 @@ export default function BorrowModalContent(props: BorrowModalContentProps) {
const requiredAnte =
accountEtherBalance !== undefined && accountEtherBalance.lt(ante) ? ante.sub(accountEtherBalance) : GN.zero(18);

const maxBorrowsBasedOnMarket = isBorrowingToken0
? marketInfo?.lender0AvailableAssets
: marketInfo?.lender1AvailableAssets;
const lenderInfo = lendingPair?.[isBorrowingToken0 ? 'kitty0Info' : 'kitty1Info'];
const inventoryTotal = lenderInfo?.inventory || 0;
const inventoryAvailable = inventoryTotal * (lenderInfo?.utilization || 0);

// Compute updated utilization and apr
const inventoryAvailableNew = inventoryAvailable - borrowAmount.toNumber();
let utilizationNew = inventoryTotal > 0 ? 1 - inventoryAvailableNew / inventoryTotal : 0;
if (inventoryAvailableNew < 0) utilizationNew = 1;
const apr = yieldPerSecondToAPR(RateModel.computeYieldPerSecond(utilizationNew)) * 100;

// TODO: use GN
const maxBorrowsBasedOnHealth = maxBorrowAndWithdraw(
Expand All @@ -236,7 +242,7 @@ export default function BorrowModalContent(props: BorrowModalContentProps) {
)[isBorrowingToken0 ? 0 : 1];

// TODO: use GN
const max = Math.min(maxBorrowsBasedOnHealth, maxBorrowsBasedOnMarket?.toNumber() ?? 0);
const max = Math.min(maxBorrowsBasedOnHealth, inventoryAvailable);

// Mitigate the case when the number is represented in scientific notation
const eightyPercentMaxBorrowAmount = GN.fromNumber(max, borrowToken.decimals).recklessMul(80).recklessDiv(100);
Expand All @@ -258,21 +264,10 @@ export default function BorrowModalContent(props: BorrowModalContentProps) {
borrower.token1.decimals
);

const availableAssets = isBorrowingToken0 ? marketInfo?.lender0AvailableAssets : marketInfo?.lender1AvailableAssets;
const remainingAvailableAssets = availableAssets?.sub(borrowAmount);

const lenderTotalAssets = isBorrowingToken0 ? marketInfo?.lender0TotalAssets : marketInfo?.lender1TotalAssets;
// TODO: use GN
const newUtilization =
lenderTotalAssets && remainingAvailableAssets && lenderTotalAssets.isGtZero()
? 1 - remainingAvailableAssets.div(lenderTotalAssets).toNumber()
: 0;
const apr = yieldPerSecondToAPR(RateModel.computeYieldPerSecond(newUtilization)) * 100;

// A user is considered unhealthy if their health is 1 or less
const isUnhealthy = newHealth <= 1;
// A user cannot borrow more than the total supply of the market
const notEnoughSupply = maxBorrowsBasedOnMarket?.lt(borrowAmount) ?? false;
const notEnoughSupply = borrowAmount.toNumber() > inventoryAvailable;

return (
<>
Expand Down Expand Up @@ -338,7 +333,7 @@ export default function BorrowModalContent(props: BorrowModalContentProps) {
<ConfirmButton
borrowAmount={borrowAmount}
borrower={borrower}
isLoading={marketInfo === undefined}
isLoading={lendingPair === undefined}
isUnhealthy={isUnhealthy}
notEnoughSupply={notEnoughSupply}
requiredAnte={requiredAnte}
Expand Down

0 comments on commit 638d375

Please sign in to comment.