Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error handling #210

Merged
merged 9 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions app/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ input[type='password']:autofill {
inset: 0px;
}

.bottom-4 {
bottom: 1rem;
}

.left-4 {
left: 1rem;
}
Expand All @@ -550,6 +554,18 @@ input[type='password']:autofill {
top: 0.5rem;
}

.bottom-auto {
bottom: auto;
}

.top-auto {
top: auto;
}

.bottom-0 {
bottom: 0px;
}

.z-10 {
z-index: 10;
}
Expand All @@ -562,6 +578,10 @@ input[type='password']:autofill {
grid-column: 1 / -1;
}

.row-span-2 {
grid-row: span 2 / span 2;
}

.row-start-2 {
grid-row-start: 2;
}
Expand Down Expand Up @@ -874,6 +894,10 @@ input[type='password']:autofill {
grid-template-rows: 1fr min-content;
}

.grid-rows-\[min-content\2c min-content\] {
grid-template-rows: min-content min-content;
}

.flex-col {
flex-direction: column;
}
Expand Down Expand Up @@ -950,6 +974,10 @@ input[type='password']:autofill {
row-gap: 0.75rem;
}

.gap-y-2 {
row-gap: 0.5rem;
}

.overflow-hidden {
overflow: hidden;
}
Expand Down Expand Up @@ -1002,6 +1030,10 @@ input[type='password']:autofill {
border-style: dashed;
}

.border-amber-500\/50 {
border-color: rgb(245 158 11 / 0.5);
}

.border-lime-400\/40 {
border-color: rgb(163 230 53 / 0.4);
}
Expand All @@ -1015,6 +1047,10 @@ input[type='password']:autofill {
border-color: rgb(248 113 113 / 0.2);
}

.border-red-400\/50 {
border-color: rgb(248 113 113 / 0.5);
}

.border-transparent {
border-color: transparent;
}
Expand Down Expand Up @@ -1044,6 +1080,10 @@ input[type='password']:autofill {
border-bottom-color: rgb(255 255 255 / 0.1);
}

.bg-amber-500\/10 {
background-color: rgb(245 158 11 / 0.1);
}

.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
Expand Down Expand Up @@ -1075,6 +1115,10 @@ input[type='password']:autofill {
background-color: rgb(23 23 23 / var(--tw-bg-opacity));
}

.bg-red-400\/10 {
background-color: rgb(248 113 113 / 0.1);
}

.bg-red-400\/5 {
background-color: rgb(248 113 113 / 0.05);
}
Expand Down Expand Up @@ -1108,6 +1152,14 @@ input[type='password']:autofill {
background-color: rgb(255 255 255 / 0.5);
}

.bg-black\/80 {
background-color: rgb(0 0 0 / 0.8);
}

.bg-neutral-900\/80 {
background-color: rgb(23 23 23 / 0.8);
}

.p-10 {
padding: 2.5rem;
}
Expand Down Expand Up @@ -1706,6 +1758,22 @@ input[type='password']:autofill {
}

@media (min-width: 1024px) {
.lg\:right-4 {
right: 1rem;
}

.lg\:top-4 {
top: 1rem;
}

.lg\:bottom-auto {
bottom: auto;
}

.lg\:left-auto {
left: auto;
}

.lg\:hidden {
display: none;
}
Expand Down
32 changes: 32 additions & 0 deletions app/ts/components/AccountReconnect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useSignalEffect } from '@preact/signals'
import { useEffect } from 'preact/hooks'
import { useWallet } from '../context/Wallet.js'
import { useEthereumProvider } from '../context/Ethereum.js'
import { useAsyncState } from '../library/preact-utilities.js'
import { EthereumAddress } from '../schema.js'

export const AccountReconnect = () => {
const { browserProvider } = useEthereumProvider()
const { account } = useWallet()
const { value: query, waitFor } = useAsyncState<EthereumAddress>()

const attemptToConnect = () => {
if (!browserProvider.value) return
const provider = browserProvider.value
waitFor(async () => {
const [signer] = await provider.listAccounts()
return EthereumAddress.parse(signer.address)
})
}

const listenForQueryChanges = () => {
// do not reset shared state for other instances of this hooks
if (query.value.state === 'inactive') return
account.value = query.value
}

useSignalEffect(listenForQueryChanges)
useEffect(attemptToConnect, [])

return <></>
}
33 changes: 16 additions & 17 deletions app/ts/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import { Route, Router } from './HashRouter.js'
import { Notices } from './Notice.js'
import { SplashScreen } from './SplashScreen.js'
import { TransactionPage } from './TransactionPage/index.js'
import { ErrorAlert } from './ErrorAlert.js'
import { TransferPage } from './TransferPage/index.js'
import { EthereumProvider } from '../context/Ethereum.js'
import { WalletProvider } from '../context/Wallet.js'
import { AccountProvider } from '../context/Account.js'
import { NotificationProvider } from '../context/Notification.js'

export function App() {
return (
<SplashScreen>
<WalletProvider>
<AccountProvider>
<Router>
<Route path=''>
<TransferPage />
</Route>
<Route path='#tx/:transaction_hash'>
<TransactionPage />
</Route>
</Router>
<Notices />
<ErrorAlert />
</AccountProvider>
</WalletProvider>
<NotificationProvider>
<EthereumProvider>
<WalletProvider>
<Router>
<Route path=''>
<TransferPage />
</Route>
<Route path='#tx/:transaction_hash'>
<TransactionPage />
</Route>
</Router>
</WalletProvider>
</EthereumProvider>
</NotificationProvider>
</SplashScreen>
)
}
51 changes: 36 additions & 15 deletions app/ts/components/ConnectAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { useSignalEffect } from '@preact/signals'
import { makeError } from 'ethers'
import { useAsyncState } from '../library/preact-utilities.js'
import { EthereumAddress } from '../schema.js'
import { useEthereumProvider } from '../context/Ethereum.js'
import { useWallet } from '../context/Wallet.js'
import { useAccount } from '../context/Account.js'
import { useNotice } from '../store/notice.js'
import { useNotification } from '../context/Notification.js'
import { AsyncText } from './AsyncText.js'
import SVGBlockie from './SVGBlockie.js'
import { humanReadableEthersError, isJsonRpcError, isEthersError, humanReadableJsonRpcError } from '../library/errors.js'

export const ConnectAccount = () => {
const { browserProvider } = useWallet()
const { account } = useAccount()
const { browserProvider } = useEthereumProvider()
const { account } = useWallet()
const { value: query, waitFor } = useAsyncState<EthereumAddress>()
const { notify } = useNotice()
const { notify } = useNotification()

const connect = () => {
if (!browserProvider) {
notify({ message: 'No compatible web3 wallet detected.', title: 'Failed to connect' })
return
}
waitFor(async () => {
const signer = await browserProvider.getSigner()
if (!browserProvider.value) {
throw makeError('No compatible web3 wallet detected.', 'UNKNOWN_ERROR', { error: { code: 4900 } })
}
const signer = await browserProvider.value.getSigner()
return EthereumAddress.parse(signer.address)
})
}
Expand All @@ -33,8 +34,28 @@ export const ConnectAccount = () => {
useSignalEffect(listenForQueryChanges)

switch (account.value.state) {
case 'inactive':
case 'rejected':
const accountError = account.value.error
if (isEthersError(accountError)) {
let message = humanReadableEthersError(accountError).message
if (accountError.code === 'UNKNOWN_ERROR' && isJsonRpcError(accountError.error)) {
message = humanReadableJsonRpcError(accountError.error).message
}
notify({ message, title: 'Notice' })
}

return (
<div class='grid grid-cols-[1fr,auto] gap-3 px-4 lg:px-0 h-20 border border-white/20 lg:border-none lg:place-items-end place-content-center items-center'>
<div class='grid lg:place-items-end'>
<span class='font-bold'>Get started quickly</span>
<span class='text-sm text-white/50'>by connecting your wallet</span>
</div>
<button class='h-12 px-4 border border-white/50 bg-white/20' onClick={connect}>
Connect
</button>
</div>
)
case 'inactive':
return (
<div class='grid grid-cols-[1fr,auto] gap-3 px-4 lg:px-0 h-20 border border-white/20 lg:border-none lg:place-items-end place-content-center items-center'>
<div class='grid lg:place-items-end'>
Expand All @@ -61,7 +82,7 @@ export const ConnectAccount = () => {
}

const AccountAddress = () => {
const { account } = useAccount()
const { account } = useWallet()

switch (account.value.state) {
case 'inactive':
Expand All @@ -82,7 +103,7 @@ const NetworkIcon = () => (
)

const AccountAvatar = () => {
const { account } = useAccount()
const { account } = useWallet()

switch (account.value.state) {
case 'inactive':
Expand All @@ -100,7 +121,7 @@ const AccountAvatar = () => {
}

const WalletNetwork = () => {
const { account } = useAccount()
const { account } = useWallet()

switch (account.value.state) {
case 'inactive':
Expand All @@ -119,7 +140,7 @@ const WalletNetwork = () => {
}

const NetworkName = () => {
const { network } = useWallet()
const { network } = useEthereumProvider()

switch (network.value.state) {
case 'inactive':
Expand Down
5 changes: 5 additions & 0 deletions app/ts/components/Icon/Menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const Menu = () => (
<svg width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'>
<path fill='currentColor' d='M0 636.362h448v64H0zm0 160h448v64H0zm0 160h448v64H0z' transform='translate(0 -604.362)' />
</svg>
)
1 change: 1 addition & 0 deletions app/ts/components/Icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './Check.js'
export * from './Copy.js'
export * from './Ethereum.js'
export * from './Info.js'
export * from './Menu.js'
export * from './Refresh.js'
export * from './Spinner.js'
export * from './Xmark.js'
13 changes: 0 additions & 13 deletions app/ts/components/Notice.tsx

This file was deleted.

Loading