From 3b09538dda1c62799d7cc725c8b06c7a6ebed5a6 Mon Sep 17 00:00:00 2001 From: Wenty Li Date: Wed, 30 Aug 2023 20:36:00 +0800 Subject: [PATCH] fix(dcellar-web-ui): fix trust connect provider error --- .../connectors/MetaMaskConnector.ts | 3 - .../connectors/TrustWalletConnector.ts | 115 ++++++++++++++++-- .../WalletConnectContext/connectors/index.tsx | 2 +- apps/dcellar-web-ui/typings.d.ts | 1 + 4 files changed, 104 insertions(+), 17 deletions(-) delete mode 100644 apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/MetaMaskConnector.ts diff --git a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/MetaMaskConnector.ts b/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/MetaMaskConnector.ts deleted file mode 100644 index 28f4dd58..00000000 --- a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/MetaMaskConnector.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { MetaMaskConnector as WagmiMetaMaskConnector } from 'wagmi/connectors/metaMask'; - -export class MetaMaskConnector extends WagmiMetaMaskConnector {} \ No newline at end of file diff --git a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/TrustWalletConnector.ts b/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/TrustWalletConnector.ts index f47aa532..9e4a95b3 100644 --- a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/TrustWalletConnector.ts +++ b/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/TrustWalletConnector.ts @@ -1,15 +1,27 @@ -import { Chain } from 'wagmi' -import { MetaMaskConnector as WagmiMetaMaskConnector } from 'wagmi/connectors/metaMask'; +// reference: +// https://github.com/pancakeswap/pancake-frontend/blob/38b13fd3c183851a02497330cec7efc0da2af091/packages/wagmi/connectors/trustWallet/trustWallet.ts#L49 + +import { getClient } from '@wagmi/core' +import { getAddress } from 'ethers/lib/utils.js' +import { InjectedConnector } from 'wagmi/connectors/injected' import { - getClient, -} from '@wagmi/core' + Address, + ConnectorNotFoundError, + ResourceUnavailableError, + RpcError, + UserRejectedRequestError, + Chain, +} from 'wagmi' export type TrustWalletConnectorOptions = { shimDisconnect?: boolean + shimChainChangedDisconnect?: boolean; } -export class TrustWalletConnector extends WagmiMetaMaskConnector { - readonly id: any = 'trustWallet'; + +export class TrustWalletConnector extends InjectedConnector { + readonly id = 'trust' + protected shimDisconnectKey = `${this.id}.shimDisconnect` constructor({ chains, @@ -18,13 +30,10 @@ export class TrustWalletConnector extends WagmiMetaMaskConnector { chains?: Chain[] options?: TrustWalletConnectorOptions } = {}) { - const options = { name: 'Trust Wallet', - shimDisconnect: true, - UNSTABLE_shimOnConnectSelectAccount: true, - getProvider: getTrustWalletProvider, - ..._options, + shimDisconnect: _options?.shimDisconnect ?? false, + shimChainChangedDisconnect: _options?.shimChainChangedDisconnect ?? true, } super({ @@ -33,9 +42,85 @@ export class TrustWalletConnector extends WagmiMetaMaskConnector { }) } - async disconnect() { - super.disconnect() + private handleFailedConnect(error: Error): never { + if (this.isUserRejectedRequestError(error)) { + throw new UserRejectedRequestError(error) + } + + if ((error as RpcError).code === -32002) { + throw new ResourceUnavailableError(error) + } + + throw error + } + + async connect({ chainId }: { chainId?: number } = {}) { + try { + const provider = await this.getProvider() + if (!provider) { + throw new ConnectorNotFoundError() + } + + if (provider.on) { + provider.on('accountsChanged', this.onAccountsChanged) + provider.on('chainChanged', this.onChainChanged) + provider.on('disconnect', this.onDisconnect) + } + + this.emit('message', { type: 'connecting' }) + // Attempt to show wallet select prompt with `wallet_requestPermissions` when + // `shimDisconnect` is active and account is in disconnected state (flag in storage) + let account: Address | null = null + + if (this.options?.shimDisconnect && !getClient().storage?.getItem(this.shimDisconnectKey)) { + account = await this.getAccount().catch(() => null) + const isConnected = !!account + if (isConnected) { + // Attempt to show another prompt for selecting wallet if already connected + try { + await provider.request({ + method: 'wallet_requestPermissions', + params: [{ eth_accounts: {} }], + }) + // User may have selected a different account so we will need to revalidate here. + account = await this.getAccount() + } catch (error) { + // Only bubble up error if user rejects request + if (this.isUserRejectedRequestError(error)) { + throw new UserRejectedRequestError(error as Error) + } + } + } + } + + if (!account) { + const accounts = await provider.request({ + method: 'eth_requestAccounts', + }) + account = getAddress(accounts[0] as Address) + } + + // Switch to chain if provided + let id = await this.getChainId() + let unsupported = this.isChainUnsupported(id) + if (chainId && id !== chainId) { + const chain = await this.switchChain(chainId) + id = chain.id + unsupported = this.isChainUnsupported(id) + } + + if (this.options?.shimDisconnect) { + getClient().storage?.setItem(this.shimDisconnectKey, true) + } + + return { account, chain: { id, unsupported }, provider } + } catch (error) { + this.handleFailedConnect(error as Error) + } + } + + async disconnect() { const provider: any = await this.getProvider() if (!provider?.off) return @@ -47,6 +132,10 @@ export class TrustWalletConnector extends WagmiMetaMaskConnector { getClient().storage?.removeItem(this.shimDisconnectKey) } } + + async getProvider() { + return getTrustWalletProvider() + } } export function getTrustWalletProvider() { diff --git a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/index.tsx b/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/index.tsx index 53f85a7d..2cda4c39 100644 --- a/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/index.tsx +++ b/apps/dcellar-web-ui/src/context/WalletConnectContext/connectors/index.tsx @@ -1,6 +1,6 @@ import { chains } from '@/context/WalletConnectContext/chains'; -import { MetaMaskConnector } from '@/context/WalletConnectContext/connectors/MetaMaskConnector'; import { TrustWalletConnector } from '@/context/WalletConnectContext/connectors/TrustWalletConnector'; +import { MetaMaskConnector } from 'wagmi/connectors/metaMask'; const trustWalletConnector = new TrustWalletConnector({ chains }) const metaMaskConnector = new MetaMaskConnector({ chains }) diff --git a/apps/dcellar-web-ui/typings.d.ts b/apps/dcellar-web-ui/typings.d.ts index 3fcb5b49..b537cee4 100644 --- a/apps/dcellar-web-ui/typings.d.ts +++ b/apps/dcellar-web-ui/typings.d.ts @@ -29,6 +29,7 @@ declare global { ga: any; clipboardData: any; trustWallet: any; + trustwallet: any; // zk.wasm export eddsaSign: any; }