UNPKG

@wagmi/core

Version:

VanillaJS library for Ethereum

280 lines 11.4 kB
import { numberToHex, SwitchChainError, UserRejectedRequestError, withRetry, } from 'viem'; import { parseAccount } from 'viem/utils'; import { createConnector } from '../connectors/createConnector.js'; import { ChainNotConfiguredError } from '../errors/config.js'; const tempoWalletIcon = 'data:image/svg+xml,<svg width="269" height="269" viewBox="0 0 269 269" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="269" height="269" fill="black"/><path d="M123.273 190.794H93.445L121.09 105.318H85.7334L93.445 80.2642H191.95L184.238 105.318H150.773L123.273 190.794Z" fill="white"/></svg>'; /** * Connector for the Tempo Wallet dialog. */ export function tempoWallet(parameters = {}) { const { dialog: dialogOption, host, icon = tempoWalletIcon, name, rdns, theme, ...providerParameters } = parameters; return _setup({ createAdapter(accounts) { return accounts.dialog({ dialog: dialogOption, host, icon, name, rdns, theme, }); }, icon, id: rdns ?? 'xyz.tempo', name: name ?? 'Tempo Wallet', providerParameters, rdns: rdns ?? 'xyz.tempo', type: 'injected', }); } webAuthn.type = 'webAuthn'; /** * Connector for a WebAuthn EOA. */ export function webAuthn(parameters = {}) { const { authUrl, ceremony, icon, name, rdns, ...providerParameters } = parameters; return _setup({ createAdapter(accounts) { return ceremony ? accounts.webAuthn({ ceremony, icon, name, rdns }) : accounts.webAuthn({ authUrl, icon, name, rdns }); }, icon, id: 'webAuthn', name: name ?? 'EOA (WebAuthn)', providerParameters, rdns, type: 'webAuthn', }); } dangerous_secp256k1.type = 'dangerous_secp256k1'; /** * Connector for a Secp256k1 EOA. * * WARNING: NOT RECOMMENDED FOR PRODUCTION USAGE. * This connector stores private keys in clear text, and are bound to the session * length of the storage used. */ export function dangerous_secp256k1(parameters = {}) { const { icon, name, privateKey, rdns, ...providerParameters } = parameters; return _setup({ createAdapter(accounts) { return accounts.dangerous_secp256k1({ icon, name, privateKey, rdns }); }, icon, id: 'secp256k1', name: name ?? 'EOA (Secp256k1)', providerParameters, rdns, type: 'secp256k1', }); } function _setup(parameters) { return createConnector((config) => { const chains = config.chains; let providerPromise; let accountsChanged; let chainChanged; let connect; let disconnect; async function getAccountsModule() { return await import('accounts').catch(() => { throw new Error('dependency "accounts" not found'); }); } async function getProvider() { providerPromise ??= (async () => { const accounts = await getAccountsModule(); return accounts.Provider.create({ ...parameters.providerParameters, adapter: parameters.createAdapter(accounts), chains: config.chains, transports: config.transports, }); })(); return await providerPromise; } return { icon: parameters.icon, id: parameters.id, name: parameters.name, rdns: parameters.rdns, type: parameters.type, async connect(connectParameters = {}) { const { chainId, isReconnecting, withCapabilities } = connectParameters; const capabilities = 'capabilities' in connectParameters ? connectParameters.capabilities : undefined; let accounts = []; let currentChainId; if (isReconnecting) { accounts = await this.getAccounts() .then((accounts) => accounts.map((address) => ({ address, capabilities: {} }))) .catch(() => []); } try { if (!accounts.length && !isReconnecting) { const provider = await getProvider(); const response = (await provider.request({ method: 'wallet_connect', params: [ { ...(chainId ? { chainId } : {}), ...(capabilities ? { capabilities } : {}), }, ], })); accounts = response.accounts; } currentChainId ??= await this.getChainId(); if (!currentChainId) throw new ChainNotConfiguredError(); const provider = await getProvider(); if (connect) { provider.removeListener('connect', connect); connect = undefined; } if (!accountsChanged) { accountsChanged = this.onAccountsChanged.bind(this); provider.on('accountsChanged', accountsChanged); } if (!chainChanged) { chainChanged = this.onChainChanged.bind(this); provider.on('chainChanged', chainChanged); } if (!disconnect) { disconnect = this.onDisconnect.bind(this); provider.on('disconnect', disconnect); } return { accounts: (withCapabilities ? accounts : accounts.map((account) => account.address)), chainId: currentChainId, }; } catch (error) { const rpcError = error; if (rpcError.code === UserRejectedRequestError.code) throw new UserRejectedRequestError(rpcError); throw rpcError; } }, async disconnect() { const provider = await getProvider(); if (chainChanged) { provider.removeListener('chainChanged', chainChanged); chainChanged = undefined; } if (disconnect) { provider.removeListener('disconnect', disconnect); disconnect = undefined; } if (!connect) { connect = this.onConnect?.bind(this); if (connect) provider.on('connect', connect); } await provider.request({ method: 'wallet_disconnect' }); }, async getAccounts() { const provider = await getProvider(); return await provider.request({ method: 'eth_accounts' }); }, async getChainId() { const provider = await getProvider(); return Number(await provider.request({ method: 'eth_chainId' })); }, async getClient({ chainId } = {}) { const provider = await getProvider(); // Always provide a JSON-RPC account; the SDK provider performs // access key orchestration internally before signing. const { address } = provider.getAccount({ accessKey: false }); return Object.assign(provider.getClient({ chainId }), { account: parseAccount(address), }); }, async getProvider() { return await getProvider(); }, async isAuthorized() { try { const accounts = await withRetry(() => this.getAccounts()); return !!accounts.length; } catch { return false; } }, onAccountsChanged(accounts) { config.emitter.emit('change', { accounts: accounts, }); }, onChainChanged(chain) { config.emitter.emit('change', { chainId: Number(chain) }); }, async onConnect(connectInfo) { const accounts = await this.getAccounts(); if (accounts.length === 0) return; const chainId = Number(connectInfo.chainId); config.emitter.emit('connect', { accounts, chainId }); const provider = await getProvider(); if (connect) { provider.removeListener('connect', connect); connect = undefined; } if (!accountsChanged) { accountsChanged = this.onAccountsChanged.bind(this); provider.on('accountsChanged', accountsChanged); } if (!chainChanged) { chainChanged = this.onChainChanged.bind(this); provider.on('chainChanged', chainChanged); } if (!disconnect) { disconnect = this.onDisconnect.bind(this); provider.on('disconnect', disconnect); } }, async onDisconnect(_error) { const provider = await getProvider(); config.emitter.emit('disconnect'); if (chainChanged) { provider.removeListener('chainChanged', chainChanged); chainChanged = undefined; } if (disconnect) { provider.removeListener('disconnect', disconnect); disconnect = undefined; } if (!connect) { connect = this.onConnect?.bind(this); if (connect) provider.on('connect', connect); } }, async setup() { if (!connect) { const provider = await getProvider(); connect = this.onConnect?.bind(this); if (connect) provider.on('connect', connect); } }, async switchChain({ chainId }) { const chain = chains.find((chain) => chain.id === chainId); if (!chain) throw new SwitchChainError(new ChainNotConfiguredError()); const provider = await getProvider(); await provider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: numberToHex(chainId) }], }); return chain; }, }; }); } //# sourceMappingURL=Connectors.js.map