From 06c49f9c196fef700b50697646c66ae64ea5f06a Mon Sep 17 00:00:00 2001 From: Zach Couchman Date: Thu, 20 Jul 2023 13:18:08 +1000 Subject: [PATCH] Handle network switch events in wallet --- .../ConnectLoader/ConnectLoader.tsx | 59 +------------ .../src/widgets/wallet/WalletWidget.tsx | 85 ++++++++++++++++--- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx index c9acb9197d..a0f96e338d 100644 --- a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx +++ b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.tsx @@ -25,15 +25,11 @@ import { ConnectWidgetViews } from '../../context/view-context/ConnectViewContex import { ErrorView } from '../../views/error/ErrorView'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; import { - WidgetTheme, ConnectTargetLayer, getTargetLayerChainId, getL2ChainId, getL1ChainId, + WidgetTheme, ConnectTargetLayer, getTargetLayerChainId, } from '../../lib'; import { useInterval } from '../../lib/hooks/useInterval'; -import { - addProviderAccountsListener, - addProviderChainListener, - removeProviderEventListeners, -} from '../../lib/providerEvents'; import { SharedViews } from '../../context/view-context/ViewContext'; +import { addProviderAccountsListener, removeProviderEventListeners } from '../../lib/providerEvents'; export interface ConnectLoaderProps { children?: React.ReactNode; @@ -96,20 +92,13 @@ export function ConnectLoader({ }; clearInterval = useInterval(() => checkIfWeb3ProviderSet(), 10); + /** Handle account change events and reload widget when changed */ useEffect(() => { if (!web3Provider) { - // connectLoaderDispatch({ - // payload: { - // type: ConnectLoaderActions.UPDATE_CONNECTION_STATUS, - // connectionStatus: ConnectionStatus.NOT_CONNECTED_NO_PROVIDER, - // }, - // }); return () => {}; } function handleAccountsChanged(e: any) { - alert(`[ConnectLoader]: You changed your account ${e[0]}`); - if (e.length === 0) { connectLoaderDispatch({ payload: { @@ -130,54 +119,14 @@ export function ConnectLoader({ }); } - function handleChainChanged(e: any) { - alert(`[ConnectLoader]: You changed the chain ${e}`); - const chainId = parseInt(e, 16); - console.log(chainId); - - const checkout = new Checkout({ baseConfig: { environment: widgetConfig.environment } }); - // needs to be if chainId is targetChainId for this widget, then you may pass - // otherwise go to connected_wrong_network - if (chainId === getL2ChainId(checkout.config) && targetLayer === ConnectTargetLayer.LAYER2) { - console.log('imtbl zkevm testnet'); - } else if (chainId === getL1ChainId(checkout.config) && targetLayer === ConnectTargetLayer.LAYER1) { - console.log('l1 chain'); - } else { - connectLoaderDispatch({ - payload: { - type: ConnectLoaderActions.UPDATE_CONNECTION_STATUS, - connectionStatus: ConnectionStatus.CONNECTED_WRONG_NETWORK, - deepLink: SharedViews.SWITCH_NETWORK, - }, - }); - } - } - // subscribe addProviderAccountsListener(web3Provider, handleAccountsChanged); - addProviderChainListener(web3Provider, handleChainChanged); - - function handleDisconnect(e:any) { - console.log(e); - connectLoaderDispatch({ - payload: { - type: ConnectLoaderActions.UPDATE_CONNECTION_STATUS, - connectionStatus: ConnectionStatus.NOT_CONNECTED_NO_PROVIDER, - }, - }); - return () => {}; - } - console.log('subscribing to disconnect event'); - (web3Provider.provider as any).on('disconnect', handleDisconnect); return () => { - // unsubscribe - console.log('unsubscribing'); removeProviderEventListeners( web3Provider, handleAccountsChanged, - handleChainChanged, + () => {}, ); - (web3Provider.provider as any).removeListener('disconnect', handleDisconnect); }; }, [web3Provider]); diff --git a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx index 52f5a46c3e..de091d0d95 100644 --- a/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/wallet/WalletWidget.tsx @@ -3,7 +3,7 @@ import { BaseTokens, onDarkBase, onLightBase } from '@biom3/design-tokens'; import { Checkout, } from '@imtbl/checkout-sdk'; -import { useEffect, useReducer } from 'react'; +import { useCallback, useEffect, useReducer } from 'react'; import { Web3Provider } from '@ethersproject/providers'; import { IMTBLWidgetEvents } from '@imtbl/checkout-widgets'; import { @@ -27,9 +27,15 @@ import { import { WalletWidgetViews } from '../../context/view-context/WalletViewContextTypes'; import { Settings } from './views/Settings'; import { StrongCheckoutWidgetsConfig } from '../../lib/withDefaultWidgetConfig'; -import { WidgetTheme } from '../../lib'; +import { WidgetTheme, getL1ChainId, getL2ChainId } from '../../lib'; import { CoinInfo } from './views/CoinInfo'; import { TopUpView } from '../../views/top-up/TopUpView'; +import { SwitchNetwork } from '../../views/switch-network/SwitchNetwork'; +import { ImmutableNetworkHero } from '../../components/Hero/ImmutableNetworkHero'; +import { + addProviderChainListener, + removeProviderEventListeners, +} from '../../lib/providerEvents'; export interface WalletWidgetProps { config: StrongCheckoutWidgetsConfig, @@ -37,8 +43,8 @@ export interface WalletWidgetProps { } export function WalletWidget(props: WalletWidgetProps) { + /** Handle Widget Props */ const { config, web3Provider } = props; - const { environment, theme, isOnRampEnabled, isSwapEnabled, isBridgeEnabled, } = config; @@ -46,13 +52,16 @@ export function WalletWidget(props: WalletWidgetProps) { const biomeTheme: BaseTokens = theme.toLowerCase() === WidgetTheme.LIGHT.toLowerCase() ? onLightBase : onDarkBase; - const [viewState, viewDispatch] = useReducer(viewReducer, initialViewState); + /** Setup Wallet Widget State */ + const [viewState, viewDispatch] = useReducer(viewReducer, initialViewState); const [walletState, walletDispatch] = useReducer( walletReducer, initialWalletState, ); + const { checkout, provider } = walletState; + /** Set provider as it is passed in */ useEffect(() => { if (web3Provider) { walletDispatch({ @@ -64,8 +73,7 @@ export function WalletWidget(props: WalletWidgetProps) { } }, [web3Provider]); - const { checkout } = walletState; - + /** Set Checkout instance and save config */ useEffect(() => { walletDispatch({ payload: { @@ -86,6 +94,7 @@ export function WalletWidget(props: WalletWidgetProps) { }); }, [isBridgeEnabled, isSwapEnabled, isOnRampEnabled, environment]); + /** Setup Wallet Widget */ useEffect(() => { (async () => { if (!checkout || !web3Provider) return; @@ -117,11 +126,55 @@ export function WalletWidget(props: WalletWidgetProps) { })(); }, [checkout]); - const errorAction = () => { - // TODO: please remove or if necessary keep the eslint ignore - // eslint-disable-next-line no-console - console.log('Something went wrong'); - }; + /* Handle Wallet Events */ + useEffect(() => { + if (!provider) return () => {}; + if (!checkout) return () => {}; + + function handleChainChanged(e: any) { + const chainId = parseInt(e, 16); + + if (chainId !== getL1ChainId(checkout!.config) && chainId !== getL2ChainId(checkout!.config)) { + viewDispatch({ + payload: { + type: ViewActions.UPDATE_VIEW, + view: { + type: SharedViews.SWITCH_NETWORK, + }, + }, + }); + } + } + addProviderChainListener(provider, handleChainChanged); + + return () => { + removeProviderEventListeners(provider, () => {}, handleChainChanged); + }; + }, [provider, checkout]); + + const switchNetwork = useCallback(async () => { + if (!provider || !checkout) return; + + const switchRes = await checkout.switchNetwork({ + provider, + chainId: getL2ChainId(checkout.config), + }); + walletDispatch({ + payload: { + type: WalletActions.SET_PROVIDER, + provider: switchRes.provider, + }, + }); + + viewDispatch({ + payload: { + type: ViewActions.UPDATE_VIEW, + view: { + type: WalletWidgetViews.WALLET_BALANCES, + }, + }, + }); + }, [provider, walletDispatch, viewDispatch]); return ( @@ -142,10 +195,18 @@ export function WalletWidget(props: WalletWidgetProps) { {viewState.view.type === WalletWidgetViews.COIN_INFO && ( )} + {viewState.view.type === SharedViews.SWITCH_NETWORK && ( + } + switchNetwork={switchNetwork} + onClose={sendWalletWidgetCloseEvent} + switchToZkEVM + /> + )} {viewState.view.type === SharedViews.ERROR_VIEW && ( )}