[vault modal] add borrow max calcs (#337)
* [vault modal] add borrow max calcs * fixed test
This commit is contained in:
parent
1a55d8bd39
commit
103c8bed9a
@ -27,6 +27,8 @@ jest.mock('hooks/broadcast/useDepositVault', () => jest.fn(() => ({ actions: []
|
|||||||
|
|
||||||
jest.mock('components/DisplayCurrency')
|
jest.mock('components/DisplayCurrency')
|
||||||
|
|
||||||
|
jest.mock('hooks/useHealthComputer', () => jest.fn(() => ({ computeMaxBorrowAmount: () => {} })))
|
||||||
|
|
||||||
const mockedDisplayCurrency = jest
|
const mockedDisplayCurrency = jest
|
||||||
.mocked(DisplayCurrency)
|
.mocked(DisplayCurrency)
|
||||||
.mockImplementation(() => <div>Display currency</div>)
|
.mockImplementation(() => <div>Display currency</div>)
|
||||||
|
@ -24,12 +24,15 @@ interface Props {
|
|||||||
export default function AssetSelectTable(props: Props) {
|
export default function AssetSelectTable(props: Props) {
|
||||||
const defaultSelected = useMemo(() => {
|
const defaultSelected = useMemo(() => {
|
||||||
const assets = props.assets as BorrowAsset[]
|
const assets = props.assets as BorrowAsset[]
|
||||||
return assets.reduce((acc, asset, index) => {
|
return assets.reduce(
|
||||||
if (props.selectedDenoms?.includes(asset.denom)) {
|
(acc, asset, index) => {
|
||||||
acc[index] = true
|
if (props.selectedDenoms?.includes(asset.denom)) {
|
||||||
}
|
acc[index] = true
|
||||||
return acc
|
}
|
||||||
}, {} as { [key: number]: boolean })
|
return acc
|
||||||
|
},
|
||||||
|
{} as { [key: number]: boolean },
|
||||||
|
)
|
||||||
}, [props.selectedDenoms, props.assets])
|
}, [props.selectedDenoms, props.assets])
|
||||||
const [sorting, setSorting] = useState<SortingState>([{ id: 'symbol', desc: false }])
|
const [sorting, setSorting] = useState<SortingState>([{ id: 'symbol', desc: false }])
|
||||||
const [selected, setSelected] = useState<RowSelectionState>(defaultSelected)
|
const [selected, setSelected] = useState<RowSelectionState>(defaultSelected)
|
||||||
|
@ -16,6 +16,7 @@ import { BNCoin } from 'types/classes/BNCoin'
|
|||||||
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||||
import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
|
import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
|
||||||
import { formatPercent } from 'utils/formatters'
|
import { formatPercent } from 'utils/formatters'
|
||||||
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
|
|
||||||
export interface VaultBorrowingsProps {
|
export interface VaultBorrowingsProps {
|
||||||
updatedAccount: Account
|
updatedAccount: Account
|
||||||
@ -36,7 +37,19 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
const vaultModal = useStore((s) => s.vaultModal)
|
const vaultModal = useStore((s) => s.vaultModal)
|
||||||
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
||||||
const [isConfirming, setIsConfirming] = useState(false)
|
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(() => {
|
const borrowingValue = useMemo(() => {
|
||||||
return props.borrowings.reduce((prev, curr) => {
|
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'>
|
<div className='flex flex-1 flex-col gap-4 p-4'>
|
||||||
{props.borrowings.map((coin) => {
|
{props.borrowings.map((coin) => {
|
||||||
const asset = getAssetByDenom(coin.denom)
|
const asset = getAssetByDenom(coin.denom)
|
||||||
const maxAmount = maxBorrowAmounts.find(
|
const maxAmount = maxBorrowAmounts.find((maxAmount) => maxAmount.denom === coin.denom)
|
||||||
(maxAmount) => maxAmount.denom === coin.denom,
|
?.amount
|
||||||
)?.amount
|
|
||||||
if (!asset || !maxAmount)
|
if (!asset || !maxAmount)
|
||||||
return <React.Fragment key={`input-${coin.denom}`}></React.Fragment>
|
return <React.Fragment key={`input-${coin.denom}`}></React.Fragment>
|
||||||
return (
|
return (
|
||||||
|
@ -43,57 +43,66 @@ export default function useHealthComputer(account?: Account) {
|
|||||||
|
|
||||||
const vaultPositionValues = useMemo(() => {
|
const vaultPositionValues = useMemo(() => {
|
||||||
if (!account?.vaults) return null
|
if (!account?.vaults) return null
|
||||||
return account.vaults.reduce((prev, curr) => {
|
return account.vaults.reduce(
|
||||||
const baseCoinPrice = prices.find((price) => price.denom === curr.denoms.lp)?.amount || 0
|
(prev, curr) => {
|
||||||
prev[curr.address] = {
|
const baseCoinPrice = prices.find((price) => price.denom === curr.denoms.lp)?.amount || 0
|
||||||
base_coin: {
|
prev[curr.address] = {
|
||||||
amount: '0', // Not used by healthcomputer
|
base_coin: {
|
||||||
denom: curr.denoms.lp,
|
amount: '0', // Not used by healthcomputer
|
||||||
value: curr.amounts.unlocking.times(baseCoinPrice).integerValue().toString(),
|
denom: curr.denoms.lp,
|
||||||
},
|
value: curr.amounts.unlocking.times(baseCoinPrice).integerValue().toString(),
|
||||||
vault_coin: {
|
},
|
||||||
amount: '0', // Not used by healthcomputer
|
vault_coin: {
|
||||||
denom: curr.denoms.vault,
|
amount: '0', // Not used by healthcomputer
|
||||||
value: curr.values.primary
|
denom: curr.denoms.vault,
|
||||||
.div(baseCurrencyPrice)
|
value: curr.values.primary
|
||||||
.plus(curr.values.secondary.div(baseCurrencyPrice))
|
.div(baseCurrencyPrice)
|
||||||
.integerValue()
|
.plus(curr.values.secondary.div(baseCurrencyPrice))
|
||||||
.toString(),
|
.integerValue()
|
||||||
},
|
.toString(),
|
||||||
}
|
},
|
||||||
return prev
|
}
|
||||||
}, {} as { [key: string]: VaultPositionValue })
|
return prev
|
||||||
|
},
|
||||||
|
{} as { [key: string]: VaultPositionValue },
|
||||||
|
)
|
||||||
}, [account?.vaults, prices, baseCurrencyPrice])
|
}, [account?.vaults, prices, baseCurrencyPrice])
|
||||||
|
|
||||||
const priceData = useMemo(() => {
|
const priceData = useMemo(() => {
|
||||||
const baseCurrencyPrice =
|
const baseCurrencyPrice =
|
||||||
prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0
|
prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0
|
||||||
|
|
||||||
return prices.reduce((prev, curr) => {
|
return prices.reduce(
|
||||||
prev[curr.denom] = curr.amount.div(baseCurrencyPrice).decimalPlaces(18).toString()
|
(prev, curr) => {
|
||||||
return prev
|
prev[curr.denom] = curr.amount.div(baseCurrencyPrice).decimalPlaces(18).toString()
|
||||||
}, {} as { [key: string]: string })
|
return prev
|
||||||
|
},
|
||||||
|
{} as { [key: string]: string },
|
||||||
|
)
|
||||||
}, [prices, baseCurrency.denom])
|
}, [prices, baseCurrency.denom])
|
||||||
|
|
||||||
const denomsData = useMemo(
|
const denomsData = useMemo(
|
||||||
() =>
|
() =>
|
||||||
assetParams.reduce((prev, curr) => {
|
assetParams.reduce(
|
||||||
const params: AssetParamsBaseForAddr = {
|
(prev, curr) => {
|
||||||
...curr,
|
const params: AssetParamsBaseForAddr = {
|
||||||
// The following overrides are required as testnet is 'broken' and new contracts are not updated yet
|
...curr,
|
||||||
// These overrides are not used by the healthcomputer internally, so they're not important anyways.
|
// The following overrides are required as testnet is 'broken' and new contracts are not updated yet
|
||||||
protocol_liquidation_fee: '1',
|
// These overrides are not used by the healthcomputer internally, so they're not important anyways.
|
||||||
liquidation_bonus: {
|
protocol_liquidation_fee: '1',
|
||||||
max_lb: '1',
|
liquidation_bonus: {
|
||||||
min_lb: '1',
|
max_lb: '1',
|
||||||
slope: '1',
|
min_lb: '1',
|
||||||
starting_lb: '1',
|
slope: '1',
|
||||||
},
|
starting_lb: '1',
|
||||||
}
|
},
|
||||||
prev[params.denom] = params
|
}
|
||||||
|
prev[params.denom] = params
|
||||||
|
|
||||||
return prev
|
return prev
|
||||||
}, {} as { [key: string]: AssetParamsBaseForAddr }),
|
},
|
||||||
|
{} as { [key: string]: AssetParamsBaseForAddr },
|
||||||
|
),
|
||||||
[assetParams],
|
[assetParams],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,10 +112,13 @@ export default function useHealthComputer(account?: Account) {
|
|||||||
const vaultPositionDenoms = positions.vaults.map((vault) => vault.vault.address)
|
const vaultPositionDenoms = positions.vaults.map((vault) => vault.vault.address)
|
||||||
return vaultConfigs
|
return vaultConfigs
|
||||||
.filter((config) => vaultPositionDenoms.includes(config.addr))
|
.filter((config) => vaultPositionDenoms.includes(config.addr))
|
||||||
.reduce((prev, curr) => {
|
.reduce(
|
||||||
prev[curr.addr] = curr
|
(prev, curr) => {
|
||||||
return prev
|
prev[curr.addr] = curr
|
||||||
}, {} as { [key: string]: VaultConfigBaseForString })
|
return prev
|
||||||
|
},
|
||||||
|
{} as { [key: string]: VaultConfigBaseForString },
|
||||||
|
)
|
||||||
}, [vaultConfigs, positions])
|
}, [vaultConfigs, positions])
|
||||||
|
|
||||||
const healthComputer: HealthComputer | null = useMemo(() => {
|
const healthComputer: HealthComputer | null = useMemo(() => {
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Inter;
|
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');
|
url('../fonts/Inter-ExtraLight.woff') format('woff');
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -13,7 +14,8 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Inter;
|
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');
|
url('../fonts/Inter-Regular.woff') format('woff');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -22,7 +24,8 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Inter;
|
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');
|
url('../fonts/Inter-SemiBold.woff') format('woff');
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -105,7 +105,7 @@ export function convertAccountToPositions(account: Account): Positions {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as VaultPosition),
|
}) as VaultPosition,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user