Skip to content

Commit

Permalink
throw errors inline, update connector api, improve example component …
Browse files Browse the repository at this point in the history
…(#567)

* add clearState, remove reportError, add onError

* core error removal

* remove reportError

* update hooks test

* fix provider

* onerror

* don't catch

* remove supported wallet ids

* remove allowedchainids

* remove report error tests

* remove onError for now

* remove report error

* update example code

* clearState in actions

* clearState -> resetState

* fix examples

* rm error from store

* rm error from some tests

* error, setError in component

* simplify Card components

* get title

* move margin

* move to utils

* add onError to Connector

* clear error

* coinbase wallet changes

* metamask changes

* gnosis safe changes

* change frame

* eip

* magic

* url

* update connectors and walletconnect

* rm abstract

* undo change to walletconnect

* rm reset state

* fix coinbase wallet spec

* update network spec and constructor

* metamask spec fix

* more spec fixes

* more spec fixes

* network fix

* reset state

* reset state more

* handle coinbase

* handle metamask

* specific error

* tweaks

Co-authored-by: Noah Zinsmeister <[email protected]>
  • Loading branch information
vm and NoahZinsmeister authored Jun 7, 2022
1 parent 0280f6b commit 58a8912
Show file tree
Hide file tree
Showing 38 changed files with 474 additions and 475 deletions.
9 changes: 4 additions & 5 deletions packages/coinbase-wallet/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ describe('Coinbase Wallet', () => {
beforeEach(() => {
let actions: Actions
;[store, actions] = createWeb3ReactStoreAndActions()
connector = new CoinbaseWallet(
connector = new CoinbaseWallet({
actions,
{
options: {
appName: 'test',
url: 'https://mock.url',
},
true
)
connectEagerly: true,
})
})

beforeEach(async () => {
Expand All @@ -48,7 +48,6 @@ describe('Coinbase Wallet', () => {
chainId: Number.parseInt(chainId, 16),
accounts,
activating: false,
error: undefined,
})
})
})
Expand Down
87 changes: 50 additions & 37 deletions packages/coinbase-wallet/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,22 @@ export class CoinbaseWallet extends Connector {
public coinbaseWallet: CoinbaseWalletSDK | undefined

/**
* @param options - Options to pass to `@coinbase/wallet-sdk`
* @param options - Options to pass to `@coinbase/wallet-sdk`.
* @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed.
* @param onError - Handler to report errors thrown from eventListeners.
*/
constructor(actions: Actions, options: CoinbaseWalletSDKOptions, connectEagerly = false) {
super(actions)
constructor({
actions,
options,
connectEagerly = false,
onError,
}: {
actions: Actions
options: CoinbaseWalletSDKOptions
connectEagerly?: boolean
onError?: (error: Error) => void
}) {
super(actions, onError)

if (connectEagerly && this.serverSide) {
throw new Error('connectEagerly = true is invalid for SSR, instead use the connectEagerly method in a useEffect')
Expand Down Expand Up @@ -60,7 +71,8 @@ export class CoinbaseWallet extends Connector {
})

this.provider.on('disconnect', (error: ProviderRpcError): void => {
this.actions.reportError(error)
this.onError?.(error)
this.actions.resetState()
})

this.provider.on('chainChanged', (chainId: string): void => {
Expand Down Expand Up @@ -139,8 +151,9 @@ export class CoinbaseWallet extends Connector {
throw error
}
})
.catch((error: ProviderRpcError) => {
this.actions.reportError(error)
.catch((error: Error) => {
this.actions.resetState()
throw error
})
}

Expand All @@ -152,37 +165,37 @@ export class CoinbaseWallet extends Connector {
this.provider!.request<string>({ method: 'eth_chainId' }),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.provider!.request<string[]>({ method: 'eth_requestAccounts' }),
])
.then(([chainId, accounts]) => {
const receivedChainId = parseChainId(chainId)

if (!desiredChainId || desiredChainId === receivedChainId) {
return this.actions.update({ chainId: receivedChainId, accounts })
}

// if we're here, we can try to switch networks
const desiredChainIdHex = `0x${desiredChainId.toString(16)}`
return this.provider
?.request<void>({
method: 'wallet_switchEthereumChain',
params: [{ chainId: desiredChainIdHex }],
})
.catch(async (error: ProviderRpcError) => {
if (error.code === 4902 && typeof desiredChainIdOrChainParameters !== 'number') {
// if we're here, we can try to add a new network
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.provider!.request<void>({
method: 'wallet_addEthereumChain',
params: [{ ...desiredChainIdOrChainParameters, chainId: desiredChainIdHex }],
})
} else {
throw error
}
})
})
.catch((error: Error) => {
this.actions.reportError(error)
})
]).then(([chainId, accounts]) => {
const receivedChainId = parseChainId(chainId)

if (!desiredChainId || desiredChainId === receivedChainId) {
return this.actions.update({ chainId: receivedChainId, accounts })
}

// if we're here, we can try to switch networks
const desiredChainIdHex = `0x${desiredChainId.toString(16)}`
return this.provider
?.request<void>({
method: 'wallet_switchEthereumChain',
params: [{ chainId: desiredChainIdHex }],
})
.catch(async (error: ProviderRpcError) => {
if (error.code === 4902 && typeof desiredChainIdOrChainParameters !== 'number') {
// if we're here, we can try to add a new network
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.provider!.request<void>({
method: 'wallet_addEthereumChain',
params: [{ ...desiredChainIdOrChainParameters, chainId: desiredChainIdHex }],
})
} else {
throw error
}
})
.catch((error: Error) => {
this.actions.resetState()
throw error
})
})
}

/** {@inheritdoc Connector.deactivate} */
Expand Down
19 changes: 4 additions & 15 deletions packages/core/src/hooks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ class MockConnector extends Connector {
public update(...args: Parameters<Actions['update']>) {
this.actions.update(...args)
}
public reportError(...args: Parameters<Actions['reportError']>) {
this.actions.reportError(...args)
}
}

class MockConnector2 extends MockConnector {}
Expand All @@ -34,11 +31,11 @@ describe('#initializeConnector', () => {
let hooks: Web3ReactHooks

beforeEach(() => {
[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
;[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
})

test('#useChainId', () => {
const { result, rerender } = renderHook(() => hooks.useChainId())
const { result } = renderHook(() => hooks.useChainId())
expect(result.current).toBe(undefined)

act(() => connector.update({ chainId: 1 }))
Expand Down Expand Up @@ -104,14 +101,6 @@ describe('#initializeConnector', () => {
expect(result.current).toBeInstanceOf(Web3Provider)
})
})

test('#useError', () => {
const { result } = renderHook(() => hooks.useError())
expect(result.current).toBe(undefined)

act(() => connector.reportError(new Error()))
expect(result.current).toBeInstanceOf(Error)
})
})

describe('#getSelectedConnector', () => {
Expand All @@ -124,7 +113,7 @@ describe('#getSelectedConnector', () => {
let selectedConnectorHooks: Web3ReactSelectedHooks

beforeEach(() => {
[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
;[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
;[connector2, hooks2] = initializeConnector((actions) => new MockConnector2(actions))

selectedConnectorHooks = getSelectedConnector([connector, hooks], [connector2, hooks2])
Expand Down Expand Up @@ -185,7 +174,7 @@ describe('#getPriorityConnector', () => {
let priorityConnectorHooks: Web3ReactPriorityHooks

beforeEach(() => {
[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
;[connector, hooks] = initializeConnector((actions) => new MockConnector(actions))
;[connector2, hooks2] = initializeConnector((actions) => new MockConnector2(actions))

priorityConnectorHooks = getPriorityConnector([connector, hooks], [connector2, hooks2])
Expand Down
37 changes: 6 additions & 31 deletions packages/core/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,12 @@ export type Web3ReactPriorityHooks = ReturnType<typeof getPriorityConnector>
*
* @typeParam T - The type of the `connector` returned from `f`.
* @param f - A function which is called with `actions` bound to the returned `store`.
* @param allowedChainIds - An optional array of chainIds which the `connector` may connect to. If the `connector` is
* connected to a chainId which is not allowed, a ChainIdNotAllowedError error will be reported.
* If this argument is unspecified, the `connector` may connect to any chainId.
* @returns [connector, hooks, store] - The initialized connector, a variety of hooks, and a zustand store.
*/
export function initializeConnector<T extends Connector>(
f: (actions: Actions) => T,
allowedChainIds?: number[]
f: (actions: Actions) => T
): [T, Web3ReactHooks, Web3ReactStore] {
const [store, actions] = createWeb3ReactStoreAndActions(allowedChainIds)
const [store, actions] = createWeb3ReactStoreAndActions()

const connector = f(actions)
const useConnector = create(store)
Expand All @@ -54,8 +50,8 @@ export function initializeConnector<T extends Connector>(
return [connector, { ...stateHooks, ...derivedHooks, ...augmentedHooks }, store]
}

function computeIsActive({ chainId, accounts, activating, error }: Web3ReactState) {
return Boolean(chainId && accounts && !activating && !error)
function computeIsActive({ chainId, accounts, activating }: Web3ReactState) {
return Boolean(chainId && accounts && !activating)
}

/**
Expand Down Expand Up @@ -99,12 +95,6 @@ export function getSelectedConnector(
return values[getIndex(connector)]
}

function useSelectedError(connector: Connector) {
// eslint-disable-next-line react-hooks/rules-of-hooks
const values = initializedConnectors.map(([, { useError }]) => useError())
return values[getIndex(connector)]
}

function useSelectedAccount(connector: Connector) {
// eslint-disable-next-line react-hooks/rules-of-hooks
const values = initializedConnectors.map(([, { useAccount }]) => useAccount())
Expand Down Expand Up @@ -153,7 +143,6 @@ export function getSelectedConnector(
useSelectedChainId,
useSelectedAccounts,
useSelectedIsActivating,
useSelectedError,
useSelectedAccount,
useSelectedIsActive,
useSelectedProvider,
Expand All @@ -177,7 +166,6 @@ export function getPriorityConnector(
useSelectedChainId,
useSelectedAccounts,
useSelectedIsActivating,
useSelectedError,
useSelectedAccount,
useSelectedIsActive,
useSelectedProvider,
Expand Down Expand Up @@ -208,10 +196,6 @@ export function getPriorityConnector(
return useSelectedIsActivating(usePriorityConnector())
}

function usePriorityError() {
return useSelectedError(usePriorityConnector())
}

function usePriorityAccount() {
return useSelectedAccount(usePriorityConnector())
}
Expand Down Expand Up @@ -242,7 +226,6 @@ export function getPriorityConnector(
useSelectedChainId,
useSelectedAccounts,
useSelectedIsActivating,
useSelectedError,
useSelectedAccount,
useSelectedIsActive,
useSelectedProvider,
Expand All @@ -253,7 +236,6 @@ export function getPriorityConnector(
usePriorityChainId,
usePriorityAccounts,
usePriorityIsActivating,
usePriorityError,
usePriorityAccount,
usePriorityIsActive,
usePriorityProvider,
Expand All @@ -270,7 +252,6 @@ const ACCOUNTS_EQUALITY_CHECKER: EqualityChecker<Web3ReactState['accounts']> = (
oldAccounts.length === newAccounts?.length &&
oldAccounts.every((oldAccount, i) => oldAccount === newAccounts[i]))
const ACTIVATING = ({ activating }: Web3ReactState) => activating
const ERROR = ({ error }: Web3ReactState) => error

function getStateHooks(useConnector: UseBoundStore<Web3ReactStore>) {
function useChainId(): Web3ReactState['chainId'] {
Expand All @@ -285,14 +266,10 @@ function getStateHooks(useConnector: UseBoundStore<Web3ReactStore>) {
return useConnector(ACTIVATING)
}

function useError(): Web3ReactState['error'] {
return useConnector(ERROR)
}

return { useChainId, useAccounts, useIsActivating, useError }
return { useChainId, useAccounts, useIsActivating }
}

function getDerivedHooks({ useChainId, useAccounts, useIsActivating, useError }: ReturnType<typeof getStateHooks>) {
function getDerivedHooks({ useChainId, useAccounts, useIsActivating }: ReturnType<typeof getStateHooks>) {
function useAccount(): string | undefined {
return useAccounts()?.[0]
}
Expand All @@ -301,13 +278,11 @@ function getDerivedHooks({ useChainId, useAccounts, useIsActivating, useError }:
const chainId = useChainId()
const accounts = useAccounts()
const activating = useIsActivating()
const error = useError()

return computeIsActive({
chainId,
accounts,
activating,
error,
})
}

Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export type Web3ContextType<T extends BaseProvider = Web3Provider> = {
chainId: ReturnType<Web3ReactPriorityHooks['useSelectedChainId']>
accounts: ReturnType<Web3ReactPriorityHooks['useSelectedAccounts']>
isActivating: ReturnType<Web3ReactPriorityHooks['useSelectedIsActivating']>
error: ReturnType<Web3ReactPriorityHooks['useSelectedError']>
account: ReturnType<Web3ReactPriorityHooks['useSelectedAccount']>
isActive: ReturnType<Web3ReactPriorityHooks['useSelectedIsActive']>
provider: T | undefined
Expand Down Expand Up @@ -57,7 +56,6 @@ export function Web3ReactProvider({
useSelectedChainId,
useSelectedAccounts,
useSelectedIsActivating,
useSelectedError,
useSelectedAccount,
useSelectedIsActive,
useSelectedProvider,
Expand All @@ -71,7 +69,6 @@ export function Web3ReactProvider({
const chainId = useSelectedChainId(connector)
const accounts = useSelectedAccounts(connector)
const isActivating = useSelectedIsActivating(connector)
const error = useSelectedError(connector)
const account = useSelectedAccount(connector)
const isActive = useSelectedIsActive(connector)
// note that we've omitted a <T extends BaseProvider = Web3Provider> generic type
Expand All @@ -90,7 +87,6 @@ export function Web3ReactProvider({
chainId,
accounts,
isActivating,
error,
account,
isActive,
provider,
Expand Down
Loading

0 comments on commit 58a8912

Please sign in to comment.