UNPKG

@web3auth/wallet-connect-v2-adapter

Version:
276 lines (271 loc) 10.2 kB
import _objectSpread from '@babel/runtime/helpers/objectSpread2'; import _defineProperty from '@babel/runtime/helpers/defineProperty'; import { getAccountsFromNamespaces, parseAccountId } from '@walletconnect/utils'; import { providerErrors, JRPCEngine, providerFromEngine } from '@web3auth/auth'; import { CHAIN_NAMESPACES, WalletLoginError, log, getChainConfig } from '@web3auth/base'; import { BaseProvider } from '@web3auth/base-provider'; import { createEthMiddleware, createJsonRpcClient, createChainSwitchMiddleware } from '@web3auth/ethereum-provider'; import { createSolanaMiddleware, createJsonRpcClient as createJsonRpcClient$1 } from '@web3auth/solana-provider'; import { switchChain, addChain, getAccounts, getEthProviderHandlers, getSolProviderHandlers } from './walletConnectV2Utils.js'; var _WalletConnectV2Provider; class WalletConnectV2Provider extends BaseProvider { constructor({ clientId, config, state, connector }) { super({ config: { chainConfig: config.chainConfig, skipLookupNetwork: !!config.skipLookupNetwork }, state: _objectSpread(_objectSpread({}, state || {}), {}, { chainId: "loading", accounts: [] }) }); _defineProperty(this, "connector", null); _defineProperty(this, "clientId", void 0); this.connector = connector || null; this.clientId = clientId; } async enable() { if (!this.connector) throw providerErrors.custom({ message: "Connector is not initialized, pass wallet connect connector in constructor", code: 4902 }); await this.setupProvider(this.connector); return this._providerEngineProxy.request({ method: "eth_accounts" }); } async setupProvider(connector) { this.onConnectorStateUpdate(connector); await this.setupEngine(connector); } async switchChain({ chainId }) { if (!this.connector) throw providerErrors.custom({ message: "Connector is not initialized, pass wallet connect connector in constructor", code: 4902 }); const currentChainConfig = this.getChainConfig(chainId); const { chainId: currentChainId } = this.config.chainConfig; const currentNumChainId = parseInt(currentChainId, 16); await switchChain({ connector: this.connector, chainId: currentNumChainId, newChainId: chainId }); this.configure({ chainConfig: currentChainConfig }); await this.setupEngine(this.connector); this.lookupNetwork(this.connector); } async addChain(chainConfig) { const { chainId: currentChainId } = this.config.chainConfig; const numChainId = parseInt(currentChainId, 16); await addChain({ connector: this.connector, chainId: numChainId, chainConfig: { chainId: chainConfig.chainId, chainName: chainConfig.displayName, nativeCurrency: { name: chainConfig.tickerName, symbol: chainConfig.ticker.toLocaleUpperCase(), decimals: chainConfig.decimals || 18 }, rpcUrls: [chainConfig.rpcTarget], blockExplorerUrls: [chainConfig.blockExplorerUrl], iconUrls: [chainConfig.logo] } }); super.addChain(chainConfig); } // no need to implement this method in wallet connect v2. async lookupNetwork(_) { const newChainId = this.config.chainConfig.chainId; this.update({ chainId: newChainId }); this.emit("chainChanged", newChainId); this.emit("connect", { chainId: newChainId }); return this.config.chainConfig.chainId; } async setupEngine(connector) { if (this.config.chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) { return this.setupEthEngine(connector); } else if (this.config.chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) { return this.setupSolEngine(connector); } throw new Error(`Unsupported chainNamespace: ${this.config.chainConfig.chainNamespace}`); } async setupEthEngine(connector) { const { chainId } = this.config.chainConfig; const numChainId = parseInt(chainId, 16); const providerHandlers = getEthProviderHandlers({ connector, chainId: numChainId }); const jrpcRes = await getAccounts(connector); this.update({ accounts: jrpcRes || [] }); const ethMiddleware = createEthMiddleware(providerHandlers); const chainSwitchMiddleware = this.getEthChainSwitchMiddleware(); const engine = new JRPCEngine(); const { networkMiddleware } = createJsonRpcClient(this.config.chainConfig); engine.push(ethMiddleware); engine.push(chainSwitchMiddleware); engine.push(networkMiddleware); const provider = providerFromEngine(engine); this.updateProviderEngineProxy(provider); } async setupSolEngine(connector) { const { chainId } = this.config.chainConfig; const providerHandlers = getSolProviderHandlers({ connector, chainId }); const jrpcRes = await getAccounts(connector); this.update({ accounts: jrpcRes || [] }); const solMiddleware = createSolanaMiddleware(providerHandlers); const engine = new JRPCEngine(); const { networkMiddleware } = createJsonRpcClient$1(this.config.chainConfig); engine.push(solMiddleware); engine.push(networkMiddleware); const provider = providerFromEngine(engine); this.updateProviderEngineProxy(provider); } getEthChainSwitchMiddleware() { const chainSwitchHandlers = { addChain: async params => { const { chainId, chainName, rpcUrls, blockExplorerUrls, nativeCurrency, iconUrls } = params; this.addChain({ chainNamespace: CHAIN_NAMESPACES.EIP155, chainId, ticker: (nativeCurrency === null || nativeCurrency === void 0 ? void 0 : nativeCurrency.symbol) || "ETH", tickerName: (nativeCurrency === null || nativeCurrency === void 0 ? void 0 : nativeCurrency.name) || "Ether", displayName: chainName, rpcTarget: rpcUrls[0], blockExplorerUrl: (blockExplorerUrls === null || blockExplorerUrls === void 0 ? void 0 : blockExplorerUrls[0]) || "", decimals: (nativeCurrency === null || nativeCurrency === void 0 ? void 0 : nativeCurrency.decimals) || 18, logo: (iconUrls === null || iconUrls === void 0 ? void 0 : iconUrls[0]) || "https://images.toruswallet.io/eth.svg" }); }, switchChain: async params => { const { chainId } = params; await this.switchChain({ chainId }); } }; const chainSwitchMiddleware = createChainSwitchMiddleware(chainSwitchHandlers); return chainSwitchMiddleware; } connectedTopic() { var _this$connector; if (!this.connector) throw WalletLoginError.notConnectedError("Wallet connect connector is not connected"); if ((_this$connector = this.connector) !== null && _this$connector !== void 0 && (_this$connector = _this$connector.session) !== null && _this$connector !== void 0 && _this$connector.length) { var _this$connector$sessi; // currently we are supporting only 1 active session const lastKeyIndex = this.connector.session.keys.length - 1; return (_this$connector$sessi = this.connector.session.get(this.connector.session.keys[lastKeyIndex])) === null || _this$connector$sessi === void 0 ? void 0 : _this$connector$sessi.topic; } return undefined; } checkIfAccountAllowed(address) { if (!this.connector || !this.connectedTopic()) return false; const sessionData = this.connector.session.get(this.connectedTopic()); const allAccounts = getAccountsFromNamespaces(sessionData.namespaces); let accountAllowed = false; for (const account of allAccounts) { var _parsedAccount$addres; const parsedAccount = parseAccountId(account); if (((_parsedAccount$addres = parsedAccount.address) === null || _parsedAccount$addres === void 0 ? void 0 : _parsedAccount$addres.toLowerCase()) === (address === null || address === void 0 ? void 0 : address.toLowerCase())) { accountAllowed = true; break; } } return accountAllowed; } async onConnectorStateUpdate(connector) { connector.events.on("session_event", async payload => { log.debug("session_event data", payload); if (!this.provider) throw WalletLoginError.notConnectedError("Wallet connect connector is not connected"); const { event } = payload.params; const { name, data } = event || {}; // Check if accounts changed and trigger event if (name === "accountsChanged" && data !== null && data !== void 0 && data.length && this.state.accounts[0] !== data[0] && this.checkIfAccountAllowed(data[0])) { this.update({ accounts: data }); this.emit("accountsChanged", data); } if (event.name === "chainChanged") { if (!data) return; const connectedChainId = data; const connectedHexChainId = `0x${connectedChainId.toString(16)}`; // Check if chainId changed and trigger event if (connectedHexChainId && this.state.chainId !== connectedHexChainId) { const maybeConfig = getChainConfig(CHAIN_NAMESPACES.EIP155, connectedHexChainId, this.clientId); // Handle rpcUrl update this.configure({ chainConfig: _objectSpread(_objectSpread({}, maybeConfig), {}, { chainId: connectedHexChainId, chainNamespace: CHAIN_NAMESPACES.EIP155 }) }); await this.setupEngine(connector); } } }); } } _WalletConnectV2Provider = WalletConnectV2Provider; _defineProperty(WalletConnectV2Provider, "getProviderInstance", async params => { const providerFactory = new _WalletConnectV2Provider({ clientId: params.clientId, config: { chainConfig: params.chainConfig, skipLookupNetwork: params.skipLookupNetwork } }); await providerFactory.setupProvider(params.connector); return providerFactory; }); export { WalletConnectV2Provider };