Skip to content

Commit

Permalink
frontend: improve send result view
Browse files Browse the repository at this point in the history
- show errors in send result view instead of popups
- add edit transaction if there was an error
- add new transaction on success
- add buy ETH if there was gasfeetoolow error
  • Loading branch information
thisconnect committed Jan 9, 2025
1 parent 5d90189 commit d1e7d07
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 22 deletions.
3 changes: 3 additions & 0 deletions frontends/web/src/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,7 @@
},
"availableBalance": "Available balance",
"button": "Review",
"buyEth": "Buy ETH",
"coincontrol": {
"address": "Address",
"addressReused": "Address re-used",
Expand All @@ -1614,6 +1615,7 @@
"to": "To",
"total": "Total"
},
"edit": "Edit transaction",
"error": {
"erc20InsufficientGasFunds": "It seems like you do not have enough Ether to pay for this ERC20 transaction. Please make sure you hold enough Ether in your wallet",
"feeTooLow": "fee too low",
Expand Down Expand Up @@ -1665,6 +1667,7 @@
},
"maximum": "Send all",
"maximumSelectedCoins": "Send selected coins",
"newTransaction": "New transaction",
"noFeeTargets": "Fee rate estimations are currently unavailable. Please try again later or enter a custom fee.",
"priority": "Priority",
"scanQR": "Scan QR code",
Expand Down
90 changes: 73 additions & 17 deletions frontends/web/src/routes/account/send/components/result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@
* limitations under the License.
*/

import type { ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import type { AccountCode, TSendTx } from '@/api/account';
import { View, ViewButtons, ViewContent, ViewHeader } from '@/components/view/view';
import { Button } from '@/components/forms/button';
import { alertUser } from '@/components/alert/Alert';

type TProps = {
children?: ReactNode;
code: AccountCode;
onContinue: () => void;
onRetry: () => void;
result: TSendTx | undefined;
};

Expand All @@ -33,45 +35,99 @@ type TProps = {
* @returns view
*/
export const SendResult = ({
children,
code,
result,
onContinue,
onRetry,
}: TProps) => {
const navigate = useNavigate();
const { t } = useTranslation();
const navigate = useNavigate();

if (!result) {
return null;
}

const isAborted = 'aborted' in result;

if (!result.success && !isAborted) {
if (!result.success) {
if ('aborted' in result) {
return (
<View fullscreen textCenter verticallyCentered width="520px">
<ViewHeader />
<ViewContent withIcon="error">
<p>
{t('send.abort')}
</p>
</ViewContent>
<ViewButtons>
<Button primary onClick={() => navigate(`/account/${code}`)}>
{t('button.done')}
</Button>
<Button secondary onClick={() => onRetry()}>
{t('send.edit')}
</Button>
</ViewButtons>
</View>
);
}
switch (result.errorCode) {
case 'erc20InsufficientGasFunds':
alertUser(t(`send.error.${result.errorCode}`));
break;
return (
<View fullscreen textCenter verticallyCentered width="520px">
<ViewHeader />
<ViewContent withIcon="error">
<p>
{t(`send.error.${result.errorCode}`)}
</p>
</ViewContent>
<ViewButtons>
<Button primary onClick={() => navigate(`/account/${code}`)}>
{t('button.done')}
</Button>
<Button secondary onClick={() => navigate(`/exchange/select/${code}`, { replace: true })}>
{t('send.buyEth')}
</Button>
</ViewButtons>
</View>
);
default:
const { errorMessage } = result;
if (errorMessage) {
alertUser(t('unknownError', { errorMessage }));
} else {
alertUser(t('unknownError'));
}
return (
<View fullscreen textCenter verticallyCentered width="520px">
<ViewHeader />
<ViewContent withIcon="error">
<p>
{t('unknownError', { errorMessage })}
</p>
</ViewContent>
<ViewButtons>
<Button primary onClick={() => navigate(`/account/${code}`)}>
{t('button.done')}
</Button>
<Button secondary onClick={() => onRetry()}>
{t('send.edit')}
</Button>
</ViewButtons>
</View>
);
}
return null;
}

return (
<View fullscreen textCenter verticallyCentered width="520px">
<ViewHeader />
<ViewContent withIcon={result.success ? 'success' : 'error'}>
<ViewContent withIcon="success">
<p>
{ result.success ? t('send.success') : t('send.abort') }
{t('send.success')}
</p>
{children}
</ViewContent>
<ViewButtons>
<Button primary onClick={() => navigate(`/account/${code}`)}>Done</Button>
<Button secondary onClick={() => onContinue()}>New transaction</Button>
<Button primary onClick={() => navigate(`/account/${code}`)}>
{t('button.done')}
</Button>
<Button secondary onClick={() => onContinue()}>
{t('send.newTransaction')}
</Button>
</ViewButtons>
</View>
);
Expand Down
34 changes: 29 additions & 5 deletions frontends/web/src/routes/account/send/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Button } from '@/components/forms';
import { BackButton } from '@/components/backbutton/backbutton';
import { Column, ColumnButtons, Grid, GuideWrapper, GuidedContent, Header, Main } from '@/components/layout';
import { translate, TranslateProps } from '@/decorators/translate';
import { Amount } from '@/components/amount/amount';
import { FeeTargets } from './feetargets';
import { isBitcoinBased } from '@/routes/account/utils';
import { ConfirmSend } from './components/confirm/confirm';
Expand All @@ -36,6 +37,7 @@ import { ReceiverAddressInput } from './components/inputs/receiver-address-input
import { CoinInput } from './components/inputs/coin-input';
import { FiatInput } from './components/inputs/fiat-input';
import { NoteInput } from './components/inputs/note-input';
import { FiatValue } from './components/fiat-value';
import { TSelectedUTXOs } from './utxos';
import { TProposalError, txProposalErrorHandling } from './services';
import { CoinControl } from './coin-control';
Expand Down Expand Up @@ -137,9 +139,6 @@ class Send extends Component<Props, State> {
try {
const result = await accountApi.sendTx(code, this.state.note);
this.setState({ sendResult: result, isConfirming: false });
if (result.success) {
this.reset();
}
} catch (err) {
console.error(err);
} finally {
Expand Down Expand Up @@ -354,6 +353,13 @@ class Send extends Component<Props, State> {
});
};

private handleContinue = () => {
this.setState({
sendResult: undefined,
});
this.reset();
};

public render() {
const {
account,
Expand Down Expand Up @@ -397,8 +403,26 @@ class Send extends Component<Props, State> {
<SendResult
code={account.code}
result={sendResult || { success: true }}
onContinue={() => this.setState({ sendResult: undefined })}
/>
onContinue={this.handleContinue}
onRetry={() => this.setState({ sendResult: undefined })}>
<p>
{(proposedAmount &&
<Amount alwaysShowAmounts amount={proposedAmount.amount} unit={proposedAmount.unit}/>) || 'N/A'}
{' '}
<span className={style.unit}>
{(proposedAmount && proposedAmount.unit) || 'N/A'}
</span>
</p>
{(proposedAmount && proposedAmount.conversions && proposedAmount.conversions[activeCurrency]) ? (
<FiatValue baseCurrencyUnit={activeCurrency} amount={proposedAmount.conversions[activeCurrency] || ''} />
) : null}
{/* <A href={
account.blockExplorerTxPrefix
+ '' // TODO: tx.id
}>
View transaction in block explorer
</A> */}
</SendResult>
);
}

Expand Down

0 comments on commit d1e7d07

Please sign in to comment.