-
{`${props.primaryAsset.symbol}-${props.secondaryAsset.symbol} Deposit Value`}
+
{`${primaryAsset.symbol}-${secondaryAsset.symbol} Deposit Value`}
diff --git a/src/components/Modals/Vault/VaultModalContent.tsx b/src/components/Modals/Vault/VaultModalContent.tsx
index 65d7bfea..327811e3 100644
--- a/src/components/Modals/Vault/VaultModalContent.tsx
+++ b/src/components/Modals/Vault/VaultModalContent.tsx
@@ -1,5 +1,5 @@
import BigNumber from 'bignumber.js'
-import { useCallback, useMemo, useState } from 'react'
+import { useCallback, useEffect, useState } from 'react'
import Accordion from 'components/Accordion'
import AccountSummary from 'components/Account/AccountSummary'
@@ -8,9 +8,9 @@ import VaultBorrowingsSubTitle from 'components/Modals/Vault/VaultBorrowingsSubT
import VaultDeposit from 'components/Modals/Vault/VaultDeposits'
import VaultDepositSubTitle from 'components/Modals/Vault/VaultDepositsSubTitle'
import useIsOpenArray from 'hooks/useIsOpenArray'
-import useUpdateAccount from 'hooks/useUpdateAccount'
-import { BNCoin } from 'types/classes/BNCoin'
import { BN } from 'utils/helpers'
+import useDepositVault from 'hooks/broadcast/useDepositVault'
+import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
interface Props {
vault: Vault | DepositedVault
@@ -21,35 +21,30 @@ interface Props {
}
export default function VaultModalContent(props: Props) {
- const { updatedAccount, onChangeBorrowings, borrowings } = useUpdateAccount(
- props.account,
- props.vault,
- )
+ const { addDebt, removeDeposits, addedDebt, removedDeposits, updatedAccount, addVaultValues } =
+ useUpdatedAccount(props.account)
+
const [isOpen, toggleOpen] = useIsOpenArray(2, false)
- const [primaryAmount, setPrimaryAmount] = useState
(BN(0))
- const [secondaryAmount, setSecondaryAmount] = useState(BN(0))
const [isCustomRatio, setIsCustomRatio] = useState(false)
- const deposits: BNCoin[] = useMemo(() => {
- const primaryBNCoin = new BNCoin({
- denom: props.vault.denoms.primary,
- amount: primaryAmount.toString(),
- })
- const secondaryBNCoin = new BNCoin({
- denom: props.vault.denoms.secondary,
- amount: secondaryAmount.toString(),
- })
- return [primaryBNCoin, secondaryBNCoin]
- }, [primaryAmount, secondaryAmount, props.vault.denoms.primary, props.vault.denoms.secondary])
+ const {
+ actions: depositActions,
+ fee: depositFee,
+ totalValue,
+ } = useDepositVault({
+ vault: props.vault,
+ deposits: removedDeposits,
+ borrowings: addedDebt,
+ })
- const onChangePrimaryAmount = useCallback(
- (amount: BigNumber) => setPrimaryAmount(amount.decimalPlaces(0)),
- [setPrimaryAmount],
- )
- const onChangeSecondaryAmount = useCallback(
- (amount: BigNumber) => setSecondaryAmount(amount.decimalPlaces(0)),
- [setSecondaryAmount],
- )
+ useEffect(() => {
+ addVaultValues([
+ {
+ address: props.vault.address,
+ value: totalValue,
+ },
+ ])
+ }, [totalValue, addVaultValues, props.vault.address])
const onChangeIsCustomRatio = useCallback(
(isCustomRatio: boolean) => setIsCustomRatio(isCustomRatio),
@@ -64,8 +59,12 @@ export default function VaultModalContent(props: Props) {
return (
coin.denom === props.primaryAsset.denom)?.amount || BN(0)
+ }
+ secondaryAmount={
+ removedDeposits.find((coin) => coin.denom === props.secondaryAsset.denom)?.amount || BN(0)
+ }
primaryAsset={props.primaryAsset}
secondaryAsset={props.secondaryAsset}
/>
@@ -78,7 +77,7 @@ export default function VaultModalContent(props: Props) {
if (isOpen[1]) return null
- return
+ return
}
return (
@@ -89,10 +88,8 @@ export default function VaultModalContent(props: Props) {
{
renderContent: () => (
(
),
title: 'Borrow',
diff --git a/src/constants/assets.ts b/src/constants/assets.ts
index 39613183..9abae6fa 100644
--- a/src/constants/assets.ts
+++ b/src/constants/assets.ts
@@ -108,8 +108,8 @@ export const ASSETS: Asset[] = [
logo: '/tokens/axlusdc.svg',
decimals: 6,
hasOraclePrice: true,
- isEnabled: true,
- isMarket: true,
+ isEnabled: !IS_TESTNET,
+ isMarket: !IS_TESTNET,
isDisplayCurrency: true,
isStable: true,
poolId: 678,
@@ -132,4 +132,19 @@ export const ASSETS: Asset[] = [
isStable: true,
pythPriceFeedId: 'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',
},
+ {
+ symbol: 'gamm/pool/6',
+ name: 'OSMO-USDC.n Pool Token',
+ id: 'gamm/pool/6',
+ denom: 'gamm/pool/6',
+ color: '',
+ logo: '',
+ decimals: 6,
+ hasOraclePrice: true,
+ isEnabled: true,
+ isMarket: false,
+ isDisplayCurrency: false,
+ isStable: false,
+ forceFetchPrice: true,
+ },
]
diff --git a/src/constants/vaults.ts b/src/constants/vaults.ts
index edf5263f..6a7e2094 100644
--- a/src/constants/vaults.ts
+++ b/src/constants/vaults.ts
@@ -1,3 +1,6 @@
+import { VaultStatus } from 'types/enums/vault'
+import { BN } from 'utils/helpers'
+
export const VAULT_DEPOSIT_BUFFER = 0.999
export const TESTNET_VAULTS_META_DATA: VaultMetaData[] = [
@@ -13,6 +16,7 @@ export const TESTNET_VAULTS_META_DATA: VaultMetaData[] = [
primary: 'uosmo',
secondary: 'ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4',
lp: 'gamm/pool/6',
+ vault: 'factory/osmo1q40xvrzpldwq5he4ftsf7zm2jf80tj373qaven38yqrvhex8r9rs8n94kv/cwVTT',
},
symbols: {
primary: 'OSMO',
@@ -32,6 +36,7 @@ export const TESTNET_VAULTS_META_DATA: VaultMetaData[] = [
primary: 'uosmo',
secondary: 'ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4',
lp: 'gamm/pool/6',
+ vault: 'factory/osmo14lu7m4ganxs20258dazafrjfaulmfxruq9n0r0th90gs46jk3tuqwfkqwn/cwVTT',
},
symbols: {
primary: 'OSMO',
@@ -51,6 +56,7 @@ export const TESTNET_VAULTS_META_DATA: VaultMetaData[] = [
primary: 'uosmo',
secondary: 'ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4',
lp: 'gamm/pool/6',
+ vault: 'factory/osmo1fmq9hw224fgz8lk48wyd0gfg028kvvzggt6c3zvnaqkw23x68cws5nd5em/cwVTT',
},
symbols: {
primary: 'OSMO',
@@ -74,6 +80,7 @@ export const VAULTS_META_DATA: VaultMetaData[] = [
primary: 'uosmo',
secondary: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
lp: 'gamm/pool/1',
+ vault: 'factory/osmo1g3kmqpp8608szfp0pdag3r6z85npph7wmccat8lgl3mp407kv73qlj7qwp/cwVTT',
},
symbols: {
primary: 'OSMO',
@@ -82,3 +89,28 @@ export const VAULTS_META_DATA: VaultMetaData[] = [
isFeatured: true,
},
]
+
+export const MOCK_DEPOSITED_VAULT_POSITION = {
+ values: {
+ primary: BN(0),
+ secondary: BN(0),
+ },
+ amounts: {
+ primary: BN(0),
+ secondary: BN(0),
+ locked: BN(0),
+ unlocked: BN(0),
+ unlocking: BN(0),
+ },
+ status: VaultStatus.ACTIVE,
+ apy: null,
+ ltv: {
+ liq: 0,
+ max: 0,
+ },
+ cap: {
+ denom: '',
+ max: BN(0),
+ used: BN(0),
+ },
+}
diff --git a/src/hooks/broadcast/useDepositVault.ts b/src/hooks/broadcast/useDepositVault.ts
index 8ab77041..761aa478 100644
--- a/src/hooks/broadcast/useDepositVault.ts
+++ b/src/hooks/broadcast/useDepositVault.ts
@@ -21,7 +21,12 @@ interface Props {
deposits: BNCoin[]
borrowings: BNCoin[]
}
-export default function useDepositVault(props: Props): { actions: Action[]; fee: StdFee } {
+export default function useDepositVault(props: Props): {
+ actions: Action[]
+ fee: StdFee
+ minLpToReceive: string
+ totalValue: BigNumber
+} {
const [minLpToReceive, setMinLpToReceive] = useState(BN(0))
const { data: prices } = usePrices()
const [slippage] = useLocalStorage(SLIPPAGE_KEY, DEFAULT_SETTINGS.slippage)
@@ -74,7 +79,8 @@ export default function useDepositVault(props: Props): { actions: Action[]; fee:
])
const enterVaultActions: Action[] = useMemo(() => {
- if (primaryCoin.amount.isZero() || secondaryCoin.amount.isZero()) return []
+ if (primaryCoin.amount.isZero() || secondaryCoin.amount.isZero() || minLpToReceive.isZero())
+ return []
return getEnterVaultActions(props.vault, primaryCoin, secondaryCoin, minLpToReceive)
}, [props.vault, primaryCoin, secondaryCoin, minLpToReceive])
@@ -84,5 +90,10 @@ export default function useDepositVault(props: Props): { actions: Action[]; fee:
[borrowActions, swapActions, enterVaultActions],
)
- return { actions, fee: hardcodedFee }
+ return {
+ actions,
+ fee: hardcodedFee,
+ minLpToReceive: minLpToReceive.toString(),
+ totalValue,
+ }
}
diff --git a/src/hooks/useAccount.tsx b/src/hooks/useAccount.tsx
new file mode 100644
index 00000000..0f2e0259
--- /dev/null
+++ b/src/hooks/useAccount.tsx
@@ -0,0 +1,9 @@
+import useSWR from 'swr'
+
+import getAccount from 'api/accounts/getAccount'
+
+export default function useAccounts(accountId?: string) {
+ return useSWR(`account${accountId}`, () => getAccount(accountId || ''), {
+ refreshInterval: 30000,
+ })
+}
diff --git a/src/hooks/useAccountDebts.tsx b/src/hooks/useAccountDebts.tsx
deleted file mode 100644
index 63826155..00000000
--- a/src/hooks/useAccountDebts.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import useSWR from 'swr'
-
-import getAccountDebts from 'api/accounts/getAccountDebts'
-
-export default function useAccountDebts(accountId?: string) {
- return useSWR(`accountDebts${accountId}`, () => getAccountDebts(accountId || ''), {
- suspense: true,
- isPaused: () => !accountId,
- })
-}
diff --git a/src/hooks/useAssetParams.tsx b/src/hooks/useAssetParams.tsx
new file mode 100644
index 00000000..6e991ca9
--- /dev/null
+++ b/src/hooks/useAssetParams.tsx
@@ -0,0 +1,9 @@
+import useSWR from 'swr'
+
+import getAssetParams from 'api/params/getAssetParams'
+
+export default function useAssetParams() {
+ return useSWR('assetParams', getAssetParams, {
+ fallbackData: [],
+ })
+}
diff --git a/src/hooks/useHealthComputer.tsx b/src/hooks/useHealthComputer.tsx
new file mode 100644
index 00000000..64ca92a6
--- /dev/null
+++ b/src/hooks/useHealthComputer.tsx
@@ -0,0 +1,157 @@
+import { useCallback, useMemo } from 'react'
+
+import usePrices from 'hooks/usePrices'
+import useAssetParams from 'hooks/useAssetParams'
+import {
+ AssetParamsBaseForAddr,
+ HealthComputer,
+} from 'types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types'
+import { VaultConfigBaseForString } from 'types/generated/mars-params/MarsParams.types'
+import useVaultConfigs from 'hooks/useVaultConfigs'
+import {
+ compute_health_js,
+ max_borrow_estimate_js,
+ max_withdraw_estimate_js,
+} from 'utils/health_computer'
+import { convertAccountToPositions } from 'utils/accounts'
+import { VaultPositionValue } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
+import useStore from 'store'
+
+export default function useHealthComputer(account: Account) {
+ const { data: prices } = usePrices()
+ const { data: assetParams } = useAssetParams()
+ const { data: vaultConfigs } = useVaultConfigs()
+ const baseCurrency = useStore((s) => s.baseCurrency)
+
+ const positions = useMemo(() => convertAccountToPositions(account), [account])
+ const baseCurrencyPrice = useMemo(
+ () => prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0,
+ [prices, baseCurrency.denom],
+ )
+
+ const vaultPositionValues = useMemo(
+ () =>
+ 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 })
+ }, [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
+
+ return prev
+ }, {} as { [key: string]: AssetParamsBaseForAddr }),
+ [assetParams],
+ )
+
+ const vaultConfigsData = useMemo(() => {
+ if (!positions || !vaultConfigs.length) return null
+
+ 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 })
+ }, [vaultConfigs, positions])
+
+ const healthComputer: HealthComputer | null = useMemo(() => {
+ if (
+ !positions ||
+ !vaultPositionValues ||
+ !vaultConfigsData ||
+ Object.keys(denomsData).length === 0 ||
+ Object.keys(priceData).length === 0 ||
+ positions.vaults.length !== Object.keys(vaultPositionValues).length
+ )
+ return null
+
+ return {
+ denoms_data: { params: denomsData, prices: priceData },
+ vaults_data: {
+ vault_configs: vaultConfigsData,
+ vault_values: vaultPositionValues,
+ },
+ positions: positions,
+ kind: 'default',
+ }
+ }, [priceData, denomsData, vaultConfigsData, vaultPositionValues, positions])
+
+ const computeHealth = useCallback(() => {
+ async function callComputeHealthWasmFn(): Promise {
+ if (!healthComputer) return 0
+ return Number((await compute_health_js(healthComputer)).max_ltv_health_factor) || 0
+ }
+
+ return callComputeHealthWasmFn()
+ }, [healthComputer])
+
+ const computeMaxBorrowAmount = useCallback(
+ (denom: string) => {
+ async function callMaxBorrowWasmFn(denom: string): Promise {
+ if (!healthComputer) return 0
+ return await max_borrow_estimate_js(healthComputer, denom)
+ }
+
+ return callMaxBorrowWasmFn(denom)
+ },
+ [healthComputer],
+ )
+
+ const computeMaxWithdrawAmount = useCallback(
+ (denom: string) => {
+ async function callMaxWithdrawWasmFn(denom: string): Promise {
+ if (!healthComputer) return 0
+ return await max_withdraw_estimate_js(healthComputer, denom)
+ }
+
+ return callMaxWithdrawWasmFn(denom)
+ },
+ [healthComputer],
+ )
+
+ return { computeHealth, computeMaxBorrowAmount, computeMaxWithdrawAmount }
+}
diff --git a/src/hooks/useUpdateAccount.tsx b/src/hooks/useUpdateAccount.tsx
deleted file mode 100644
index 37eccb04..00000000
--- a/src/hooks/useUpdateAccount.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import BigNumber from 'bignumber.js'
-import { useCallback, useState } from 'react'
-
-import { BNCoin } from 'types/classes/BNCoin'
-import { BN } from 'utils/helpers'
-
-export default function useUpdateAccount(account: Account, vault: Vault) {
- const [updatedAccount, setUpdatedAccount] = useState(account)
- const [borrowings, setBorrowings] = useState([])
-
- function getCoin(denom: string, amount: BigNumber): Coin {
- return {
- denom,
- amount: amount.decimalPlaces(0).toString(),
- }
- }
-
- const onChangeBorrowings = useCallback(
- (borrowings: BNCoin[]) => {
- const debts: Coin[] = [...account.debts]
- const deposits: Coin[] = [...account.deposits]
- const currentDebtDenoms = debts.map((debt) => debt.denom)
- const currentDepositDenoms = deposits.map((deposit) => deposit.denom)
-
- borrowings.map((coin) => {
- if (coin.amount.isZero()) return
-
- if (currentDebtDenoms.includes(coin.denom)) {
- const index = currentDebtDenoms.indexOf(coin.denom)
- const newAmount = BN(debts[index].amount).plus(coin.amount)
- debts[index] = getCoin(coin.denom, newAmount)
- } else {
- debts.push(coin.toCoin())
- }
-
- if (currentDepositDenoms.includes(coin.denom)) {
- const index = currentDepositDenoms.indexOf(coin.denom)
- const newAmount = BN(deposits[index].amount).plus(coin.amount)
- deposits[index] = getCoin(coin.denom, newAmount)
- } else {
- deposits.push(coin.toCoin())
- }
- })
-
- setBorrowings(borrowings)
- setUpdatedAccount({
- ...account,
- debts,
- deposits,
- })
- },
- [account],
- )
-
- return { borrowings, updatedAccount, onChangeBorrowings }
-}
diff --git a/src/hooks/useUpdatedAccount/functions.ts b/src/hooks/useUpdatedAccount/functions.ts
new file mode 100644
index 00000000..adfb9c42
--- /dev/null
+++ b/src/hooks/useUpdatedAccount/functions.ts
@@ -0,0 +1,69 @@
+import { BNCoin } from 'types/classes/BNCoin'
+import { BN } from 'utils/helpers'
+import { VaultValue } from 'hooks/useUpdatedAccount'
+import { getVaultMetaData } from 'utils/vaults'
+import { MOCK_DEPOSITED_VAULT_POSITION } from 'constants/vaults'
+
+export function addCoins(additionalCoins: BNCoin[], currentCoins: BNCoin[]) {
+ const currentDenoms = currentCoins.map((coin) => coin.denom)
+
+ additionalCoins.forEach((coin) => {
+ if (coin.amount.isZero()) return
+
+ if (currentDenoms.includes(coin.denom)) {
+ const index = currentDenoms.indexOf(coin.denom)
+ currentCoins[index].amount = BN(currentCoins[index].amount).plus(coin.amount)
+ } else {
+ currentCoins.push(coin)
+ }
+ })
+
+ return currentCoins
+}
+
+export function removeCoins(coinsToRemove: BNCoin[], currentCoins: BNCoin[]) {
+ const currentDenoms = currentCoins.map((coin) => coin.denom)
+
+ coinsToRemove.forEach((coin) => {
+ if (coin.amount.isZero()) return
+ if (!currentDenoms.includes(coin.denom)) return
+
+ const index = currentDenoms.indexOf(coin.denom)
+ currentCoins[index].amount = BN(currentCoins[index].amount).minus(coin.amount)
+ })
+
+ return currentCoins
+}
+
+export function addValueToVaults(
+ vaultValues: VaultValue[],
+ vaults: DepositedVault[],
+): DepositedVault[] {
+ const currentVaultAddresses = vaults.map((vault) => vault.address)
+
+ vaultValues.forEach((vaultValue) => {
+ if (vaultValue.value.isZero()) return
+ const halfValue = vaultValue.value.div(2)
+
+ if (currentVaultAddresses.includes(vaultValue.address)) {
+ const index = currentVaultAddresses.indexOf(vaultValue.address)
+ vaults[index].values.primary = BN(vaults[index].values.primary).plus(halfValue)
+ vaults[index].values.secondary = BN(vaults[index].values.secondary).plus(halfValue)
+ } else {
+ const vaultMetaData = getVaultMetaData(vaultValue.address)
+
+ if (!vaultMetaData) return
+
+ vaults.push({
+ ...vaultMetaData,
+ ...MOCK_DEPOSITED_VAULT_POSITION,
+ values: {
+ primary: halfValue,
+ secondary: halfValue,
+ },
+ })
+ }
+ })
+
+ return vaults
+}
diff --git a/src/hooks/useUpdatedAccount/index.ts b/src/hooks/useUpdatedAccount/index.ts
new file mode 100644
index 00000000..fa50d7b5
--- /dev/null
+++ b/src/hooks/useUpdatedAccount/index.ts
@@ -0,0 +1,46 @@
+import { useEffect, useState } from 'react'
+
+import { BNCoin } from 'types/classes/BNCoin'
+import { addCoins, addValueToVaults, removeCoins } from 'hooks/useUpdatedAccount/functions'
+import { cloneAccount } from 'utils/accounts'
+
+export interface VaultValue {
+ address: string
+ value: BigNumber
+}
+
+export function useUpdatedAccount(account: Account) {
+ const [updatedAccount, setUpdatedAccount] = useState(cloneAccount(account))
+ const [addedDeposits, addDeposits] = useState([])
+ const [removedDeposits, removeDeposits] = useState([])
+ const [addedDebt, addDebt] = useState([])
+ const [removedDebt, removeDebt] = useState([])
+ const [addedVaultValues, addVaultValues] = useState([])
+
+ useEffect(() => {
+ async function updateAccount() {
+ const accountCopy = cloneAccount(account)
+ accountCopy.deposits = addCoins(addedDeposits, [...accountCopy.deposits])
+ accountCopy.debts = addCoins(addedDebt, [...accountCopy.debts])
+ accountCopy.vaults = addValueToVaults(addedVaultValues, [...accountCopy.vaults])
+ accountCopy.deposits = removeCoins(removedDeposits, [...accountCopy.deposits])
+ accountCopy.debts = removeCoins(removedDebt, [...accountCopy.debts])
+ setUpdatedAccount(accountCopy)
+ }
+
+ updateAccount()
+ }, [account, addedDebt, removedDebt, addedDeposits, removedDeposits, addedVaultValues])
+
+ return {
+ updatedAccount,
+ addDeposits,
+ removeDeposits,
+ addDebt,
+ removeDebt,
+ addVaultValues,
+ addedDeposits,
+ addedDebt,
+ removedDeposits,
+ removedDebt,
+ }
+}
diff --git a/src/hooks/useVaultConfigs.tsx b/src/hooks/useVaultConfigs.tsx
new file mode 100644
index 00000000..500623c5
--- /dev/null
+++ b/src/hooks/useVaultConfigs.tsx
@@ -0,0 +1,9 @@
+import useSWR from 'swr'
+
+import { getVaultConfigs } from 'api/vaults/getVaultConfigs'
+
+export default function useVaultConfigs() {
+ return useSWR('vaultConfigs', getVaultConfigs, {
+ fallbackData: [],
+ })
+}
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index c47f4fa4..e0426492 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -2,6 +2,7 @@ import { AppProps } from 'next/app'
import { useEffect, useState } from 'react'
import DefaultPageHead from 'components/DefaultPageHead'
+import init from 'utils/health_computer'
import 'react-toastify/dist/ReactToastify.min.css'
import 'styles/globals.css'
@@ -9,6 +10,14 @@ import 'styles/globals.css'
export default function App({ Component, pageProps }: AppProps) {
const PageComponent = Component as any
const [isServer, setIsServer] = useState(true)
+
+ useEffect(() => {
+ const loadHealthComputerWasm = async () => {
+ await init()
+ }
+ loadHealthComputerWasm()
+ }, [])
+
useEffect(() => {
setIsServer(false)
}, [])
diff --git a/src/types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types.ts b/src/types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types.ts
index 4227dd32..98f84b76 100644
--- a/src/types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types.ts
+++ b/src/types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types.ts
@@ -47,8 +47,9 @@ export interface DenomsData {
export interface AssetParamsBaseForAddr {
credit_manager: CmSettingsForAddr
denom: string
- liquidation_bonus: Decimal
+ liquidation_bonus: LiquidationBonus
liquidation_threshold: Decimal
+ protocol_liquidation_fee: Decimal
max_loan_to_value: Decimal
red_bank: RedBankSettings
}
@@ -128,3 +129,10 @@ export interface CoinValue {
denom: string
value: Uint128
}
+
+export interface LiquidationBonus {
+ max_lb: Decimal
+ min_lb: Decimal
+ slope: Decimal
+ starting_lb: Decimal
+}
diff --git a/src/types/interfaces/account.d.ts b/src/types/interfaces/account.d.ts
index 4104ea84..f4ca6903 100644
--- a/src/types/interfaces/account.d.ts
+++ b/src/types/interfaces/account.d.ts
@@ -3,14 +3,14 @@ interface Account extends AccountChange {
deposits: BNCoin[]
debts: BNCoin[]
lends: BNCoin[]
- vaults: import('types/generated/mars-mock-credit-manager/MarsMockCreditManager.types').ArrayOfVaultInfoResponse
+ vaults: DepositedVault[]
}
interface AccountChange {
deposits?: BNCoin[]
debts?: BNCoin[]
lends?: BNCoin[]
- vaults?: import('types/generated/mars-mock-credit-manager/MarsMockCreditManager.types').ArrayOfVaultInfoResponse
+ vaults?: DepositedVault[]
}
interface AccountBalanceRow {
diff --git a/src/types/interfaces/asset.d.ts b/src/types/interfaces/asset.d.ts
index 32af095c..aa2c6505 100644
--- a/src/types/interfaces/asset.d.ts
+++ b/src/types/interfaces/asset.d.ts
@@ -2,8 +2,26 @@ interface Asset {
color: string
name: string
denom: string
- symbol: 'OSMO' | 'ATOM' | 'MARS' | 'stATOM' | 'USDC.axl' | 'USDC.n' | 'WBTC.axl' | 'WETH.axl'
- id: 'OSMO' | 'ATOM' | 'MARS' | 'stATOM' | 'axlUSDC' | 'axlWBTC' | 'axlWETH' | 'nUSDC'
+ symbol:
+ | 'OSMO'
+ | 'ATOM'
+ | 'MARS'
+ | 'stATOM'
+ | 'USDC.axl'
+ | 'USDC.n'
+ | 'WBTC.axl'
+ | 'WETH.axl'
+ | 'gamm/pool/6'
+ id:
+ | 'OSMO'
+ | 'ATOM'
+ | 'MARS'
+ | 'stATOM'
+ | 'axlUSDC'
+ | 'axlWBTC'
+ | 'axlWETH'
+ | 'nUSDC'
+ | 'gamm/pool/6'
prefix?: string
contract_addr?: string
logo: string
diff --git a/src/types/interfaces/vaults.d.ts b/src/types/interfaces/vaults.d.ts
index 5f01ad81..7713ec1e 100644
--- a/src/types/interfaces/vaults.d.ts
+++ b/src/types/interfaces/vaults.d.ts
@@ -11,6 +11,7 @@ interface VaultMetaData {
primary: string
secondary: string
lp: string
+ vault: string
}
symbols: {
primary: string
diff --git a/src/utils/accounts.ts b/src/utils/accounts.ts
index 3a82a931..55503f6e 100644
--- a/src/utils/accounts.ts
+++ b/src/utils/accounts.ts
@@ -1,8 +1,11 @@
import BigNumber from 'bignumber.js'
+import {
+ Positions,
+ VaultPosition,
+} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
+import { BN } from 'utils/helpers'
import { BNCoin } from 'types/classes/BNCoin'
-import { BN, getApproximateHourlyInterest } from 'utils/helpers'
-import { getTokenValue } from 'utils/tokens'
export const calculateAccountBalance = (
account: Account | AccountChange,
@@ -25,6 +28,7 @@ export const calculateAccountDeposits = (
return acc.plus(depositValue)
}, BN(0))
}
+
export const calculateAccountDebt = (
account: Account | AccountChange,
prices: BNCoin[],
@@ -63,34 +67,73 @@ export function getAmount(denom: string, coins: Coin[]): BigNumber {
return BN(coins.find((asset) => asset.denom === denom)?.amount ?? 0)
}
-export function getNetCollateralValue(account: Account, marketAssets: Market[], prices: BNCoin[]) {
- const depositCollateralValue = account.deposits.reduce((acc, coin) => {
- const asset = marketAssets.find((asset) => asset.denom === coin.denom)
-
- if (!asset) return acc
-
- const marketValue = BN(getTokenValue(coin, prices))
- const collateralValue = marketValue.multipliedBy(asset.maxLtv)
-
- return collateralValue.plus(acc)
- }, BN(0))
-
- // Implement Vault Collateral calculation (MP-2915)
-
- const liabilitiesValue = account.debts.reduce((acc, coin) => {
- const asset = marketAssets.find((asset) => asset.denom === coin.denom)
-
- if (!asset) return acc
-
- const estimatedInterestAmount = getApproximateHourlyInterest(coin.amount, asset.borrowRate)
- const liability = BN(getTokenValue(coin, prices)).plus(estimatedInterestAmount)
-
- return liability.plus(acc)
- }, BN(0))
-
- if (liabilitiesValue.isGreaterThan(depositCollateralValue)) {
- return BN(0)
+export function convertAccountToPositions(account: Account): Positions {
+ return {
+ account_id: account.id,
+ debts: account.debts.map((debt) => ({
+ shares: '0', // This is not needed, but required by the contract
+ amount: debt.amount.toString(),
+ denom: debt.denom,
+ })),
+ deposits: account.deposits.map((deposit) => deposit.toCoin()),
+ lends: account.lends.map((lend) => ({
+ shares: '0', // This is not needed, but required by the contract
+ amount: lend.amount.toString(),
+ denom: lend.denom,
+ })),
+ vaults: account.vaults.map(
+ (vault) =>
+ ({
+ vault: {
+ address: vault.address,
+ },
+ amount: {
+ locking: {
+ locked: vault.amounts.locked.toString(),
+ unlocking: [
+ {
+ id: 0,
+ coin: { amount: vault.amounts.unlocking.toString(), denom: vault.denoms.lp },
+ },
+ ],
+ },
+ },
+ } as VaultPosition),
+ ),
+ }
+}
+
+export function cloneAccount(account: Account): Account {
+ return {
+ id: account.id,
+ debts: account.debts.map(
+ (debt) =>
+ new BNCoin({
+ amount: debt.amount.toString(),
+ denom: debt.denom,
+ }),
+ ),
+ deposits: account.deposits.map((deposit) => new BNCoin(deposit.toCoin())),
+ lends: account.lends.map(
+ (lend) =>
+ new BNCoin({
+ amount: lend.amount.toString(),
+ denom: lend.denom,
+ }),
+ ),
+ vaults: account.vaults.map((vault) => ({
+ ...vault,
+ amounts: {
+ locked: BN(vault.amounts.locked),
+ unlocking: BN(vault.amounts.unlocking),
+ unlocked: BN(vault.amounts.unlocked),
+ primary: BN(vault.amounts.primary),
+ secondary: BN(vault.amounts.secondary),
+ },
+ values: {
+ primary: BN(vault.values.primary),
+ secondary: BN(vault.values.secondary),
+ },
+ })),
}
-
- return depositCollateralValue.minus(liabilitiesValue)
}
diff --git a/src/utils/health_computer/index.d.ts b/src/utils/health_computer/index.d.ts
new file mode 100644
index 00000000..febd00d0
--- /dev/null
+++ b/src/utils/health_computer/index.d.ts
@@ -0,0 +1,60 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * @param {any} health_computer
+ * @returns {any}
+ */
+export function compute_health_js(health_computer: any): any
+/**
+ * @param {any} health_computer
+ * @param {any} withdraw_denom
+ * @returns {HealthResponse}
+ */
+export function max_withdraw_estimate_js(health_computer: any, withdraw_denom: any): any
+/**
+ * @param {any} health_computer
+ * @param {any} borrow_denom
+ * @returns {any}
+ */
+export function max_borrow_estimate_js(health_computer: any, borrow_denom: any): any
+
+export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module
+
+export interface InitOutput {
+ readonly memory: WebAssembly.Memory
+ readonly compute_health_js: (a: number) => number
+ readonly max_withdraw_estimate_js: (a: number, b: number) => number
+ readonly max_borrow_estimate_js: (a: number, b: number) => number
+ readonly allocate: (a: number) => number
+ readonly deallocate: (a: number) => void
+ readonly requires_stargate: () => void
+ readonly requires_iterator: () => void
+ readonly interface_version_8: () => void
+ readonly __wbindgen_malloc: (a: number, b: number) => number
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void
+ readonly __wbindgen_exn_store: (a: number) => void
+}
+
+export type SyncInitInput = BufferSource | WebAssembly.Module
+/**
+ * Instantiates the given `module`, which can either be bytes or
+ * a precompiled `WebAssembly.Module`.
+ *
+ * @param {SyncInitInput} module
+ *
+ * @returns {InitOutput}
+ */
+export function initSync(module: SyncInitInput): InitOutput
+
+/**
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
+ * for everything else, calls `WebAssembly.instantiate` directly.
+ *
+ * @param {InitInput | Promise} module_or_path
+ *
+ * @returns {Promise}
+ */
+export default function __wbg_init(
+ module_or_path?: InitInput | Promise,
+): Promise
diff --git a/src/utils/health_computer/index.js b/src/utils/health_computer/index.js
new file mode 100644
index 00000000..5b2b264f
--- /dev/null
+++ b/src/utils/health_computer/index.js
@@ -0,0 +1,568 @@
+let wasm
+
+const heap = new Array(128).fill(undefined)
+
+heap.push(undefined, null, true, false)
+
+function getObject(idx) {
+ return heap[idx]
+}
+
+let heap_next = heap.length
+
+function dropObject(idx) {
+ if (idx < 132) return
+ heap[idx] = heap_next
+ heap_next = idx
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx)
+ dropObject(idx)
+ return ret
+}
+
+let WASM_VECTOR_LEN = 0
+
+let cachedUint8Memory0 = null
+
+function getUint8Memory0() {
+ if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
+ cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer)
+ }
+ return cachedUint8Memory0
+}
+
+const cachedTextEncoder =
+ typeof TextEncoder !== 'undefined'
+ ? new TextEncoder('utf-8')
+ : {
+ encode: () => {
+ throw Error('TextEncoder not available')
+ },
+ }
+
+const encodeString =
+ typeof cachedTextEncoder.encodeInto === 'function'
+ ? function (arg, view) {
+ return cachedTextEncoder.encodeInto(arg, view)
+ }
+ : function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg)
+ view.set(buf)
+ return {
+ read: arg.length,
+ written: buf.length,
+ }
+ }
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg)
+ const ptr = malloc(buf.length, 1) >>> 0
+ getUint8Memory0()
+ .subarray(ptr, ptr + buf.length)
+ .set(buf)
+ WASM_VECTOR_LEN = buf.length
+ return ptr
+ }
+
+ let len = arg.length
+ let ptr = malloc(len, 1) >>> 0
+
+ const mem = getUint8Memory0()
+
+ let offset = 0
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset)
+ if (code > 0x7f) break
+ mem[ptr + offset] = code
+ }
+
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset)
+ }
+ ptr = realloc(ptr, len, (len = offset + arg.length * 3), 1) >>> 0
+ const view = getUint8Memory0().subarray(ptr + offset, ptr + len)
+ const ret = encodeString(arg, view)
+
+ offset += ret.written
+ }
+
+ WASM_VECTOR_LEN = offset
+ return ptr
+}
+
+function isLikeNone(x) {
+ return x === undefined || x === null
+}
+
+let cachedInt32Memory0 = null
+
+function getInt32Memory0() {
+ if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
+ cachedInt32Memory0 = new Int32Array(wasm.memory.buffer)
+ }
+ return cachedInt32Memory0
+}
+
+const cachedTextDecoder =
+ typeof TextDecoder !== 'undefined'
+ ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true })
+ : {
+ decode: () => {
+ throw Error('TextDecoder not available')
+ },
+ }
+
+if (typeof TextDecoder !== 'undefined') {
+ cachedTextDecoder.decode()
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0
+ return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len))
+}
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1)
+ const idx = heap_next
+ heap_next = heap[idx]
+
+ heap[idx] = obj
+ return idx
+}
+
+let cachedFloat64Memory0 = null
+
+function getFloat64Memory0() {
+ if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
+ cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer)
+ }
+ return cachedFloat64Memory0
+}
+
+let cachedBigInt64Memory0 = null
+
+function getBigInt64Memory0() {
+ if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) {
+ cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer)
+ }
+ return cachedBigInt64Memory0
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`
+ }
+ if (type == 'string') {
+ return `"${val}"`
+ }
+ if (type == 'symbol') {
+ const description = val.description
+ if (description == null) {
+ return 'Symbol'
+ } else {
+ return `Symbol(${description})`
+ }
+ }
+ if (type == 'function') {
+ const name = val.name
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`
+ } else {
+ return 'Function'
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length
+ let debug = '['
+ if (length > 0) {
+ debug += debugString(val[0])
+ }
+ for (let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i])
+ }
+ debug += ']'
+ return debug
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val))
+ let className
+ if (builtInMatches.length > 1) {
+ className = builtInMatches[1]
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val)
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')'
+ } catch (_) {
+ return 'Object'
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className
+}
+/**
+ * @param {any} health_computer
+ * @returns {any}
+ */
+export function compute_health_js(health_computer) {
+ const ret = wasm.compute_health_js(addHeapObject(health_computer))
+ return takeObject(ret)
+}
+
+/**
+ * @param {any} health_computer
+ * @param {any} withdraw_denom
+ * @returns {any}
+ */
+export function max_withdraw_estimate_js(health_computer, withdraw_denom) {
+ const ret = wasm.max_withdraw_estimate_js(
+ addHeapObject(health_computer),
+ addHeapObject(withdraw_denom),
+ )
+ return takeObject(ret)
+}
+
+/**
+ * @param {any} health_computer
+ * @param {any} borrow_denom
+ * @returns {any}
+ */
+export function max_borrow_estimate_js(health_computer, borrow_denom) {
+ const ret = wasm.max_borrow_estimate_js(
+ addHeapObject(health_computer),
+ addHeapObject(borrow_denom),
+ )
+ return takeObject(ret)
+}
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args)
+ } catch (e) {
+ wasm.__wbindgen_exn_store(addHeapObject(e))
+ }
+}
+
+async function __wbg_load(module, imports) {
+ if (typeof Response === 'function' && module instanceof Response) {
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
+ try {
+ return await WebAssembly.instantiateStreaming(module, imports)
+ } catch (e) {
+ if (module.headers.get('Content-Type') != 'application/wasm') {
+ console.warn(
+ '`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n',
+ e,
+ )
+ } else {
+ throw e
+ }
+ }
+ }
+
+ const bytes = await module.arrayBuffer()
+ return await WebAssembly.instantiate(bytes, imports)
+ } else {
+ const instance = await WebAssembly.instantiate(module, imports)
+
+ if (instance instanceof WebAssembly.Instance) {
+ return { instance, module }
+ } else {
+ return instance
+ }
+ }
+}
+
+function __wbg_get_imports() {
+ const imports = {}
+ imports.wbg = {}
+ imports.wbg.__wbindgen_object_drop_ref = function (arg0) {
+ takeObject(arg0)
+ }
+ imports.wbg.__wbindgen_is_object = function (arg0) {
+ const val = getObject(arg0)
+ const ret = typeof val === 'object' && val !== null
+ return ret
+ }
+ imports.wbg.__wbindgen_is_undefined = function (arg0) {
+ const ret = getObject(arg0) === undefined
+ return ret
+ }
+ imports.wbg.__wbindgen_in = function (arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1)
+ return ret
+ }
+ imports.wbg.__wbindgen_string_get = function (arg0, arg1) {
+ const obj = getObject(arg1)
+ const ret = typeof obj === 'string' ? obj : undefined
+ var ptr1 = isLikeNone(ret)
+ ? 0
+ : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)
+ var len1 = WASM_VECTOR_LEN
+ getInt32Memory0()[arg0 / 4 + 1] = len1
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1
+ }
+ imports.wbg.__wbindgen_error_new = function (arg0, arg1) {
+ const ret = new Error(getStringFromWasm0(arg0, arg1))
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbindgen_is_string = function (arg0) {
+ const ret = typeof getObject(arg0) === 'string'
+ return ret
+ }
+ imports.wbg.__wbindgen_boolean_get = function (arg0) {
+ const v = getObject(arg0)
+ const ret = typeof v === 'boolean' ? (v ? 1 : 0) : 2
+ return ret
+ }
+ imports.wbg.__wbindgen_is_bigint = function (arg0) {
+ const ret = typeof getObject(arg0) === 'bigint'
+ return ret
+ }
+ imports.wbg.__wbindgen_bigint_from_u64 = function (arg0) {
+ const ret = BigInt.asUintN(64, arg0)
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbindgen_jsval_eq = function (arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1)
+ return ret
+ }
+ imports.wbg.__wbg_new_abda76e883ba8a5f = function () {
+ const ret = new Error()
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_stack_658279fe44541cf6 = function (arg0, arg1) {
+ const ret = getObject(arg1).stack
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)
+ const len1 = WASM_VECTOR_LEN
+ getInt32Memory0()[arg0 / 4 + 1] = len1
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1
+ }
+ imports.wbg.__wbg_error_f851667af71bcfc6 = function (arg0, arg1) {
+ let deferred0_0
+ let deferred0_1
+ try {
+ deferred0_0 = arg0
+ deferred0_1 = arg1
+ console.error(getStringFromWasm0(arg0, arg1))
+ } finally {
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1)
+ }
+ }
+ imports.wbg.__wbindgen_jsval_loose_eq = function (arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1)
+ return ret
+ }
+ imports.wbg.__wbindgen_number_get = function (arg0, arg1) {
+ const obj = getObject(arg1)
+ const ret = typeof obj === 'number' ? obj : undefined
+ getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret
+ getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret)
+ }
+ imports.wbg.__wbindgen_object_clone_ref = function (arg0) {
+ const ret = getObject(arg0)
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbindgen_string_new = function (arg0, arg1) {
+ const ret = getStringFromWasm0(arg0, arg1)
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_getwithrefkey_5e6d9547403deab8 = function (arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)]
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_set_841ac57cff3d672b = function (arg0, arg1, arg2) {
+ getObject(arg0)[takeObject(arg1)] = takeObject(arg2)
+ }
+ imports.wbg.__wbg_get_44be0491f933a435 = function (arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0]
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_length_fff51ee6522a1a18 = function (arg0) {
+ const ret = getObject(arg0).length
+ return ret
+ }
+ imports.wbg.__wbindgen_is_function = function (arg0) {
+ const ret = typeof getObject(arg0) === 'function'
+ return ret
+ }
+ imports.wbg.__wbg_next_526fc47e980da008 = function (arg0) {
+ const ret = getObject(arg0).next
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_next_ddb3312ca1c4e32a = function () {
+ return handleError(function (arg0) {
+ const ret = getObject(arg0).next()
+ return addHeapObject(ret)
+ }, arguments)
+ }
+ imports.wbg.__wbg_done_5c1f01fb660d73b5 = function (arg0) {
+ const ret = getObject(arg0).done
+ return ret
+ }
+ imports.wbg.__wbg_value_1695675138684bd5 = function (arg0) {
+ const ret = getObject(arg0).value
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_iterator_97f0c81209c6c35a = function () {
+ const ret = Symbol.iterator
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_get_97b561fb56f034b5 = function () {
+ return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1))
+ return addHeapObject(ret)
+ }, arguments)
+ }
+ imports.wbg.__wbg_call_cb65541d95d71282 = function () {
+ return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1))
+ return addHeapObject(ret)
+ }, arguments)
+ }
+ imports.wbg.__wbg_new_b51585de1b234aff = function () {
+ const ret = new Object()
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function (arg0) {
+ const ret = Array.isArray(getObject(arg0))
+ return ret
+ }
+ imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function (arg0) {
+ let result
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer
+ } catch {
+ result = false
+ }
+ const ret = result
+ return ret
+ }
+ imports.wbg.__wbg_isSafeInteger_bb8e18dd21c97288 = function (arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0))
+ return ret
+ }
+ imports.wbg.__wbg_entries_e51f29c7bba0c054 = function (arg0) {
+ const ret = Object.entries(getObject(arg0))
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_buffer_085ec1f694018c4f = function (arg0) {
+ const ret = getObject(arg0).buffer
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_new_8125e318e6245eed = function (arg0) {
+ const ret = new Uint8Array(getObject(arg0))
+ return addHeapObject(ret)
+ }
+ imports.wbg.__wbg_set_5cf90238115182c3 = function (arg0, arg1, arg2) {
+ getObject(arg0).set(getObject(arg1), arg2 >>> 0)
+ }
+ imports.wbg.__wbg_length_72e2208bbc0efc61 = function (arg0) {
+ const ret = getObject(arg0).length
+ return ret
+ }
+ imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function (arg0) {
+ let result
+ try {
+ result = getObject(arg0) instanceof Uint8Array
+ } catch {
+ result = false
+ }
+ const ret = result
+ return ret
+ }
+ imports.wbg.__wbindgen_bigint_get_as_i64 = function (arg0, arg1) {
+ const v = getObject(arg1)
+ const ret = typeof v === 'bigint' ? v : undefined
+ getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret
+ getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret)
+ }
+ imports.wbg.__wbindgen_debug_string = function (arg0, arg1) {
+ const ret = debugString(getObject(arg1))
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)
+ const len1 = WASM_VECTOR_LEN
+ getInt32Memory0()[arg0 / 4 + 1] = len1
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1
+ }
+ imports.wbg.__wbindgen_throw = function (arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1))
+ }
+ imports.wbg.__wbindgen_memory = function () {
+ const ret = wasm.memory
+ return addHeapObject(ret)
+ }
+
+ return imports
+}
+
+function __wbg_init_memory(imports, maybe_memory) {}
+
+function __wbg_finalize_init(instance, module) {
+ wasm = instance.exports
+ __wbg_init.__wbindgen_wasm_module = module
+ cachedBigInt64Memory0 = null
+ cachedFloat64Memory0 = null
+ cachedInt32Memory0 = null
+ cachedUint8Memory0 = null
+
+ return wasm
+}
+
+function initSync(module) {
+ if (wasm !== undefined) return wasm
+
+ const imports = __wbg_get_imports()
+
+ __wbg_init_memory(imports)
+
+ if (!(module instanceof WebAssembly.Module)) {
+ module = new WebAssembly.Module(module)
+ }
+
+ const instance = new WebAssembly.Instance(module, imports)
+
+ return __wbg_finalize_init(instance, module)
+}
+
+async function __wbg_init(input) {
+ if (wasm !== undefined) return wasm
+
+ if (typeof input === 'undefined') {
+ input = new URL('index_bg.wasm', import.meta.url)
+ }
+ const imports = __wbg_get_imports()
+
+ if (
+ typeof input === 'string' ||
+ (typeof Request === 'function' && input instanceof Request) ||
+ (typeof URL === 'function' && input instanceof URL)
+ ) {
+ input = fetch(input)
+ }
+
+ __wbg_init_memory(imports)
+
+ const { instance, module } = await __wbg_load(await input, imports)
+
+ return __wbg_finalize_init(instance, module)
+}
+
+export { initSync }
+export default __wbg_init
diff --git a/src/utils/health_computer/index_bg.wasm b/src/utils/health_computer/index_bg.wasm
new file mode 100644
index 00000000..aa04b916
Binary files /dev/null and b/src/utils/health_computer/index_bg.wasm differ
diff --git a/src/utils/health_computer/index_bg.wasm.d.ts b/src/utils/health_computer/index_bg.wasm.d.ts
new file mode 100644
index 00000000..da007578
--- /dev/null
+++ b/src/utils/health_computer/index_bg.wasm.d.ts
@@ -0,0 +1,15 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory
+export function compute_health_js(a: number): number
+export function max_withdraw_estimate_js(a: number, b: number): number
+export function max_borrow_estimate_js(a: number, b: number): number
+export function allocate(a: number): number
+export function deallocate(a: number): void
+export function requires_stargate(): void
+export function requires_iterator(): void
+export function interface_version_8(): void
+export function __wbindgen_malloc(a: number, b: number): number
+export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number
+export function __wbindgen_free(a: number, b: number, c: number): void
+export function __wbindgen_exn_store(a: number): void
diff --git a/src/utils/resolvers.ts b/src/utils/resolvers.ts
index 047d724b..3a9ee39e 100644
--- a/src/utils/resolvers.ts
+++ b/src/utils/resolvers.ts
@@ -1,21 +1,5 @@
-import { BNCoin } from 'types/classes/BNCoin'
-import { Positions as CreditManagerPosition } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
import { Market as RedBankMarket } from 'types/generated/mars-mock-red-bank/MarsMockRedBank.types'
-export function resolvePositionResponses(responses: CreditManagerPosition[]): Account[] {
- return responses.map(resolvePositionResponse)
-}
-
-export function resolvePositionResponse(response: CreditManagerPosition): Account {
- return {
- id: response.account_id,
- debts: response.debts.map((debt) => new BNCoin(debt)),
- lends: response.lends.map((lend) => new BNCoin(lend)),
- deposits: response.deposits.map((deposit) => new BNCoin(deposit)),
- vaults: response.vaults,
- }
-}
-
export function resolveMarketResponses(responses: RedBankMarket[]): Market[] {
return responses.map(resolveMarketResponse)
}
diff --git a/src/utils/vaults.ts b/src/utils/vaults.ts
index 79bdc738..9bd44636 100644
--- a/src/utils/vaults.ts
+++ b/src/utils/vaults.ts
@@ -2,40 +2,18 @@ import { IS_TESTNET } from 'constants/env'
import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
import { BNCoin } from 'types/classes/BNCoin'
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
-import { getNetCollateralValue } from 'utils/accounts'
import { BN } from 'utils/helpers'
import { getTokenPrice, getTokenValue } from 'utils/tokens'
+export function getVaultsMetaData() {
+ return IS_TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA
+}
+
export function getVaultMetaData(address: string) {
const vaults = IS_TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA
return vaults.find((vault) => vault.address === address)
}
-// This should be replaced when the calculation is made part of the Health Computer (MP-2877)
-export function calculateMaxBorrowAmounts(
- account: Account,
- marketAssets: Market[],
- prices: BNCoin[],
- denoms: string[],
-): BNCoin[] {
- const maxAmounts: BNCoin[] = []
- const collateralValue = getNetCollateralValue(account, marketAssets, prices)
-
- for (const denom of denoms) {
- const borrowAsset = marketAssets.find((asset) => asset.denom === denom)
- const borrowAssetPrice = prices.find((price) => price.denom === denom)?.amount
-
- if (!borrowAssetPrice || !borrowAsset) continue
-
- const borrowValue = BN(1).minus(borrowAsset.maxLtv).multipliedBy(borrowAssetPrice)
- const amount = collateralValue.dividedBy(borrowValue).decimalPlaces(0)
-
- maxAmounts.push(new BNCoin({ denom, amount: amount.toString() }))
- }
-
- return maxAmounts
-}
-
export function getVaultDepositCoinsAndValue(
vault: Vault,
deposits: BNCoin[],
@@ -68,7 +46,7 @@ export function getVaultDepositCoinsAndValue(
denom: vault.denoms.secondary,
amount: secondaryDepositAmount.toString(),
}),
- totalValue,
+ totalValue: totalValue.integerValue(),
}
}