UNPKG

@web3auth/wallet-connect-v2-adapter

Version:
278 lines (272 loc) 10.3 kB
'use strict'; var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var _defineProperty = require('@babel/runtime/helpers/defineProperty'); var utils = require('@walletconnect/utils'); var auth = require('@web3auth/auth'); var base = require('@web3auth/base'); var baseProvider = require('@web3auth/base-provider'); var ethereumProvider = require('@web3auth/ethereum-provider'); var solanaProvider = require('@web3auth/solana-provider'); var walletConnectV2Utils = require('./walletConnectV2Utils.js'); var _WalletConnectV2Provider; class WalletConnectV2Provider extends baseProvider.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 auth.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 auth.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 walletConnectV2Utils.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 walletConnectV2Utils.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 === base.CHAIN_NAMESPACES.EIP155) { return this.setupEthEngine(connector); } else if (this.config.chainConfig.chainNamespace === base.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 = walletConnectV2Utils.getEthProviderHandlers({ connector, chainId: numChainId }); const jrpcRes = await walletConnectV2Utils.getAccounts(connector); this.update({ accounts: jrpcRes || [] }); const ethMiddleware = ethereumProvider.createEthMiddleware(providerHandlers); const chainSwitchMiddleware = this.getEthChainSwitchMiddleware(); const engine = new auth.JRPCEngine(); const { networkMiddleware } = ethereumProvider.createJsonRpcClient(this.config.chainConfig); engine.push(ethMiddleware); engine.push(chainSwitchMiddleware); engine.push(networkMiddleware); const provider = auth.providerFromEngine(engine); this.updateProviderEngineProxy(provider); } async setupSolEngine(connector) { const { chainId } = this.config.chainConfig; const providerHandlers = walletConnectV2Utils.getSolProviderHandlers({ connector, chainId }); const jrpcRes = await walletConnectV2Utils.getAccounts(connector); this.update({ accounts: jrpcRes || [] }); const solMiddleware = solanaProvider.createSolanaMiddleware(providerHandlers); const engine = new auth.JRPCEngine(); const { networkMiddleware } = solanaProvider.createJsonRpcClient(this.config.chainConfig); engine.push(solMiddleware); engine.push(networkMiddleware); const provider = auth.providerFromEngine(engine); this.updateProviderEngineProxy(provider); } getEthChainSwitchMiddleware() { const chainSwitchHandlers = { addChain: async params => { const { chainId, chainName, rpcUrls, blockExplorerUrls, nativeCurrency, iconUrls } = params; this.addChain({ chainNamespace: base.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 = ethereumProvider.createChainSwitchMiddleware(chainSwitchHandlers); return chainSwitchMiddleware; } connectedTopic() { var _this$connector; if (!this.connector) throw base.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 = utils.getAccountsFromNamespaces(sessionData.namespaces); let accountAllowed = false; for (const account of allAccounts) { var _parsedAccount$addres; const parsedAccount = utils.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 => { base.log.debug("session_event data", payload); if (!this.provider) throw base.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 = base.getChainConfig(base.CHAIN_NAMESPACES.EIP155, connectedHexChainId, this.clientId); // Handle rpcUrl update this.configure({ chainConfig: _objectSpread(_objectSpread({}, maybeConfig), {}, { chainId: connectedHexChainId, chainNamespace: base.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; }); exports.WalletConnectV2Provider = WalletConnectV2Provider;