mirror of
https://github.com/cerc-io/mars-interface.git
synced 2024-12-22 20:27:44 +00:00
v1.2.1
This commit is contained in:
parent
53797b4342
commit
ec0eee27ec
@ -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",
|
||||||
|
@ -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>
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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' />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -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}
|
||||||
|
@ -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(),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -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',
|
||||||
|
@ -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,
|
||||||
|
@ -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}>
|
||||||
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
@ -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 &&
|
||||||
|
@ -21,6 +21,7 @@ export const vault: Vault = {
|
|||||||
secondary: 'ATOM',
|
secondary: 'ATOM',
|
||||||
},
|
},
|
||||||
vaultCap: {
|
vaultCap: {
|
||||||
|
denom: 'uosmo',
|
||||||
used: 1000,
|
used: 1000,
|
||||||
max: 5000,
|
max: 5000,
|
||||||
},
|
},
|
||||||
|
@ -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'
|
||||||
|
@ -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>
|
||||||
|
@ -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 =
|
||||||
|
@ -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) {
|
||||||
|
@ -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),
|
||||||
},
|
},
|
||||||
|
@ -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',
|
||||||
}
|
}
|
||||||
|
2
src/types/interfaces/fields.d.ts
vendored
2
src/types/interfaces/fields.d.ts
vendored
@ -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
|
||||||
}
|
}
|
||||||
|
14
yarn.lock
14
yarn.lock
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user