Skip to content

Commit

Permalink
fix: improve issue form insufficient funds notice (#1380)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao authored Jun 30, 2023
1 parent b296507 commit fadf8ba
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@
"please_enter_no_higher_available_balance": "Please enter an amount no higher than your available balance",
"field_amount": "{{field}} amount",
"please_enter_a_valid_address": "Please enter a valid address",
"ensure_adequate_amount_left_to_cover_fees": "Ensure that an adequate number of coins are left to cover the fees"
"ensure_adequate_amount_left_to_cover_action": "Ensure that an adequate number of coins are left to cover the {{ action }}"
},
"xcm_transfer": {
"validation": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ const TransactionFeeDetails = ({
)})`
: `${0.0} ${ticker} (${formatUSD(0)})`;

const errorMessage = showInsufficientBalance && t('forms.ensure_adequate_amount_left_to_cover_fees');
const errorMessage =
showInsufficientBalance &&
t('forms.ensure_adequate_amount_left_to_cover_action', { action: t('fees').toLowerCase() });

const handleSelectionChange = (key: Key) => setTicker(key as string);

Expand Down
69 changes: 38 additions & 31 deletions src/pages/Bridge/BridgeOverview/components/IssueForm/IssueForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { CurrencyExt, getIssueRequestsFromExtrinsicResult, isCurrencyEqual, Issue } from '@interlay/interbtc-api';
import {
CurrencyExt,
getIssueRequestsFromExtrinsicResult,
isCurrencyEqual,
Issue,
newMonetaryAmount
} from '@interlay/interbtc-api';
import { IssueLimits } from '@interlay/interbtc-api/build/src/parachain/issue';
import { BitcoinAmount, MonetaryAmount } from '@interlay/monetary-js';
import { mergeProps } from '@react-aria/utils';
Expand Down Expand Up @@ -41,7 +47,7 @@ type IssueFormProps = { requestLimits: IssueLimits } & IssueData;
const IssueForm = ({ requestLimits, dustValue, issueFee }: IssueFormProps): JSX.Element => {
const { t } = useTranslation();
const prices = useGetPrices();
const { getBalance } = useGetBalances();
const { getAvailableBalance } = useGetBalances();
const { getSecurityDeposit } = useGetIssueData();
const { getCurrencyFromTicker, isLoading: isLoadingCurrencies } = useGetCurrencies(true);

Expand All @@ -52,6 +58,10 @@ const IssueForm = ({ requestLimits, dustValue, issueFee }: IssueFormProps): JSX.

useDebounce(() => setDebouncedAmount(amount), 500, [amount]);

const [securityDeposit, setSecurityDeposit] = useState<MonetaryAmount<CurrencyExt>>(
newMonetaryAmount(0, GOVERNANCE_TOKEN)
);

const [selectedVault, setSelectedVault] = useState<BridgeVaultData>();

const { data: vaultsData, getAvailableVaults } = useGetVaults(BridgeActions.ISSUE);
Expand Down Expand Up @@ -154,6 +164,21 @@ const IssueForm = ({ requestLimits, dustValue, issueFee }: IssueFormProps): JSX.
}
});

const griefingCollateralTicker = form.values[BRIDGE_ISSUE_GRIEFING_COLLATERAL_TOKEN];

useEffect(() => {
const computeSecurityDeposit = async () => {
const btcAmount = safeBitcoinAmount(amount || 0);
const deposit = await getSecurityDeposit(btcAmount, griefingCollateralTicker);

if (!deposit) return;

setSecurityDeposit(deposit);
};

computeSecurityDeposit();
}, [amount, griefingCollateralTicker, setSecurityDeposit, getSecurityDeposit]);

const handleToggleCustomVault = (e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.checked) {
form.setFieldTouched(BRIDGE_ISSUE_CUSTOM_VAULT_FIELD, false, true);
Expand All @@ -180,43 +205,31 @@ const IssueForm = ({ requestLimits, dustValue, issueFee }: IssueFormProps): JSX.

const bridgeFee = monetaryAmount.mul(issueFee.toBig());

const griefingCollateralTicker = form.values[BRIDGE_ISSUE_GRIEFING_COLLATERAL_TOKEN];

const [securityDeposit, setSecurityDeposit] = useState<MonetaryAmount<CurrencyExt>>();
useEffect(() => {
const computeSecurityDeposit = async () => {
const btcAmount = safeBitcoinAmount(amount || 0);
const griefingCollateralTicker = form.values[BRIDGE_ISSUE_GRIEFING_COLLATERAL_TOKEN];
const deposit = await getSecurityDeposit(btcAmount, griefingCollateralTicker);
setSecurityDeposit(deposit);
};

computeSecurityDeposit();
}, [amount, form.values, setSecurityDeposit, getSecurityDeposit]);

const totalAmount = monetaryAmount.gte(bridgeFee) ? monetaryAmount.sub(bridgeFee) : new BitcoinAmount(0);
const totalAmountUSD = totalAmount
? convertMonetaryAmountToValueInUSD(totalAmount, getTokenPrice(prices, totalAmount.currency.ticker)?.usd) || 0
: 0;

const isSelectingVault = form.values[BRIDGE_ISSUE_CUSTOM_VAULT_SWITCH];

const isBtnDisabled = isTransactionFormDisabled(form, transaction.fee);

const griefingCollateralCurrencyBalance = griefingCollateralTicker
? getBalance(griefingCollateralTicker)?.free
? getAvailableBalance(griefingCollateralTicker)
: undefined;

const hasEnoughGriefingCollateralBalance = useMemo(() => {
if (!debouncedAmount) return true;

if (
securityDeposit === undefined ||
griefingCollateralCurrencyBalance === undefined ||
!griefingCollateralCurrencyBalance ||
!isCurrencyEqual(securityDeposit.currency, griefingCollateralCurrencyBalance.currency)
) {
return false;
}

return griefingCollateralCurrencyBalance.gte(securityDeposit);
}, [securityDeposit, griefingCollateralCurrencyBalance]);
}, [debouncedAmount, griefingCollateralCurrencyBalance, securityDeposit]);

const isBtnDisabled = isTransactionFormDisabled(form, transaction.fee) || !hasEnoughGriefingCollateralBalance;

return (
<>
Expand Down Expand Up @@ -259,20 +272,14 @@ const IssueForm = ({ requestLimits, dustValue, issueFee }: IssueFormProps): JSX.
bridgeFee={bridgeFee}
securityDeposit={securityDeposit}
securityDepositSelectProps={form.getFieldProps(BRIDGE_ISSUE_GRIEFING_COLLATERAL_TOKEN, true)}
showInsufficientSecurityBalance={!hasEnoughGriefingCollateralBalance}
feeDetailsProps={{
...transaction.fee.detailsProps,
selectProps: form.getFieldProps(BRIDGE_ISSUE_FEE_TOKEN, true)
}}
/>
<AuthCTA
type='submit'
disabled={isBtnDisabled || !hasEnoughGriefingCollateralBalance}
size='large'
loading={transaction.isLoading}
>
{hasEnoughGriefingCollateralBalance
? t('issue')
: t('insufficient_token_balance', { token: griefingCollateralTicker })}
<AuthCTA type='submit' disabled={isBtnDisabled} size='large' loading={transaction.isLoading}>
{t('issue')}
</AuthCTA>
</Flex>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Currency, MonetaryAmount } from '@interlay/monetary-js';
import { useId } from '@react-aria/utils';
import { useTranslation } from 'react-i18next';

import { displayMonetaryAmountInUSDFormat } from '@/common/utils/utils';
import { Flex, TokenInput } from '@/component-library';
import { Alert, Flex, TokenInput } from '@/component-library';
import {
TransactionDetails as BaseTransactionDetails,
TransactionDetailsDd,
Expand Down Expand Up @@ -30,6 +31,7 @@ type TransactionDetailsProps = {
bitcoinNetworkFee?: MonetaryAmount<Currency>;
feeDetailsProps?: TransactionFeeDetailsProps;
securityDepositSelectProps?: TransactionSelectTokenProps;
showInsufficientSecurityBalance?: boolean;
};

const TransactionDetails = ({
Expand All @@ -42,11 +44,14 @@ const TransactionDetails = ({
securityDeposit,
bitcoinNetworkFee,
feeDetailsProps,
securityDepositSelectProps
securityDepositSelectProps,
showInsufficientSecurityBalance
}: TransactionDetailsProps): JSX.Element => {
const prices = useGetPrices();
const { t } = useTranslation();

const griefingCollateralErrorMessageId = useId();

const { items: griefingCollateralCurrencies } = useSelectCurrency(
SelectCurrencyFilter.ISSUE_GRIEFING_COLLATERAL_CURRENCY
);
Expand Down Expand Up @@ -92,6 +97,8 @@ const TransactionDetails = ({
<TransactionSelectToken
label={t('bridge.security_deposit_token')}
items={griefingCollateralCurrencies}
aria-describedby={griefingCollateralErrorMessageId}
validationState={showInsufficientSecurityBalance ? 'invalid' : 'valid'}
{...securityDepositSelectProps}
/>
)}
Expand All @@ -111,6 +118,13 @@ const TransactionDetails = ({
</>
)}
</BaseTransactionDetails>
{showInsufficientSecurityBalance && (
<Alert id={griefingCollateralErrorMessageId} status='error'>
{t('forms.ensure_adequate_amount_left_to_cover_action', {
action: t('bridge.security_deposit_token').toLowerCase()
})}
</Alert>
)}
{bitcoinNetworkFee && (
<TransactionFeeDetails label={t('bridge.bitcoin_network_fee')} amount={bitcoinNetworkFee} />
)}
Expand Down

2 comments on commit fadf8ba

@vercel
Copy link

@vercel vercel bot commented on fadf8ba Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on fadf8ba Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.