@dynamic-labs/ethereum 2.0.0-alpha.3 → 2.0.0-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/package.json +11 -12
  3. package/src/EthWalletConnector.cjs +13 -21
  4. package/src/EthWalletConnector.d.ts +16 -14
  5. package/src/EthWalletConnector.js +15 -23
  6. package/src/coinbase/client/client.cjs +14 -14
  7. package/src/coinbase/client/client.d.ts +5 -4
  8. package/src/coinbase/client/client.js +13 -13
  9. package/src/coinbase/client/types.d.ts +6 -3
  10. package/src/coinbase/coinbase.cjs +31 -15
  11. package/src/coinbase/coinbase.d.ts +20 -18
  12. package/src/coinbase/coinbase.js +32 -16
  13. package/src/ethProviderHelper.cjs +11 -6
  14. package/src/ethProviderHelper.d.ts +6 -4
  15. package/src/ethProviderHelper.js +11 -6
  16. package/src/index.cjs +9 -13
  17. package/src/index.d.ts +2 -0
  18. package/src/index.js +8 -13
  19. package/src/injected/ExodusEvm.cjs +1 -0
  20. package/src/injected/ExodusEvm.d.ts +1 -0
  21. package/src/injected/ExodusEvm.js +1 -0
  22. package/src/injected/InjectedWalletBase.cjs +28 -19
  23. package/src/injected/InjectedWalletBase.d.ts +2 -2
  24. package/src/injected/InjectedWalletBase.js +28 -19
  25. package/src/injected/PhantomEvm.cjs +4 -3
  26. package/src/injected/PhantomEvm.d.ts +2 -1
  27. package/src/injected/PhantomEvm.js +4 -3
  28. package/src/injected/Zerion.cjs +38 -0
  29. package/src/injected/Zerion.d.ts +10 -0
  30. package/src/injected/Zerion.js +34 -0
  31. package/src/injected/fetchInjectedWalletConnectors.cjs +25 -0
  32. package/src/injected/fetchInjectedWalletConnectors.d.ts +0 -1
  33. package/src/injected/fetchInjectedWalletConnectors.js +25 -0
  34. package/src/utils/index.d.ts +1 -0
  35. package/src/utils/isEthWalletConnector/index.d.ts +1 -0
  36. package/src/utils/isEthWalletConnector/isEthWalletConnector.cjs +7 -0
  37. package/src/utils/isEthWalletConnector/isEthWalletConnector.d.ts +3 -0
  38. package/src/utils/isEthWalletConnector/isEthWalletConnector.js +3 -0
  39. package/src/walletConnect/fetchWalletConnectWallets.cjs +14 -33
  40. package/src/walletConnect/fetchWalletConnectWallets.d.ts +2 -5
  41. package/src/walletConnect/fetchWalletConnectWallets.js +14 -33
  42. package/src/walletConnect/index.d.ts +0 -1
  43. package/src/walletConnect/walletConnect.cjs +452 -78
  44. package/src/walletConnect/walletConnect.d.ts +313 -31
  45. package/src/walletConnect/walletConnect.js +453 -80
  46. package/src/walletConnect/client/client.cjs +0 -201
  47. package/src/walletConnect/client/client.d.ts +0 -17
  48. package/src/walletConnect/client/client.js +0 -187
  49. package/src/walletConnect/client/index.d.ts +0 -1
  50. package/src/walletConnect/client/types.d.ts +0 -4
  51. package/src/walletConnect/walletConnectV2.cjs +0 -475
  52. package/src/walletConnect/walletConnectV2.d.ts +0 -333
  53. package/src/walletConnect/walletConnectV2.js +0 -466
@@ -1,146 +1,519 @@
1
- import { __rest, __awaiter } from '../../_virtual/_tslib.js';
2
- import WalletConnectProvider from '@walletconnect/ethereum-provider';
1
+ import { __awaiter } from '../../_virtual/_tslib.js';
2
+ import EthereumProvider from '@walletconnect/ethereum-provider';
3
+ import EventEmitter from 'eventemitter3';
3
4
  import { createWalletClient, custom } from 'viem';
4
- import { getDeepLink } from '@dynamic-labs/wallet-connector-core';
5
+ import { logger, performPlatformSpecificConnectionMethod, getDeepLink } from '@dynamic-labs/wallet-connector-core';
5
6
  import { getWalletBookWallet } from '@dynamic-labs/wallet-book';
6
- import { isMobile, DynamicError } from '@dynamic-labs/utils';
7
+ import { DynamicError, sleep, isMobile } from '@dynamic-labs/utils';
8
+ import { chainsMap } from '@dynamic-labs/viem-utils';
7
9
  import { EthWalletConnector } from '../EthWalletConnector.js';
8
- import { INFURA_ID } from '../constants.js';
9
- import { initClient, setupWalletConnectEventListeners, teardownWalletConnectEventListeners, fetchWalletConnectEVMPublicAddress, signWalletConnectPersonalMessage, killWalletConnectSession } from './client/client.js';
10
+ import { parseIntSafe } from '../utils/parseIntSafe.js';
10
11
 
12
+ const activeAccountKey = (walletName) => `dynamic-wc2-active-account-${walletName}`;
13
+ const sessionTopicKey = (walletName) => `dynamic-wc2-session-topic-${walletName}`;
14
+ const swicthedNetworkKey = (walletName) => `dynamic-wc2-switched-network-${walletName}`;
15
+ const currentChainKey = (walletName) => `dynamic-wc2-current-chain-${walletName}`;
16
+ const ee = new EventEmitter();
11
17
  class WalletConnect extends EthWalletConnector {
12
- constructor(_a) {
13
- var { walletConnectV1Bridge, walletName } = _a, props = __rest(_a, ["walletConnectV1Bridge", "walletName"]);
14
- super(props);
18
+ constructor(opts) {
19
+ var _a;
20
+ super(opts);
15
21
  this.supportedChains = ['EVM', 'ETH'];
16
22
  this.connectedChain = 'EVM';
17
- this.bridge = 'https://bridge.walletconnect.org';
23
+ this.isInitialized = false;
18
24
  this.canConnectViaQrCode = true;
19
25
  this.isWalletConnect = true;
20
- this.switchNetworkOnlyFromWallet = false;
21
- this.name = walletName;
22
- if (walletConnectV1Bridge) {
23
- this.bridge = walletConnectV1Bridge;
26
+ this.preferredChains = [];
27
+ // When trying to switch network for MetaMask, the switch promise gets stuck
28
+ // if the switch got trigged once already, so we need to keep track of that
29
+ this._hasSwitchedNetwork = false;
30
+ this.sessionEventHandler = () => { };
31
+ this.sessionDeleteHandler = () => { };
32
+ this.name = opts.walletName;
33
+ this.projectId = opts.projectId;
34
+ this.deepLinkPreference = opts.deepLinkPreference || 'native';
35
+ this.preferredChains = opts.walletConnectPreferredChains || [];
36
+ this.hasSwitchedNetwork =
37
+ (_a = Boolean(localStorage.getItem(this.swicthedNetworkKey))) !== null && _a !== void 0 ? _a : false;
38
+ const lsCurrentChain = localStorage.getItem(this.currentChainKey);
39
+ this.currentChainId = lsCurrentChain
40
+ ? parseIntSafe(lsCurrentChain)
41
+ : undefined;
42
+ }
43
+ getMappedChains() {
44
+ return (this.evmNetworks
45
+ // Filters out palm that crashes Trust Wallet
46
+ .filter((network) => network.chainId !== 11297108109)
47
+ .map((network) => `eip155:${network.chainId}`));
48
+ }
49
+ getMappedChainsByPreferredOrder() {
50
+ const allChains = this.getMappedChains();
51
+ const reorderedChains = this.preferredChains.filter((chain) => allChains.includes(chain));
52
+ const remainingChains = allChains.filter((chain) => !this.preferredChains.includes(chain));
53
+ return [...reorderedChains, ...remainingChains].map((chain) => Number(chain.split(':')[1]));
54
+ }
55
+ initConnection() {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const { provider } = WalletConnect;
58
+ if (!provider) {
59
+ throw new DynamicError('No provider found (init connection)');
60
+ }
61
+ // this means there is already a connection in progress, so don't call connect again
62
+ if (provider === null || provider === void 0 ? void 0 : provider.signer.uri) {
63
+ return;
64
+ }
65
+ provider.connect().catch((e) => {
66
+ logger.error(e);
67
+ ee.emit('walletconnect_connection_failed', e);
68
+ });
69
+ });
70
+ }
71
+ createProvider() {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ return EthereumProvider.init({
74
+ events: ['chainChanged', 'accountsChanged'],
75
+ methods: [],
76
+ optionalChains: this.getMappedChainsByPreferredOrder(),
77
+ optionalMethods: [
78
+ 'eth_chainId',
79
+ 'eth_signTypedData',
80
+ 'eth_signTransaction',
81
+ 'eth_sign',
82
+ 'personal_sign',
83
+ 'eth_sendTransaction',
84
+ 'eth_signTypedData_v4',
85
+ 'wallet_switchEthereumChain',
86
+ 'wallet_addEthereumChain',
87
+ ],
88
+ projectId: this.projectId,
89
+ rpcMap: this.evmNetworkRpcMap(),
90
+ showQrModal: false,
91
+ });
92
+ });
93
+ }
94
+ getWalletClientFromInitializedProvider() {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ const walletConnect = this.createProvider();
97
+ const walletClient = createWalletClient({
98
+ account: this.getActiveAccount(),
99
+ transport: custom(yield walletConnect),
100
+ });
101
+ return walletClient;
102
+ });
103
+ }
104
+ createInitProviderPromise() {
105
+ return __awaiter(this, void 0, void 0, function* () {
106
+ WalletConnect.provider = yield this.createProvider();
107
+ this.teardownEventListeners();
108
+ this.setupEventListeners();
109
+ });
110
+ }
111
+ // We need to add a gate to this method since we will be calling it asynchronously
112
+ // from different places (such as setShowAuthFlow), which means there's a chance for
113
+ // a race condition to happen where createInitProviderPromise is called multiple times
114
+ initProvider() {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ const { provider } = WalletConnect;
117
+ if (!provider) {
118
+ if (this.initializePromise === undefined) {
119
+ this.initializePromise = this.createInitProviderPromise();
120
+ }
121
+ yield this.initializePromise;
122
+ }
123
+ });
124
+ }
125
+ refreshSession() {
126
+ var _a, _b, _c, _d, _e;
127
+ if ((_b = (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.session) === null || _b === void 0 ? void 0 : _b.topic) {
128
+ if (localStorage.getItem(this.sessionTopicKey) ===
129
+ ((_d = (_c = WalletConnect.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
130
+ this.session = WalletConnect.provider.session;
131
+ this.setActiveAccount(((_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined));
132
+ }
24
133
  }
25
- this.deepLinkPreference = props.deepLinkPreference || 'native';
26
134
  }
27
- getClient() {
28
- if (this.client) {
29
- return this.client;
135
+ init() {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ yield this.initProvider();
138
+ yield this.initConnection();
139
+ this.isInitialized = true;
140
+ });
141
+ }
142
+ get sessionTopicKey() {
143
+ return sessionTopicKey(this.key);
144
+ }
145
+ get activeAccountKey() {
146
+ return activeAccountKey(this.key);
147
+ }
148
+ get swicthedNetworkKey() {
149
+ return swicthedNetworkKey(this.key);
150
+ }
151
+ get currentChainKey() {
152
+ return currentChainKey(this.key);
153
+ }
154
+ set currentChainId(value) {
155
+ this._currentChainId = value;
156
+ if (value) {
157
+ localStorage.setItem(this.currentChainKey, value.toString());
158
+ }
159
+ else {
160
+ localStorage.removeItem(this.currentChainKey);
30
161
  }
31
- this.client = initClient(this.key, this.bridge, this.clientOptions);
32
- return this.client;
33
162
  }
34
- supportsNetworkSwitching() {
35
- if (this.connectedChain === 'EVM') {
36
- return true;
163
+ get currentChainId() {
164
+ return this._currentChainId;
165
+ }
166
+ set hasSwitchedNetwork(value) {
167
+ this._hasSwitchedNetwork = value;
168
+ if (value) {
169
+ localStorage.setItem(this.swicthedNetworkKey, value.toString());
37
170
  }
38
171
  else {
39
- const client = this.getClient();
40
- return Boolean(client === null || client === void 0 ? void 0 : client.chainId);
172
+ localStorage.removeItem(this.swicthedNetworkKey);
41
173
  }
42
174
  }
175
+ get hasSwitchedNetwork() {
176
+ return this._hasSwitchedNetwork;
177
+ }
178
+ supportsNetworkSwitching() {
179
+ return true;
180
+ }
43
181
  setupEventListeners() {
44
- setupWalletConnectEventListeners(this, this.getClient());
182
+ if (!WalletConnect.provider) {
183
+ return;
184
+ }
185
+ this.sessionEventHandler = ({ params, }) => {
186
+ logger.debug('session_event was called', { params });
187
+ if (!params || !params.event) {
188
+ logger.debug('session_event was called without params or params.event');
189
+ return;
190
+ }
191
+ const { name, data } = params.event;
192
+ if (name === 'chainChanged') {
193
+ const chainId = parseIntSafe(data);
194
+ if (chainId === this.currentChainId) {
195
+ logger.debug(`ignoring chainChanged event with same chain id as current chain id: ${chainId}`);
196
+ return;
197
+ }
198
+ if (chainId === undefined) {
199
+ logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
200
+ return;
201
+ }
202
+ this.currentChainId = chainId;
203
+ this.emit('chainChange', { chain: String(chainId) });
204
+ this.hasSwitchedNetwork = true;
205
+ // When a user switches network from their wallet, we need the provider to change network
206
+ // such that any future calls to `getNetwork` will return the correct network
207
+ this.switchNetwork({ networkChainId: chainId });
208
+ }
209
+ else if (name === 'accountsChanged') {
210
+ if (!Array.isArray(data)) {
211
+ logger.debug(`received unexpected data for accountsChanged: ${data} with type ${typeof data}}`);
212
+ return;
213
+ }
214
+ // eslint-disable-next-line prefer-destructuring
215
+ const account = data[0].split(':')[2];
216
+ this.setWCActiveAccount(account);
217
+ }
218
+ };
219
+ WalletConnect.provider.on('session_event', this.sessionEventHandler);
220
+ this.sessionDeleteHandler = () => __awaiter(this, void 0, void 0, function* () {
221
+ this.endSession();
222
+ this.emit('disconnect');
223
+ });
224
+ WalletConnect.provider.on('session_delete', this.sessionDeleteHandler);
45
225
  }
46
226
  teardownEventListeners() {
47
- teardownWalletConnectEventListeners(this.getClient());
48
- }
49
- getWalletClient() {
50
- const client = this.getClient();
51
- return client
52
- ? createWalletClient({
53
- transport: custom(new WalletConnectProvider({
54
- connector: client,
55
- infuraId: INFURA_ID,
56
- rpc: this.evmNetworkRpcMap(),
57
- })),
58
- })
59
- : undefined;
227
+ if (!WalletConnect.provider) {
228
+ return;
229
+ }
230
+ WalletConnect.provider.off('session_event', this.sessionEventHandler);
231
+ WalletConnect.provider.off('session_delete', this.sessionDeleteHandler);
232
+ }
233
+ getWalletClient(chainId) {
234
+ if (!WalletConnect.provider) {
235
+ return;
236
+ }
237
+ return createWalletClient({
238
+ account: this.getActiveAccount(),
239
+ chain: chainsMap[chainId !== null && chainId !== void 0 ? chainId : String(this.currentChainId)],
240
+ transport: custom(WalletConnect.provider),
241
+ });
60
242
  }
61
- fetchPublicAddress(opts) {
243
+ getAddress(opts) {
244
+ var _a, _b;
62
245
  return __awaiter(this, void 0, void 0, function* () {
63
- return fetchWalletConnectEVMPublicAddress(getWalletBookWallet(this.walletBook, this.key), this.getClient(), this.deepLinkPreference, Object.assign(Object.assign({}, opts), { onConnect: (payload) => {
64
- var _a, _b;
65
- (_a = opts === null || opts === void 0 ? void 0 : opts.onConnect) === null || _a === void 0 ? void 0 : _a.call(opts, payload);
66
- this.connectedChain = payload.params[0].chainId ? 'EVM' : 'SOL';
67
- if ((_b = payload.params[0].accounts) === null || _b === void 0 ? void 0 : _b.length) {
68
- this.emit('accountChange', {
69
- accounts: payload.params[0].accounts,
70
- });
246
+ const activeAccount = this.getActiveAccount();
247
+ if (activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.address) {
248
+ return activeAccount.address;
249
+ }
250
+ if (!WalletConnect.provider || !((_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.signer.uri)) {
251
+ logger.debug('No WC2 provider found, re-initializing...');
252
+ yield this.endSession();
253
+ yield this.init();
254
+ // sleep 1 s to wait for connect call to finish
255
+ // the connect call isn't await-ed because it only resolves once
256
+ // the connection is established, but we need to wait for it to
257
+ // finish setting up the connection URI and making it available
258
+ // on the provider
259
+ yield sleep(1000);
260
+ if (!WalletConnect.provider || !((_b = WalletConnect.provider) === null || _b === void 0 ? void 0 : _b.signer.uri)) {
261
+ logger.debug('No WC2 provider found, escaping and throwing error');
262
+ throw new DynamicError('No provider found');
263
+ }
264
+ }
265
+ const metadata = getWalletBookWallet(this.walletBook, this.key, this.walletFallback);
266
+ performPlatformSpecificConnectionMethod(WalletConnect.provider.signer.uri, metadata, {
267
+ onDesktopUri: opts === null || opts === void 0 ? void 0 : opts.onDesktopUri,
268
+ onDisplayUri: opts === null || opts === void 0 ? void 0 : opts.onDisplayUri,
269
+ }, this.deepLinkPreference);
270
+ return new Promise((resolve, reject) => {
271
+ if (!WalletConnect.provider) {
272
+ reject(new DynamicError('No provider found'));
273
+ return;
274
+ }
275
+ const onFail = () => {
276
+ const error = new DynamicError('Connection rejected. Please try again.');
277
+ error.code = 'connection_rejected';
278
+ if (WalletConnect.provider) {
279
+ WalletConnect.provider.signer.uri = undefined;
280
+ // this is needed for mobile to work when using universal links.
281
+ // if the user cancels the connection, we need to re-initialize the provider
282
+ // so that the async work is done ahead of time, before the user tries to connect again,
283
+ // otherwise they will trigger the iOS bug where they are redirected to the app store
284
+ this.init();
285
+ }
286
+ reject(error);
287
+ // We must clean up the onConnect and onFail listeners
288
+ // whenever the connection attempt either succeeds or fails
289
+ cleanupListeners();
290
+ };
291
+ const onConnect = () => {
292
+ var _a;
293
+ const session = (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.session;
294
+ if (!session) {
295
+ reject(new DynamicError('No session found'));
296
+ return;
71
297
  }
72
- } }));
298
+ this.setSession(session);
299
+ this.setWCActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
300
+ this.getNetwork().then((chainId) => {
301
+ var _a;
302
+ this.currentChainId = chainId;
303
+ resolve((_a = this.getActiveAccount()) === null || _a === void 0 ? void 0 : _a.address);
304
+ });
305
+ // We must clean up the onConnect and onFail listeners
306
+ // whenever the connection attempt either succeeds or fails
307
+ cleanupListeners();
308
+ };
309
+ const cleanupListeners = () => {
310
+ var _a;
311
+ ee.off('walletconnect_connection_failed', onFail);
312
+ (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.off('connect', onConnect);
313
+ };
314
+ ee.on('walletconnect_connection_failed', onFail);
315
+ WalletConnect.provider.on('connect', onConnect);
316
+ });
317
+ });
318
+ }
319
+ /**
320
+ * WalletConnect V2 will fail to send the sign message request if the chainId
321
+ * is not the same as the one in the session. This method will wait for the
322
+ * chainId to change and then retry the sign message request.
323
+ *
324
+ * Otherwise it will just return the result of the sign message request.
325
+ *
326
+ * @param signMessageFn - Function to sign message with provider
327
+ * @param messageToSign - Message to sign
328
+ * @returns
329
+ */
330
+ waitForSignMessage(signMessageFn, messageToSign) {
331
+ return __awaiter(this, void 0, void 0, function* () {
332
+ const raceConditionPromise = new Promise((resolve, reject) => {
333
+ // Create listener for chain change event
334
+ this.on('chainChange', () => resolve({ success: false }));
335
+ signMessageFn(messageToSign)
336
+ .then((result) => resolve({ signedMessage: result, success: true }))
337
+ .catch(reject);
338
+ });
339
+ const signedMessageResult = yield raceConditionPromise;
340
+ if (signedMessageResult.success === false) {
341
+ return signMessageFn(messageToSign);
342
+ }
343
+ return signedMessageResult.signedMessage;
73
344
  });
74
345
  }
75
346
  getDeepLink() {
76
347
  var _a;
77
- const wallet = getWalletBookWallet(this.walletBook, this.key);
78
- if (!isMobile() && !((_a = wallet.desktop) === null || _a === void 0 ? void 0 : _a.native)) {
79
- return undefined;
348
+ if (!this.session) {
349
+ return;
80
350
  }
81
- return getDeepLink({
82
- metadata: wallet,
351
+ const metadata = getWalletBookWallet(this.walletBook, this.key);
352
+ const deepLink = getDeepLink({
353
+ metadata,
83
354
  mode: 'regular',
84
355
  preference: this.deepLinkPreference,
85
- uri: this.getClient().uri,
356
+ uri: (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.signer.uri,
86
357
  });
358
+ if (!deepLink) {
359
+ return;
360
+ }
361
+ // we need to include the session topic here because it helps the wallet
362
+ // auto redirect back to the dapp after signing
363
+ return `${deepLink}?sessionTopic=${this.session.topic}`;
87
364
  }
88
365
  signMessage(messageToSign) {
89
366
  return __awaiter(this, void 0, void 0, function* () {
90
- return signWalletConnectPersonalMessage(messageToSign, getWalletBookWallet(this.walletBook, this.key), this.getClient(), this.deepLinkPreference,
91
- // don't call getPublicClient until we really need to
92
- () => __awaiter(this, void 0, void 0, function* () { return this.getPublicClient(); }));
367
+ if (!this.session) {
368
+ throw new DynamicError('no session');
369
+ }
370
+ const deepLink = this.getDeepLink();
371
+ if (isMobile() && deepLink) {
372
+ window.location.href = deepLink;
373
+ }
374
+ const signMessageFn = (messageToSign) => __awaiter(this, void 0, void 0, function* () {
375
+ const activeAccount = this.getActiveAccount();
376
+ if (!activeAccount) {
377
+ return;
378
+ }
379
+ const walletClient = yield this.getWalletClientFromInitializedProvider();
380
+ return walletClient.signMessage({
381
+ account: activeAccount,
382
+ message: messageToSign,
383
+ });
384
+ });
385
+ const response = yield this.waitForSignMessage(signMessageFn, messageToSign);
386
+ return response;
93
387
  });
94
388
  }
389
+ clearActiveAccount() {
390
+ localStorage.removeItem(this.activeAccountKey);
391
+ this.setActiveAccount(undefined);
392
+ }
393
+ clearSession() {
394
+ localStorage.removeItem(this.sessionTopicKey);
395
+ this.session = undefined;
396
+ }
397
+ setWCActiveAccount(account) {
398
+ localStorage.setItem(this.activeAccountKey, account);
399
+ this.setActiveAccount(account);
400
+ this.emit('accountChange', { accounts: [account] });
401
+ }
402
+ setSession(session) {
403
+ localStorage.setItem(this.sessionTopicKey, session.topic);
404
+ this.session = session;
405
+ }
95
406
  endSession() {
407
+ var _a;
96
408
  return __awaiter(this, void 0, void 0, function* () {
97
- killWalletConnectSession(this.getClient());
409
+ this.clearActiveAccount();
410
+ this.clearSession();
411
+ this.hasSwitchedNetwork = false;
412
+ this.currentChainId = undefined;
413
+ if (!((_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.session)) {
414
+ return;
415
+ }
416
+ try {
417
+ yield WalletConnect.provider.disconnect();
418
+ // We must unset provider on logout so that a new session can be established
419
+ // If we don't then the provider will still have the old session and will hang
420
+ WalletConnect.provider = undefined;
421
+ }
422
+ catch (e) {
423
+ logger.debug(e);
424
+ }
425
+ });
426
+ }
427
+ getNetwork() {
428
+ const _super = Object.create(null, {
429
+ getNetwork: { get: () => super.getNetwork }
430
+ });
431
+ return __awaiter(this, void 0, void 0, function* () {
432
+ if (this.currentChainId) {
433
+ return this.currentChainId;
434
+ }
435
+ yield this.initProvider();
436
+ return _super.getNetwork.call(this);
98
437
  });
99
438
  }
100
- providerSwitchNetwork({ network, provider, }) {
439
+ providerSwitchNetwork({ network, }) {
101
440
  const _super = Object.create(null, {
102
441
  providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
103
442
  });
104
443
  return __awaiter(this, void 0, void 0, function* () {
105
- const client = this.getClient();
444
+ const supportedNetworks = yield this.getSupportedNetworks();
445
+ if (!(supportedNetworks === null || supportedNetworks === void 0 ? void 0 : supportedNetworks.includes(network.chainId.toString()))) {
446
+ const error = new DynamicError('Network switching is not available at this time. The user should manually switch network in their wallet');
447
+ error.code = 'network_switching_only_available_in_wallet';
448
+ throw error;
449
+ }
106
450
  const currentNetworkId = yield this.getNetwork();
107
451
  if (currentNetworkId && currentNetworkId === network.chainId) {
108
452
  return;
109
453
  }
110
- if (this.switchNetworkOnlyFromWallet !== undefined &&
111
- this.switchNetworkOnlyFromWallet) {
454
+ if (this.switchNetworkOnlyFromWallet) {
112
455
  throw new DynamicError('Network switching is only supported through the wallet');
113
456
  }
114
457
  if (!this.supportsNetworkSwitching()) {
115
458
  throw new DynamicError('Network switching not supported');
116
459
  }
117
- if (!client) {
118
- throw new DynamicError('Client not found');
460
+ const walletClient = yield this.getWalletClientFromInitializedProvider();
461
+ if (this.isMetaMask()) {
462
+ const deepLink = this.getDeepLink();
463
+ if (deepLink) {
464
+ window.location.href = deepLink;
465
+ }
119
466
  }
120
- if (isMobile()) {
121
- const deepLink = getDeepLink({
122
- metadata: getWalletBookWallet(this.walletBook, this.key),
123
- mode: 'regular',
124
- preference: this.deepLinkPreference,
125
- uri: client.uri,
126
- });
127
- window.location.href = deepLink;
128
- }
129
- return _super.providerSwitchNetwork.call(this, { network, provider });
467
+ yield _super.providerSwitchNetwork.call(this, { network, provider: walletClient });
468
+ this.currentChainId = network.chainId;
469
+ this.hasSwitchedNetwork = true;
470
+ this.emit('chainChange', { chain: String(network.chainId) });
130
471
  });
131
472
  }
132
473
  getConnectedAccounts() {
133
474
  return __awaiter(this, void 0, void 0, function* () {
134
- const client = this.getClient();
135
- if (!client.connected)
475
+ if (this.isInitialized === false) {
476
+ yield this.initProvider();
477
+ this.refreshSession();
478
+ this.isInitialized = true;
479
+ }
480
+ const activeAccount = this.getActiveAccount();
481
+ if (!(activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.address)) {
136
482
  return [];
137
- return client.accounts;
483
+ }
484
+ return [activeAccount.address];
138
485
  });
139
486
  }
140
- getSession() {
487
+ isMetaMask() {
488
+ var _a, _b, _c, _d, _e;
489
+ return ((_e = (_d = (_c = (_b = (_a = this.session) === null || _a === void 0 ? void 0 : _a.peer) === null || _b === void 0 ? void 0 : _b.metadata) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.toLowerCase().startsWith('metamask')) !== null && _e !== void 0 ? _e : false);
490
+ }
491
+ getSupportedNetworks() {
141
492
  var _a;
142
493
  return __awaiter(this, void 0, void 0, function* () {
143
- return (_a = this.client) === null || _a === void 0 ? void 0 : _a.session;
494
+ yield this.initProvider();
495
+ this.refreshSession();
496
+ if (this.isMetaMask()) {
497
+ if (this.hasSwitchedNetwork) {
498
+ return [String(this.currentChainId)];
499
+ }
500
+ return this.evmNetworks.map((network) => network.chainId.toString());
501
+ }
502
+ if (!this.session) {
503
+ return [];
504
+ }
505
+ const chains = [];
506
+ // Some wallet (i.e ZenGo) use namespaces.account to list supported chains
507
+ // while others use keys within the namespaces object
508
+ Object.keys(this.session.namespaces).forEach((key) => {
509
+ if (key.startsWith('eip155:')) {
510
+ chains.push(key.split(':')[1]);
511
+ }
512
+ });
513
+ (_a = this.session.namespaces.eip155) === null || _a === void 0 ? void 0 : _a.accounts.forEach((account) => chains.push(account.split(':')[1]));
514
+ return chains.length
515
+ ? chains
516
+ : this.evmNetworks.map((network) => network.chainId.toString());
144
517
  });
145
518
  }
146
519
  }