import { ReactNode, useRef, useState } from 'react'; import { EIP6963ProviderDetail, EIP6963ProviderInfo, WalletProviderRdns, WrappedBrowserProvider, } from '@imtbl/checkout-sdk'; import { MenuItemProps } from '@biom3/react'; import { WalletDrawer } from './WalletDrawer'; import { WalletChangeEvent } from './WalletDrawerEvents'; import { isPassportProvider } from '../../lib/provider'; import { ProvidersContextActions, useProvidersContext, } from '../../context/providers-context/ProvidersContext'; import { UnableToConnectDrawer } from '../UnableToConnectDrawer/UnableToConnectDrawer'; import { connectEIP6963Provider, ConnectEIP6963ProviderError, } from '../../lib/connectEIP6963Provider'; import { EOAWarningDrawer } from '../EOAWarningDrawer/EOAWarningDrawer'; import { } from '../../lib/utils'; type ConnectWalletDrawerProps = { heading: string; visible: boolean; onClose: (address?: string) => void; onConnect?: ( provider: WrappedBrowserProvider, providerInfo: EIP6963ProviderInfo ) => void; onError?: (errorType: ConnectEIP6963ProviderError) => void; providerType: 'from' | 'to'; walletOptions: EIP6963ProviderDetail[]; bottomSlot?: ReactNode; menuItemSize?: MenuItemProps['size']; disabledOptions?: { label: string; rdns: string; }[]; getShouldRequestWalletPermissions?: (providerInfo: EIP6963ProviderInfo) => boolean | undefined; drawerBackground: string | undefined; }; export function ConnectWalletDrawer({ heading, visible, onClose, onConnect, onError, providerType, walletOptions, bottomSlot, menuItemSize = 'small', disabledOptions = [], getShouldRequestWalletPermissions, drawerBackground, }: ConnectWalletDrawerProps) { const { providersState: { checkout, fromProvider, lockedToProvider }, providersDispatch, } = useProvidersContext(); const prevWalletChangeEvent = useRef(); const [showUnableToConnectDrawer, setShowUnableToConnectDrawer] = useState(false); const [showEOAWarningDrawer, setShowEOAWarningDrawer] = useState(false); const setProviderInContext = async ( provider: WrappedBrowserProvider, providerInfo: EIP6963ProviderInfo, ) => { const address = await (await provider.getSigner()).getAddress(); if (providerType === 'from') { providersDispatch({ payload: { type: ProvidersContextActions.SET_PROVIDER, fromAddress: address, fromProvider: provider, fromProviderInfo: providerInfo, }, }); } if (providerType === 'to') { providersDispatch({ payload: { type: ProvidersContextActions.SET_PROVIDER, toAddress: address, toProvider: provider, toProviderInfo: providerInfo, }, }); } return address; }; const handleWalletConnection = async (event: WalletChangeEvent) => { const { providerDetail } = event; const { info } = providerDetail; if (info.rdns === WalletProviderRdns.PASSPORT) { const { isConnected } = await checkout.checkIsWalletConnected({ provider: new WrappedBrowserProvider(providerDetail.provider!), }); if (isConnected) { if ((providerType === 'from' && !lockedToProvider) || (providerType === 'to' && !isPassportProvider(fromProvider))) { await checkout.passport?.logout(); } } } let address: string | undefined; // Proceed to connect selected provider const shouldRequestWalletPermissions = getShouldRequestWalletPermissions?.(info); try { const { provider } = await connectEIP6963Provider( providerDetail, checkout, shouldRequestWalletPermissions, ); // Store selected provider as fromProvider in context address = await setProviderInContext(provider, providerDetail.info); // Notify successful connection onConnect?.(provider, providerDetail.info); } catch (error: ConnectEIP6963ProviderError | any) { let errorType = error.message; switch (error.message) { case ConnectEIP6963ProviderError.CONNECT_ERROR: setShowUnableToConnectDrawer(true); break; default: errorType = ConnectEIP6963ProviderError.CONNECT_ERROR; } // Notify failure to connect onError?.(errorType as ConnectEIP6963ProviderError); return; } onClose(address); }; const handleOnWalletChangeEvent = async (event: WalletChangeEvent) => { // Keep prev wallet change event prevWalletChangeEvent.current = event; const { info } = event.providerDetail; if (providerType === 'to' && info.rdns !== WalletProviderRdns.PASSPORT) { setShowEOAWarningDrawer(true); return; } handleWalletConnection(event); }; const retrySelectedWallet = () => { if (prevWalletChangeEvent.current) { handleWalletConnection(prevWalletChangeEvent.current); } }; const handleProceedEOA = () => { retrySelectedWallet(); setShowEOAWarningDrawer(false); }; const handleCloseEOAWarningDrawer = () => { setShowEOAWarningDrawer(false); }; return ( <> { if (show === false) onClose(); }} onWalletChange={handleOnWalletChangeEvent} bottomSlot={bottomSlot} drawerBackground={drawerBackground} /> setShowUnableToConnectDrawer(false)} onTryAgain={() => setShowUnableToConnectDrawer(false)} /> ); }