UNPKG

@magiclabs/wagmi-connector

Version:
133 lines (132 loc) 5.36 kB
import { createConnector } from '@wagmi/core'; import { getAddress } from 'viem'; import { normalizeChainId } from '../utils.js'; import { magicConnector } from './magicConnector.js'; export function universalWalletConnector({ chains, options }) { const { id, name, type, getAccount, getMagicSDK, getProvider, onAccountsChanged } = magicConnector({ chains, options: { ...options, connectorType: 'universal' }, }); const magic = getMagicSDK(); const registerProviderEventListeners = (provider, onChainChanged, onDisconnect) => { if (provider.on) { provider.on('accountsChanged', onAccountsChanged); provider.on('chainChanged', chain => onChainChanged(chain)); provider.on('disconnect', onDisconnect); } }; return createConnector(config => ({ id, name, type, magic, getProvider, getAccount, onAccountsChanged, async connect() { await this.magic?.wallet.connectWithUI(); const provider = (await this.getProvider()); const chainId = await this.getChainId(); if (provider) { registerProviderEventListeners(provider, chain => { const chainId = normalizeChainId(chain); config.emitter.emit('change', { chainId }); }, this.onDisconnect); } const account = await this.getAccount(); return { accounts: [account], chainId, }; }, async getAccounts() { const provider = await this.getProvider(); const accounts = (await provider?.request({ method: 'eth_accounts', })); return accounts.map(x => getAddress(x)); }, onChainChanged: chain => { const chainId = normalizeChainId(chain); config.emitter.emit('change', { chainId }); }, async onConnect(connectInfo) { const chainId = normalizeChainId(connectInfo.chainId); const accounts = await this.getAccounts(); config.emitter.emit('connect', { accounts, chainId }); }, async disconnect() { try { await this.magic?.user.logout(); config.emitter.emit('disconnect'); } catch (error) { console.error('Error disconnecting from Magic SDK:', error); } }, async isAuthorized() { try { const walletInfo = await this.magic?.user.getInfo(); return !!walletInfo; } catch { return false; } }, getChainId: async () => { const provider = await getProvider(); if (provider) { const chainId = await provider.send('eth_chainId', []); return normalizeChainId(chainId); } const networkOptions = options.magicSdkConfiguration?.network; if (typeof networkOptions === 'object') { const chainID = networkOptions.chainId; if (chainID) return normalizeChainId(chainID); } throw new Error('Chain ID is not defined'); }, switchChain: async function ({ chainId }) { if (!options.networks) { throw new Error('switch chain not supported: please provide networks in options'); } const normalizedChainId = normalizeChainId(chainId); const chain = chains.find(x => x.id === normalizedChainId); if (!chain) throw new Error(`Unsupported chainId: ${chainId}`); const network = options.networks.find(x => typeof x === 'object' && x.chainId ? normalizeChainId(x.chainId) === normalizedChainId : normalizeChainId(x) === normalizedChainId); if (!network) throw new Error(`Unsupported chainId: ${chainId}`); const account = await this.getAccount(); const provider = (await this.getProvider()); if (provider?.off) { provider.off('accountsChanged', this.onAccountsChanged); provider.off('chainChanged', this.onChainChanged); provider.off('disconnect', this.onDisconnect); } const newOptions = { ...options, connectorType: 'universal', }; newOptions.magicSdkConfiguration.network = network; const { getAccount, getMagicSDK, getProvider, onAccountsChanged } = magicConnector({ chains, options: newOptions, }); this.getAccount = getAccount; this.magic = getMagicSDK(); this.getProvider = getProvider; this.onAccountsChanged = onAccountsChanged; registerProviderEventListeners(this.magic.rpcProvider, this.onChainChanged, this.onDisconnect); this.onChainChanged(chain.id.toString()); this.onAccountsChanged([account]); return chain; }, onDisconnect: () => { config.emitter.emit('disconnect'); }, })); }