mirror of
https://github.com/cerc-io/mars-interface.git
synced 2026-09-15 03:14:07 +00:00
v1.2.1
This commit is contained in:
@@ -1,14 +1,26 @@
|
||||
import classNames from 'classnames'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import styles from './ErrorMessage.module.scss'
|
||||
|
||||
interface Props {
|
||||
errorMessage?: string
|
||||
message: unknown
|
||||
alignment?: 'left' | 'center' | 'right'
|
||||
}
|
||||
|
||||
export const ErrorMessage = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
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')}
|
||||
</a>
|
||||
<a
|
||||
className={styles.item}
|
||||
href={DocURL.SECURITY}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
title={t('global.security')}
|
||||
>
|
||||
{t('global.security')}
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.column3}>
|
||||
<div className={styles.header}>{t('global.community')}</div>
|
||||
|
||||
@@ -215,7 +215,7 @@ export const IncentivesButton = () => {
|
||||
onClick={() => (submitted ? null : claimRewards())}
|
||||
color='primary'
|
||||
/>
|
||||
<ErrorMessage errorMessage={error} alignment='center' />
|
||||
<ErrorMessage message={error} alignment='center' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,8 +7,10 @@ interface Props {
|
||||
value: string
|
||||
className: string
|
||||
maxDecimals: number
|
||||
minValue?: number
|
||||
maxValue?: number
|
||||
maxLength?: number
|
||||
allowNegative?: boolean
|
||||
suffix?: string
|
||||
onChange: (value: number) => void
|
||||
onBlur?: () => void
|
||||
@@ -79,6 +81,13 @@ export const NumberInput = (props: Props) => {
|
||||
const isNumber = !isNaN(Number(value))
|
||||
const hasMultipleDots = (value.match(/[.,]/g)?.length || 0) > 1
|
||||
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) {
|
||||
updateValues('0.', 0)
|
||||
@@ -90,17 +99,21 @@ export const NumberInput = (props: Props) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isNumber) return
|
||||
if (hasMultipleDots) return
|
||||
if (!isNumber || hasMultipleDots) return
|
||||
|
||||
if (props.maxDecimals !== undefined && decimals > props.maxDecimals) {
|
||||
if (exceedsMaxDecimals) {
|
||||
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) {
|
||||
updateValues(String(props.maxValue), props.maxValue)
|
||||
if (isLowerThanMinimum) {
|
||||
updateValues(String(props.minValue), props.minValue!)
|
||||
return
|
||||
}
|
||||
|
||||
if (isHigherThanMaximum) {
|
||||
updateValues(String(props.maxValue), props.maxValue!)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ export const Action = ({
|
||||
showProgressIndicator={actionButtonSpec.fetching}
|
||||
text={actionButtonSpec.text}
|
||||
/>
|
||||
<ErrorMessage errorMessage={feeError} alignment='center' />
|
||||
<ErrorMessage message={feeError} alignment='center' />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ export const useActiveVaultsColumns = () => {
|
||||
<>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
denom: vaultCap.denom,
|
||||
amount: vaultCap.max.toString(),
|
||||
}}
|
||||
/>
|
||||
@@ -212,7 +212,7 @@ export const useActiveVaultsColumns = () => {
|
||||
<TokenBalance
|
||||
showSymbol
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
denom: vaultCap.denom,
|
||||
amount: vaultCap.max.toString(),
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -74,7 +74,7 @@ export const AvailableVaultsTableMobile = () => {
|
||||
<span>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
denom: vault.vaultCap?.denom || '',
|
||||
amount: (vault.vaultCap?.max || 0).toString(),
|
||||
}}
|
||||
className={styles.inline}
|
||||
|
||||
@@ -159,7 +159,7 @@ export const useAvailableVaultsColumns = () => {
|
||||
<>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
denom: vaultCap.denom,
|
||||
amount: vaultCap.max.toString(),
|
||||
}}
|
||||
/>
|
||||
@@ -172,7 +172,7 @@ export const useAvailableVaultsColumns = () => {
|
||||
<TokenBalance
|
||||
showSymbol
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
denom: vaultCap.denom,
|
||||
amount: vaultCap.max.toString(),
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -42,6 +42,7 @@ export const BreakdownTable = (props: Props) => {
|
||||
const primaryAsset = useAsset({ denom: props.vault.denoms.primary })
|
||||
const secondaryAsset = useAsset({ denom: props.vault.denoms.secondary })
|
||||
const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency)
|
||||
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
|
||||
|
||||
const primaryPrice = usePrice(props.vault.denoms.primary)
|
||||
const secondaryPrice = usePrice(props.vault.denoms.secondary)
|
||||
@@ -165,13 +166,23 @@ export const BreakdownTable = (props: Props) => {
|
||||
const additionalPositionValue = props.isSetUp
|
||||
? props.newPosition.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
|
||||
? props.vault.vaultCap.used + additionalPositionValue > vaultCap
|
||||
? vaultCapUsedValue + additionalPositionValue > vaultCapValue
|
||||
: false
|
||||
|
||||
if (isVaultCapReached && props.vault.vaultCap) {
|
||||
const leftoverCap = vaultCap - props.vault.vaultCap.used
|
||||
const leftoverCap = vaultCapValue - vaultCapUsedValue
|
||||
const maxPositionValue = convertToDisplayCurrency({
|
||||
amount: ((props.isSetUp ? 0 : props.prevPosition.values.total) + leftoverCap).toString(),
|
||||
denom: 'uosmo',
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
border: 1px solid;
|
||||
@@ -37,6 +38,17 @@
|
||||
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,
|
||||
.select {
|
||||
color: $colorWhite;
|
||||
@@ -44,6 +56,11 @@
|
||||
outline: none;
|
||||
@include padding(1.5, 2);
|
||||
background: $backgroundInTile;
|
||||
|
||||
option {
|
||||
background: $backgroundInTile;
|
||||
color: $colorWhite;
|
||||
}
|
||||
}
|
||||
|
||||
.input:focus,
|
||||
|
||||
@@ -23,6 +23,7 @@ interface Props {
|
||||
export const TokenInput = (props: Props) => {
|
||||
const userBalances = useStore((s) => s.userBalances)
|
||||
const { t } = useTranslation()
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
|
||||
const walletBalance = findByDenom(userBalances, props.input.denom) as Coin
|
||||
const asset = useAsset({ denom: props.input.denom })
|
||||
@@ -54,12 +55,15 @@ export const TokenInput = (props: Props) => {
|
||||
props.onChange(microValue)
|
||||
}
|
||||
|
||||
if (!asset) return <></>
|
||||
if (!asset) return null
|
||||
|
||||
const maxAmount =
|
||||
(props.maxAmount === undefined ? Number(walletBalance.amount) : props.maxAmount) /
|
||||
10 ** asset.decimals
|
||||
|
||||
const showGasWarning =
|
||||
props.maxAmount && props.amount >= props.maxAmount && asset.denom === baseCurrency.denom
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<Button
|
||||
@@ -75,9 +79,11 @@ export const TokenInput = (props: Props) => {
|
||||
onChange={onValueEntered}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
minValue={0}
|
||||
maxValue={(props.maxAmount || 0) / 10 ** asset.decimals}
|
||||
value={(props.amount / 10 ** asset.decimals).toString()}
|
||||
maxDecimals={6}
|
||||
allowNegative={false}
|
||||
suffix={isSingleToken ? ` ${props.input.symbol}` : ''}
|
||||
className={inputClasses}
|
||||
/>
|
||||
@@ -98,6 +104,11 @@ export const TokenInput = (props: Props) => {
|
||||
</select>
|
||||
</>
|
||||
)}
|
||||
{showGasWarning ? (
|
||||
<div className={styles.inputWarning}>
|
||||
<p className='tippyContainer'>{t('common.lowUstAmountAfterTransaction')}</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.bottomInfo}>
|
||||
|
||||
Reference in New Issue
Block a user