react-icons/hi#HiOutlineExclamationCircle TypeScript Examples
The following examples show how to use
react-icons/hi#HiOutlineExclamationCircle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: EnterBTCAmount.tsx From polkabtc-ui with Apache License 2.0 | 4 votes |
EnterBTCAmount = (): JSX.Element | null => {
const dispatch = useDispatch();
const { t } = useTranslation();
const [status, setStatus] = React.useState(STATUSES.IDLE);
const [error, setError] = React.useState<Error | null>(null);
const {
polkaBtcLoaded,
address,
bitcoinHeight,
btcRelayHeight,
prices,
parachainStatus,
balanceDOT
} = useSelector((state: StoreType) => state.general);
const {
register,
handleSubmit,
watch,
formState: { errors }
} = useForm<IssueForm>({
mode: 'onChange' // 'onBlur'
});
const btcAmount = watch(BTC_AMOUNT);
// Additional info: bridge fee, security deposit, amount BTC
// Current fee model specification taken from: https://interlay.gitlab.io/polkabtc-spec/spec/fee.html
const [feeRate, setFeeRate] = React.useState(new Big(0.005)); // Set default to 0.5%
const [depositRate, setDepositRate] = React.useState(new Big(0.00005)); // Set default to 0.005%
const [btcToDOTRate, setBTCToDOTRate] = React.useState(new Big(0));
const [vaults, setVaults] = React.useState<Map<AccountId, Big>>();
const [dustValue, setDustValue] = React.useState('0');
const [vaultMaxAmount, setVaultMaxAmount] = React.useState('');
const [submitStatus, setSubmitStatus] = React.useState(STATUSES.IDLE);
const [submitError, setSubmitError] = React.useState<Error | null>(null);
React.useEffect(() => {
if (!polkaBtcLoaded) return;
(async () => {
try {
setStatus(STATUSES.PENDING);
const [
theFeeRate,
theDepositRate,
issuePeriodInBlocks,
theDustValue,
btcToDot,
theVaults
] = await Promise.all([
// Loading this data is not strictly required as long as the constantly set values did
// not change. However, you will not see the correct value for the security deposit.
window.polkaBTC.issue.getFeeRate(),
window.polkaBTC.fee.getIssueGriefingCollateralRate(),
window.polkaBTC.issue.getIssuePeriod(),
window.polkaBTC.redeem.getDustValue(),
window.polkaBTC.oracle.getExchangeRate(),
// This data (the vaults) is strictly required to request issue
window.polkaBTC.vaults.getVaultsWithIssuableTokens()
]);
setStatus(STATUSES.RESOLVED);
setFeeRate(theFeeRate);
setDepositRate(theDepositRate);
const issuePeriod = issuePeriodInBlocks * BLOCK_TIME;
dispatch(updateIssuePeriodAction(issuePeriod));
setDustValue(theDustValue.toString());
setBTCToDOTRate(btcToDot);
let theVaultMaxAmount = new Big(0);
// The first item is the vault with the largest capacity
theVaultMaxAmount = theVaults.values().next().value;
setVaultMaxAmount(theVaultMaxAmount.toString());
setVaults(theVaults);
} catch (error) {
setStatus(STATUSES.REJECTED);
setError(error);
}
})();
}, [
polkaBtcLoaded,
dispatch
]);
if (status === STATUSES.REJECTED && error) {
return (
<ErrorHandler error={error} />
);
}
if (status === STATUSES.IDLE || status === STATUSES.PENDING) {
return (
<div
className={clsx(
'flex',
'justify-center'
)}>
<EllipsisLoader dotClassName='bg-interlayRose-400' />
</div>
);
}
const validateBTCAmount = (value = 0): string | undefined => {
const bigBTCAmount = new Big(value);
const securityDeposit = bigBTCAmount.mul(btcToDOTRate).mul(depositRate);
const minimumRequiredDOTAmount = new Big(EXTRA_REQUIRED_DOT_AMOUNT).add(securityDeposit);
if (new Big(balanceDOT) <= minimumRequiredDOTAmount) {
return t('insufficient_funds_dot');
}
if (value > MAXIMUM_ISSUABLE_POLKA_BTC_AMOUNT) {
return t('issue_page.validation_max_value');
} else if (bigBTCAmount < new Big(dustValue)) {
return `${t('issue_page.validation_min_value')}${dustValue} BTC).`;
}
const vaultId = getRandomVaultIdWithCapacity(Array.from(vaults || new Map()), bigBTCAmount);
if (!vaultId) {
return t('issue_page.maximum_in_single_request', {
maxAmount: parseFloat(Number(vaultMaxAmount).toFixed(5))
});
}
if (bitcoinHeight - btcRelayHeight > BLOCKS_BEHIND_LIMIT) {
return t('issue_page.error_more_than_6_blocks_behind');
}
if (!polkaBtcLoaded) {
return 'PolkaBTC must be loaded!';
}
if (btcToSat(value.toString()) === undefined) {
return 'Invalid BTC amount input!';
}
return undefined;
};
const onSubmit = async (data: IssueForm) => {
try {
const polkaBTCAmount = new Big(data[BTC_AMOUNT]);
setSubmitStatus(STATUSES.PENDING);
const result = await window.polkaBTC.issue.request(polkaBTCAmount);
// ray test touch <
// TODO: handle issue aggregation
const issueRequest = await parachainToUIIssueRequest(result[0].id, result[0].issueRequest);
// ray test touch >
setSubmitStatus(STATUSES.RESOLVED);
// Get the issue ID from the request issue event
const issueId = stripHexPrefix(result[0].id.toString());
dispatch(changeIssueIdAction(issueId));
// Update the issue status
dispatch(addIssueRequestAction(issueRequest));
dispatch(changeIssueStepAction('BTC_PAYMENT'));
} catch (error) {
setSubmitStatus(STATUSES.REJECTED);
setSubmitError(error);
}
};
if (status === STATUSES.RESOLVED) {
const bigBTCAmount = new Big(btcAmount || 0);
const bridgeFee = bigBTCAmount.mul(feeRate);
const securityDeposit = bigBTCAmount.mul(btcToDOTRate).mul(depositRate);
const polkaBTCAmount = bigBTCAmount.sub(bridgeFee);
return (
<>
<form
className='space-y-8'
onSubmit={handleSubmit(onSubmit)}>
<h4
className={clsx(
'font-medium',
'text-center',
'text-interlayRose'
)}>
{t('issue_page.mint_polka_by_wrapping')}
</h4>
<PolkaBTCField
id='btc-amount'
name={BTC_AMOUNT}
type='number'
label='BTC'
step='any'
placeholder='0.00'
min={0}
ref={register({
required: {
value: true,
message: t('issue_page.enter_valid_amount')
},
validate: value => validateBTCAmount(value)
})}
approxUSD={`≈ $ ${getUsdAmount(btcAmount || '0', prices.bitcoin.usd)}`}
error={!!errors[BTC_AMOUNT]}
helperText={errors[BTC_AMOUNT]?.message} />
<ParachainStatusInfo status={parachainStatus} />
<PriceInfo
title={
<h5 className='text-textSecondary'>
{t('bridge_fee')}
</h5>
}
unitIcon={
<BitcoinLogoIcon
width={23}
height={23} />
}
value={displayBtcAmount(bridgeFee)}
unitName='BTC'
approxUSD={getUsdAmount(bridgeFee, prices.bitcoin.usd)}
tooltip={
<Tooltip overlay={t('issue_page.tooltip_bridge_fee')}>
<HiOutlineExclamationCircle className='text-textSecondary' />
</Tooltip>
} />
<PriceInfo
title={
<h5 className='text-textSecondary'>
{t('issue_page.security_deposit')}
</h5>
}
unitIcon={
<PolkadotLogoIcon
width={20}
height={20} />
}
value={displayDotAmount(securityDeposit)}
unitName='DOT'
approxUSD={getUsdAmount(securityDeposit, prices.polkadot.usd)}
tooltip={
<Tooltip overlay={t('issue_page.tooltip_security_deposit')}>
<HiOutlineExclamationCircle className='text-textSecondary' />
</Tooltip>
} />
<hr
className={clsx(
'border-t-2',
'my-2.5',
'border-textSecondary'
)} />
<PriceInfo
title={
<h5 className='text-textPrimary'>
{t('you_will_receive')}
</h5>
}
unitIcon={
<PolkaBTCLogoIcon
width={23}
height={23} />
}
value={displayBtcAmount(polkaBTCAmount)}
unitName='PolkaBTC'
approxUSD={getUsdAmount(polkaBTCAmount, prices.bitcoin.usd)} />
<InterlayButton
type='submit'
style={{ display: 'flex' }}
className='mx-auto'
variant='contained'
color='primary'
disabled={
// TODO: `parachainStatus` and `address` should be checked at upper levels
parachainStatus !== ParachainStatus.Running ||
!address
}
pending={submitStatus === STATUSES.PENDING}>
{t('confirm')}
</InterlayButton>
</form>
{(submitStatus === STATUSES.REJECTED && submitError) && (
<ErrorModal
open={!!submitError}
onClose={() => {
setSubmitStatus(STATUSES.IDLE);
setSubmitError(null);
}}
title='Error'
description={
typeof submitError === 'string' ?
submitError :
submitError.message
} />
)}
</>
);
}
return null;
}