Here is the modified source code that allows connecting to MetaMask:
import {ChainNotConfiguredError, createConnector, normalizeChainId} from '@wagmi/core';
import type {IProvider, IWeb3Auth, WALLET_ADAPTER_TYPE} from '@web3auth/base';
import {ADAPTER_STATUS, CHAIN_NAMESPACES, log} from '@web3auth/base';
import type {OpenloginLoginParams} from '@web3auth/openlogin-adapter';
import {Chain, Hex, SwitchChainError, UserRejectedRequestError, getAddress} from 'viem';
export interface Web3AuthConnectorParams {
web3AuthInstance: IWeb3Auth;
walletName: WALLET_ADAPTER_TYPE;
loginParams?: OpenloginLoginParams;
}
export const CustomWeb3AuthConnector = (parameters: Web3AuthConnectorParams) => {
let walletProvider: IProvider | null = null;
const {web3AuthInstance, walletName, loginParams} = parameters;
return createConnector<IProvider>(config => ({
id: 'web3auth',
name: 'Web3Auth',
type: 'Web3Auth',
async connect({chainId} = {}) {
try {
config.emitter.emit('message', {
type: 'connecting',
});
const provider = await this.getProvider();
provider.on('accountsChanged', this.onAccountsChanged);
provider.on('chainChanged', this.onChainChanged);
provider.on('disconnect', this.onDisconnect.bind(this));
if (!web3AuthInstance.connected) {
await web3AuthInstance.connectTo(walletName, loginParams ?? undefined);
}
let currentChainId = await this.getChainId();
if (chainId && currentChainId !== chainId) {
const chain = await this.switchChain!({chainId}).catch(error => {
if (error.code === UserRejectedRequestError.code) throw error;
return {id: currentChainId};
});
currentChainId = chain?.id ?? currentChainId;
}
const accounts = await this.getAccounts();
return {accounts, chainId: currentChainId};
} catch (error) {
log.error('error while connecting', error);
this.onDisconnect();
throw new UserRejectedRequestError('Something went wrong' as unknown as Error);
}
},
async getAccounts(): Promise<Hex[]> {
const provider = await this.getProvider();
const result = await provider.request<{method: string}, string[]>({
method: 'eth_accounts',
});
if (!Array.isArray(result)) {
throw new Error('Invalid accounts result');
}
// @ts-ignore
return result.map((x: string) => getAddress(x));
},
async getChainId() {
const provider = await this.getProvider();
const chainId = await provider.request<unknown, number>({method: 'eth_chainId'});
return normalizeChainId(chainId);
},
async getProvider(): Promise<IProvider> {
if (walletProvider) {
return walletProvider;
}
if (web3AuthInstance.status === ADAPTER_STATUS.NOT_READY) {
await web3AuthInstance.init();
}
walletProvider = web3AuthInstance.provider;
if (!walletProvider) {
throw new Error('Provider not found');
}
return walletProvider;
},
async isAuthorized() {
try {
const accounts = await this.getAccounts();
return !!accounts.length;
} catch {
return false;
}
},
async switchChain({chainId}): Promise<Chain> {
try {
const chain = config.chains.find(x => x.id === chainId);
if (!chain) throw new SwitchChainError(new ChainNotConfiguredError());
await web3AuthInstance.addChain({
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: `0x${chain.id.toString(16)}`,
rpcTarget: chain.rpcUrls.default.http[0],
displayName: chain.name,
blockExplorerUrl: chain.blockExplorers?.default.url[0] || '',
ticker: chain.nativeCurrency?.symbol || 'ETH',
tickerName: chain.nativeCurrency?.name || 'Ethereum',
decimals: chain.nativeCurrency?.decimals || 18,
logo: chain.nativeCurrency?.symbol
? `https://images.toruswallet.io/${chain.nativeCurrency?.symbol.toLowerCase()}.svg`
: 'https://images.toruswallet.io/eth.svg',
});
log.info('Chain Added: ', chain.name);
await web3AuthInstance.switchChain({chainId: `0x${chain.id.toString(16)}`});
log.info('Chain Switched to ', chain.name);
config.emitter.emit('change', {
chainId,
});
return chain;
} catch (error: unknown) {
log.error('Error: Cannot change chain', error);
throw new SwitchChainError(error as Error);
}
},
async disconnect(): Promise<void> {
await web3AuthInstance.logout();
const provider = await this.getProvider();
provider.removeListener('accountsChanged', this.onAccountsChanged);
provider.removeListener('chainChanged', this.onChainChanged);
},
onAccountsChanged(accounts) {
if (accounts.length === 0) config.emitter.emit('disconnect');
else
config.emitter.emit('change', {
accounts: accounts.map(x => getAddress(x)),
});
},
onChainChanged(chain) {
const chainId = normalizeChainId(chain);
config.emitter.emit('change', {chainId});
},
onDisconnect(): void {
config.emitter.emit('disconnect');
},
}));
};