Skip to content

Commit

Permalink
Merge pull request #8 from MakerXStudio/handle-transaction-errors
Browse files Browse the repository at this point in the history
chore: handle errors in transactions
  • Loading branch information
neilcampbell authored Apr 10, 2024
2 parents 7cf7653 + eab0f13 commit 587c2d8
Show file tree
Hide file tree
Showing 18 changed files with 252 additions and 175 deletions.
6 changes: 0 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"react-router-dom": "^6.22.3",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"tiny-invariant": "^1.3.3",
"vaul": "^0.9.0"
},
"devDependencies": {
Expand Down
10 changes: 6 additions & 4 deletions src/App.routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import { evalTemplates } from './routes/templated-route'
import { TransactionPage } from './features/transactions/pages/transaction-page'
import { ExplorePage } from './features/explore/pages/explore-page'
import { GroupPage } from './features/transactions/pages/group-page'
import ErrorBoundary from './features/errors/components/error-boundary'
import { transactionPageConstants } from './features/theme/constant'
import { ErrorPage } from './features/common/pages/error-page'

export const routes = evalTemplates([
{
template: Urls.Index,
element: (
<LayoutPage>
<ErrorBoundary>
<Outlet />
</ErrorBoundary>
<Outlet />
</LayoutPage>
),
errorElement: <ErrorPage />,
children: [
{
template: Urls.Index,
Expand All @@ -28,6 +28,7 @@ export const routes = evalTemplates([
},
{
template: Urls.Explore,
errorElement: <ErrorPage />,
children: [
{
template: Urls.Explore,
Expand All @@ -36,6 +37,7 @@ export const routes = evalTemplates([
{
template: Urls.Explore.Transaction.ById,
element: <TransactionPage />,
errorElement: <ErrorPage title={transactionPageConstants.title} />,
},
{
template: Urls.Explore.Group.ById,
Expand Down
2 changes: 1 addition & 1 deletion src/features/blocks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const subscribeToBlocksEffect = atomEffect((get, set) => {
},
},
],
maxRoundsToSync: 1, // TODO: NC - Do we want this higher?
maxRoundsToSync: 1,
waitForBlockWhenAtTip: true,
syncBehaviour: 'skip-sync-newest',
watermarkPersistence: {
Expand Down
25 changes: 25 additions & 0 deletions src/features/common/components/render-loadable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { asError } from '@/utils/error'
import { Loadable } from 'jotai/vanilla/utils/loadable'
import { Loader2 as Loader } from 'lucide-react'

type RenderLoadableProps<T> = {
loadable: Loadable<T>
children: (data: Awaited<T>) => React.ReactNode
fallback?: React.ReactNode
transformError?: (error: Error) => Error | undefined
}

export function RenderLoadable<T>({ loadable, children, fallback, transformError }: RenderLoadableProps<T>) {
if (loadable.state === 'hasData') {
return <>{children(loadable.data)}</>
} else if (loadable.state === 'loading') {
return <>{fallback ?? <Loader className="size-10 animate-spin" />}</>
}

const error = transformError ? transformError(asError(loadable.error)) : asError(loadable.error)
if (error) {
throw error
}

return <></>
}
18 changes: 18 additions & 0 deletions src/features/common/pages/error-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { cn } from '@/features/common/utils'
import { asError } from '@/utils/error'
import { useRouteError } from 'react-router-dom'

type ErrorPageProps = {
title?: string
}

export function ErrorPage({ title }: ErrorPageProps) {
const error = asError(useRouteError())

return (
<div>
<h1 className={cn('text-2xl text-primary font-bold')}>{title ?? 'Error'}</h1>
<p>Error: {error.message}</p>
</div>
)
}
47 changes: 0 additions & 47 deletions src/features/errors/components/error-boundary.tsx

This file was deleted.

6 changes: 4 additions & 2 deletions src/features/theme/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ export const themeConstants = {
}

export const transactionPageConstants = {
transactionNotFound: 'Transaction not found',
genericError: 'Error loading transaction',
title: 'Transaction',
notFoundMessage: 'Transaction not found',
invalidIdMessage: 'Transaction Id is invalid',
failedToLoadMessage: 'Transaction failed to load',
labels: {
transactionId: 'Transaction ID',
type: 'Type',
Expand Down
16 changes: 6 additions & 10 deletions src/features/transactions/components/transaction.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { cn } from '@/features/common/utils'
import { PaymentTransaction } from './payment-transaction'
import { MultisigTransactionSignature, TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
import { MultisigModel, PaymentTransactionModel, TransactionType } from '../models'
import algosdk from 'algosdk'
import invariant from 'tiny-invariant'
import { invariant } from '@/utils/invariant'
import { publicKeyToAddress } from '@/utils/publickey-to-addess'

type Props = {
Expand Down Expand Up @@ -40,12 +39,9 @@ const asMultisig = (signature: MultisigTransactionSignature): MultisigModel => {
}

export function Transaction({ transaction }: Props) {
return (
<div>
<h1 className={cn('text-2xl text-primary font-bold')}>Transaction</h1>
{transaction['tx-type'] === algosdk.TransactionType.pay && (
<PaymentTransaction transaction={asPaymentTransaction(transaction)} rawTransaction={transaction} />
)}
</div>
)
if (transaction['tx-type'] === algosdk.TransactionType.pay) {
return <PaymentTransaction transaction={asPaymentTransaction(transaction)} rawTransaction={transaction} />
}

return <></>
}
6 changes: 3 additions & 3 deletions src/features/transactions/data.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { atom, useAtomValue, useStore } from 'jotai'
import * as algokit from '@algorandfoundation/algokit-utils'
import { useMemo } from 'react'
import { TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
import { atomEffect } from 'jotai-effect'
import { loadable } from 'jotai/utils'
import { getAlgoIndexerClient, lookupTransactionById } from '@algorandfoundation/algokit-utils'

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

get(syncEffect)

return algokit.lookupTransactionById(transactionId, indexer).then((result) => {
return lookupTransactionById(transactionId, indexer).then((result) => {
return result.transaction
})
})
Expand Down
Loading

0 comments on commit 587c2d8

Please sign in to comment.