@web3auth/wallet-connect-v2-adapter
Version:
wallet connect v2 adapter for web3auth
278 lines (272 loc) • 10.3 kB
JavaScript
'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;