diff --git a/packages/huma-shared/src/utils/WalletConnect.ts b/packages/huma-shared/src/utils/WalletConnect.ts deleted file mode 100644 index 619526c..0000000 --- a/packages/huma-shared/src/utils/WalletConnect.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable max-classes-per-file */ - -import { - URI_AVAILABLE, - WalletConnect, - WalletConnectConstructorArgs, -} from '@web3-react/walletconnect' -import QRCode from 'qrcode' - -export class WalletConnectPopup extends WalletConnect { - constructor({ - actions, - options, - defaultChainId, - timeout, - onError, - }: WalletConnectConstructorArgs) { - super({ - actions, - options: { ...options, qrcode: true }, - defaultChainId, - timeout, - onError, - }) - } -} - -export class WalletConnectQR extends WalletConnect { - static SVG_AVAILABLE = 'svg_available' - - svg?: string - - constructor({ - actions, - options, - defaultChainId, - timeout, - onError, - }: WalletConnectConstructorArgs) { - super({ - actions, - options: { ...options, qrcode: false }, - defaultChainId, - timeout, - onError, - }) - - this.events.once(URI_AVAILABLE, () => { - this.provider?.connector.on('disconnect', () => { - this.deactivate() - }) - }) - - this.events.on(URI_AVAILABLE, async (uri) => { - this.svg = undefined - if (!uri) return - - this.svg = await QRCode.toString(uri, { - // Leave a margin to increase contrast in dark mode. - margin: 1, - // Use 55*2=110 for the width to prevent distortion. The generated viewbox is "0 0 55 55". - width: 110, - type: 'svg', - }) - this.events.emit(WalletConnectQR.SVG_AVAILABLE, this.svg) - }) - } - - deactivate() { - this.events.emit(URI_AVAILABLE) - return super.deactivate() - } -} diff --git a/packages/huma-shared/src/utils/index.ts b/packages/huma-shared/src/utils/index.ts index 246aaeb..35deb97 100644 --- a/packages/huma-shared/src/utils/index.ts +++ b/packages/huma-shared/src/utils/index.ts @@ -1,5 +1,4 @@ export * from './JsonRpcConnector' -export * from './WalletConnect' export * from './chain' export * from './common' export * from './config' diff --git a/packages/huma-web-shared/src/hooks/index.tsx b/packages/huma-web-shared/src/hooks/index.tsx index e90e22e..6201ba4 100644 --- a/packages/huma-web-shared/src/hooks/index.tsx +++ b/packages/huma-web-shared/src/hooks/index.tsx @@ -1,5 +1,4 @@ export * from './useERC2612Permit' -export * from './web3' export * from './useActiveRoute' export * from './useAsyncError' export * from './useAuthErrorHandling' diff --git a/packages/huma-web-shared/src/hooks/web3/index.tsx b/packages/huma-web-shared/src/hooks/web3/index.tsx deleted file mode 100644 index ae7efe9..0000000 --- a/packages/huma-web-shared/src/hooks/web3/index.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' -import { - ChainEnum, - JsonRpcConnector, - MetaMaskConnectionError, - supportedChainId, - WalletConnectPopup, - WalletConnectQR, -} from '@huma-finance/shared' -import { - initializeConnector, - Web3ReactHooks, - Web3ReactProvider, -} from '@web3-react/core' -import { EIP1193 } from '@web3-react/eip1193' -import { MetaMask } from '@web3-react/metamask' -import { Network } from '@web3-react/network' -import { Connector, Provider as Eip1193Provider } from '@web3-react/types' -import React, { PropsWithChildren, useEffect, useMemo, useRef } from 'react' - -import { useAsyncError } from '../useAsyncError' -import { Provider as ConnectorsProvider } from './useConnectors' -import { - JsonRpcConnectionMap, - Provider as JsonRpcUrlMapProvider, - toJsonRpcConnectionMap, - toJsonRpcUrlMap, -} from './useJsonRpcUrlsMap' - -const DEFAULT_CHAIN_ID = ChainEnum.Polygon - -type Web3ReactConnector = [T, Web3ReactHooks] - -interface Web3ReactConnectors { - user: Web3ReactConnector | undefined - metaMask: Web3ReactConnector - walletConnect: Web3ReactConnector - walletConnectQR: Web3ReactConnector - network: Web3ReactConnector -} - -export interface ProviderProps { - defaultChainId?: ChainEnum - jsonRpcUrlMap?: JsonRpcConnectionMap - provider: Eip1193Provider | JsonRpcProvider -} - -function initializeWeb3ReactConnector( - Constructor: { new (options: P): T }, - options: Omit, -): Web3ReactConnector { - const [connector, hooks] = initializeConnector( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (actions) => new Constructor({ actions, ...options } as any), - ) - if (options && 'provider' in options) { - // Short-circuit provider selection to improve performance and testability. - // Without doing so, provider will be unavailable for a frame. - hooks.useProvider = (() => - (options as Record<'provider', unknown>) - .provider) as typeof hooks.useProvider - } - return [connector, hooks] -} - -function useWeb3ReactConnectors({ - defaultChainId, - provider, - jsonRpcUrlMap, -}: ProviderProps) { - const [urlMap, connectionMap] = useMemo( - () => [ - toJsonRpcUrlMap(jsonRpcUrlMap), - toJsonRpcConnectionMap(jsonRpcUrlMap), - ], - [jsonRpcUrlMap], - ) - - const throwAsync = useAsyncError() - - const user = useMemo(() => { - if (!provider) return - if (JsonRpcProvider.isProvider(provider)) { - // eslint-disable-next-line consistent-return - return initializeWeb3ReactConnector(JsonRpcConnector, { - provider, - onError: console.error, - }) - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (JsonRpcProvider.isProvider((provider as any).provider)) { - throw new Error( - 'Eip1193Bridge is experimental: pass your ethers Provider directly', - ) - } else { - // eslint-disable-next-line consistent-return - return initializeWeb3ReactConnector(EIP1193, { - provider, - onError: console.error, - }) - } - }, [provider]) - const metaMask = useMemo( - () => - initializeWeb3ReactConnector(MetaMask, { - onError: () => { - throwAsync(new MetaMaskConnectionError()) - }, - }), - [throwAsync], - ) - const walletConnect = useMemo( - () => - initializeWeb3ReactConnector(WalletConnectPopup, { - options: { rpc: urlMap }, - defaultChainId, - onError: console.error, - }), - [defaultChainId, urlMap], - ) - const walletConnectQR = useMemo( - () => - initializeWeb3ReactConnector(WalletConnectQR, { - options: { rpc: urlMap }, - defaultChainId, - onError: console.error, - }), - [defaultChainId, urlMap], - ) - const network = useMemo( - () => - initializeWeb3ReactConnector(Network, { - urlMap: connectionMap, - defaultChainId, - }), - [connectionMap, defaultChainId], - ) - - return useMemo( - () => ({ - user, - metaMask, - walletConnect, - walletConnectQR, - network, - }), - [metaMask, network, user, walletConnect, walletConnectQR], - ) -} - -export function Provider({ - defaultChainId: chainId = ChainEnum.Polygon, - jsonRpcUrlMap, - provider, - children, -}: PropsWithChildren) { - const defaultChainId = useMemo(() => { - if (!supportedChainId(chainId)) { - console.warn( - `Unsupported chainId: ${chainId}. Falling back to ${DEFAULT_CHAIN_ID} (${ChainEnum[DEFAULT_CHAIN_ID]}).`, - ) - return DEFAULT_CHAIN_ID - } - return chainId - }, [chainId]) - - const web3ReactConnectors = useWeb3ReactConnectors({ - provider, - jsonRpcUrlMap, - defaultChainId, - }) - - const key = useRef(0) - const prioritizedConnectors = useMemo(() => { - // Re-key Web3ReactProvider before rendering new connectors, as it expects connectors to be - // referentially static. - key.current += 1 - - const prioritizedConnectors: (Web3ReactConnector | null | undefined)[] = [ - web3ReactConnectors.user, - web3ReactConnectors.metaMask, - web3ReactConnectors.walletConnect, - web3ReactConnectors.walletConnectQR, - web3ReactConnectors.network, - ] - return prioritizedConnectors.filter( - (connector): connector is Web3ReactConnector => Boolean(connector), - ) - }, [web3ReactConnectors]) - - const connectors = useMemo( - () => ({ - user: web3ReactConnectors.user?.[0], - metaMask: web3ReactConnectors.metaMask[0], - walletConnect: web3ReactConnectors.walletConnect[0], - walletConnectQR: web3ReactConnectors.walletConnectQR[0], - network: web3ReactConnectors.network[0], - }), - [web3ReactConnectors], - ) - - const shouldEagerlyConnect = provider === undefined // !== null - useEffect(() => { - // Ignore any errors during connection so they do not propagate to the widget. - if (connectors.user) { - connectors.user.activate().catch(() => undefined) - return - } - if (shouldEagerlyConnect) { - const eagerConnectors = [connectors.metaMask, connectors.walletConnect] - eagerConnectors.forEach((connector) => - connector.connectEagerly().catch(() => undefined), - ) - } - connectors.network.activate().catch(() => undefined) - }, [ - connectors.metaMask, - connectors.network, - connectors.user, - connectors.walletConnect, - shouldEagerlyConnect, - ]) - - return ( - - - - {children} - - - - ) -} diff --git a/packages/huma-web-shared/src/hooks/web3/useConnectors.tsx b/packages/huma-web-shared/src/hooks/web3/useConnectors.tsx deleted file mode 100644 index 235f182..0000000 --- a/packages/huma-web-shared/src/hooks/web3/useConnectors.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { - JsonRpcConnector, - WalletConnectPopup, - WalletConnectQR, -} from '@huma-finance/shared' -import { useWeb3React } from '@web3-react/core' -import { EIP1193 } from '@web3-react/eip1193' -import { MetaMask } from '@web3-react/metamask' -import { Network } from '@web3-react/network' -import React, { - createContext, - PropsWithChildren, - useContext, - useEffect, -} from 'react' -import invariant from 'tiny-invariant' - -export interface Connectors { - user: EIP1193 | JsonRpcConnector | undefined - metaMask: MetaMask - walletConnect: WalletConnectPopup - walletConnectQR: WalletConnectQR - network: Network -} - -const ConnectorsContext = createContext(null) - -export function Provider({ - connectors, - children, -}: PropsWithChildren<{ connectors: Connectors }>) { - const { chainId, connector } = useWeb3React() - // The network chainId must be kept synchronized to avoid a loop when disconnecting and for a better UX. - useEffect(() => { - if (connector !== connectors.network) { - try { - connectors.network.activate(chainId) - } catch (e) { - // Unknown chains (eg hardhat) will fail to connect, and should not crash - } - } - }, [chainId, connector, connectors.network]) - - return ( - - {children} - - ) -} - -export default function useConnectors() { - const connectors = useContext(ConnectorsContext) - invariant(connectors, 'useConnectors used without initializing the context') - return connectors -} diff --git a/packages/huma-widget/package.json b/packages/huma-widget/package.json index dda558d..65478a8 100644 --- a/packages/huma-widget/package.json +++ b/packages/huma-widget/package.json @@ -41,9 +41,6 @@ "@notifi-network/notifi-react": "^1.1.2", "@reduxjs/toolkit": "^1.8.6", "@types/utf8": "^3.0.1", - "@walletconnect/ethereum-provider": "1.8.0", - "@walletconnect/jsonrpc-http-connection": "^1.0.3", - "@walletconnect/jsonrpc-provider": "^1.0.5", "@web3-react/coinbase-wallet": "^8.2.0", "@web3-react/core": "^8.2.0", "@web3-react/eip1193": "^8.2.0", @@ -53,7 +50,6 @@ "@web3-react/network": "^8.2.0", "@web3-react/types": "^8.2.0", "@web3-react/url": "^8.2.0", - "@web3-react/walletconnect": "^8.2.0", "buffer": "^6.0.3", "customize-cra": "^1.0.0", "dayjs": "^1.11.6", diff --git a/packages/huma-widget/src/index.tsx b/packages/huma-widget/src/index.tsx index 711c1b2..7897218 100644 --- a/packages/huma-widget/src/index.tsx +++ b/packages/huma-widget/src/index.tsx @@ -1,8 +1,4 @@ import { JsonRpcProvider } from '@ethersproject/providers' -import { - Provider as Web3Provider, - ProviderProps as Web3Props, -} from '@huma-finance/web-shared' import { ThemeProvider } from '@mui/material' import { Provider as Eip1193Provider } from '@web3-react/types' import { Provider as AtomProvider } from 'jotai' @@ -135,15 +131,13 @@ function Widget(props: WCProps) { return ( - - - - - {children} - - - - + + + + {children} + + + )