From a3fe963a9b43a75b7c74c92a1103d18cc7f674b7 Mon Sep 17 00:00:00 2001 From: "nature.xie" Date: Wed, 3 Jan 2024 00:25:33 +0800 Subject: [PATCH 1/2] limit min relay amount for usn token --- components/Modal/Action.tsx | 38 ++++++++++++++++++++++----------- components/Modal/index.tsx | 9 ++++++-- components/Modal/utils.ts | 16 +++++++++++--- store/actions/repay.ts | 10 ++++++--- styles/global.css | 10 +++------ utils/wallet-selector-compat.ts | 6 +++--- 6 files changed, 59 insertions(+), 30 deletions(-) diff --git a/components/Modal/Action.tsx b/components/Modal/Action.tsx index 2e3e2889..e1a75483 100644 --- a/components/Modal/Action.tsx +++ b/components/Modal/Action.tsx @@ -1,8 +1,5 @@ import { useState, useMemo, useEffect } from "react"; -import { Box, Typography, Switch, Tooltip, Alert, useTheme } from "@mui/material"; -import LoadingButton from "@mui/lab/LoadingButton"; - -import { FcInfo } from "@react-icons/all-files/fc/FcInfo"; +import Decimal from "decimal.js"; import { nearTokenId } from "../../utils"; import { toggleUseAsCollateral, hideModal } from "../../redux/appSlice"; import { getModalData } from "./utils"; @@ -18,8 +15,9 @@ import { getSelectedValues, getAssetData } from "../../redux/appSelectors"; import { trackActionButton, trackUseAsCollateral } from "../../utils/telemetry"; import { useDegenMode } from "../../hooks/hooks"; import { SubmitButton, AlertWarning } from "./components"; +import { expandToken } from "../../store"; -export default function Action({ maxBorrowAmount, healthFactor }) { +export default function Action({ maxBorrowAmount, healthFactor, poolAsset }) { const [loading, setLoading] = useState(false); const { amount, useAsCollateral, isMax } = useAppSelector(getSelectedValues); const dispatch = useAppDispatch(); @@ -27,13 +25,14 @@ export default function Action({ maxBorrowAmount, healthFactor }) { const { action = "Deposit", tokenId } = asset; const { isRepayFromDeposits } = useDegenMode(); - const { available, canUseAsCollateral, extraDecimals, collateral, disabled } = getModalData({ - ...asset, - maxBorrowAmount, - healthFactor, - amount, - isRepayFromDeposits, - }); + const { available, canUseAsCollateral, extraDecimals, collateral, disabled, decimals } = + getModalData({ + ...asset, + maxBorrowAmount, + healthFactor, + amount, + isRepayFromDeposits, + }); useEffect(() => { if (!canUseAsCollateral) { @@ -96,11 +95,26 @@ export default function Action({ maxBorrowAmount, healthFactor }) { extraDecimals, }); } else { + let usnMinRepay = "0"; + const isUsn = tokenId === "usn"; + if (isUsn && poolAsset?.supplied?.shares) { + usnMinRepay = new Decimal( + expandToken( + new Decimal(poolAsset?.supplied?.balance) + .div(poolAsset?.supplied?.shares) + .mul(2) + .toFixed(), + decimals, + ), + ).toFixed(0); + } await repay({ tokenId, amount, extraDecimals, isMax, + isUsn, + usnMinRepay, }); } break; diff --git a/components/Modal/index.tsx b/components/Modal/index.tsx index 6a223522..530a836c 100644 --- a/components/Modal/index.tsx +++ b/components/Modal/index.tsx @@ -38,10 +38,10 @@ const Modal = () => { const accountId = useAppSelector(getAccountId); const asset = useAppSelector(getAssetData); const { amount } = useAppSelector(getSelectedValues); + const assets = useAppSelector((state) => state.assets?.data || {}); const dispatch = useAppDispatch(); const { isRepayFromDeposits } = useDegenMode(); const theme = useTheme(); - const { action = "Deposit", tokenId } = asset; const healthFactor = useAppSelector( @@ -78,6 +78,7 @@ const Modal = () => { isRepayFromDeposits, healthFactor, amount, + poolAsset: assets[tokenId], }); const total = (price * +amount).toLocaleString(undefined, USD_FORMAT); @@ -129,7 +130,11 @@ const Modal = () => { )} - + diff --git a/components/Modal/utils.ts b/components/Modal/utils.ts index 7ec6d06f..7b92e41c 100644 --- a/components/Modal/utils.ts +++ b/components/Modal/utils.ts @@ -51,6 +51,8 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => maxWithdrawAmount, isRepayFromDeposits, canUseAsCollateral, + tokenId, + poolAsset, } = asset; const data: any = { apy: borrowApy, @@ -117,7 +119,15 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => data.available = getAvailableWithdrawOrAdjust; data.rates = []; break; - case "Repay": + case "Repay": { + let minRepay = 0; + const isUsn = tokenId === "usn"; + if (isUsn && poolAsset?.supplied?.shares) { + minRepay = new Decimal(poolAsset?.supplied?.balance) + .div(poolAsset?.supplied?.shares) + .mul(2) + .toNumber(); + } data.totalTitle = `Repay Borrow Amount`; data.available = toDecimal( isRepayFromDeposits @@ -126,7 +136,7 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => isWrappedNear ? Number(Math.max(0, available + availableNEAR - NEAR_STORAGE_DEPOSIT)) : available, - borrowed, + isUsn ? Math.max(borrowed, minRepay) : borrowed, ), ); data.alerts = {}; @@ -146,7 +156,7 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => }); } break; - + } default: } if ( diff --git a/store/actions/repay.ts b/store/actions/repay.ts index 5e35b63a..0344d2a5 100644 --- a/store/actions/repay.ts +++ b/store/actions/repay.ts @@ -14,11 +14,15 @@ export async function repay({ amount, extraDecimals, isMax, + usnMinRepay, + isUsn, }: { tokenId: string; amount: string; extraDecimals: number; isMax: boolean; + usnMinRepay: string; + isUsn: boolean; }) { const { account, logicContract } = await getBurrow(); const tokenContract = await getTokenContract(tokenId); @@ -32,8 +36,9 @@ export async function repay({ ); const extraDecimalMultiplier = expandTokenDecimal(1, extraDecimals); - - const tokenBorrowedBalance = borrowedBalance.divToInt(extraDecimalMultiplier); + const tokenBorrowedBalance = isUsn + ? Decimal.max(borrowedBalance.divToInt(extraDecimalMultiplier), usnMinRepay) + : borrowedBalance.divToInt(extraDecimalMultiplier); const tokenBalance = new Decimal(await getBalance(tokenId, account.accountId)); const accountBalance = decimalMax( @@ -43,7 +48,6 @@ export async function repay({ const maxAvailableBalance = isNEAR ? tokenBalance.add(accountBalance) : tokenBalance; const maxAmount = decimalMin(tokenBorrowedBalance, maxAvailableBalance); - const expandedAmountToken = isMax ? maxAmount : decimalMin(maxAmount, expandTokenDecimal(amount, decimals)); diff --git a/styles/global.css b/styles/global.css index 37b604cd..ce64f80e 100644 --- a/styles/global.css +++ b/styles/global.css @@ -22,7 +22,7 @@ body { color: #fff; } -#__next{ +#__next { background: #14162b; height: 100%; } @@ -740,11 +740,7 @@ options-list::-webkit-scrollbar { .nws-form-control .account br { display: none; } -.nws-modal-wrapper - .nws-modal - .choose-ledger-account-form-wrapper - .nws-form-control - .account { +.nws-modal-wrapper .nws-modal .choose-ledger-account-form-wrapper .nws-form-control .account { display: flex; align-items: center; gap: 4px; @@ -755,7 +751,7 @@ options-list::-webkit-scrollbar { .choose-ledger-account-form-wrapper .nws-form-control .account - input[type='checkbox'] { + input[type="checkbox"] { transform: scale(1.2); } .nws-modal-wrapper .nws-modal .overview-wrapper .account { diff --git a/utils/wallet-selector-compat.ts b/utils/wallet-selector-compat.ts index ec9d56f6..dd9ef8ba 100644 --- a/utils/wallet-selector-compat.ts +++ b/utils/wallet-selector-compat.ts @@ -97,10 +97,10 @@ export const getWalletSelector = async ({ onAccountChange }: GetWalletSelectorAr debug: !!isTestnet, optimizeWalletOrder: false, }); - - const subscription = selector.store.observable + const { observable }: { observable: any } = selector.store; + const subscription = observable .pipe( - map((s) => s.accounts), + map((s: any) => s.accounts), distinctUntilChanged(), ) .subscribe((nextAccounts) => { From 1cc636509df5fd4dcf08a00510e9479d8922661d Mon Sep 17 00:00:00 2001 From: "nature.xie" Date: Wed, 3 Jan 2024 09:11:07 +0800 Subject: [PATCH 2/2] handle usn decimals --- components/Modal/Action.tsx | 22 +++++++++++++--------- components/Modal/utils.ts | 21 ++++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/components/Modal/Action.tsx b/components/Modal/Action.tsx index e1a75483..786966d7 100644 --- a/components/Modal/Action.tsx +++ b/components/Modal/Action.tsx @@ -98,15 +98,19 @@ export default function Action({ maxBorrowAmount, healthFactor, poolAsset }) { let usnMinRepay = "0"; const isUsn = tokenId === "usn"; if (isUsn && poolAsset?.supplied?.shares) { - usnMinRepay = new Decimal( - expandToken( - new Decimal(poolAsset?.supplied?.balance) - .div(poolAsset?.supplied?.shares) - .mul(2) - .toFixed(), - decimals, - ), - ).toFixed(0); + // usnMinRepay = new Decimal( + // expandToken( + // new Decimal(poolAsset?.supplied?.balance) + // .div(poolAsset?.supplied?.shares) + // .mul(2) + // .toFixed(0, 2), + // decimals, + // ), + // ).toFixed(0); + usnMinRepay = new Decimal(poolAsset?.supplied?.balance) + .div(poolAsset?.supplied?.shares) + .mul(2) + .toFixed(0, 2); } await repay({ tokenId, diff --git a/components/Modal/utils.ts b/components/Modal/utils.ts index 7b92e41c..7b722ae6 100644 --- a/components/Modal/utils.ts +++ b/components/Modal/utils.ts @@ -2,7 +2,7 @@ import Decimal from "decimal.js"; import { USD_FORMAT, TOKEN_FORMAT, PERCENT_DIGITS, NEAR_STORAGE_DEPOSIT } from "../../store"; import type { UIAsset } from "../../interfaces"; import { formatWithCommas_number, toDecimal } from "../../utils/uiNumber"; -import { expandToken } from "../../store/helper"; +import { expandToken, shrinkToken } from "../../store/helper"; import { decimalMax } from "../../utils"; interface Alert { @@ -120,13 +120,20 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => data.rates = []; break; case "Repay": { - let minRepay = 0; + let minRepay = "0"; const isUsn = tokenId === "usn"; if (isUsn && poolAsset?.supplied?.shares) { - minRepay = new Decimal(poolAsset?.supplied?.balance) - .div(poolAsset?.supplied?.shares) - .mul(2) - .toNumber(); + // minRepay = new Decimal(poolAsset?.supplied?.balance) + // .div(poolAsset?.supplied?.shares) + // .mul(2) + // .toNumber(); + minRepay = shrinkToken( + new Decimal(poolAsset?.supplied?.balance) + .div(poolAsset?.supplied?.shares) + .mul(2) + .toFixed(0, 2), + 18, + ); } data.totalTitle = `Repay Borrow Amount`; data.available = toDecimal( @@ -136,7 +143,7 @@ export const getModalData = (asset): UIAsset & Props & { disabled: boolean } => isWrappedNear ? Number(Math.max(0, available + availableNEAR - NEAR_STORAGE_DEPOSIT)) : available, - isUsn ? Math.max(borrowed, minRepay) : borrowed, + isUsn ? Math.max(borrowed, +minRepay) : borrowed, ), ); data.alerts = {};