mirror of
https://github.com/cerc-io/mars-interface.git
synced 2025-08-08 02:20:06 +00:00
133 lines
4.2 KiB
TypeScript
133 lines
4.2 KiB
TypeScript
import { Coin } from '@cosmjs/proto-signing'
|
|
import classNames from 'classnames'
|
|
import { Button, DisplayCurrency, NumberInput } from 'components/common'
|
|
import { findByDenom } from 'functions'
|
|
import { useAsset } from 'hooks/data'
|
|
import { formatValue, magnify } from 'libs/parse'
|
|
import { useTranslation } from 'react-i18next'
|
|
import useStore from 'store'
|
|
|
|
import styles from './TokenInput.module.scss'
|
|
|
|
interface Props {
|
|
tokens: string[]
|
|
input: Input
|
|
amount: number
|
|
maxAmount?: number
|
|
maxAmountLabel: string
|
|
borrowRate?: number
|
|
disableGasWarning?: boolean
|
|
onChange: (amount: number) => void
|
|
onSelect?: (denom: string) => void
|
|
}
|
|
|
|
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 })
|
|
const isSingleToken = props.tokens.length === 1
|
|
const inputClasses = classNames([
|
|
styles.input,
|
|
'number',
|
|
's',
|
|
styles.secondary,
|
|
isSingleToken && styles.singleToken,
|
|
])
|
|
const selectClasses = classNames([styles.select, 's', isSingleToken && styles.disabled])
|
|
const containerClasses = classNames([
|
|
styles.container,
|
|
styles.secondary,
|
|
props.borrowRate !== undefined && styles.isBorrow,
|
|
])
|
|
|
|
const onValueEntered = (newValue: number) => {
|
|
let microValue = Number(magnify(newValue, asset?.decimals || 0))
|
|
|
|
if (props.maxAmount !== undefined) {
|
|
if (microValue >= (props.maxAmount ?? 0)) microValue = props.maxAmount
|
|
} else {
|
|
if (!walletBalance?.amount) microValue = 0
|
|
if (microValue >= (Number(walletBalance?.amount) ?? 0))
|
|
microValue = Number(walletBalance?.amount)
|
|
}
|
|
props.onChange(microValue)
|
|
}
|
|
|
|
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 &&
|
|
!props.disableGasWarning
|
|
|
|
return (
|
|
<div className={styles.wrapper}>
|
|
<Button
|
|
color='quaternary'
|
|
className={`xxsCaps faded ${styles.maxBtn}`}
|
|
onClick={() => onValueEntered(maxAmount)}
|
|
text={`${props.maxAmountLabel}: ${maxAmount}`}
|
|
variant='transparent'
|
|
/>
|
|
<div className={styles.input}>
|
|
<div className={containerClasses}>
|
|
<NumberInput
|
|
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}
|
|
/>
|
|
{!isSingleToken && (
|
|
<>
|
|
<div className={styles.divider} />
|
|
<select
|
|
onChange={(e) => props.onSelect && props.onSelect(e.target.value)}
|
|
className={selectClasses}
|
|
tabIndex={isSingleToken ? -1 : 0}
|
|
value={props.input.symbol}
|
|
>
|
|
{props.tokens.map((token) => (
|
|
<option key={token} value={token}>
|
|
{token}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</>
|
|
)}
|
|
{showGasWarning ? (
|
|
<div className={styles.inputWarning}>
|
|
<p className='tippyContainer'>{t('common.lowUstAmountAfterTransaction')}</p>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
<div className={styles.bottomInfo}>
|
|
<DisplayCurrency
|
|
prefixClass='xxsCaps faded'
|
|
valueClass='xxsCaps faded'
|
|
coin={{ denom: asset.denom, amount: props.amount.toString() }}
|
|
/>
|
|
{props.borrowRate && (
|
|
<span className='xxsCaps number faded'>
|
|
{formatValue(props.borrowRate, 2, 2, true, false, `% ${t('common.apr')}`)}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|