@dynamic-labs/ethereum 0.18.0-RC.7 → 0.18.0-RC.8

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,27 @@
1
1
 
2
+ ## [0.18.0-RC.8](https://github.com/dynamic-labs/DynamicAuth/compare/v0.18.0-RC.7...v0.18.0-RC.8) (2023-06-29)
3
+
4
+
5
+ ### Features
6
+
7
+ * add support for custom walletconnect v1 bridge ([#2487](https://github.com/dynamic-labs/DynamicAuth/issues/2487)) ([5b0ca2e](https://github.com/dynamic-labs/DynamicAuth/commit/5b0ca2e4e8aa241ed13e4f38346c31da8479a6c4))
8
+ * **DYN-2623:** improve error message on sign cancellation for wallets ([#2493](https://github.com/dynamic-labs/DynamicAuth/issues/2493)) ([081c515](https://github.com/dynamic-labs/DynamicAuth/commit/081c515c9d28d6fa4c0eaac388ee421a7b23144b))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * clearing the activeAccount value ([#2469](https://github.com/dynamic-labs/DynamicAuth/issues/2469)) ([ff75bde](https://github.com/dynamic-labs/DynamicAuth/commit/ff75bde938a4178541568b79754f773607b9d87f))
14
+ * don't initialize provider if it's already initialized ([#2490](https://github.com/dynamic-labs/DynamicAuth/issues/2490)) ([878d38f](https://github.com/dynamic-labs/DynamicAuth/commit/878d38f5c8d7d7448c65e58b25cefd9f3518217e))
15
+ * more wcv2 improvements ([#2475](https://github.com/dynamic-labs/DynamicAuth/issues/2475)) ([13baa84](https://github.com/dynamic-labs/DynamicAuth/commit/13baa84218d6259d02df7d8c387b40dc3cb11ce5)), closes [#2469](https://github.com/dynamic-labs/DynamicAuth/issues/2469) [#2470](https://github.com/dynamic-labs/DynamicAuth/issues/2470) [#2471](https://github.com/dynamic-labs/DynamicAuth/issues/2471) [#2477](https://github.com/dynamic-labs/DynamicAuth/issues/2477) [#2479](https://github.com/dynamic-labs/DynamicAuth/issues/2479) [#2471](https://github.com/dynamic-labs/DynamicAuth/issues/2471) [#2476](https://github.com/dynamic-labs/DynamicAuth/issues/2476)
16
+ * multiple improvements for WC2 ([#2458](https://github.com/dynamic-labs/DynamicAuth/issues/2458)) ([0813af2](https://github.com/dynamic-labs/DynamicAuth/commit/0813af2aafa8019868117084efe8ae147ac24581))
17
+ * revert changes since latest wcv2 improvements ([#2473](https://github.com/dynamic-labs/DynamicAuth/issues/2473)) ([3375371](https://github.com/dynamic-labs/DynamicAuth/commit/337537101a13d67b860748b62f172eba01d0b461)), closes [#2471](https://github.com/dynamic-labs/DynamicAuth/issues/2471) [#2470](https://github.com/dynamic-labs/DynamicAuth/issues/2470) [#2469](https://github.com/dynamic-labs/DynamicAuth/issues/2469)
18
+ * sync issue within connect-only mode ([#2496](https://github.com/dynamic-labs/DynamicAuth/issues/2496)) ([44af274](https://github.com/dynamic-labs/DynamicAuth/commit/44af274618c30fe65ec95739cd16a8ddde08e34e))
19
+ * typo in terms of service ([#2401](https://github.com/dynamic-labs/DynamicAuth/issues/2401)) ([5b195e5](https://github.com/dynamic-labs/DynamicAuth/commit/5b195e54479d9a88bd017fc45f2f2455d1caedc4))
20
+ * **wc_v1_bridget:** disable WC v2 when WC v1 bridge is set ([#2505](https://github.com/dynamic-labs/DynamicAuth/issues/2505)) ([b3f0a68](https://github.com/dynamic-labs/DynamicAuth/commit/b3f0a6895095bb37c635984fc970b52446e04f56))
21
+ * wc2 android improvements ([#2488](https://github.com/dynamic-labs/DynamicAuth/issues/2488)) ([f60ef9c](https://github.com/dynamic-labs/DynamicAuth/commit/f60ef9c1dd672f78199eee40edbe2707c043e1b5))
22
+ * **wcv2:** make sure to clear active account when ending session ([#2471](https://github.com/dynamic-labs/DynamicAuth/issues/2471)) ([b766df3](https://github.com/dynamic-labs/DynamicAuth/commit/b766df39a7e4dabc54fda9131b7bd9b53895cf2f))
23
+ * **wcv2:** use native or universal link when signing message ([#2502](https://github.com/dynamic-labs/DynamicAuth/issues/2502)) ([6e3e3fb](https://github.com/dynamic-labs/DynamicAuth/commit/6e3e3fbb58fb9e3eb314e6631ac2123237f41e8c))
24
+
2
25
  ## [0.18.0-RC.7](https://github.com/dynamic-labs/DynamicAuth/compare/v0.18.0-RC.6...v0.18.0-RC.7) (2023-06-23)
3
26
 
4
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/ethereum",
3
- "version": "0.18.0-RC.7",
3
+ "version": "0.18.0-RC.8",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/dynamic-labs/DynamicAuth.git",
@@ -28,14 +28,15 @@
28
28
  "dependencies": {
29
29
  "@walletconnect/client": "1.8.0",
30
30
  "@walletconnect/ethereum-provider": "1.8.0",
31
- "@walletconnect/universal-provider": "2.8.0",
31
+ "@walletconnect/universal-provider": "2.8.3",
32
32
  "ethers": "5.7.2",
33
+ "eventemitter3": "5.0.1",
33
34
  "buffer": "6.0.3",
34
- "@dynamic-labs/rpc-providers": "0.18.0-RC.7",
35
- "@dynamic-labs/types": "0.18.0-RC.7",
36
- "@dynamic-labs/utils": "0.18.0-RC.7",
37
- "@dynamic-labs/wallet-book": "0.18.0-RC.7",
38
- "@dynamic-labs/wallet-connector-core": "0.18.0-RC.7"
35
+ "@dynamic-labs/rpc-providers": "0.18.0-RC.8",
36
+ "@dynamic-labs/types": "0.18.0-RC.8",
37
+ "@dynamic-labs/utils": "0.18.0-RC.8",
38
+ "@dynamic-labs/wallet-book": "0.18.0-RC.8",
39
+ "@dynamic-labs/wallet-connector-core": "0.18.0-RC.8"
39
40
  },
40
41
  "peerDependencies": {}
41
42
  }
package/src/index.cjs CHANGED
@@ -4,13 +4,13 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  require('./polyfills.cjs');
6
6
  var index = require('./injected/index.cjs');
7
- require('@walletconnect/universal-provider');
7
+ require('./walletConnect/walletConnectV2.cjs');
8
+ require('@walletconnect/ethereum-provider');
8
9
  require('ethers');
9
10
  require('@dynamic-labs/wallet-connector-core');
10
11
  require('@dynamic-labs/wallet-book');
11
12
  require('@dynamic-labs/utils');
12
13
  var EthWalletConnector = require('./EthWalletConnector.cjs');
13
- require('@walletconnect/ethereum-provider');
14
14
  var constants = require('./constants.cjs');
15
15
  require('@walletconnect/client');
16
16
  var fetchWalletConnectWallets = require('./walletConnect/fetchWalletConnectWallets.cjs');
package/src/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import './polyfills.js';
2
2
  import { injectedWallets } from './injected/index.js';
3
3
  export { injectedWallets } from './injected/index.js';
4
- import '@walletconnect/universal-provider';
4
+ import './walletConnect/walletConnectV2.js';
5
+ import '@walletconnect/ethereum-provider';
5
6
  import 'ethers';
6
7
  import '@dynamic-labs/wallet-connector-core';
7
8
  import '@dynamic-labs/wallet-book';
8
9
  import '@dynamic-labs/utils';
9
10
  export { EthWalletConnector } from './EthWalletConnector.js';
10
- import '@walletconnect/ethereum-provider';
11
11
  export { INFURA_ID } from './constants.js';
12
12
  import '@walletconnect/client';
13
13
  import { fetchWalletConnectWallets, getWalletConnectConnector } from './walletConnect/fetchWalletConnectWallets.js';
@@ -0,0 +1 @@
1
+ export declare const isString: (value: unknown) => value is string;
@@ -0,0 +1 @@
1
+ export declare const last: <T = unknown>(array: T[]) => T | undefined;
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
6
+
7
+ const parseIntSafe = (value, radix = 10) => {
8
+ try {
9
+ const int = parseInt(String(value), radix);
10
+ if (isNaN(int)) {
11
+ walletConnectorCore.logger.error(`Error parsing ${value}`);
12
+ return undefined;
13
+ }
14
+ return int;
15
+ }
16
+ catch (e) {
17
+ walletConnectorCore.logger.error(`Error parsing ${value} to int: ${e}`);
18
+ }
19
+ return undefined;
20
+ };
21
+
22
+ exports.parseIntSafe = parseIntSafe;
@@ -0,0 +1 @@
1
+ export declare const parseIntSafe: (value: string | number, radix?: number) => number | undefined;
@@ -0,0 +1,18 @@
1
+ import { logger } from '@dynamic-labs/wallet-connector-core';
2
+
3
+ const parseIntSafe = (value, radix = 10) => {
4
+ try {
5
+ const int = parseInt(String(value), radix);
6
+ if (isNaN(int)) {
7
+ logger.error(`Error parsing ${value}`);
8
+ return undefined;
9
+ }
10
+ return int;
11
+ }
12
+ catch (e) {
13
+ logger.error(`Error parsing ${value} to int: ${e}`);
14
+ }
15
+ return undefined;
16
+ };
17
+
18
+ export { parseIntSafe };
@@ -12,12 +12,12 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
12
12
 
13
13
  var Client__default = /*#__PURE__*/_interopDefaultLegacy(Client);
14
14
 
15
- const initClient = (name, settings) => {
15
+ const initClient = (name, bridge, settings) => {
16
16
  const storageId = `walletconnect-${name}`;
17
17
  const session = localStorage.getItem(storageId);
18
18
  const clientArgs = session
19
19
  ? { session: JSON.parse(session), storageId }
20
- : { bridge: 'https://bridge.walletconnect.org', storageId };
20
+ : { bridge, storageId };
21
21
  return new Client__default["default"](Object.assign(Object.assign({}, clientArgs), settings));
22
22
  };
23
23
  /**
@@ -2,7 +2,7 @@ import Client from '@walletconnect/client';
2
2
  import { ethers } from 'ethers';
3
3
  import { FetchPublicAddressOpts, PayloadParams, WalletEventListeners } from '@dynamic-labs/wallet-connector-core';
4
4
  import { WalletSchema } from '@dynamic-labs/wallet-book';
5
- export declare const initClient: (name: string, settings?: any) => Client;
5
+ export declare const initClient: (name: string, bridge: string, settings?: any) => Client;
6
6
  /**
7
7
  * Attach event handlers to WalletConnect events.
8
8
  */
@@ -4,12 +4,12 @@ import { Contract, ethers } from 'ethers';
4
4
  import { isSameAddress, logger, performPlatformSpecificConnectionMethod, getDeepLink } from '@dynamic-labs/wallet-connector-core';
5
5
  import { isMobile } from '@dynamic-labs/utils';
6
6
 
7
- const initClient = (name, settings) => {
7
+ const initClient = (name, bridge, settings) => {
8
8
  const storageId = `walletconnect-${name}`;
9
9
  const session = localStorage.getItem(storageId);
10
10
  const clientArgs = session
11
11
  ? { session: JSON.parse(session), storageId }
12
- : { bridge: 'https://bridge.walletconnect.org', storageId };
12
+ : { bridge, storageId };
13
13
  return new Client(Object.assign(Object.assign({}, clientArgs), settings));
14
14
  };
15
15
  /**
@@ -18,20 +18,24 @@ var WalletConnectProvider__default = /*#__PURE__*/_interopDefaultLegacy(WalletCo
18
18
 
19
19
  class WalletConnect extends EthWalletConnector.EthWalletConnector {
20
20
  constructor(_a) {
21
- var { walletName } = _a, props = _tslib.__rest(_a, ["walletName"]);
21
+ var { walletConnectV1Bridge, walletName } = _a, props = _tslib.__rest(_a, ["walletConnectV1Bridge", "walletName"]);
22
22
  super(props);
23
23
  this.supportedChains = ['EVM', 'ETH'];
24
24
  this.connectedChain = 'EVM';
25
+ this.bridge = 'https://bridge.walletconnect.org';
25
26
  this.canConnectViaQrCode = true;
26
27
  this.isWalletConnect = true;
27
28
  this.switchNetworkOnlyFromWallet = false;
28
29
  this.name = walletName;
30
+ if (walletConnectV1Bridge) {
31
+ this.bridge = walletConnectV1Bridge;
32
+ }
29
33
  }
30
34
  getClient() {
31
35
  if (this.client) {
32
36
  return this.client;
33
37
  }
34
- this.client = client.initClient(walletConnectorCore.normalizeWalletName(this.name), this.clientOptions);
38
+ this.client = client.initClient(walletConnectorCore.normalizeWalletName(this.name), this.bridge, this.clientOptions);
35
39
  return this.client;
36
40
  }
37
41
  supportsNetworkSwitching() {
@@ -4,18 +4,20 @@ import { Chain, FetchPublicAddressOpts, WalletEventListeners } from '@dynamic-la
4
4
  import { EvmNetwork } from '@dynamic-labs/types';
5
5
  import { EthWalletConnector, EthWalletConnectorOpts } from '../EthWalletConnector';
6
6
  export type WalletConnectOpts = EthWalletConnectorOpts & {
7
+ walletConnectV1Bridge: string;
7
8
  walletName: string;
8
9
  };
9
10
  export declare class WalletConnect extends EthWalletConnector {
10
11
  supportedChains: Chain[];
11
12
  connectedChain: Chain;
12
13
  name: string;
14
+ bridge: string;
13
15
  canConnectViaQrCode: boolean;
14
16
  isWalletConnect: boolean;
15
17
  switchNetworkOnlyFromWallet: boolean;
16
18
  client?: Client;
17
19
  clientOptions?: any;
18
- constructor({ walletName, ...props }: WalletConnectOpts);
20
+ constructor({ walletConnectV1Bridge, walletName, ...props }: WalletConnectOpts);
19
21
  getClient(): Client;
20
22
  supportsNetworkSwitching(): boolean;
21
23
  setupEventListeners(listeners: WalletEventListeners): void;
@@ -10,20 +10,24 @@ import { initClient, setupWalletConnectEventListeners, teardownWalletConnectEven
10
10
 
11
11
  class WalletConnect extends EthWalletConnector {
12
12
  constructor(_a) {
13
- var { walletName } = _a, props = __rest(_a, ["walletName"]);
13
+ var { walletConnectV1Bridge, walletName } = _a, props = __rest(_a, ["walletConnectV1Bridge", "walletName"]);
14
14
  super(props);
15
15
  this.supportedChains = ['EVM', 'ETH'];
16
16
  this.connectedChain = 'EVM';
17
+ this.bridge = 'https://bridge.walletconnect.org';
17
18
  this.canConnectViaQrCode = true;
18
19
  this.isWalletConnect = true;
19
20
  this.switchNetworkOnlyFromWallet = false;
20
21
  this.name = walletName;
22
+ if (walletConnectV1Bridge) {
23
+ this.bridge = walletConnectV1Bridge;
24
+ }
21
25
  }
22
26
  getClient() {
23
27
  if (this.client) {
24
28
  return this.client;
25
29
  }
26
- this.client = initClient(normalizeWalletName(this.name), this.clientOptions);
30
+ this.client = initClient(normalizeWalletName(this.name), this.bridge, this.clientOptions);
27
31
  return this.client;
28
32
  }
29
33
  supportsNetworkSwitching() {
@@ -5,21 +5,27 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _tslib = require('../../_virtual/_tslib.cjs');
6
6
  var Provider = require('@walletconnect/universal-provider');
7
7
  var ethers = require('ethers');
8
+ var EventEmitter = require('eventemitter3');
8
9
  var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
9
10
  var walletBook = require('@dynamic-labs/wallet-book');
10
11
  var utils = require('@dynamic-labs/utils');
11
12
  var EthWalletConnector = require('../EthWalletConnector.cjs');
13
+ var parseIntSafe = require('../utils/parseIntSafe.cjs');
12
14
 
13
15
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
16
 
15
17
  var Provider__default = /*#__PURE__*/_interopDefaultLegacy(Provider);
18
+ var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
16
19
 
20
+ const activeAccountKey = (walletName) => `dynamic-wc2-active-account-${walletName}`;
17
21
  const sessionTopicKey = (walletName) => `dynamic-wc2-session-topic-${walletName}`;
22
+ const ee = new EventEmitter__default["default"]();
18
23
  class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
19
24
  constructor(opts) {
20
25
  super(opts);
21
26
  this.supportedChains = ['EVM', 'ETH'];
22
27
  this.connectedChain = 'EVM';
28
+ this.isInitialized = false;
23
29
  this.canConnectViaQrCode = true;
24
30
  this.isWalletConnect = true;
25
31
  this.name = opts.walletName;
@@ -35,44 +41,69 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
35
41
  if (provider === null || provider === void 0 ? void 0 : provider.uri) {
36
42
  return;
37
43
  }
38
- yield provider.connect({
44
+ const defaultChain = 1;
45
+ provider
46
+ .connect({
39
47
  namespaces: {
48
+ eip155: {
49
+ chains: [`eip155:${defaultChain}`],
50
+ events: ['chainChanged', 'accountsChanged'],
51
+ methods: ['personal_sign', 'eth_sendTransaction'],
52
+ rpcMap: this.evmNetworkRpcMap(),
53
+ },
54
+ },
55
+ optionalNamespaces: {
40
56
  eip155: {
41
57
  chains: this.evmNetworks
42
- // filtering out Palm for now since it causes Trust to crash
43
- .filter((network) => network.chainId !== 11297108109)
58
+ // Filters out mainnet which is required and palm that crashes Trust Wallet
59
+ .filter((network) => network.chainId !== 11297108109 &&
60
+ network.chainId !== defaultChain)
44
61
  .map((network) => `eip155:${network.chainId}`),
45
- events: ['chainChanged', 'accountsChanged'],
62
+ events: [],
46
63
  methods: [
47
- 'eth_sendTransaction',
64
+ 'eth_signTypedData',
48
65
  'eth_signTransaction',
49
66
  'eth_sign',
50
67
  'personal_sign',
51
- 'eth_signTypedData',
68
+ 'eth_sendTransaction',
52
69
  ],
53
70
  rpcMap: this.evmNetworkRpcMap(),
54
71
  },
55
72
  },
73
+ })
74
+ .catch((e) => {
75
+ walletConnectorCore.logger.error(e);
76
+ ee.emit('walletconnect_connection_failed');
56
77
  });
57
78
  });
58
79
  }
80
+ createInitProviderPromise() {
81
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
82
+ const provider = yield Provider__default["default"].init({
83
+ projectId: this.projectId,
84
+ });
85
+ WalletConnectV2.provider = provider;
86
+ });
87
+ }
59
88
  initProvider() {
60
89
  return _tslib.__awaiter(this, void 0, void 0, function* () {
61
- let { provider } = WalletConnectV2;
90
+ const { provider } = WalletConnectV2;
62
91
  if (!provider) {
63
- provider = yield Provider__default["default"].init({
64
- projectId: this.projectId,
65
- });
66
- WalletConnectV2.provider = provider;
92
+ if (this.initializePromise === undefined) {
93
+ this.initializePromise = this.createInitProviderPromise();
94
+ }
95
+ yield this.initializePromise;
67
96
  }
68
97
  });
69
98
  }
70
99
  refreshSession() {
71
- var _a, _b, _c, _d;
100
+ var _a, _b, _c, _d, _e;
72
101
  if ((_b = (_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session) === null || _b === void 0 ? void 0 : _b.topic) {
73
102
  if (localStorage.getItem(this.sessionTopicKey) ===
74
103
  ((_d = (_c = WalletConnectV2.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
75
104
  this.session = WalletConnectV2.provider.session;
105
+ this.activeAccount =
106
+ (_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined;
76
107
  }
77
108
  }
78
109
  }
@@ -80,11 +111,15 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
80
111
  return _tslib.__awaiter(this, void 0, void 0, function* () {
81
112
  yield this.initProvider();
82
113
  yield this.initConnection();
114
+ this.isInitialized = true;
83
115
  });
84
116
  }
85
117
  get sessionTopicKey() {
86
118
  return sessionTopicKey(this.key);
87
119
  }
120
+ get activeAccountKey() {
121
+ return activeAccountKey(this.key);
122
+ }
88
123
  supportsNetworkSwitching() {
89
124
  return true;
90
125
  }
@@ -100,23 +135,27 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
100
135
  }
101
136
  const { name, data } = params.event;
102
137
  if (name === 'chainChanged') {
103
- if (typeof data !== 'string') {
138
+ const chainId = parseIntSafe.parseIntSafe(data);
139
+ if (chainId === undefined) {
104
140
  walletConnectorCore.logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
105
141
  return;
106
142
  }
107
- (_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, data);
143
+ (_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, String(chainId));
108
144
  }
109
145
  else if (name === 'accountsChanged') {
110
- if (typeof data !== 'string' || !Array.isArray(data)) {
146
+ if (!Array.isArray(data)) {
111
147
  walletConnectorCore.logger.debug(`received unexpected data for accountsChanged: ${data} with type ${typeof data}}`);
112
148
  return;
113
149
  }
114
- (_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, data);
150
+ // eslint-disable-next-line prefer-destructuring
151
+ const account = data[0].split(':')[2];
152
+ this.setActiveAccount(account);
153
+ (_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, [account]);
115
154
  }
116
155
  });
117
156
  WalletConnectV2.provider.client.on('session_delete', () => _tslib.__awaiter(this, void 0, void 0, function* () {
118
157
  var _a;
119
- localStorage.removeItem(this.sessionTopicKey);
158
+ this.endSession();
120
159
  yield ((_a = listeners.onDisconnect) === null || _a === void 0 ? void 0 : _a.call(listeners));
121
160
  }));
122
161
  }
@@ -127,20 +166,6 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
127
166
  WalletConnectV2.provider.client.removeAllListeners('session_event');
128
167
  WalletConnectV2.provider.client.removeAllListeners('session_delete');
129
168
  }
130
- getDeepLink() {
131
- var _a, _b;
132
- if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri))
133
- return;
134
- const wallet = walletBook.getWalletBookWallet(this.walletBook, this.name);
135
- if (!utils.isMobile() && !((_b = wallet.desktop) === null || _b === void 0 ? void 0 : _b.native)) {
136
- return undefined;
137
- }
138
- return walletConnectorCore.getDeepLink({
139
- metadata: wallet,
140
- mode: 'regular',
141
- uri: WalletConnectV2.provider.uri,
142
- });
143
- }
144
169
  getWeb3Provider() {
145
170
  if (!WalletConnectV2.provider) {
146
171
  throw new Error('No provider found');
@@ -148,15 +173,25 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
148
173
  return new ethers.ethers.providers.Web3Provider(WalletConnectV2.provider, 'any');
149
174
  }
150
175
  fetchPublicAddress(opts) {
176
+ var _a, _b;
151
177
  return _tslib.__awaiter(this, void 0, void 0, function* () {
152
- if (this.session) {
153
- return this.session.namespaces.eip155.accounts[0].split(':')[2];
154
- }
155
- if (!WalletConnectV2.provider) {
156
- throw new utils.DynamicError('No provider found');
178
+ if (this.activeAccount) {
179
+ return this.activeAccount;
157
180
  }
158
- if (!WalletConnectV2.provider.uri) {
159
- throw new utils.DynamicError('No uri found');
181
+ if (!WalletConnectV2.provider || !((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri)) {
182
+ walletConnectorCore.logger.debug('No WC2 provider found, re-initializing...');
183
+ yield this.endSession();
184
+ yield this.init();
185
+ // sleep 1 s to wait for connect call to finish
186
+ // the connect call isn't await-ed because it only resolves once
187
+ // the connection is established, but we need to wait for it to
188
+ // finish setting up the connection URI and making it available
189
+ // on the provider
190
+ yield new Promise((resolve) => setTimeout(resolve, 1000));
191
+ if (!WalletConnectV2.provider || !((_b = WalletConnectV2.provider) === null || _b === void 0 ? void 0 : _b.uri)) {
192
+ walletConnectorCore.logger.debug('No WC2 provider found, escaping and throwing error');
193
+ throw new utils.DynamicError('No provider found');
194
+ }
160
195
  }
161
196
  const metadata = walletBook.getWalletBookWallet(this.walletBook, this.name);
162
197
  walletConnectorCore.performPlatformSpecificConnectionMethod(WalletConnectV2.provider.uri, metadata, {
@@ -168,18 +203,27 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
168
203
  reject(new utils.DynamicError('No provider found'));
169
204
  return;
170
205
  }
206
+ ee.on('walletconnect_connection_failed', () => {
207
+ const error = new utils.DynamicError('Connection rejected. Please try again.');
208
+ error.code = 'connection_rejected';
209
+ if (WalletConnectV2.provider) {
210
+ WalletConnectV2.provider.uri = undefined;
211
+ }
212
+ reject(error);
213
+ });
171
214
  WalletConnectV2.provider.on('connect', ({ session }) => {
172
215
  if (!session) {
173
216
  reject(new utils.DynamicError('No session found'));
174
217
  }
175
- this.session = session;
176
- localStorage.setItem(this.sessionTopicKey, session.topic);
177
- resolve(this.session.namespaces.eip155.accounts[0].split(':')[2]);
218
+ this.setSession(session);
219
+ this.setActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
220
+ resolve(this.activeAccount);
178
221
  });
179
222
  });
180
223
  });
181
224
  }
182
225
  signMessage(messageToSign) {
226
+ var _a, _b;
183
227
  return _tslib.__awaiter(this, void 0, void 0, function* () {
184
228
  if (!this.session) {
185
229
  throw new utils.DynamicError('no session');
@@ -189,39 +233,72 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
189
233
  }
190
234
  const metadata = walletBook.getWalletBookWallet(this.walletBook, this.name);
191
235
  if (utils.isMobile()) {
192
- // for sign message, no uri is needed because the uri encodes connection details,
193
- // and at this point we are already connected
194
- const deepLink = walletConnectorCore.getDeepLink({ metadata, mode: 'regular' });
236
+ const deepLink = ((_a = metadata['mobile']) === null || _a === void 0 ? void 0 : _a.native) || ((_b = metadata['mobile']) === null || _b === void 0 ? void 0 : _b.universal) || '';
195
237
  window.location.href = deepLink;
196
238
  }
197
- // eslint-disable-next-line prefer-destructuring
198
- const address = this.session.namespaces.eip155.accounts[0].split(':')[2];
199
239
  const web3Provider = this.getWeb3Provider();
200
- return web3Provider.send('personal_sign', [
240
+ const response = web3Provider.send('personal_sign', [
201
241
  walletConnectorCore.utf8ToHex(messageToSign, true),
202
- address,
242
+ this.activeAccount,
203
243
  ]);
244
+ try {
245
+ // A terrible hack to get MM to sign the message when it is on the wrong chain
246
+ // Since MM supports only one chain at a time, it just hangs when we call
247
+ // to sign, and it is not on Mainnet. For some magical reason,
248
+ // when we attempt to call again it just works.
249
+ if (this.key === 'metamask') {
250
+ yield this.promiseWithTimeout(7000, response);
251
+ }
252
+ }
253
+ catch (e) {
254
+ walletConnectorCore.logger.debug('metmask failed to sign message');
255
+ throw e;
256
+ }
257
+ return response;
204
258
  });
205
259
  }
260
+ clearActiveAccount() {
261
+ localStorage.removeItem(this.activeAccountKey);
262
+ this.activeAccount = undefined;
263
+ }
264
+ clearSession() {
265
+ localStorage.removeItem(this.sessionTopicKey);
266
+ this.session = undefined;
267
+ }
268
+ setActiveAccount(account) {
269
+ localStorage.setItem(this.activeAccountKey, account);
270
+ this.activeAccount = account;
271
+ }
272
+ setSession(session) {
273
+ localStorage.setItem(this.sessionTopicKey, session.topic);
274
+ this.session = session;
275
+ }
206
276
  endSession() {
277
+ var _a;
207
278
  return _tslib.__awaiter(this, void 0, void 0, function* () {
208
- if (!this.session) {
209
- return;
210
- }
211
- if (!WalletConnectV2.provider) {
279
+ this.clearActiveAccount();
280
+ this.clearSession();
281
+ if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session)) {
212
282
  return;
213
283
  }
214
284
  try {
215
285
  yield WalletConnectV2.provider.disconnect();
216
286
  WalletConnectV2.provider.uri = undefined;
217
- localStorage.removeItem(this.sessionTopicKey);
218
- this.session = undefined;
219
287
  }
220
288
  catch (e) {
221
289
  walletConnectorCore.logger.debug(e);
222
290
  }
223
291
  });
224
292
  }
293
+ getNetwork() {
294
+ const _super = Object.create(null, {
295
+ getNetwork: { get: () => super.getNetwork }
296
+ });
297
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
298
+ yield this.initProvider();
299
+ return _super.getNetwork.call(this);
300
+ });
301
+ }
225
302
  providerSwitchNetwork({ network, provider, }) {
226
303
  const _super = Object.create(null, {
227
304
  providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
@@ -244,14 +321,46 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
244
321
  });
245
322
  }
246
323
  getConnectedAccounts() {
324
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
325
+ yield this.initProvider();
326
+ this.refreshSession();
327
+ this.isInitialized = true;
328
+ if (!this.activeAccount) {
329
+ return [];
330
+ }
331
+ return [this.activeAccount];
332
+ });
333
+ }
334
+ getSupportedNetworks() {
247
335
  return _tslib.__awaiter(this, void 0, void 0, function* () {
248
336
  yield this.initProvider();
249
337
  this.refreshSession();
250
338
  if (!this.session) {
251
339
  return [];
252
340
  }
253
- return [this.session.namespaces.eip155.accounts[0].split(':')[2]];
341
+ const chains = [];
342
+ // Some wallet (i.e ZenGo) use namespaces.account to list supported chains
343
+ // while others use keys within the namespaces object
344
+ Object.keys(this.session.namespaces).forEach((key) => {
345
+ if (key.startsWith('eip155:')) {
346
+ chains.push(key.split(':')[1]);
347
+ }
348
+ });
349
+ this.session.namespaces.eip155.accounts.forEach((account) => chains.push(account.split(':')[1]));
350
+ return chains.length ? chains : undefined;
351
+ });
352
+ }
353
+ // a HACK for MM to sign message when the selected chain is not mainnet
354
+ promiseWithTimeout(ms, promise) {
355
+ // Create a promise that rejects in <ms> milliseconds
356
+ const timeout = new Promise((_, reject) => {
357
+ const id = setTimeout(() => {
358
+ clearTimeout(id);
359
+ reject(new utils.DynamicError(undefined, 'metamask_timeout'));
360
+ }, ms);
254
361
  });
362
+ // Returns a race between our timeout and the passed in promise
363
+ return Promise.race([promise, timeout]);
255
364
  }
256
365
  }
257
366
 
@@ -12,27 +12,38 @@ export declare class WalletConnectV2 extends EthWalletConnector {
12
12
  connectedChain: Chain;
13
13
  name: string;
14
14
  session: SessionTypes.Struct | undefined;
15
+ activeAccount: string | undefined;
16
+ isInitialized: boolean;
17
+ initializePromise: Promise<void> | undefined;
15
18
  canConnectViaQrCode: boolean;
16
19
  isWalletConnect: boolean;
17
20
  private static provider;
18
21
  private projectId?;
19
22
  constructor(opts: WalletConnectorV2Opts);
20
23
  private initConnection;
24
+ private createInitProviderPromise;
21
25
  private initProvider;
22
26
  private refreshSession;
23
27
  init(): Promise<void>;
24
28
  get sessionTopicKey(): string;
29
+ get activeAccountKey(): string;
25
30
  supportsNetworkSwitching(): boolean;
26
31
  setupEventListeners(listeners: WalletEventListeners): void;
27
32
  teardownEventListeners(): void;
28
- getDeepLink(): string | undefined;
29
33
  getWeb3Provider(): ethers.providers.Web3Provider;
30
34
  fetchPublicAddress(opts?: FetchPublicAddressOpts): Promise<string | undefined>;
31
35
  signMessage(messageToSign: string): Promise<string | undefined>;
36
+ private clearActiveAccount;
37
+ private clearSession;
38
+ private setActiveAccount;
39
+ private setSession;
32
40
  endSession(): Promise<void>;
41
+ getNetwork(): Promise<number | undefined>;
33
42
  providerSwitchNetwork({ network, provider, }: {
34
43
  network: EvmNetwork;
35
44
  provider: ethers.providers.Web3Provider;
36
45
  }): Promise<void>;
37
46
  getConnectedAccounts(): Promise<string[]>;
47
+ getSupportedNetworks(): Promise<string[] | undefined>;
48
+ private promiseWithTimeout;
38
49
  }
@@ -1,17 +1,22 @@
1
1
  import { __awaiter } from '../../_virtual/_tslib.js';
2
2
  import Provider from '@walletconnect/universal-provider';
3
3
  import { ethers } from 'ethers';
4
- import { logger, getDeepLink, performPlatformSpecificConnectionMethod, utf8ToHex } from '@dynamic-labs/wallet-connector-core';
4
+ import EventEmitter from 'eventemitter3';
5
+ import { logger, performPlatformSpecificConnectionMethod, utf8ToHex } from '@dynamic-labs/wallet-connector-core';
5
6
  import { getWalletBookWallet } from '@dynamic-labs/wallet-book';
6
7
  import { DynamicError, isMobile } from '@dynamic-labs/utils';
7
8
  import { EthWalletConnector } from '../EthWalletConnector.js';
9
+ import { parseIntSafe } from '../utils/parseIntSafe.js';
8
10
 
11
+ const activeAccountKey = (walletName) => `dynamic-wc2-active-account-${walletName}`;
9
12
  const sessionTopicKey = (walletName) => `dynamic-wc2-session-topic-${walletName}`;
13
+ const ee = new EventEmitter();
10
14
  class WalletConnectV2 extends EthWalletConnector {
11
15
  constructor(opts) {
12
16
  super(opts);
13
17
  this.supportedChains = ['EVM', 'ETH'];
14
18
  this.connectedChain = 'EVM';
19
+ this.isInitialized = false;
15
20
  this.canConnectViaQrCode = true;
16
21
  this.isWalletConnect = true;
17
22
  this.name = opts.walletName;
@@ -27,44 +32,69 @@ class WalletConnectV2 extends EthWalletConnector {
27
32
  if (provider === null || provider === void 0 ? void 0 : provider.uri) {
28
33
  return;
29
34
  }
30
- yield provider.connect({
35
+ const defaultChain = 1;
36
+ provider
37
+ .connect({
31
38
  namespaces: {
39
+ eip155: {
40
+ chains: [`eip155:${defaultChain}`],
41
+ events: ['chainChanged', 'accountsChanged'],
42
+ methods: ['personal_sign', 'eth_sendTransaction'],
43
+ rpcMap: this.evmNetworkRpcMap(),
44
+ },
45
+ },
46
+ optionalNamespaces: {
32
47
  eip155: {
33
48
  chains: this.evmNetworks
34
- // filtering out Palm for now since it causes Trust to crash
35
- .filter((network) => network.chainId !== 11297108109)
49
+ // Filters out mainnet which is required and palm that crashes Trust Wallet
50
+ .filter((network) => network.chainId !== 11297108109 &&
51
+ network.chainId !== defaultChain)
36
52
  .map((network) => `eip155:${network.chainId}`),
37
- events: ['chainChanged', 'accountsChanged'],
53
+ events: [],
38
54
  methods: [
39
- 'eth_sendTransaction',
55
+ 'eth_signTypedData',
40
56
  'eth_signTransaction',
41
57
  'eth_sign',
42
58
  'personal_sign',
43
- 'eth_signTypedData',
59
+ 'eth_sendTransaction',
44
60
  ],
45
61
  rpcMap: this.evmNetworkRpcMap(),
46
62
  },
47
63
  },
64
+ })
65
+ .catch((e) => {
66
+ logger.error(e);
67
+ ee.emit('walletconnect_connection_failed');
48
68
  });
49
69
  });
50
70
  }
71
+ createInitProviderPromise() {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const provider = yield Provider.init({
74
+ projectId: this.projectId,
75
+ });
76
+ WalletConnectV2.provider = provider;
77
+ });
78
+ }
51
79
  initProvider() {
52
80
  return __awaiter(this, void 0, void 0, function* () {
53
- let { provider } = WalletConnectV2;
81
+ const { provider } = WalletConnectV2;
54
82
  if (!provider) {
55
- provider = yield Provider.init({
56
- projectId: this.projectId,
57
- });
58
- WalletConnectV2.provider = provider;
83
+ if (this.initializePromise === undefined) {
84
+ this.initializePromise = this.createInitProviderPromise();
85
+ }
86
+ yield this.initializePromise;
59
87
  }
60
88
  });
61
89
  }
62
90
  refreshSession() {
63
- var _a, _b, _c, _d;
91
+ var _a, _b, _c, _d, _e;
64
92
  if ((_b = (_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session) === null || _b === void 0 ? void 0 : _b.topic) {
65
93
  if (localStorage.getItem(this.sessionTopicKey) ===
66
94
  ((_d = (_c = WalletConnectV2.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
67
95
  this.session = WalletConnectV2.provider.session;
96
+ this.activeAccount =
97
+ (_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined;
68
98
  }
69
99
  }
70
100
  }
@@ -72,11 +102,15 @@ class WalletConnectV2 extends EthWalletConnector {
72
102
  return __awaiter(this, void 0, void 0, function* () {
73
103
  yield this.initProvider();
74
104
  yield this.initConnection();
105
+ this.isInitialized = true;
75
106
  });
76
107
  }
77
108
  get sessionTopicKey() {
78
109
  return sessionTopicKey(this.key);
79
110
  }
111
+ get activeAccountKey() {
112
+ return activeAccountKey(this.key);
113
+ }
80
114
  supportsNetworkSwitching() {
81
115
  return true;
82
116
  }
@@ -92,23 +126,27 @@ class WalletConnectV2 extends EthWalletConnector {
92
126
  }
93
127
  const { name, data } = params.event;
94
128
  if (name === 'chainChanged') {
95
- if (typeof data !== 'string') {
129
+ const chainId = parseIntSafe(data);
130
+ if (chainId === undefined) {
96
131
  logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
97
132
  return;
98
133
  }
99
- (_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, data);
134
+ (_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, String(chainId));
100
135
  }
101
136
  else if (name === 'accountsChanged') {
102
- if (typeof data !== 'string' || !Array.isArray(data)) {
137
+ if (!Array.isArray(data)) {
103
138
  logger.debug(`received unexpected data for accountsChanged: ${data} with type ${typeof data}}`);
104
139
  return;
105
140
  }
106
- (_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, data);
141
+ // eslint-disable-next-line prefer-destructuring
142
+ const account = data[0].split(':')[2];
143
+ this.setActiveAccount(account);
144
+ (_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, [account]);
107
145
  }
108
146
  });
109
147
  WalletConnectV2.provider.client.on('session_delete', () => __awaiter(this, void 0, void 0, function* () {
110
148
  var _a;
111
- localStorage.removeItem(this.sessionTopicKey);
149
+ this.endSession();
112
150
  yield ((_a = listeners.onDisconnect) === null || _a === void 0 ? void 0 : _a.call(listeners));
113
151
  }));
114
152
  }
@@ -119,20 +157,6 @@ class WalletConnectV2 extends EthWalletConnector {
119
157
  WalletConnectV2.provider.client.removeAllListeners('session_event');
120
158
  WalletConnectV2.provider.client.removeAllListeners('session_delete');
121
159
  }
122
- getDeepLink() {
123
- var _a, _b;
124
- if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri))
125
- return;
126
- const wallet = getWalletBookWallet(this.walletBook, this.name);
127
- if (!isMobile() && !((_b = wallet.desktop) === null || _b === void 0 ? void 0 : _b.native)) {
128
- return undefined;
129
- }
130
- return getDeepLink({
131
- metadata: wallet,
132
- mode: 'regular',
133
- uri: WalletConnectV2.provider.uri,
134
- });
135
- }
136
160
  getWeb3Provider() {
137
161
  if (!WalletConnectV2.provider) {
138
162
  throw new Error('No provider found');
@@ -140,15 +164,25 @@ class WalletConnectV2 extends EthWalletConnector {
140
164
  return new ethers.providers.Web3Provider(WalletConnectV2.provider, 'any');
141
165
  }
142
166
  fetchPublicAddress(opts) {
167
+ var _a, _b;
143
168
  return __awaiter(this, void 0, void 0, function* () {
144
- if (this.session) {
145
- return this.session.namespaces.eip155.accounts[0].split(':')[2];
146
- }
147
- if (!WalletConnectV2.provider) {
148
- throw new DynamicError('No provider found');
169
+ if (this.activeAccount) {
170
+ return this.activeAccount;
149
171
  }
150
- if (!WalletConnectV2.provider.uri) {
151
- throw new DynamicError('No uri found');
172
+ if (!WalletConnectV2.provider || !((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri)) {
173
+ logger.debug('No WC2 provider found, re-initializing...');
174
+ yield this.endSession();
175
+ yield this.init();
176
+ // sleep 1 s to wait for connect call to finish
177
+ // the connect call isn't await-ed because it only resolves once
178
+ // the connection is established, but we need to wait for it to
179
+ // finish setting up the connection URI and making it available
180
+ // on the provider
181
+ yield new Promise((resolve) => setTimeout(resolve, 1000));
182
+ if (!WalletConnectV2.provider || !((_b = WalletConnectV2.provider) === null || _b === void 0 ? void 0 : _b.uri)) {
183
+ logger.debug('No WC2 provider found, escaping and throwing error');
184
+ throw new DynamicError('No provider found');
185
+ }
152
186
  }
153
187
  const metadata = getWalletBookWallet(this.walletBook, this.name);
154
188
  performPlatformSpecificConnectionMethod(WalletConnectV2.provider.uri, metadata, {
@@ -160,18 +194,27 @@ class WalletConnectV2 extends EthWalletConnector {
160
194
  reject(new DynamicError('No provider found'));
161
195
  return;
162
196
  }
197
+ ee.on('walletconnect_connection_failed', () => {
198
+ const error = new DynamicError('Connection rejected. Please try again.');
199
+ error.code = 'connection_rejected';
200
+ if (WalletConnectV2.provider) {
201
+ WalletConnectV2.provider.uri = undefined;
202
+ }
203
+ reject(error);
204
+ });
163
205
  WalletConnectV2.provider.on('connect', ({ session }) => {
164
206
  if (!session) {
165
207
  reject(new DynamicError('No session found'));
166
208
  }
167
- this.session = session;
168
- localStorage.setItem(this.sessionTopicKey, session.topic);
169
- resolve(this.session.namespaces.eip155.accounts[0].split(':')[2]);
209
+ this.setSession(session);
210
+ this.setActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
211
+ resolve(this.activeAccount);
170
212
  });
171
213
  });
172
214
  });
173
215
  }
174
216
  signMessage(messageToSign) {
217
+ var _a, _b;
175
218
  return __awaiter(this, void 0, void 0, function* () {
176
219
  if (!this.session) {
177
220
  throw new DynamicError('no session');
@@ -181,39 +224,72 @@ class WalletConnectV2 extends EthWalletConnector {
181
224
  }
182
225
  const metadata = getWalletBookWallet(this.walletBook, this.name);
183
226
  if (isMobile()) {
184
- // for sign message, no uri is needed because the uri encodes connection details,
185
- // and at this point we are already connected
186
- const deepLink = getDeepLink({ metadata, mode: 'regular' });
227
+ const deepLink = ((_a = metadata['mobile']) === null || _a === void 0 ? void 0 : _a.native) || ((_b = metadata['mobile']) === null || _b === void 0 ? void 0 : _b.universal) || '';
187
228
  window.location.href = deepLink;
188
229
  }
189
- // eslint-disable-next-line prefer-destructuring
190
- const address = this.session.namespaces.eip155.accounts[0].split(':')[2];
191
230
  const web3Provider = this.getWeb3Provider();
192
- return web3Provider.send('personal_sign', [
231
+ const response = web3Provider.send('personal_sign', [
193
232
  utf8ToHex(messageToSign, true),
194
- address,
233
+ this.activeAccount,
195
234
  ]);
235
+ try {
236
+ // A terrible hack to get MM to sign the message when it is on the wrong chain
237
+ // Since MM supports only one chain at a time, it just hangs when we call
238
+ // to sign, and it is not on Mainnet. For some magical reason,
239
+ // when we attempt to call again it just works.
240
+ if (this.key === 'metamask') {
241
+ yield this.promiseWithTimeout(7000, response);
242
+ }
243
+ }
244
+ catch (e) {
245
+ logger.debug('metmask failed to sign message');
246
+ throw e;
247
+ }
248
+ return response;
196
249
  });
197
250
  }
251
+ clearActiveAccount() {
252
+ localStorage.removeItem(this.activeAccountKey);
253
+ this.activeAccount = undefined;
254
+ }
255
+ clearSession() {
256
+ localStorage.removeItem(this.sessionTopicKey);
257
+ this.session = undefined;
258
+ }
259
+ setActiveAccount(account) {
260
+ localStorage.setItem(this.activeAccountKey, account);
261
+ this.activeAccount = account;
262
+ }
263
+ setSession(session) {
264
+ localStorage.setItem(this.sessionTopicKey, session.topic);
265
+ this.session = session;
266
+ }
198
267
  endSession() {
268
+ var _a;
199
269
  return __awaiter(this, void 0, void 0, function* () {
200
- if (!this.session) {
201
- return;
202
- }
203
- if (!WalletConnectV2.provider) {
270
+ this.clearActiveAccount();
271
+ this.clearSession();
272
+ if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session)) {
204
273
  return;
205
274
  }
206
275
  try {
207
276
  yield WalletConnectV2.provider.disconnect();
208
277
  WalletConnectV2.provider.uri = undefined;
209
- localStorage.removeItem(this.sessionTopicKey);
210
- this.session = undefined;
211
278
  }
212
279
  catch (e) {
213
280
  logger.debug(e);
214
281
  }
215
282
  });
216
283
  }
284
+ getNetwork() {
285
+ const _super = Object.create(null, {
286
+ getNetwork: { get: () => super.getNetwork }
287
+ });
288
+ return __awaiter(this, void 0, void 0, function* () {
289
+ yield this.initProvider();
290
+ return _super.getNetwork.call(this);
291
+ });
292
+ }
217
293
  providerSwitchNetwork({ network, provider, }) {
218
294
  const _super = Object.create(null, {
219
295
  providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
@@ -236,14 +312,46 @@ class WalletConnectV2 extends EthWalletConnector {
236
312
  });
237
313
  }
238
314
  getConnectedAccounts() {
315
+ return __awaiter(this, void 0, void 0, function* () {
316
+ yield this.initProvider();
317
+ this.refreshSession();
318
+ this.isInitialized = true;
319
+ if (!this.activeAccount) {
320
+ return [];
321
+ }
322
+ return [this.activeAccount];
323
+ });
324
+ }
325
+ getSupportedNetworks() {
239
326
  return __awaiter(this, void 0, void 0, function* () {
240
327
  yield this.initProvider();
241
328
  this.refreshSession();
242
329
  if (!this.session) {
243
330
  return [];
244
331
  }
245
- return [this.session.namespaces.eip155.accounts[0].split(':')[2]];
332
+ const chains = [];
333
+ // Some wallet (i.e ZenGo) use namespaces.account to list supported chains
334
+ // while others use keys within the namespaces object
335
+ Object.keys(this.session.namespaces).forEach((key) => {
336
+ if (key.startsWith('eip155:')) {
337
+ chains.push(key.split(':')[1]);
338
+ }
339
+ });
340
+ this.session.namespaces.eip155.accounts.forEach((account) => chains.push(account.split(':')[1]));
341
+ return chains.length ? chains : undefined;
342
+ });
343
+ }
344
+ // a HACK for MM to sign message when the selected chain is not mainnet
345
+ promiseWithTimeout(ms, promise) {
346
+ // Create a promise that rejects in <ms> milliseconds
347
+ const timeout = new Promise((_, reject) => {
348
+ const id = setTimeout(() => {
349
+ clearTimeout(id);
350
+ reject(new DynamicError(undefined, 'metamask_timeout'));
351
+ }, ms);
246
352
  });
353
+ // Returns a race between our timeout and the passed in promise
354
+ return Promise.race([promise, timeout]);
247
355
  }
248
356
  }
249
357