[vault modal] add borrow max calcs (#337)

* [vault modal] add borrow max calcs

* fixed test
This commit is contained in:
Bob van der Helm 2023-08-03 12:03:03 +02:00 committed by GitHub
parent 1a55d8bd39
commit 103c8bed9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 58 deletions

View File

@ -27,6 +27,8 @@ jest.mock('hooks/broadcast/useDepositVault', () => jest.fn(() => ({ actions: []
jest.mock('components/DisplayCurrency')
jest.mock('hooks/useHealthComputer', () => jest.fn(() => ({ computeMaxBorrowAmount: () => {} })))
const mockedDisplayCurrency = jest
.mocked(DisplayCurrency)
.mockImplementation(() => <div>Display currency</div>)

View File

@ -24,12 +24,15 @@ interface Props {
export default function AssetSelectTable(props: Props) {
const defaultSelected = useMemo(() => {
const assets = props.assets as BorrowAsset[]
return assets.reduce((acc, asset, index) => {
if (props.selectedDenoms?.includes(asset.denom)) {
acc[index] = true
}
return acc
}, {} as { [key: number]: boolean })
return assets.reduce(
(acc, asset, index) => {
if (props.selectedDenoms?.includes(asset.denom)) {
acc[index] = true
}
return acc
},
{} as { [key: number]: boolean },
)
}, [props.selectedDenoms, props.assets])
const [sorting, setSorting] = useState<SortingState>([{ id: 'symbol', desc: false }])
const [selected, setSelected] = useState<RowSelectionState>(defaultSelected)

View File

@ -16,6 +16,7 @@ import { BNCoin } from 'types/classes/BNCoin'
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
import { formatPercent } from 'utils/formatters'
import useHealthComputer from 'hooks/useHealthComputer'
export interface VaultBorrowingsProps {
updatedAccount: Account
@ -36,7 +37,19 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
const vaultModal = useStore((s) => s.vaultModal)
const depositIntoVault = useStore((s) => s.depositIntoVault)
const [isConfirming, setIsConfirming] = useState(false)
const maxBorrowAmounts: BNCoin[] = []
const { computeMaxBorrowAmount } = useHealthComputer(props.updatedAccount)
const maxBorrowAmounts: BNCoin[] = useMemo(() => {
return props.borrowings.map((borrowing) => {
const maxAmount = computeMaxBorrowAmount(borrowing.denom, {
vault: { address: props.vault.address },
})
return new BNCoin({
denom: borrowing.denom,
amount: maxAmount.toString(),
})
})
}, [props.borrowings, computeMaxBorrowAmount, props.vault.address])
const borrowingValue = useMemo(() => {
return props.borrowings.reduce((prev, curr) => {
@ -144,9 +157,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
<div className='flex flex-1 flex-col gap-4 p-4'>
{props.borrowings.map((coin) => {
const asset = getAssetByDenom(coin.denom)
const maxAmount = maxBorrowAmounts.find(
(maxAmount) => maxAmount.denom === coin.denom,
)?.amount
const maxAmount = maxBorrowAmounts.find((maxAmount) => maxAmount.denom === coin.denom)
?.amount
if (!asset || !maxAmount)
return <React.Fragment key={`input-${coin.denom}`}></React.Fragment>
return (

View File

@ -43,57 +43,66 @@ export default function useHealthComputer(account?: Account) {
const vaultPositionValues = useMemo(() => {
if (!account?.vaults) return null
return account.vaults.reduce((prev, curr) => {
const baseCoinPrice = prices.find((price) => price.denom === curr.denoms.lp)?.amount || 0
prev[curr.address] = {
base_coin: {
amount: '0', // Not used by healthcomputer
denom: curr.denoms.lp,
value: curr.amounts.unlocking.times(baseCoinPrice).integerValue().toString(),
},
vault_coin: {
amount: '0', // Not used by healthcomputer
denom: curr.denoms.vault,
value: curr.values.primary
.div(baseCurrencyPrice)
.plus(curr.values.secondary.div(baseCurrencyPrice))
.integerValue()
.toString(),
},
}
return prev
}, {} as { [key: string]: VaultPositionValue })
return account.vaults.reduce(
(prev, curr) => {
const baseCoinPrice = prices.find((price) => price.denom === curr.denoms.lp)?.amount || 0
prev[curr.address] = {
base_coin: {
amount: '0', // Not used by healthcomputer
denom: curr.denoms.lp,
value: curr.amounts.unlocking.times(baseCoinPrice).integerValue().toString(),
},
vault_coin: {
amount: '0', // Not used by healthcomputer
denom: curr.denoms.vault,
value: curr.values.primary
.div(baseCurrencyPrice)
.plus(curr.values.secondary.div(baseCurrencyPrice))
.integerValue()
.toString(),
},
}
return prev
},
{} as { [key: string]: VaultPositionValue },
)
}, [account?.vaults, prices, baseCurrencyPrice])
const priceData = useMemo(() => {
const baseCurrencyPrice =
prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0
return prices.reduce((prev, curr) => {
prev[curr.denom] = curr.amount.div(baseCurrencyPrice).decimalPlaces(18).toString()
return prev
}, {} as { [key: string]: string })
return prices.reduce(
(prev, curr) => {
prev[curr.denom] = curr.amount.div(baseCurrencyPrice).decimalPlaces(18).toString()
return prev
},
{} as { [key: string]: string },
)
}, [prices, baseCurrency.denom])
const denomsData = useMemo(
() =>
assetParams.reduce((prev, curr) => {
const params: AssetParamsBaseForAddr = {
...curr,
// The following overrides are required as testnet is 'broken' and new contracts are not updated yet
// These overrides are not used by the healthcomputer internally, so they're not important anyways.
protocol_liquidation_fee: '1',
liquidation_bonus: {
max_lb: '1',
min_lb: '1',
slope: '1',
starting_lb: '1',
},
}
prev[params.denom] = params
assetParams.reduce(
(prev, curr) => {
const params: AssetParamsBaseForAddr = {
...curr,
// The following overrides are required as testnet is 'broken' and new contracts are not updated yet
// These overrides are not used by the healthcomputer internally, so they're not important anyways.
protocol_liquidation_fee: '1',
liquidation_bonus: {
max_lb: '1',
min_lb: '1',
slope: '1',
starting_lb: '1',
},
}
prev[params.denom] = params
return prev
}, {} as { [key: string]: AssetParamsBaseForAddr }),
return prev
},
{} as { [key: string]: AssetParamsBaseForAddr },
),
[assetParams],
)
@ -103,10 +112,13 @@ export default function useHealthComputer(account?: Account) {
const vaultPositionDenoms = positions.vaults.map((vault) => vault.vault.address)
return vaultConfigs
.filter((config) => vaultPositionDenoms.includes(config.addr))
.reduce((prev, curr) => {
prev[curr.addr] = curr
return prev
}, {} as { [key: string]: VaultConfigBaseForString })
.reduce(
(prev, curr) => {
prev[curr.addr] = curr
return prev
},
{} as { [key: string]: VaultConfigBaseForString },
)
}, [vaultConfigs, positions])
const healthComputer: HealthComputer | null = useMemo(() => {

View File

@ -4,7 +4,8 @@
@font-face {
font-family: Inter;
src: url('../fonts/Inter-ExtraLight.woff2') format('woff2'),
src:
url('../fonts/Inter-ExtraLight.woff2') format('woff2'),
url('../fonts/Inter-ExtraLight.woff') format('woff');
font-weight: 300;
font-style: normal;
@ -13,7 +14,8 @@
@font-face {
font-family: Inter;
src: url('../fonts/Inter-Regular.woff2') format('woff2'),
src:
url('../fonts/Inter-Regular.woff2') format('woff2'),
url('../fonts/Inter-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
@ -22,7 +24,8 @@
@font-face {
font-family: Inter;
src: url('../fonts/Inter-SemiBold.woff2') format('woff2'),
src:
url('../fonts/Inter-SemiBold.woff2') format('woff2'),
url('../fonts/Inter-SemiBold.woff') format('woff');
font-weight: 600;
font-style: normal;

View File

@ -105,7 +105,7 @@ export function convertAccountToPositions(account: Account): Positions {
],
},
},
} as VaultPosition),
}) as VaultPosition,
),
}
}