From 76b38117fdd25e0fbd31f00dcb4447bea9c496b0 Mon Sep 17 00:00:00 2001 From: "nature.xie" Date: Tue, 26 Dec 2023 17:50:43 +0800 Subject: [PATCH] Borrow limit for modal box --- components/Modal/CollateralTypeSelector.tsx | 12 +++-- components/Modal/index.tsx | 47 ++++++++++++------- redux/selectors/getBorrowMaxAmount.ts | 11 ++--- redux/selectors/getPortfolioAssets.ts | 4 +- redux/selectors/recomputeHealthFactor.ts | 11 +++-- .../selectors/recomputeHealthFactorAdjust.ts | 11 +++-- redux/selectors/recomputeHealthFactorRepay.ts | 11 +++-- .../recomputeHealthFactorRepayFromDeposits.ts | 10 ++-- ...ecomputeHealthFactorRepayFromDepositsLp.ts | 10 ++-- .../selectors/recomputeHealthFactorSupply.ts | 11 +++-- .../recomputeHealthFactorWithdraw.ts | 12 ++--- 11 files changed, 87 insertions(+), 63 deletions(-) diff --git a/components/Modal/CollateralTypeSelector.tsx b/components/Modal/CollateralTypeSelector.tsx index 64e2a451..5be5d095 100644 --- a/components/Modal/CollateralTypeSelector.tsx +++ b/components/Modal/CollateralTypeSelector.tsx @@ -153,14 +153,20 @@ export function CollateralTypeSelectorRepay({ Borrowed amount {[DEFAULT_POSITION, ...Object.keys(LPAssetMap)].map((position) => { + const borrowedAmount = repayPositions[position] || 0; + const disabled = +borrowedAmount <= 0; return (
{ - setSelectedCollateralType(position); - setShow(false); + if (!disabled) { + setSelectedCollateralType(position); + setShow(false); + } }} - className="flex items-center justify-between text-sm text-white h-[46px] hover:bg-gray-950 px-3.5 cursor-pointer" + className={`flex items-center justify-between text-sm text-white h-[46px] hover:bg-gray-950 px-3.5 ${ + disabled ? "cursor-not-allowed" : "cursor-pointer" + }`} >
{getName(position)} diff --git a/components/Modal/index.tsx b/components/Modal/index.tsx index dcd6eb3a..6c109d5a 100644 --- a/components/Modal/index.tsx +++ b/components/Modal/index.tsx @@ -34,7 +34,7 @@ import { import Controls from "./Controls"; import Action from "./Action"; import { fetchAssets, fetchRefPrices } from "../../redux/assetsSlice"; -import { useDegenMode } from "../../hooks/hooks"; +import { useDegenMode, usePortfolioAssets } from "../../hooks/hooks"; import { CollateralTypeSelectorBorrow, CollateralTypeSelectorRepay, @@ -49,11 +49,12 @@ const Modal = () => { const dispatch = useAppDispatch(); const { isRepayFromDeposits } = useDegenMode(); const theme = useTheme(); + const portfolioAssets = usePortfolioAssets(); const [selectedCollateralType, setSelectedCollateralType] = useState(DEFAULT_POSITION); const { action = "Deposit", tokenId, position } = asset; - const healthFactor = useAppSelector( + const { healthFactor, maxBorrowValue: adjustedMaxBorrowValue } = useAppSelector( action === "Withdraw" ? recomputeHealthFactorWithdraw(tokenId, +amount) : action === "Adjust" @@ -66,17 +67,18 @@ const Modal = () => { ? recomputeHealthFactorRepay(tokenId, +amount, selectedCollateralType) : recomputeHealthFactor(tokenId, +amount, selectedCollateralType), ); - const healthFactor_repay_lp = useAppSelector( - action === "Repay" && isRepayFromDeposits && selectedCollateralType !== DEFAULT_POSITION - ? recomputeHealthFactorRepayFromDepositsLp(tokenId, +amount, selectedCollateralType) - : () => { - return 0; - }, - ); + const { healthFactor: healthFactor_repay_lp, maxBorrowValue: adjustedMaxBorrowValue_repay_lp } = + useAppSelector( + action === "Repay" && isRepayFromDeposits && selectedCollateralType !== DEFAULT_POSITION + ? recomputeHealthFactorRepayFromDepositsLp(tokenId, +amount, selectedCollateralType) + : () => { + return { healthFactor: 0, maxBorrowValue: 0 }; + }, + ); const maxBorrowAmountPositions = useAppSelector(getBorrowMaxAmount(tokenId)); const maxWithdrawAmount = useAppSelector(getWithdrawMaxAmount(tokenId)); const repayPositions = useAppSelector(getRepayPositions(tokenId)); - const { maxBorrowAmount } = maxBorrowAmountPositions[selectedCollateralType]; + const { maxBorrowAmount, maxBorrowValue } = maxBorrowAmountPositions[selectedCollateralType]; const repayAmount = repayPositions[selectedCollateralType]; const { symbol, @@ -116,6 +118,12 @@ const Modal = () => { value$: new Decimal(price * +amount).toFixed(), }); } + const repay_to_lp = + action === "Repay" && isRepayFromDeposits && selectedCollateralType !== DEFAULT_POSITION; + const not_borrow_from_regular = + action === "Repay" && + isRepayFromDeposits && + !((portfolioAssets[1] || []) as any[]).find((a) => a.tokenId === tokenId); return ( { available$={available$} />
- - {action === "Repay" && - isRepayFromDeposits && - selectedCollateralType !== DEFAULT_POSITION ? ( - - ) : null} - + {repay_to_lp ? : null} + {not_borrow_from_regular ? null : ( + + )} {!canUseAsCollateral ? ( @@ -175,7 +183,10 @@ const Modal = () => { tokenId={asset.tokenId} /> )} - {/* */} +
{ const adjustedCollateralSum = getAdjustedSum("collateral", portfolio, assets, position); const adjustedBorrowedSum = getAdjustedSum("borrowed", portfolio, assets, position); - const volatiliyRatio = asset.config.volatility_ratio || 0; + // const volatiliyRatio = asset.config.volatility_ratio || 0; const price = asset.price?.usd || Infinity; - const maxBorrowPricedTemp = adjustedCollateralSum + const maxBorrowPriced = adjustedCollateralSum .sub(adjustedBorrowedSum) - .mul(volatiliyRatio) - .div(MAX_RATIO) + // .mul(volatiliyRatio) + // .div(MAX_RATIO) .mul(95) .div(100); - const maxBorrowAmountTemp = maxBorrowPricedTemp.div(price); + const maxBorrowAmountTemp = maxBorrowPriced.div(price); const maxBorrowAmount = Decimal.min( Math.max(0, maxBorrowAmountTemp.toNumber()), uiAsset.availableLiquidity || 0, ); - const maxBorrowPriced = maxBorrowAmountTemp.mul(price); return { [position]: { maxBorrowAmount: Math.max(maxBorrowAmount.toNumber(), 0), diff --git a/redux/selectors/getPortfolioAssets.ts b/redux/selectors/getPortfolioAssets.ts index 9f3823b2..960a142f 100644 --- a/redux/selectors/getPortfolioAssets.ts +++ b/redux/selectors/getPortfolioAssets.ts @@ -50,7 +50,7 @@ export const getPortfolioAssets = createSelector( (state: RootState) => state.assets, (state: RootState) => state.account, (app, assets, account) => { - if (!hasAssets(assets)) return [[], [], 0, 0]; + if (!hasAssets(assets)) return [[], [], 0, 0, {}, []]; const brrrTokenId = app.config.booster_token_id; const lpPositions = omit(account.portfolio.positions, DEFAULT_POSITION); let portfolioLpAssets = {}; @@ -196,7 +196,7 @@ export const getPortfolioAssets = createSelector( return { ...acc, [shadow_id]: b }; }, {}); - const borrowedAll = borrowed; + const borrowedAll = Array.from(borrowed); Object.entries(borrowed_LP).forEach(([positionId, value]: [string, any]) => { borrowedAll.push(...value); }); diff --git a/redux/selectors/recomputeHealthFactor.ts b/redux/selectors/recomputeHealthFactor.ts index f3003047..78b16bf3 100644 --- a/redux/selectors/recomputeHealthFactor.ts +++ b/redux/selectors/recomputeHealthFactor.ts @@ -13,8 +13,8 @@ export const recomputeHealthFactor = (tokenId: string, amount: number, position: (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; - if (!account.portfolio || !tokenId) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; + if (!account.portfolio || !tokenId) return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config } = asset; // if (!Object.keys(account.portfolio.borrowed).length && amount === 0) return -1; @@ -67,8 +67,9 @@ export const recomputeHealthFactor = (tokenId: string, amount: number, position: ); const adjustedBorrowedSum = getAdjustedSum("borrowed", portfolio, assets.data, position); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorAdjust.ts b/redux/selectors/recomputeHealthFactorAdjust.ts index 1bb7b815..c8fb10b8 100644 --- a/redux/selectors/recomputeHealthFactorAdjust.ts +++ b/redux/selectors/recomputeHealthFactorAdjust.ts @@ -13,8 +13,8 @@ export const recomputeHealthFactorAdjust = (tokenId: string, amount: number) => (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; - if (!account.portfolio || !tokenId) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; + if (!account.portfolio || !tokenId) return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config, isLpToken } = asset; const position = isLpToken ? tokenId : DEFAULT_POSITION; @@ -69,8 +69,9 @@ export const recomputeHealthFactorAdjust = (tokenId: string, amount: number) => position, ); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorRepay.ts b/redux/selectors/recomputeHealthFactorRepay.ts index bd6d4e06..9fdded99 100644 --- a/redux/selectors/recomputeHealthFactorRepay.ts +++ b/redux/selectors/recomputeHealthFactorRepay.ts @@ -12,13 +12,13 @@ export const recomputeHealthFactorRepay = (tokenId: string, amount: number, posi (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; if ( !account.portfolio || !tokenId || !account.portfolio.positions[position]?.borrowed?.[tokenId] ) - return 0; + return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config } = asset; const decimals = metadata.decimals + config.extra_decimals; @@ -46,8 +46,9 @@ export const recomputeHealthFactorRepay = (tokenId: string, amount: number, posi assets.data, position, ); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorRepayFromDeposits.ts b/redux/selectors/recomputeHealthFactorRepayFromDeposits.ts index 50c22078..1acef05c 100644 --- a/redux/selectors/recomputeHealthFactorRepayFromDeposits.ts +++ b/redux/selectors/recomputeHealthFactorRepayFromDeposits.ts @@ -14,13 +14,13 @@ export const recomputeHealthFactorRepayFromDeposits = (tokenId: string, amount: (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; if ( !account.portfolio || !tokenId || !account.portfolio.positions[DEFAULT_POSITION]?.borrowed?.[tokenId] ) - return 0; + return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config } = asset; const decimals = metadata.decimals + config.extra_decimals; @@ -74,7 +74,9 @@ export const recomputeHealthFactorRepayFromDeposits = (tokenId: string, amount: assets.data, DEFAULT_POSITION, ); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorRepayFromDepositsLp.ts b/redux/selectors/recomputeHealthFactorRepayFromDepositsLp.ts index b495afef..f671925a 100644 --- a/redux/selectors/recomputeHealthFactorRepayFromDepositsLp.ts +++ b/redux/selectors/recomputeHealthFactorRepayFromDepositsLp.ts @@ -17,13 +17,13 @@ export const recomputeHealthFactorRepayFromDepositsLp = ( (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; if ( !account.portfolio || !tokenId || !account.portfolio.positions[position]?.borrowed?.[tokenId] ) - return 0; + return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config } = asset; const decimals = metadata.decimals + config.extra_decimals; @@ -50,7 +50,9 @@ export const recomputeHealthFactorRepayFromDepositsLp = ( assets.data, position, ); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorSupply.ts b/redux/selectors/recomputeHealthFactorSupply.ts index 19615747..98248b4b 100644 --- a/redux/selectors/recomputeHealthFactorSupply.ts +++ b/redux/selectors/recomputeHealthFactorSupply.ts @@ -14,8 +14,8 @@ export const recomputeHealthFactorSupply = (tokenId: string, amount: number) => (state: RootState) => state.account, (state: RootState) => state.app, (assets, account, app) => { - if (!hasAssets(assets)) return 0; - if (!account.portfolio || !tokenId) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; + if (!account.portfolio || !tokenId) return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config, isLpToken } = asset; const position = isLpToken ? tokenId : DEFAULT_POSITION; @@ -69,8 +69,9 @@ export const recomputeHealthFactorSupply = (tokenId: string, amount: number) => position, ); - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, ); diff --git a/redux/selectors/recomputeHealthFactorWithdraw.ts b/redux/selectors/recomputeHealthFactorWithdraw.ts index a3168283..77d3bd09 100644 --- a/redux/selectors/recomputeHealthFactorWithdraw.ts +++ b/redux/selectors/recomputeHealthFactorWithdraw.ts @@ -14,8 +14,8 @@ export const recomputeHealthFactorWithdraw = (tokenId: string, amount: number) = (state: RootState) => state.assets, (state: RootState) => state.account, (assets, account) => { - if (!hasAssets(assets)) return 0; - if (!account.portfolio || !tokenId) return 0; + if (!hasAssets(assets)) return { healthFactor: 0, maxBorrowValue: 0 }; + if (!account.portfolio || !tokenId) return { healthFactor: 0, maxBorrowValue: 0 }; const asset = assets.data[tokenId]; const { metadata, config, isLpToken } = asset; const position = isLpToken ? tokenId : DEFAULT_POSITION; @@ -81,9 +81,9 @@ export const recomputeHealthFactorWithdraw = (tokenId: string, amount: number) = assets.data, position, ); - - const healthFactor = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); - - return healthFactor < MAX_RATIO ? healthFactor : MAX_RATIO; + const maxBorrowValue = adjustedCollateralSum.sub(adjustedBorrowedSum).mul(95).div(100); + const healthFactorTemp = adjustedCollateralSum.div(adjustedBorrowedSum).mul(100).toNumber(); + const healthFactor = healthFactorTemp < MAX_RATIO ? healthFactorTemp : MAX_RATIO; + return { healthFactor, maxBorrowValue }; }, );