@web3-onboard/wagmi
Version:
Module to configure, connect and return web3-onboard wallets as wagmi wallets and wagmi-config to be used with wagmi-core methods
210 lines (209 loc) • 8.08 kB
JavaScript
import { createConfig, createConnector, getConnectors } from '@wagmi/core';
import { createWagmiChains, createWalletId } from './utils';
import { connect as wagmiConnect } from '@wagmi/core';
import { validateWagmiInit } from './validation';
import EventEmitter from 'eventemitter3';
import { toHex, fromHex, UserRejectedRequestError, ResourceUnavailableRpcError } from 'viem';
import { ProviderRpcErrorCode } from '@web3-onboard/common';
export * from '@wagmi/core';
const wagmiConnectorFn = {};
const transports = {};
let chainsList;
let wagmiConfig;
let providerMethods;
function wagmiInit(initOptions) {
if (initOptions) {
const error = validateWagmiInit(initOptions);
if (error) {
throw error;
}
}
providerMethods = initOptions;
return {
buildWagmiConfig,
createWagmiConnector,
connectWalletToWagmi,
wagmiConnect,
wagmiDisconnectWallet,
getWagmiConnector
};
}
async function buildWagmiConfig(chains, wallet) {
if (wallet && (!wallet.provider || !wallet.label)) {
throw new Error('Provider and wallet label are required to initialize WAGMI with a new connector');
}
chainsList = chains !== null && chains !== void 0 ? chains : chainsList;
try {
if (wallet) {
const { label, provider } = wallet;
const latestWallet = await createWagmiConnector(label, provider);
if (latestWallet) {
wagmiConnectorFn[createWalletId(label)] = latestWallet;
}
else {
console.error(`Failed to initialize Web3-Onboard WAGMI instance because of error from creating wallet connector - Label: ${label}`);
return undefined;
}
}
const connectors = [...Object.values(wagmiConnectorFn)];
const viemChains = await createWagmiChains(chainsList || [], transports);
wagmiConfig = createConfig({
chains: [...viemChains],
transports,
multiInjectedProviderDiscovery: false,
connectors
});
return wagmiConfig;
}
catch (e) {
console.error(`Failed to initialize Web3-Onboard WAGMI instance - Error: ${e}`);
return undefined;
}
}
async function createWagmiConnector(label, provider) {
try {
if (!providerMethods) {
throw new Error('WAGMI config not initialized');
}
return createConnector(() => convertW3OToWagmiWallet(label, provider, providerMethods));
}
catch (e) {
console.error('Error creating wagmi connector', e);
return undefined;
}
}
async function connectWalletToWagmi(label, provider) {
try {
if (!wagmiConfig || !providerMethods) {
throw new Error('WAGMI connectWalletToWagmi could not be completed');
}
return await wagmiConnect(wagmiConfig, {
connector: convertW3OToWagmiWallet(label, provider, providerMethods)
});
}
catch (e) {
console.error('Error connecting wallet to wagmi', e);
return undefined;
}
}
async function wagmiDisconnectWallet(label) {
try {
delete wagmiConnectorFn[createWalletId(label)];
wagmiConfig = await buildWagmiConfig();
return wagmiConfig;
}
catch (e) {
console.error('error disconnecting wallet from wagmi', e);
}
}
function getWagmiConnector(label) {
try {
const wagmiConnectors = getConnectors(wagmiConfig);
if (!(wagmiConnectors === null || wagmiConnectors === void 0 ? void 0 : wagmiConnectors.length))
return undefined;
return wagmiConnectors.find(connector => connector.name === label);
}
catch (e) {
console.error('error disconnecting wallet from wagmi', e);
}
}
const convertW3OToWagmiWallet = (label, provider, coreProviderMethods) => {
if (!coreProviderMethods || typeof coreProviderMethods === undefined) {
console.error('Required provider methods not defined for Wagmi Module API');
return {};
}
else {
return {
name: label,
id: createWalletId(label),
connect: ({ chainId }) => {
try {
return Promise.resolve(coreProviderMethods
.requestAccounts(provider)
.then((accounts) => {
const acc = accounts;
if (chainId) {
return {
chainId,
accounts: acc
};
}
return coreProviderMethods
.getChainId(provider)
.then((id) => {
return {
chainId: fromHex(id, 'number'),
accounts: acc
};
});
}));
}
catch (err) {
const error = err;
if (error.code === UserRejectedRequestError.code)
throw new UserRejectedRequestError(error);
if (error.code === ResourceUnavailableRpcError.code)
throw new ResourceUnavailableRpcError(error);
throw error;
}
},
disconnect: () => {
wagmiDisconnectWallet(label);
coreProviderMethods.disconnect({ label });
},
getAccounts: () => coreProviderMethods.requestAccounts(provider).then((acc) => {
return acc;
}),
getChainId: () => coreProviderMethods.getChainId(provider).then((chainId) => {
return fromHex(chainId, 'number');
}),
getProvider: () => Promise.resolve(provider),
isAuthorized: () => coreProviderMethods
.requestAccounts(provider)
.then((accounts) => {
return !!accounts.length;
}),
switchChain: ({ chainId }) => {
const hexChainId = toHex(chainId);
try {
coreProviderMethods.switchChain(provider, hexChainId).then(() => {
return chainId;
});
}
catch (error) {
const { code } = error;
if (code === ProviderRpcErrorCode.CHAIN_NOT_ADDED ||
code === ProviderRpcErrorCode.UNRECOGNIZED_CHAIN_ID) {
if (!chainsList)
throw new Error('Chains list not defined');
// chain has not been added to wallet
const targetChain = chainsList.find(({ id }) => id === hexChainId);
if (!targetChain)
throw new Error('Chain not found in chains list');
coreProviderMethods.updateChain(targetChain);
// add chain to wallet
coreProviderMethods
.addOrSwitchChain(provider, targetChain)
.then((id) => {
return fromHex(id, 'number');
});
}
}
},
onAccountsChanged: (accounts) => {
// Disconnect if there are no accounts
if (accounts.length === 0)
coreProviderMethods.disconnect({ label });
},
onChainChanged: (chainId) => {
coreProviderMethods.switchChain(provider, toHex(chainId));
},
onDisconnect: () => {
wagmiDisconnectWallet(label);
coreProviderMethods.disconnect({ label });
},
emitter: new EventEmitter()
};
}
};
export default wagmiInit;