-
{`${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 0000000000000000000000000000000000000000..aa04b916ec6649bf09fed7f6de0da449d99a0d80
GIT binary patch
literal 174668
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