Skip to content

Commit 587c2d8

Browse files
authored
Merge pull request #8 from MakerXStudio/handle-transaction-errors
chore: handle errors in transactions
2 parents 7cf7653 + eab0f13 commit 587c2d8

File tree

18 files changed

+252
-175
lines changed

18 files changed

+252
-175
lines changed

package-lock.json

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
"react-router-dom": "^6.22.3",
4343
"tailwind-merge": "^2.2.1",
4444
"tailwindcss-animate": "^1.0.7",
45-
"tiny-invariant": "^1.3.3",
4645
"vaul": "^0.9.0"
4746
},
4847
"devDependencies": {

src/App.routes.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ import { evalTemplates } from './routes/templated-route'
55
import { TransactionPage } from './features/transactions/pages/transaction-page'
66
import { ExplorePage } from './features/explore/pages/explore-page'
77
import { GroupPage } from './features/transactions/pages/group-page'
8-
import ErrorBoundary from './features/errors/components/error-boundary'
8+
import { transactionPageConstants } from './features/theme/constant'
9+
import { ErrorPage } from './features/common/pages/error-page'
910

1011
export const routes = evalTemplates([
1112
{
1213
template: Urls.Index,
1314
element: (
1415
<LayoutPage>
15-
<ErrorBoundary>
16-
<Outlet />
17-
</ErrorBoundary>
16+
<Outlet />
1817
</LayoutPage>
1918
),
19+
errorElement: <ErrorPage />,
2020
children: [
2121
{
2222
template: Urls.Index,
@@ -28,6 +28,7 @@ export const routes = evalTemplates([
2828
},
2929
{
3030
template: Urls.Explore,
31+
errorElement: <ErrorPage />,
3132
children: [
3233
{
3334
template: Urls.Explore,
@@ -36,6 +37,7 @@ export const routes = evalTemplates([
3637
{
3738
template: Urls.Explore.Transaction.ById,
3839
element: <TransactionPage />,
40+
errorElement: <ErrorPage title={transactionPageConstants.title} />,
3941
},
4042
{
4143
template: Urls.Explore.Group.ById,

src/features/blocks/data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const subscribeToBlocksEffect = atomEffect((get, set) => {
4343
},
4444
},
4545
],
46-
maxRoundsToSync: 1, // TODO: NC - Do we want this higher?
46+
maxRoundsToSync: 1,
4747
waitForBlockWhenAtTip: true,
4848
syncBehaviour: 'skip-sync-newest',
4949
watermarkPersistence: {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { asError } from '@/utils/error'
2+
import { Loadable } from 'jotai/vanilla/utils/loadable'
3+
import { Loader2 as Loader } from 'lucide-react'
4+
5+
type RenderLoadableProps<T> = {
6+
loadable: Loadable<T>
7+
children: (data: Awaited<T>) => React.ReactNode
8+
fallback?: React.ReactNode
9+
transformError?: (error: Error) => Error | undefined
10+
}
11+
12+
export function RenderLoadable<T>({ loadable, children, fallback, transformError }: RenderLoadableProps<T>) {
13+
if (loadable.state === 'hasData') {
14+
return <>{children(loadable.data)}</>
15+
} else if (loadable.state === 'loading') {
16+
return <>{fallback ?? <Loader className="size-10 animate-spin" />}</>
17+
}
18+
19+
const error = transformError ? transformError(asError(loadable.error)) : asError(loadable.error)
20+
if (error) {
21+
throw error
22+
}
23+
24+
return <></>
25+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { cn } from '@/features/common/utils'
2+
import { asError } from '@/utils/error'
3+
import { useRouteError } from 'react-router-dom'
4+
5+
type ErrorPageProps = {
6+
title?: string
7+
}
8+
9+
export function ErrorPage({ title }: ErrorPageProps) {
10+
const error = asError(useRouteError())
11+
12+
return (
13+
<div>
14+
<h1 className={cn('text-2xl text-primary font-bold')}>{title ?? 'Error'}</h1>
15+
<p>Error: {error.message}</p>
16+
</div>
17+
)
18+
}

src/features/errors/components/error-boundary.tsx

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/features/theme/constant.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ export const themeConstants = {
33
}
44

55
export const transactionPageConstants = {
6-
transactionNotFound: 'Transaction not found',
7-
genericError: 'Error loading transaction',
6+
title: 'Transaction',
7+
notFoundMessage: 'Transaction not found',
8+
invalidIdMessage: 'Transaction Id is invalid',
9+
failedToLoadMessage: 'Transaction failed to load',
810
labels: {
911
transactionId: 'Transaction ID',
1012
type: 'Type',

src/features/transactions/components/transaction.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { cn } from '@/features/common/utils'
21
import { PaymentTransaction } from './payment-transaction'
32
import { MultisigTransactionSignature, TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
43
import { MultisigModel, PaymentTransactionModel, TransactionType } from '../models'
54
import algosdk from 'algosdk'
6-
import invariant from 'tiny-invariant'
5+
import { invariant } from '@/utils/invariant'
76
import { publicKeyToAddress } from '@/utils/publickey-to-addess'
87

98
type Props = {
@@ -40,12 +39,9 @@ const asMultisig = (signature: MultisigTransactionSignature): MultisigModel => {
4039
}
4140

4241
export function Transaction({ transaction }: Props) {
43-
return (
44-
<div>
45-
<h1 className={cn('text-2xl text-primary font-bold')}>Transaction</h1>
46-
{transaction['tx-type'] === algosdk.TransactionType.pay && (
47-
<PaymentTransaction transaction={asPaymentTransaction(transaction)} rawTransaction={transaction} />
48-
)}
49-
</div>
50-
)
42+
if (transaction['tx-type'] === algosdk.TransactionType.pay) {
43+
return <PaymentTransaction transaction={asPaymentTransaction(transaction)} rawTransaction={transaction} />
44+
}
45+
46+
return <></>
5147
}

src/features/transactions/data.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { atom, useAtomValue, useStore } from 'jotai'
2-
import * as algokit from '@algorandfoundation/algokit-utils'
32
import { useMemo } from 'react'
43
import { TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
54
import { atomEffect } from 'jotai-effect'
65
import { loadable } from 'jotai/utils'
6+
import { getAlgoIndexerClient, lookupTransactionById } from '@algorandfoundation/algokit-utils'
77

88
// TODO: Move this elsewhere and make it configurable once we start using it more
9-
const indexer = algokit.getAlgoIndexerClient({
9+
const indexer = getAlgoIndexerClient({
1010
server: 'https://mainnet-idx.algonode.cloud/',
1111
port: 443,
1212
})
@@ -40,7 +40,7 @@ const useTransactionAtom = (transactionId: string) => {
4040

4141
get(syncEffect)
4242

43-
return algokit.lookupTransactionById(transactionId, indexer).then((result) => {
43+
return lookupTransactionById(transactionId, indexer).then((result) => {
4444
return result.transaction
4545
})
4646
})

0 commit comments

Comments
 (0)