Onboarding error handling

This commit is contained in:
Bill He
2023-09-18 21:58:30 -07:00
parent ea81d7a150
commit 2b105fb522
5 changed files with 61 additions and 17 deletions
+5 -2
View File
@@ -66,11 +66,14 @@ const useLocalNotificationsContext = () => {
} of transferNotifications) {
try {
if (currentStatus && currentStatus?.squidTransactionStatus !== 'ongoing') continue;
const status = await squid?.getStatus({ transactionId: txHash, toChainId, fromChainId });
if (status) statuses[txHash] = status;
} catch (error) {
console.error(error);
// ignore not found errors since the route might not be available yet
if (error?.errors?.length && error.errors[0].errorType !== 'NotFoundError') {
statuses[txHash] = error;
}
}
}
return statuses;
+38 -8
View File
@@ -1,7 +1,9 @@
import { useCallback, useEffect, useMemo } from 'react';
import styled, { type AnyStyledComponent } from 'styled-components';
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
import { groupBy } from 'lodash';
import { AlertType } from '@/constants/alerts';
import { AbacusOrderStatus, ORDER_SIDES, ORDER_STATUS_STRINGS } from '@/constants/abacus';
import { DialogTypes } from '@/constants/dialogs';
import { STRING_KEYS } from '@/constants/localization';
@@ -10,6 +12,7 @@ import { ORDER_SIDE_STRINGS, TRADE_TYPE_STRINGS, TradeTypes } from '@/constants/
import { useLocalNotifications } from '@/hooks/useLocalNotifications';
import { AlertMessage } from '@/components/AlertMessage';
import { Icon, IconName } from '@/components/Icon';
import { Output, OutputType } from '@/components/Output';
import { TransferStatusToast } from '@/views/TransferStatus';
@@ -119,19 +122,33 @@ export const notificationTypes = [
const { toChainId, status, txHash, toAmount } = transfer;
const finished = Boolean(status) && status?.squidTransactionStatus !== 'ongoing';
const type = toChainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdraw';
// @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error;
// TODO: confirm with design what the description should be
const description = (
<div>
<Styled.TransferText>
{type === 'deposit' ? 'Deposit of ' : 'Withdraw of'}{' '}
<Output type={OutputType.Fiat} value={toAmount} />
</Styled.TransferText>
{error && (
<AlertMessage type={AlertType.Error}>
{stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
})}
</AlertMessage>
)}
</div>
);
trigger(
txHash,
{
icon: <Icon iconName={finished ? IconName.Transfer : IconName.Clock} />,
title: stringGetter({ key: getTitleStringKey(type, finished) }),
// TODO: confirm with design what the description should be
description: (
<>
<span>{type === 'deposit' ? 'Deposit of ' : 'Withdraw of'}</span>
<Output type={OutputType.Fiat} value={toAmount} />
</>
),
description: description,
customContent: (
<TransferStatusToast
toAmount={transfer.toAmount}
@@ -139,7 +156,12 @@ export const notificationTypes = [
status={transfer.status}
/>
),
customMenuContent: !finished && <TransferStatusSteps status={transfer.status} />,
customMenuContent: !finished && (
<div>
{description}
<TransferStatusSteps status={transfer.status} />
</div>
),
toastSensitivity: 'foreground',
},
[]
@@ -149,3 +171,11 @@ export const notificationTypes = [
},
},
] satisfies NotificationTypeConfig[];
const Styled: Record<string, AnyStyledComponent> = {};
Styled.TransferText = styled.span`
display: inline-flex;
align-items: center;
gap: 0.5ch;
`
+15
View File
@@ -7,9 +7,11 @@ import { StatusResponse } from '@0xsquid/sdk';
import { useInterval, useStringGetter } from '@/hooks';
import { STRING_KEYS } from '@/constants/localization';
import { AlertType } from '@/constants/alerts';
import { formatSeconds } from '@/lib/timeUtils';
import { AlertMessage } from '@/components/AlertMessage';
import { Output, OutputType } from '@/components/Output';
import { WithReceipt } from '@/components/WithReceipt';
import { Icon, IconName } from '@/components/Icon';
@@ -33,6 +35,9 @@ export const TransferStatusToast = ({
const [open, setOpen] = useState<boolean>(false);
const [secondsLeft, setSecondsLeft] = useState<number | undefined>();
// @ts-ignore status.errors is not in the type definition but can be returned
const error = status?.errors?.length ? status?.errors[0] : status?.error;
const type = useMemo(
() => (status?.toChain?.chainData?.chainId === TESTNET_CHAIN_ID ? 'deposit' : 'withdrawal'),
[status]
@@ -74,6 +79,16 @@ export const TransferStatusToast = ({
},
})}
</Styled.Status>
{error && (
<AlertMessage type={AlertType.Error}>
{stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: {
ERROR_MESSAGE: error.message || stringGetter({ key: STRING_KEYS.UNKNOWN_ERROR }),
},
})}
</AlertMessage>
)}
<Styled.Trigger>
<Styled.TriggerIcon>
<Icon iconName={IconName.Caret} />
+1 -1
View File
@@ -59,7 +59,7 @@ export const TransferStatusSteps = ({ status }: ElementProps) => {
},
];
const currentStatus = routeStatus[routeStatus?.length - 1];
const currentStatus = routeStatus ? routeStatus[routeStatus?.length - 1] : undefined;
let currentStep = TransferStatusStep.Bridge;
@@ -38,6 +38,7 @@ import { getTransferInputs } from '@/state/inputsSelectors';
import abacusStateManager from '@/lib/abacus';
import { MustBigNumber } from '@/lib/numbers';
import { log } from '@/lib/telemetry';
import { parseWalletError } from '@/lib/wallet';
import { ChainSelectMenu } from './ChainSelectMenu';
import { TokenSelectMenu } from './TokenSelectMenu';
@@ -286,12 +287,7 @@ export const DepositForm = ({ onDeposit, onError }: DepositFormProps) => {
const errorMessage = useMemo(() => {
if (error) {
return error?.message
? stringGetter({
key: STRING_KEYS.SOMETHING_WENT_WRONG_WITH_MESSAGE,
params: { ERROR_MESSAGE: error.message },
})
: stringGetter({ key: STRING_KEYS.SOMETHING_WENT_WRONG });
return parseWalletError({ error, stringGetter }).message;
}
if (fromAmount) {