Skip to content

Commit

Permalink
fix: tx error handling bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
earthtojake authored Apr 4, 2023
1 parent 64d5cf4 commit 0b871be
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 76 deletions.
18 changes: 1 addition & 17 deletions app/src/components/dev/ModalDemoCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IconType } from '@lyra/ui/components/Icon'
import Modal from '@lyra/ui/components/Modal'
import ModalBody from '@lyra/ui/components/Modal/ModalBody'
import Text from '@lyra/ui/components/Text'
import { createPendingToast, createToast } from '@lyra/ui/components/Toast'
import { createToast } from '@lyra/ui/components/Toast'
import { MarginProps } from '@lyra/ui/types'
import React, { useState } from 'react'

Expand Down Expand Up @@ -190,22 +190,6 @@ export default function ModalDemoCard({ ...marginProps }: MarginProps): CardElem
})
}}
/>
<Button
variant={'primary'}
mr={2}
mt={2}
isOutline
label="Create Pending Toast"
size={'medium'}
onClick={() => {
createPendingToast({
description: 'Pending: This is a pending toast.',
hrefLabel: 'This is hrefLabel',
href: '/portfolio',
target: 'blank',
})
}}
/>
</CardSection>
</Card>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { ErrorDescription } from '@ethersproject/abi/lib/interface'
import { JsonRpcProvider, TransactionReceipt, TransactionResponse } from '@ethersproject/providers'
import { IconType } from '@lyra/ui/components/Icon'
import { closeToast, createPendingToast, updatePendingToast, updateToast } from '@lyra/ui/components/Toast'
import Spinner from '@lyra/ui/components/Spinner'
import { closeToast, createToast, updateToast } from '@lyra/ui/components/Toast'
import { BigNumber, Contract, ContractReceipt, PopulatedTransaction } from 'ethers'
import { useCallback } from 'react'
import React, { useCallback } from 'react'

import { AppNetwork, Network } from '@/app/constants/networks'
import { TransactionType } from '@/app/constants/screen'
Expand Down Expand Up @@ -127,6 +128,8 @@ export type TransactionOptions = {
metadata?: TransactionMetadata
}

const ToastSpinner = () => <Spinner size={20} />

const extractError = (rawError: any, options: TransactionErrorOptions): TransactionError => {
const error = rawError?.error?.error ?? rawError?.error ?? rawError
const errorCode = error?.code
Expand All @@ -136,7 +139,6 @@ const extractError = (rawError: any, options: TransactionErrorOptions): Transact
if (errorData && options['contract']) {
try {
errorDescription = options['contract'].interface.parseError(errorData)
console.log({ errorDescription })
} catch (_err) {}
}

Expand Down Expand Up @@ -189,14 +191,9 @@ const handleError = (rawError: any, options: TransactionErrorOptions) => {
const { handler, network, toastId, receipt } = options

const error = extractError(rawError, options)
const errorReasonMessage = error.reason
? formatErrorReason(error.reason, options)
: options.stage === TransactionErrorStage.Reverted
? 'Transaction reverted'
: 'Failed to send transaction'

if (!errorReasonMessage) {
// Ignore the transaction if no error reason is returned (e.g for denied transaction)
if (error.reason === TransactionErrorReason.UserDenied) {
// Ignore user denied reason
closeToast(toastId)
return
}
Expand All @@ -208,11 +205,20 @@ const handleError = (rawError: any, options: TransactionErrorOptions) => {

const txHash = receipt?.transactionHash

const toastDescription = error.reason
? formatErrorReason(error.reason, options)
: error.message
? error.message.substring(0, 140)
: options.stage === TransactionErrorStage.Reverted
? 'Transaction reverted'
: 'Failed to send transaction'

updateToast(toastId, {
variant: 'error',
description: errorReasonMessage,
description: toastDescription,
icon: IconType.AlertTriangle,
href: txHash ? getExplorerUrl(network, txHash) : undefined,
hrefLabel: txHash ? 'View on etherscan' : undefined,
target: '_blank',
autoClose: DEFAULT_TOAST_ERROR_TIMEOUT,
})
Expand Down Expand Up @@ -291,7 +297,9 @@ export default function useTransaction(network: Network) {
return null
}

const toastId = createPendingToast({
const toastId = createToast({
variant: 'info',
icon: <ToastSpinner />,
description: 'Confirm your transaction',
autoClose: false,
})
Expand Down Expand Up @@ -369,9 +377,12 @@ export default function useTransaction(network: Network) {
const autoClose = transactionTimeout + POLL_INTERVAL // add buffer
const txHref = getExplorerUrl(network, response.hash)

updatePendingToast(toastId, {
description: `Your transaction is pending, click to view on etherscan`,
updateToast(toastId, {
variant: 'info',
icon: <ToastSpinner />,
description: `Your transaction is pending`,
href: txHref,
hrefLabel: 'View on etherscan',
target: '_blank',
autoClose,
})
Expand Down Expand Up @@ -422,6 +433,7 @@ export default function useTransaction(network: Network) {
variant: 'success',
description: `Your transaction was successful`,
href: txHref,
hrefLabel: 'View on etherscan',
target: '_blank',
autoClose: DEFAULT_TOAST_INFO_TIMEOUT,
icon: IconType.Check,
Expand All @@ -432,10 +444,9 @@ export default function useTransaction(network: Network) {
// Transaction timed out
updateToast(toastId, {
variant: 'warning',
description: `Your transaction took longer than ${Math.floor(
transactionTimeout / 1000
)} seconds, click to view on etherscan`,
description: 'Your transaction is taking longer than expected',
href: txHref,
hrefLabel: 'View on etherscan',
target: '_blank',
autoClose: DEFAULT_TOAST_INFO_TIMEOUT,
icon: IconType.AlertTriangle,
Expand Down
75 changes: 33 additions & 42 deletions ui/components/Toast/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { ButtonVariant } from '../Button'
import IconButton from '../Button/IconButton'
import IconOrImage from '../Icon/IconOrImage'
import { IconType } from '../Icon/IconSVG'
import BaseLink from '../Link/BaseLink'
import Spinner from '../Spinner'
import Link from '../Link'

const PROGRESS_STYLE = { background: 'rgba(255, 255, 255, 0.25)', height: '4px' }

export type ToastVariant = 'info' | 'success' | 'error' | 'warning'

Expand Down Expand Up @@ -45,37 +46,19 @@ export function createToast(options: CreateToastOptions): string {
autoClose,
closeOnClick: false,
draggable: false,
progressStyle: { background: 'rgba(255, 255, 255, 0.25)', height: '3.5px' },
progressStyle: PROGRESS_STYLE,
}
)
return toastId as string
}

export function createPendingToast(options: Omit<CreateToastOptions, 'variant'>): string {
const { autoClose = false } = options
return createToast({
variant: 'info',
icon: <Spinner size={20} />,
autoClose,
...options,
})
}

export function updatePendingToast(toastId: string, options: Omit<UpdateToastOptions, 'variant'>): void {
updateToast(toastId, {
variant: 'info',
icon: <Spinner size={20} />,
...options,
})
}

export function updateToast(toastId: string, options: UpdateToastOptions) {
const { icon, description, href, target, variant, autoClose = false, ...updateOptions } = options
const { icon, description, href, hrefLabel, target, variant, autoClose = false, ...updateOptions } = options
if (toast.isActive(toastId)) {
toast.update(toastId, {
...updateOptions,
autoClose,
progressStyle: { background: 'rgba(255, 255, 255, 0.25)', height: '3.5px' },
progressStyle: PROGRESS_STYLE,
draggable: false,
closeOnClick: false,
render: ({ toastProps, closeToast }) => (
Expand All @@ -84,6 +67,7 @@ export function updateToast(toastId: string, options: UpdateToastOptions) {
icon={icon}
description={description}
href={href}
hrefLabel={hrefLabel}
target={target}
toastProps={toastProps}
closeToast={closeToast}
Expand Down Expand Up @@ -128,53 +112,60 @@ const getButtonVariant = (variant: ToastVariant): ButtonVariant => {
export default function Toast({
variant = 'info',
description,
hrefLabel,
href,
hrefLabel,
target,
icon,
closeToast,
toastProps: { autoClose },
}: ToastProps) {
return (
<Flex
onClick={() => {
if (closeToast) {
if (href) {
window.open(href, target)
} else if (closeToast) {
closeToast()
}
}}
as={href ? BaseLink : 'div'}
href={href}
target={target}
variant={getToastVariantKey(variant)}
height={'100%'}
alignItems="center"
width="100%"
py={2}
px={3}
maxWidth={340}
pt={2}
pb={autoClose ? '10px' : 2}
>
{icon ? (
<Box mr={2} minWidth={20}>
<Box ml={2} minWidth={20}>
{typeof icon === 'string' ? (
<IconOrImage size={20} color={variant === 'info' ? 'secondaryText' : 'white'} strokeWidth={2} src={icon} />
) : (
icon
)}
</Box>
) : null}
<Text mr={2} color="inherit" variant="secondary" fontWeight={'medium'}>
{description}{' '}
<Text
as="span"
color="inherit"
sx={{ textDecoration: 'underline', display: 'inline' }}
variant="secondary"
fontWeight={'medium'}
>
{hrefLabel}
<Box mx={2}>
<Text color="inherit" variant="secondaryMedium">
{description}
</Text>
</Text>
{href ? (
<Link
textVariant="secondaryMedium"
showRightIcon
variant="secondary"
color="inherit"
href={href}
target="_blank"
>
{hrefLabel ?? 'View more'}
</Link>
) : null}
</Box>
<IconButton
ml="auto"
size="sm"
mr={2}
variant={getButtonVariant(variant)}
icon={IconType.X}
onClick={e => {
Expand Down

0 comments on commit 0b871be

Please sign in to comment.