This commit is contained in:
Linkie Link 2023-02-18 13:58:48 +01:00
parent 53797b4342
commit ec0eee27ec
No known key found for this signature in database
GPG Key ID: 5318B0F2564D38EA
24 changed files with 178 additions and 103 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "mars", "name": "mars",
"homepage": "./", "homepage": "./",
"version": "1.2.0", "version": "1.2.1",
"private": false, "private": false,
"license": "SEE LICENSE IN LICENSE FILE", "license": "SEE LICENSE IN LICENSE FILE",
"scripts": { "scripts": {
@ -22,7 +22,7 @@
"@cosmjs/launchpad": "^0.27.1", "@cosmjs/launchpad": "^0.27.1",
"@cosmjs/proto-signing": "^0.29.5", "@cosmjs/proto-signing": "^0.29.5",
"@cosmjs/stargate": "^0.29.5", "@cosmjs/stargate": "^0.29.5",
"@marsprotocol/wallet-connector": "^1.4.2", "@marsprotocol/wallet-connector": "^1.4.5",
"@material-ui/core": "^4.12.4", "@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3", "@material-ui/icons": "^4.11.3",
"@ramonak/react-progress-bar": "^5.0.3", "@ramonak/react-progress-bar": "^5.0.3",

View File

@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="https://osmosis.marsprotocol.io/favicon.svg" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#dd5b65" />
<link rel="canonical" href="https://osmosis.marsprotocol.io" />
<meta name="robots" content="index,follow" />
<meta
name="description"
content="Lend, borrow and earn on the galaxy's most powerful credit protocol or enter the Fields of Mars for advanced DeFi strategies."
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@mars_protocol" />
<meta name="twitter:creator" content="@mars_protocol" />
<meta property="og:url" content="https://osmosis.marsprotocol.io" />
<meta property="og:title" content="Mars Protocol Application - Powered by Terra" />
<meta
property="og:description"
content="Lend, borrow and earn on the galaxy's most powerful credit protocol or enter the Fields of Mars for advanced DeFi strategies."
/>
<meta property="og:image" content="https://osmosis.marsprotocol.io/banner.png" />
<meta property="og:site_name" content="Mars Protocol" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="theme-color" content="#ffffff" />
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no" />
<title>Mars Protocol</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@ -1,14 +1,26 @@
import classNames from 'classnames' import classNames from 'classnames'
import { useTranslation } from 'react-i18next'
import styles from './ErrorMessage.module.scss' import styles from './ErrorMessage.module.scss'
interface Props { interface Props {
errorMessage?: string message: unknown
alignment?: 'left' | 'center' | 'right' alignment?: 'left' | 'center' | 'right'
} }
export const ErrorMessage = (props: Props) => { export const ErrorMessage = (props: Props) => {
const { t } = useTranslation()
const classes = classNames(styles.errorMessage, props.alignment && styles[props.alignment]) const classes = classNames(styles.errorMessage, props.alignment && styles[props.alignment])
return props.errorMessage ? <p className={classes}>{props.errorMessage}</p> : null if (!props.message) return null
if (typeof props.message === 'object') {
return <p className={classes}>{JSON.stringify(props.message)}</p>
}
if (typeof props.message === 'string') {
return <p className={classes}>{props.message}</p>
}
return <p className={classes}>{t('error.errorEstimatedFee')}</p>
} }

View File

@ -102,6 +102,15 @@ export const Footer = () => {
> >
{t('global.privacyPolicy')} {t('global.privacyPolicy')}
</a> </a>
<a
className={styles.item}
href={DocURL.SECURITY}
rel='noopener noreferrer'
target='_blank'
title={t('global.security')}
>
{t('global.security')}
</a>
</div> </div>
<div className={styles.column3}> <div className={styles.column3}>
<div className={styles.header}>{t('global.community')}</div> <div className={styles.header}>{t('global.community')}</div>

View File

@ -215,7 +215,7 @@ export const IncentivesButton = () => {
onClick={() => (submitted ? null : claimRewards())} onClick={() => (submitted ? null : claimRewards())}
color='primary' color='primary'
/> />
<ErrorMessage errorMessage={error} alignment='center' /> <ErrorMessage message={error} alignment='center' />
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,8 +7,10 @@ interface Props {
value: string value: string
className: string className: string
maxDecimals: number maxDecimals: number
minValue?: number
maxValue?: number maxValue?: number
maxLength?: number maxLength?: number
allowNegative?: boolean
suffix?: string suffix?: string
onChange: (value: number) => void onChange: (value: number) => void
onBlur?: () => void onBlur?: () => void
@ -79,6 +81,13 @@ export const NumberInput = (props: Props) => {
const isNumber = !isNaN(Number(value)) const isNumber = !isNaN(Number(value))
const hasMultipleDots = (value.match(/[.,]/g)?.length || 0) > 1 const hasMultipleDots = (value.match(/[.,]/g)?.length || 0) > 1
const isSeparator = lastChar === '.' || lastChar === ',' const isSeparator = lastChar === '.' || lastChar === ','
const isNegative = value.indexOf('-') > -1
const isLowerThanMinimum = props.minValue !== undefined && Number(value) < props.minValue
const isHigherThanMaximum = props.maxValue !== undefined && Number(value) > props.maxValue
const isTooLong = props.maxLength !== undefined && numberCount > props.maxLength
const exceedsMaxDecimals = props.maxDecimals !== undefined && decimals > props.maxDecimals
if (isNegative && !props.allowNegative) return
if (isSeparator && value.length === 1) { if (isSeparator && value.length === 1) {
updateValues('0.', 0) updateValues('0.', 0)
@ -90,17 +99,21 @@ export const NumberInput = (props: Props) => {
return return
} }
if (!isNumber) return if (!isNumber || hasMultipleDots) return
if (hasMultipleDots) return
if (props.maxDecimals !== undefined && decimals > props.maxDecimals) { if (exceedsMaxDecimals) {
value = value.substring(0, value.length - 1) value = value.substring(0, value.length - 1)
} }
if (props.maxLength !== undefined && numberCount > props.maxLength) return if (isTooLong) return
if ((props.maxValue && Number(value) > props.maxValue) || props.maxValue === 0) { if (isLowerThanMinimum) {
updateValues(String(props.maxValue), props.maxValue) updateValues(String(props.minValue), props.minValue!)
return
}
if (isHigherThanMaximum) {
updateValues(String(props.maxValue), props.maxValue!)
return return
} }

View File

@ -330,7 +330,7 @@ export const Action = ({
showProgressIndicator={actionButtonSpec.fetching} showProgressIndicator={actionButtonSpec.fetching}
text={actionButtonSpec.text} text={actionButtonSpec.text}
/> />
<ErrorMessage errorMessage={feeError} alignment='center' /> <ErrorMessage message={feeError} alignment='center' />
</> </>
) )
} }

View File

@ -199,7 +199,7 @@ export const useActiveVaultsColumns = () => {
<> <>
<DisplayCurrency <DisplayCurrency
coin={{ coin={{
denom: baseCurrency.denom, denom: vaultCap.denom,
amount: vaultCap.max.toString(), amount: vaultCap.max.toString(),
}} }}
/> />
@ -212,7 +212,7 @@ export const useActiveVaultsColumns = () => {
<TokenBalance <TokenBalance
showSymbol showSymbol
coin={{ coin={{
denom: baseCurrency.denom, denom: vaultCap.denom,
amount: vaultCap.max.toString(), amount: vaultCap.max.toString(),
}} }}
/> />

View File

@ -74,7 +74,7 @@ export const AvailableVaultsTableMobile = () => {
<span> <span>
<DisplayCurrency <DisplayCurrency
coin={{ coin={{
denom: baseCurrency.denom, denom: vault.vaultCap?.denom || '',
amount: (vault.vaultCap?.max || 0).toString(), amount: (vault.vaultCap?.max || 0).toString(),
}} }}
className={styles.inline} className={styles.inline}

View File

@ -159,7 +159,7 @@ export const useAvailableVaultsColumns = () => {
<> <>
<DisplayCurrency <DisplayCurrency
coin={{ coin={{
denom: baseCurrency.denom, denom: vaultCap.denom,
amount: vaultCap.max.toString(), amount: vaultCap.max.toString(),
}} }}
/> />
@ -172,7 +172,7 @@ export const useAvailableVaultsColumns = () => {
<TokenBalance <TokenBalance
showSymbol showSymbol
coin={{ coin={{
denom: baseCurrency.denom, denom: vaultCap.denom,
amount: vaultCap.max.toString(), amount: vaultCap.max.toString(),
}} }}
/> />

View File

@ -42,6 +42,7 @@ export const BreakdownTable = (props: Props) => {
const primaryAsset = useAsset({ denom: props.vault.denoms.primary }) const primaryAsset = useAsset({ denom: props.vault.denoms.primary })
const secondaryAsset = useAsset({ denom: props.vault.denoms.secondary }) const secondaryAsset = useAsset({ denom: props.vault.denoms.secondary })
const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency) const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency)
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
const primaryPrice = usePrice(props.vault.denoms.primary) const primaryPrice = usePrice(props.vault.denoms.primary)
const secondaryPrice = usePrice(props.vault.denoms.secondary) const secondaryPrice = usePrice(props.vault.denoms.secondary)
@ -165,13 +166,23 @@ export const BreakdownTable = (props: Props) => {
const additionalPositionValue = props.isSetUp const additionalPositionValue = props.isSetUp
? props.newPosition.values.total ? props.newPosition.values.total
: props.newPosition.values.total - props.prevPosition.values.total : props.newPosition.values.total - props.prevPosition.values.total
const vaultCap = (props.vault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER
const vaultCapValue = convertToBaseCurrency({
amount: ((props.vault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER).toString(),
denom: props.vault.vaultCap?.denom || '',
})
const vaultCapUsedValue = convertToBaseCurrency({
amount: (props.vault.vaultCap?.used || 0).toString(),
denom: props.vault.vaultCap?.denom || '',
})
const isVaultCapReached = props.vault.vaultCap const isVaultCapReached = props.vault.vaultCap
? props.vault.vaultCap.used + additionalPositionValue > vaultCap ? vaultCapUsedValue + additionalPositionValue > vaultCapValue
: false : false
if (isVaultCapReached && props.vault.vaultCap) { if (isVaultCapReached && props.vault.vaultCap) {
const leftoverCap = vaultCap - props.vault.vaultCap.used const leftoverCap = vaultCapValue - vaultCapUsedValue
const maxPositionValue = convertToDisplayCurrency({ const maxPositionValue = convertToDisplayCurrency({
amount: ((props.isSetUp ? 0 : props.prevPosition.values.total) + leftoverCap).toString(), amount: ((props.isSetUp ? 0 : props.prevPosition.values.total) + leftoverCap).toString(),
denom: 'uosmo', denom: 'uosmo',

View File

@ -26,6 +26,7 @@
} }
.container { .container {
position: relative;
display: flex; display: flex;
flex: 1; flex: 1;
border: 1px solid; border: 1px solid;
@ -37,6 +38,17 @@
border-color: rgba($colorSecondary, 0.8) !important; border-color: rgba($colorSecondary, 0.8) !important;
} }
.inputWarning {
position: absolute;
bottom: rem-calc(36);
left: 0;
width: 100%;
text-align: center;
display: flex;
justify-content: center;
@include typoS;
}
.input, .input,
.select { .select {
color: $colorWhite; color: $colorWhite;
@ -44,6 +56,11 @@
outline: none; outline: none;
@include padding(1.5, 2); @include padding(1.5, 2);
background: $backgroundInTile; background: $backgroundInTile;
option {
background: $backgroundInTile;
color: $colorWhite;
}
} }
.input:focus, .input:focus,

View File

@ -23,6 +23,7 @@ interface Props {
export const TokenInput = (props: Props) => { export const TokenInput = (props: Props) => {
const userBalances = useStore((s) => s.userBalances) const userBalances = useStore((s) => s.userBalances)
const { t } = useTranslation() const { t } = useTranslation()
const baseCurrency = useStore((s) => s.baseCurrency)
const walletBalance = findByDenom(userBalances, props.input.denom) as Coin const walletBalance = findByDenom(userBalances, props.input.denom) as Coin
const asset = useAsset({ denom: props.input.denom }) const asset = useAsset({ denom: props.input.denom })
@ -54,12 +55,15 @@ export const TokenInput = (props: Props) => {
props.onChange(microValue) props.onChange(microValue)
} }
if (!asset) return <></> if (!asset) return null
const maxAmount = const maxAmount =
(props.maxAmount === undefined ? Number(walletBalance.amount) : props.maxAmount) / (props.maxAmount === undefined ? Number(walletBalance.amount) : props.maxAmount) /
10 ** asset.decimals 10 ** asset.decimals
const showGasWarning =
props.maxAmount && props.amount >= props.maxAmount && asset.denom === baseCurrency.denom
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<Button <Button
@ -75,9 +79,11 @@ export const TokenInput = (props: Props) => {
onChange={onValueEntered} onChange={onValueEntered}
onFocus={() => {}} onFocus={() => {}}
onBlur={() => {}} onBlur={() => {}}
minValue={0}
maxValue={(props.maxAmount || 0) / 10 ** asset.decimals} maxValue={(props.maxAmount || 0) / 10 ** asset.decimals}
value={(props.amount / 10 ** asset.decimals).toString()} value={(props.amount / 10 ** asset.decimals).toString()}
maxDecimals={6} maxDecimals={6}
allowNegative={false}
suffix={isSingleToken ? ` ${props.input.symbol}` : ''} suffix={isSingleToken ? ` ${props.input.symbol}` : ''}
className={inputClasses} className={inputClasses}
/> />
@ -98,6 +104,11 @@ export const TokenInput = (props: Props) => {
</select> </select>
</> </>
)} )}
{showGasWarning ? (
<div className={styles.inputWarning}>
<p className='tippyContainer'>{t('common.lowUstAmountAfterTransaction')}</p>
</div>
) : null}
</div> </div>
</div> </div>
<div className={styles.bottomInfo}> <div className={styles.bottomInfo}>

View File

@ -223,7 +223,11 @@ export const useEditPosition = (props: Props) => {
props.isReducingPosition, props.isReducingPosition,
]) ])
const { data: fee, isLoading } = useEstimateFarmFee({ const {
data: fee,
isLoading,
error,
} = useEstimateFarmFee({
accountId: props.accountId, accountId: props.accountId,
actions: actions, actions: actions,
funds, funds,
@ -231,5 +235,5 @@ export const useEditPosition = (props: Props) => {
isLoading: props.isLoading, isLoading: props.isLoading,
}) })
return { editActions: actions, editFunds: funds, editFee: fee, isLoading } return { editActions: actions, editFunds: funds, editFee: fee, isLoading, error }
} }

View File

@ -50,19 +50,21 @@ export const useEstimateFarmFee = (props: Props) => {
const result = await client.simulate(simulateOptions) const result = await client.simulate(simulateOptions)
return result.success if (result.success) {
? { return {
amount: result.fee ? result.fee.amount : [], amount: result.fee ? result.fee.amount : [],
gas: new BigNumber(result.fee ? result.fee.gas : 0) gas: new BigNumber(result.fee ? result.fee.gas : 0)
.multipliedBy(gasAdjustment) .multipliedBy(gasAdjustment)
.toFixed(0), .toFixed(0),
} }
: null }
} catch { throw result.error
return null } catch (e) {
throw e
} }
}, },
{ {
retry: 1,
enabled: enabled:
!props.isLoading && !props.isLoading &&
!!client && !!client &&

View File

@ -21,6 +21,7 @@ export const vault: Vault = {
secondary: 'ATOM', secondary: 'ATOM',
}, },
vaultCap: { vaultCap: {
denom: 'uosmo',
used: 1000, used: 1000,
max: 5000, max: 5000,
}, },

View File

@ -4,7 +4,6 @@ import { VAULT_DEPOSIT_BUFFER } from 'constants/appConstants'
import { DEFAULT_POSITION } from 'constants/defaults' import { DEFAULT_POSITION } from 'constants/defaults'
import { useAvailableVault } from 'hooks/data' import { useAvailableVault } from 'hooks/data'
import cloneDeep from 'lodash.clonedeep' import cloneDeep from 'lodash.clonedeep'
import Link from 'next/link'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -18,6 +17,7 @@ const Create = () => {
const address = String(router.query.address) const address = String(router.query.address)
const availableVault = useAvailableVault(address) const availableVault = useAvailableVault(address)
const setPositionInStore = useStore((s) => s.setPosition) const setPositionInStore = useStore((s) => s.setPosition)
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
const [position, setPosition] = useState<Position>(cloneDeep(DEFAULT_POSITION)) const [position, setPosition] = useState<Position>(cloneDeep(DEFAULT_POSITION))
@ -28,10 +28,25 @@ const Create = () => {
return return
} }
const vaultCap = (availableVault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER const handleSetupClick = () => {
setPositionInStore(position)
router.push(`/farm/vault/${address}/create/setup`)
}
const vaultCapValue = convertToBaseCurrency({
amount: ((availableVault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER).toString(),
denom: availableVault.vaultCap?.denom || '',
})
const vaultCapUsedValue = convertToBaseCurrency({
amount: (availableVault.vaultCap?.used || 0).toString(),
denom: availableVault.vaultCap?.denom || '',
})
const isVaultCapReached = availableVault.vaultCap const isVaultCapReached = availableVault.vaultCap
? availableVault.vaultCap.used + position.values.total > vaultCap ? vaultCapUsedValue + position.values.total > vaultCapValue
: false : false
const isDisabled = position.values.total === 0 || isVaultCapReached const isDisabled = position.values.total === 0 || isVaultCapReached
return ( return (
@ -51,14 +66,12 @@ const Create = () => {
<Breakdown vault={availableVault} newPosition={position} isSetUp /> <Breakdown vault={availableVault} newPosition={position} isSetUp />
<div className={styles.action}> <div className={styles.action}>
<div className={styles.buttonContainer}> <div className={styles.buttonContainer}>
<Link href={`/farm/vault/${address}/create/setup`}>
<Button <Button
text={t('common.setup')} text={t('common.setup')}
onClick={() => setPositionInStore(position)} onClick={handleSetupClick}
disabled={isDisabled} disabled={isDisabled}
className={styles.button} className={styles.button}
/> />
</Link>
{!isDisabled && ( {!isDisabled && (
<ActionsTooltip <ActionsTooltip
type='edit' type='edit'

View File

@ -1,4 +1,4 @@
import { Button, Card, SVG } from 'components/common' import { Button, Card, ErrorMessage, SVG } from 'components/common'
import { SetUpResponse } from 'components/fields' import { SetUpResponse } from 'components/fields'
import { useCreateCreditAccount, useUpdateAccount } from 'hooks/mutations' import { useCreateCreditAccount, useUpdateAccount } from 'hooks/mutations'
import { useEditPosition, useEstimateFarmFee } from 'hooks/queries' import { useEditPosition, useEstimateFarmFee } from 'hooks/queries'
@ -25,7 +25,6 @@ const SetupPosition = (props: Props) => {
mutate: enterVault, mutate: enterVault,
data: enterVaultData, data: enterVaultData,
isLoading: isLoadingEnterVault, isLoading: isLoadingEnterVault,
error: enterVaultError,
} = useUpdateAccount() } = useUpdateAccount()
const { const {
@ -33,6 +32,7 @@ const SetupPosition = (props: Props) => {
editFunds, editFunds,
editFee, editFee,
isLoading: isLoadingFee, isLoading: isLoadingFee,
error: enterError,
} = useEditPosition({ } = useEditPosition({
accountId: accountId, accountId: accountId,
position: props.position, position: props.position,
@ -40,7 +40,11 @@ const SetupPosition = (props: Props) => {
isReducingPosition: false, isReducingPosition: false,
isLoading: isLoadingEnterVault || !!enterVaultData, isLoading: isLoadingEnterVault || !!enterVaultData,
}) })
const { data: createFee } = useEstimateFarmFee({ const {
data: createFee,
error: createError,
isLoading: isLoadingCreateFee,
} = useEstimateFarmFee({
isCreate: true, isCreate: true,
isLoading: isLoadingCreate || !!accountId, isLoading: isLoadingCreate || !!accountId,
}) })
@ -81,11 +85,12 @@ const SetupPosition = (props: Props) => {
prefix={accountId && <SVG.Check />} prefix={accountId && <SVG.Check />}
text={t('fields.setup.step1.button')} text={t('fields.setup.step1.button')}
disabled={!!accountId || !createFee} disabled={!!accountId || !createFee}
showProgressIndicator={isLoadingCreate} showProgressIndicator={isLoadingCreate || (isLoadingCreateFee && !accountId)}
onClick={handleCreateCreditAccountClick} onClick={handleCreateCreditAccountClick}
className={styles.mintBtn} className={styles.mintBtn}
/> />
{accountId && <p className='xxsCaps'>{t('fields.setup.step1.success')}</p>} {accountId && <p className='xxsCaps'>{t('fields.setup.step1.success')}</p>}
<ErrorMessage message={createError} alignment='center' />
</div> </div>
</div> </div>
<div className={styles.section}> <div className={styles.section}>
@ -96,11 +101,9 @@ const SetupPosition = (props: Props) => {
text={t('fields.disclaimers.lockup.button', timeAndUnit)} text={t('fields.disclaimers.lockup.button', timeAndUnit)}
disabled={!accountId || !editFee} disabled={!accountId || !editFee}
className={styles.btn} className={styles.btn}
showProgressIndicator={isLoadingEnterVault} showProgressIndicator={(isLoadingEnterVault || isLoadingFee) && !!accountId}
/> />
{!isLoadingFee && !editFee && accountId && ( <ErrorMessage message={enterError} alignment='center' />
<p className='colorInfoVoteAgainst xxsCaps'>{t('fields.setup.step2.error')}</p>
)}
</div> </div>
</div> </div>
</Card> </Card>

View File

@ -18,6 +18,7 @@ import isEqual from 'lodash.isequal'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import useStore from 'store'
import styles from './EditVault.module.scss' import styles from './EditVault.module.scss'
@ -26,6 +27,7 @@ interface Props {
} }
const EditVault = (props: Props) => { const EditVault = (props: Props) => {
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
const router = useRouter() const router = useRouter()
const { const {
mutate: edit, mutate: edit,
@ -181,9 +183,17 @@ const EditVault = (props: Props) => {
} }
const additionalPositionValue = position.values.total - prevPosition.values.total const additionalPositionValue = position.values.total - prevPosition.values.total
const vaultCapValue = convertToBaseCurrency({
amount: ((props.activeVault.vaultCap?.max || 0) * VAULT_DEPOSIT_BUFFER).toString(),
denom: props.activeVault.vaultCap?.denom || '',
})
const vaultCapUsedValue = convertToBaseCurrency({
amount: (props.activeVault.vaultCap?.used || 0).toString(),
denom: props.activeVault.vaultCap?.denom || '',
})
const isVaultCapReached = props.activeVault.vaultCap const isVaultCapReached = props.activeVault.vaultCap
? props.activeVault.vaultCap.used + additionalPositionValue > ? vaultCapUsedValue + additionalPositionValue > vaultCapValue
props.activeVault.vaultCap.max * VAULT_DEPOSIT_BUFFER
: false : false
const isReducingAnyAsset = const isReducingAnyAsset =

View File

@ -59,7 +59,8 @@ const oraclesSlice = (set: NamedSet<Store>, get: GetState<Store>): OraclesSlice
.times(baseToDisplayCurrencyRatio) .times(baseToDisplayCurrencyRatio)
.toNumber() .toNumber()
} }
return amount // Prevent extremely small numbers
return amount < 0.005 ? 0 : amount
}, },
getExchangeRate: (denom1: string, denom2?: string) => { getExchangeRate: (denom1: string, denom2?: string) => {
if (!denom2) { if (!denom2) {

View File

@ -169,6 +169,7 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
({ ({
address: vaultInfo.vault.address, address: vaultInfo.vault.address,
vaultCap: { vaultCap: {
denom: vaultInfo.config.deposit_cap.denom,
used: Number(vaultInfo.utilization.amount), used: Number(vaultInfo.utilization.amount),
max: Number(vaultInfo.config.deposit_cap.amount), max: Number(vaultInfo.config.deposit_cap.amount),
}, },

View File

@ -1,9 +1,10 @@
export enum DocURL { export enum DocURL {
LANDING = 'https://docs.marsprotocol.io/',
RED_BANK = 'https://docs.marsprotocol.io/docs/learn/red-bank/red-bank-intro',
FIELDS = 'https://docs.marsprotocol.io/docs/learn/rover/rover-intro',
RED_BANK_LIQUIDATIONS = 'https://docs.marsprotocol.io/docs/learn/red-bank/red-bank-liquidations',
TERMS_OF_SERVICE_URL = 'https://docs.marsprotocol.io/docs/overview/legal/terms-of-service',
COOKIE_POLICY_URL = 'https://docs.marsprotocol.io/docs/overview/legal/cookie-policy', COOKIE_POLICY_URL = 'https://docs.marsprotocol.io/docs/overview/legal/cookie-policy',
FIELDS = 'https://docs.marsprotocol.io/docs/learn/rover/rover-intro',
LANDING = 'https://docs.marsprotocol.io/',
PRIVACY_POLICY_URL = 'https://docs.marsprotocol.io/docs/overview/legal/privacy-policy', PRIVACY_POLICY_URL = 'https://docs.marsprotocol.io/docs/overview/legal/privacy-policy',
RED_BANK = 'https://docs.marsprotocol.io/docs/learn/red-bank/red-bank-intro',
RED_BANK_LIQUIDATIONS = 'https://docs.marsprotocol.io/docs/learn/red-bank/red-bank-liquidations',
SECURITY = 'https://docs.marsprotocol.io/docs/overview/security/audits',
TERMS_OF_SERVICE_URL = 'https://docs.marsprotocol.io/docs/overview/legal/terms-of-service',
} }

View File

@ -24,6 +24,7 @@ interface Vault {
liq: number liq: number
} }
vaultCap?: { vaultCap?: {
denom: string
used: number used: number
max: number max: number
} }
@ -108,6 +109,7 @@ interface AprResponse {
interface VaultCapData { interface VaultCapData {
address: string address: string
vaultCap: { vaultCap: {
denom: string
used: number used: number
max: number max: number
} }

View File

@ -538,9 +538,9 @@
integrity sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ== integrity sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==
"@delphi-labs/shuttle@^2.3.9": "@delphi-labs/shuttle@^2.3.9":
version "2.3.10" version "2.3.9"
resolved "https://registry.yarnpkg.com/@delphi-labs/shuttle/-/shuttle-2.3.10.tgz#bd4f0fc48bb0ff13fd3a7e004246e469c5315d6e" resolved "https://registry.yarnpkg.com/@delphi-labs/shuttle/-/shuttle-2.3.9.tgz#d82c7160c9d297b9b6abfbce3b3e2bd96af99ccc"
integrity sha512-fS7vN7nFkeynbf7p01E8OTF3L+pKPnW2yuTWQTzHLzCSpzSaLkgIPnXxg4/C5/abr4FZ5ZytxpS9TKyj7hP4wA== integrity sha512-zst45B/nLp52DMCncouGcfrHw8X+FvBGUQnSiqynKDtJikolMRVU7DtE8iNpWXFGqK8hTnkn4srl/qoiL3wNDg==
dependencies: dependencies:
"@cosmjs/amino" "^0.29.5" "@cosmjs/amino" "^0.29.5"
"@cosmjs/cosmwasm-stargate" "^0.29.5" "@cosmjs/cosmwasm-stargate" "^0.29.5"
@ -1498,10 +1498,10 @@
resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f" resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f"
integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw== integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==
"@marsprotocol/wallet-connector@^1.4.2": "@marsprotocol/wallet-connector@^1.4.5":
version "1.4.2" version "1.4.5"
resolved "https://registry.yarnpkg.com/@marsprotocol/wallet-connector/-/wallet-connector-1.4.2.tgz#9dfeaf82242e821d2beef276c23e7f60313ae079" resolved "https://registry.yarnpkg.com/@marsprotocol/wallet-connector/-/wallet-connector-1.4.5.tgz#5d87cc587c9a5458bc02a412b7d5c7fe2c76e62d"
integrity sha512-rHVCbKHvAXHzmU5tZo9mV81Y4WclY6oDtO35nQqlh4X+DtIF/8j71hJRXCpGF+IuN1xwp3I8hcKAIqb08KOa5w== integrity sha512-96LjjqQe4+IYJeQGPftYjDFDSY2TOSkS+j0pP0HhbHdrbR5cT823ClvsrceNSjKAUWQESxNtdpZlf0DRQfKz8Q==
dependencies: dependencies:
"@cosmjs/cosmwasm-stargate" "^0.29.5" "@cosmjs/cosmwasm-stargate" "^0.29.5"
"@cosmjs/encoding" "^0.29.5" "@cosmjs/encoding" "^0.29.5"