diff --git a/src/config.ts b/src/config.ts index c13e2df6d..29612e8d4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,6 +7,7 @@ import { Core } from '@self.id/core'; import WalletConnect from "@walletconnect/client"; import config from "@app/config.json"; import { WalletConnectSigner } from "./WalletConnectSigner"; +import { disconnectWallet } from "./session"; declare global { interface Window { @@ -129,6 +130,10 @@ export class Config { ); } + changeNetwork(chainId: number): void { + this.network = ethers.providers.getNetwork(chainId); + } + setSigner(signer: ethers.Signer & TypedDataSigner | WalletConnectSigner): void { this.signer = signer; } @@ -210,7 +215,7 @@ export class Config { } } -function isMetamaskInstalled(): boolean { +export function isMetamaskInstalled(): boolean { const { ethereum } = window; return Boolean(ethereum && ethereum.isMetaMask); } diff --git a/src/session.ts b/src/session.ts index 765e33854..5e01c0407 100644 --- a/src/session.ts +++ b/src/session.ts @@ -2,9 +2,8 @@ import { get, writable, derived } from "svelte/store"; import type { Readable } from "svelte/store"; import type { BigNumber } from 'ethers'; import type { TransactionReceipt, TransactionResponse } from '@ethersproject/providers'; -import { Config, getConfig } from "@app/config"; +import { Config, getConfig, isMetamaskInstalled } from "@app/config"; import { Unreachable, assert, assertEq } from "@app/error"; -import { formatNetwork } from "@app/utils"; import * as ethers from "ethers"; export enum Connection { @@ -105,12 +104,34 @@ export const loadState = (initial: State): Store => { signer.walletConnect.chainId ); + // Instead of killing the WalletConnect session, we force the UI to change network if (network.chainId !== config.network.chainId) { - config.walletConnect.client.killSession(); - throw new Error( - `Network mismatch. Please switch your wallet to ${formatNetwork(config.network)}.` - ); + config.changeNetwork(network.chainId); } + + config.walletConnect.client.on("session_update", async (error, { params: [{ accounts, chainId }] }: { params: [{ accounts: [string]; chainId: number }] }) => { + if (error) { + throw error; + } + + try { + // We only change accounts if the address has been changed, to avoid unnecessary refreshing. + if (address !== accounts[0]) changeAccounts(accounts[0]); + // Check the current chainId, and request Metamask to change, or reload the window to get the correct chain. + if (chainId !== config.network.chainId) { + if (isMetamaskInstalled()) { + await window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: ethers.utils.hexValue(chainId) }] + }); + } else { + config.changeNetwork(chainId); + window.location.reload(); + } + } + } catch (e) { console.error(e); } + }); + store.set({ connection: Connection.Connected, session }); } catch (e) { console.log("WalletConnect: connection failed."); @@ -245,15 +266,18 @@ window.ethereum?.on('chainChanged', () => { // We disconnect the wallet to avoid out of sync state // between the account address and IDX DIDs disconnectMetamask(); - location.reload(); }); // Updates state when user changes accounts window.ethereum?.on("accountsChanged", async ([address]: string) => { + changeAccounts(address); +}); + +export async function changeAccounts(address: string): Promise { const config = await getConfig(); state.setChangedAccount(address); state.refreshBalance(config); -}); +} state.subscribe(s => { console.log("session.state", s); diff --git a/src/utils.ts b/src/utils.ts index 017cebf50..b708df093 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -107,15 +107,6 @@ export function formatHash(hash: string): string { + hash.substring(hash.length - 4, hash.length); } -export function formatNetwork(input: { name: string }): string { - let name = input.name; - - if (name === "homestead") { - name = "mainnet"; - } - return capitalize(name); -} - export function formatOrg(input: string, config: Config): string { if (isAddress(input)) { return ethers.utils.getAddress(input);