Skip to content

Commit 968ad57

Browse files
Fix multiple wallet connect issues
1 parent 72b801c commit 968ad57

File tree

5 files changed

+81
-43
lines changed

5 files changed

+81
-43
lines changed

examples/vue-app/vue.config.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ module.exports = {
2929
},
3030
chainWebpack: (config) => {
3131
if (process.env.NODE_ENV !== "production") {
32-
config.module.rule("sourcemap").test(/\.js$/).enforce("pre").use("source-map-loader").loader("source-map-loader").end();
32+
config.module
33+
.rule("sourcemap")
34+
.test(/\.${js,ts}$/)
35+
.enforce("pre")
36+
.use("source-map-loader")
37+
.loader("source-map-loader")
38+
.end();
3339
}
3440
const svgRule = config.module.rule("svg");
3541

packages/adapters/wallet-connect-v1-adapter/src/walletConnectV1adapter.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
CONNECTED_EVENT_DATA,
1414
CustomChainConfig,
1515
getChainConfig,
16-
isHexStrict,
1716
log,
1817
SafeEventEmitterProvider,
1918
UserInfo,
@@ -77,13 +76,13 @@ class WalletConnectV1Adapter extends BaseAdapter<void> {
7776
}
7877
// Create a connector
7978
this.connector = this.getWalletConnectInstance();
80-
this.wcProvider = new WalletConnectProvider({ config: { chainConfig: this.chainConfig as CustomChainConfig } });
79+
this.wcProvider = new WalletConnectProvider({ config: { chainConfig: this.chainConfig as CustomChainConfig }, connector: this.connector });
8180

8281
this.emit(ADAPTER_EVENTS.READY, WALLET_ADAPTERS.WALLET_CONNECT_V1);
8382
this.status = ADAPTER_STATUS.READY;
8483
if (this.connector.connected) {
8584
this.rehydrated = true;
86-
await this.onConnectHandler({ accounts: this.connector.accounts, chainId: this.connector.chainId.toString() });
85+
await this.onConnectHandler({ accounts: this.connector.accounts, chainId: this.connector.chainId });
8786
}
8887
}
8988

@@ -92,7 +91,7 @@ class WalletConnectV1Adapter extends BaseAdapter<void> {
9291
if (!this.connector) throw WalletInitializationError.notReady("Wallet adapter is not ready yet");
9392

9493
if (this.connected) {
95-
await this.onConnectHandler({ accounts: this.connector.accounts, chainId: this.connector.chainId.toString() });
94+
await this.onConnectHandler({ accounts: this.connector.accounts, chainId: this.connector.chainId });
9695
return this.provider;
9796
}
9897

@@ -116,7 +115,7 @@ class WalletConnectV1Adapter extends BaseAdapter<void> {
116115
});
117116
try {
118117
// Subscribe to session connection
119-
this.connector.on("connect", async (error: Error | null, payload: { params: { accounts: string[]; chainId: string }[] }) => {
118+
this.connector.on("connect", async (error: Error | null, payload: { params: { accounts: string[]; chainId: number }[] }) => {
120119
if (error) {
121120
this.emit(ADAPTER_EVENTS.ERRORED, error);
122121
}
@@ -194,25 +193,32 @@ class WalletConnectV1Adapter extends BaseAdapter<void> {
194193
});
195194
}
196195

197-
private async onConnectHandler(params: { accounts: string[]; chainId: string }) {
196+
private async onConnectHandler(params: { accounts: string[]; chainId: number }) {
198197
if (!this.connector || !this.wcProvider) throw WalletInitializationError.notReady("Wallet adapter is not ready yet");
199198
if (!this.chainConfig) throw WalletInitializationError.invalidParams("Chain config is not set");
200199

201200
const { chainId } = params;
202-
log.debug("connected chainId", chainId);
203-
const connectedChainId = parseInt(chainId, isHexStrict(chainId) ? 16 : 10);
204-
if (connectedChainId !== parseInt(this.chainConfig.chainId, 16)) {
205-
// we need to create a new session since old session is already used and
206-
// user needs to login again with correct chain with new qr code.
207-
await this.createNewSession({ forceNewSession: true });
208-
this.emit(
209-
ADAPTER_EVENTS.ERRORED,
210-
WalletInitializationError.fromCode(
211-
5000,
212-
`Not connected to correct chainId. Expected: ${this.chainConfig.chainId}, Current: ${connectedChainId}, Please switch to correct chain from wallet`
213-
)
214-
);
215-
return;
201+
log.debug("connected chainId in hex", chainId);
202+
if (chainId !== parseInt(this.chainConfig.chainId, 16)) {
203+
try {
204+
await this.wcProvider.switchChain({ chainId: this.chainConfig.chainId, lookup: false });
205+
} catch (error) {
206+
log.error(error);
207+
// we need to create a new session since old session is already used and
208+
// user needs to login again with correct chain with new qr code.
209+
await this.createNewSession({ forceNewSession: true });
210+
const connectedChainConfig = getChainConfig(CHAIN_NAMESPACES.EIP155, chainId);
211+
this.emit(
212+
ADAPTER_EVENTS.ERRORED,
213+
WalletInitializationError.fromCode(
214+
5000,
215+
`Not connected to correct network. Expected: ${this.chainConfig.displayName}, Current: ${
216+
connectedChainConfig?.displayName || chainId
217+
}, Please switch to correct network from wallet`
218+
)
219+
);
220+
return;
221+
}
216222
}
217223
await this.wcProvider.setupProvider(this.connector);
218224
this.subscribeEvents(this.connector);

packages/providers/ethereum-provider/src/providers/injectedProviders/WalletConnectProvider.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { providerFromEngine } from "@toruslabs/base-controllers";
22
import { JRPCEngine } from "@toruslabs/openlogin-jrpc";
33
import type { IConnector } from "@walletconnect/types";
4-
import { CHAIN_NAMESPACES, CustomChainConfig, isHexStrict, WalletInitializationError, WalletLoginError } from "@web3auth/base";
4+
import { CHAIN_NAMESPACES, CustomChainConfig, getChainConfig, isHexStrict, log, WalletInitializationError, WalletLoginError } from "@web3auth/base";
55
import { BaseProvider, BaseProviderConfig, BaseProviderState } from "@web3auth/base-provider";
66
import { ethErrors } from "eth-rpc-errors";
77

@@ -49,23 +49,39 @@ export class WalletConnectProvider extends BaseProvider<BaseProviderConfig, Wall
4949
await this.setupEngine(connector);
5050
}
5151

52-
public async switchChain({ chainId }: { chainId: string }): Promise<void> {
52+
public async switchChain({ chainId, lookup = true }: { chainId: string; lookup?: boolean }): Promise<void> {
53+
if (!this.connector)
54+
throw ethErrors.provider.custom({ message: "Connector is not initialized, pass wallet connect connector in constructor", code: 4902 });
5355
const currentChainConfig = this.getChainConfig(chainId);
54-
const { ticker, tickerName, rpcTarget } = currentChainConfig;
56+
const { rpcTarget, displayName } = currentChainConfig;
5557
this.update({
5658
chainId: "loading",
5759
});
58-
await this.connector.updateChain({
59-
chainId: Number.parseInt(chainId, 16),
60-
nativeCurrency: {
61-
name: tickerName,
62-
symbol: ticker,
63-
},
64-
networkId: Number.parseInt(chainId, 10),
65-
rpcUrl: rpcTarget,
66-
});
60+
try {
61+
await this.connector.sendCustomRequest({
62+
method: "wallet_addEthereumChain",
63+
params: [{ chainId, chainName: displayName, rpcUrls: [rpcTarget] }],
64+
});
65+
} catch (error) {
66+
log.error(error);
67+
}
68+
69+
try {
70+
await this.connector.sendCustomRequest({
71+
method: "wallet_switchEthereumChain",
72+
params: [{ chainId }],
73+
});
74+
} catch (error) {
75+
log.error(error);
76+
// ignore this error because metamask & others return provider.result as null
77+
// wallet connect thinks this is wrong
78+
if (error.message !== "JSON RPC response format is invalid") {
79+
throw error;
80+
}
81+
}
82+
6783
this.configure({ chainConfig: currentChainConfig });
68-
await this.lookupNetwork(this.connector);
84+
if (lookup) await this.lookupNetwork(this.connector);
6985
}
7086

7187
protected async lookupNetwork(connector: IConnector): Promise<string> {
@@ -104,7 +120,7 @@ export class WalletConnectProvider extends BaseProvider<BaseProviderConfig, Wall
104120
this.provider.emit("error", error);
105121
return;
106122
}
107-
const { accounts, chainId: connectedChainId, rpcUrl } = payload;
123+
const { accounts, chainId: connectedChainId, rpcUrl }: { accounts?: string[]; chainId?: number; rpcUrl?: string } = payload.params[0];
108124
// Check if accounts changed and trigger event
109125
if (accounts?.length && this.state.accounts[0] !== accounts[0]) {
110126
this.update({
@@ -113,12 +129,13 @@ export class WalletConnectProvider extends BaseProvider<BaseProviderConfig, Wall
113129
// await this.setupEngine(connector);
114130
this.provider.emit("accountsChanged", accounts);
115131
}
116-
const connectedHexChainId = isHexStrict(connectedChainId) ? connectedChainId : `0x${connectedChainId.toString(16)}`;
132+
const connectedHexChainId = `0x${connectedChainId.toString(16)}`;
117133
// Check if chainId changed and trigger event
118134
if (connectedChainId && this.state.chainId !== connectedHexChainId) {
135+
const maybeConfig = getChainConfig(CHAIN_NAMESPACES.EIP155, connectedChainId) || {};
119136
// Handle rpcUrl update
120137
this.configure({
121-
chainConfig: { ...this.config.chainConfig, chainId: connectedHexChainId, rpcTarget: rpcUrl },
138+
chainConfig: { ...maybeConfig, chainId: connectedHexChainId, rpcTarget: rpcUrl, chainNamespace: CHAIN_NAMESPACES.EIP155 },
122139
});
123140
await this.setupEngine(connector);
124141
}

packages/ui/src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface UIConfig {
77
adapterListener: SafeEventEmitter;
88
theme?: "light" | "dark";
99
loginMethodsOrder?: string[];
10+
displayErrorsOnModal?: boolean;
1011
}
1112

1213
export const LOGIN_MODAL_EVENTS = {

packages/ui/src/loginModal.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,16 @@ export default class LoginModal extends SafeEventEmitter {
3939

4040
private stateEmitter: SafeEventEmitter;
4141

42-
constructor({ appLogo, version, adapterListener, theme = "light" }: UIConfig) {
42+
private displayErrorsOnModal = true;
43+
44+
constructor({ appLogo, version, adapterListener, theme = "light", displayErrorsOnModal = true }: UIConfig) {
4345
super();
4446
this.appLogo = appLogo || DEFAULT_LOGO_URL;
4547
this.version = version;
4648
this.isDark = theme === "dark";
4749
this.wrapper = createWrapper();
4850
this.stateEmitter = new SafeEventEmitter();
51+
this.displayErrorsOnModal = displayErrorsOnModal;
4952
this.subscribeCoreEvents(adapterListener);
5053
}
5154

@@ -188,11 +191,16 @@ export default class LoginModal extends SafeEventEmitter {
188191
listener.on(ADAPTER_EVENTS.ERRORED, (error: Web3AuthError) => {
189192
log.error("error", error, error.message);
190193
if (error.code === 5000) {
191-
this.setState({
192-
modalVisibility: true,
193-
postLoadingMessage: error.message || "Something went wrong!",
194-
status: MODAL_STATUS.ERRORED,
195-
});
194+
if (this.displayErrorsOnModal)
195+
this.setState({
196+
modalVisibility: true,
197+
postLoadingMessage: error.message || "Something went wrong!",
198+
status: MODAL_STATUS.ERRORED,
199+
});
200+
else
201+
this.setState({
202+
modalVisibility: false,
203+
});
196204
} else {
197205
this.setState({
198206
modalVisibility: true,

0 commit comments

Comments
 (0)