Skip to content

Commit

Permalink
Merge pull request #35 from oasisprotocol/ml/handle-connect-wallet-er…
Browse files Browse the repository at this point in the history
…rors-in-Layout

Handle ConnectWallet errors in Layout
  • Loading branch information
lubej authored Mar 14, 2024
2 parents baf0696 + 101b98b commit c9e8116
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
8 changes: 5 additions & 3 deletions frontend/src/components/ConnectWallet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { METAMASK_HOME_PAGE } from '../../constants/config.ts'
import { Button } from '../Button'
import { UnknownNetworkError } from '../../utils/errors.ts'
import { ConnectedAccount } from '../ConnectedAccount'
import { useAppState } from '../../hooks/useAppState.ts'

export const ConnectWallet: FC = () => {
const { setAppError } = useAppState()

const [isLoading, setIsLoading] = useState(false)
const [providerAvailable, setProviderAvailable] = useState(true)
const [isUnknownNetwork, setIsUnknownNetwork] = useState(false)
const [, setError] = useState('')

const {
state: { isConnected, account, chainName },
Expand All @@ -35,7 +37,7 @@ export const ConnectWallet: FC = () => {
await switchNetwork()
setIsUnknownNetwork(false)
} catch (ex) {
setError((ex as Error)?.message || JSON.stringify(ex))
setAppError(ex as Error)
} finally {
setIsLoading(false)
}
Expand All @@ -49,7 +51,7 @@ export const ConnectWallet: FC = () => {
if (ex instanceof UnknownNetworkError) {
setIsUnknownNetwork(true)
} else {
setError((ex as Error)?.message || JSON.stringify(ex))
setAppError(ex as Error)
}
} finally {
setIsLoading(false)
Expand Down
19 changes: 17 additions & 2 deletions frontend/src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { LogoIcon } from '../icons/LogoIcon'
import { ConnectWallet } from '../ConnectWallet'
import { Alert } from '../Alert'
import { useAppState } from '../../hooks/useAppState.ts'
import { Button } from '../Button'
import { StringUtils } from '../../utils/string.utils.ts'

export const Layout: FC = () => {
const {
state: { isInitialLoading },
state: { isInitialLoading, appError },
clearAppError,
} = useAppState()

return (
Expand All @@ -22,10 +25,22 @@ export const Layout: FC = () => {
<h1>Oasis Mascot</h1>
</section>
<section>
{!isInitialLoading && appError && (
<Alert
type="error"
actions={
<Button variant="text" onClick={clearAppError}>
&lt; Go back&nbsp;
</Button>
}
>
{StringUtils.truncate(appError)}
</Alert>
)}
{isInitialLoading && (
<Alert headerText="Please wait" type="loading" actions={<span>Fetching poll...</span>} />
)}
{!isInitialLoading && <Outlet />}
{!isInitialLoading && !appError && <Outlet />}
</section>
</main>
</div>
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/providers/AppStateContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ export interface AppStateProviderState {
poll: Poll | null
previousVotes: VotesStorage
previousVote: MascotChoices | null
appError: string
}

export interface AppStateProviderContext {
readonly state: AppStateProviderState
setPreviousVoteForCurrentWallet: (choiceId: MascotChoices) => void
setAppError: (error: Error | object | string) => void
clearAppError: () => void
}

export const AppStateContext = createContext<AppStateProviderContext>({} as AppStateProviderContext)
29 changes: 29 additions & 0 deletions frontend/src/providers/AppStateProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const appStateProviderInitialState: AppStateProviderState = {
poll: null,
previousVotes: localStorageStore.get(StorageKeys.Votes) ?? {},
previousVote: null,
appError: '',
}

export const AppStateContextProvider: FC<PropsWithChildren> = ({ children }) => {
Expand Down Expand Up @@ -82,9 +83,37 @@ export const AppStateContextProvider: FC<PropsWithChildren> = ({ children }) =>
}))
}

const setAppError = (error: Error | object | string) => {
if (error === undefined || error === null) return

let appError = ''

if (Object.prototype.hasOwnProperty.call(error, 'message')) {
appError = (error as Error).message
} else if (typeof error === 'object') {
appError = JSON.stringify(appError)
} else {
appError = error
}

setState(prevState => ({
...prevState,
appError,
}))
}

const clearAppError = () => {
setState(prevState => ({
...prevState,
appError: '',
}))
}

const providerState: AppStateProviderContext = {
state,
setPreviousVoteForCurrentWallet,
setAppError,
clearAppError,
}

return <AppStateContext.Provider value={providerState}>{children}</AppStateContext.Provider>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/utils/string.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ export abstract class StringUtils {
static getNetworkFriendlyName = (chainName: string) => {
return NETWORK_NAMES[chainName] ?? 'Unknown network'
}

static truncate = (s: string, sliceIndex = 200) => {
return s.slice(0, sliceIndex)
}
}

0 comments on commit c9e8116

Please sign in to comment.