@dynamic-labs/ethereum 0.17.10 → 0.17.12
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 +14 -0
- package/package.json +8 -7
- package/src/index.cjs +2 -2
- package/src/index.js +2 -2
- package/src/utils/isString.d.ts +1 -0
- package/src/utils/last.d.ts +1 -0
- package/src/utils/parseIntSafe.cjs +22 -0
- package/src/utils/parseIntSafe.d.ts +1 -0
- package/src/utils/parseIntSafe.js +18 -0
- package/src/walletConnect/walletConnectV2.cjs +148 -32
- package/src/walletConnect/walletConnectV2.d.ts +10 -0
- package/src/walletConnect/walletConnectV2.js +147 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
|
|
2
|
+
### [0.17.12](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.11...v0.17.12) (2023-06-26)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* more wc2 improvements ([#2484](https://github.com/dynamic-labs/DynamicAuth/issues/2484)) ([482ed5d](https://github.com/dynamic-labs/DynamicAuth/commit/482ed5d699985ff4a96f4af2ce2a3f7565a6cc1f))
|
|
8
|
+
|
|
9
|
+
### [0.17.11](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.10...v0.17.11) (2023-06-26)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* multiple improvements for WC2 ([#2465](https://github.com/dynamic-labs/DynamicAuth/issues/2465)) ([7d5d7bd](https://github.com/dynamic-labs/DynamicAuth/commit/7d5d7bdcf2dd01ef3810e2fddd46d56a40effa95)), closes [#2458](https://github.com/dynamic-labs/DynamicAuth/issues/2458)
|
|
15
|
+
|
|
2
16
|
### [0.17.10](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.9...v0.17.10) (2023-06-23)
|
|
3
17
|
|
|
4
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/ethereum",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.12",
|
|
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.
|
|
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.17.
|
|
35
|
-
"@dynamic-labs/types": "0.17.
|
|
36
|
-
"@dynamic-labs/utils": "0.17.
|
|
37
|
-
"@dynamic-labs/wallet-book": "0.17.
|
|
38
|
-
"@dynamic-labs/wallet-connector-core": "0.17.
|
|
35
|
+
"@dynamic-labs/rpc-providers": "0.17.12",
|
|
36
|
+
"@dynamic-labs/types": "0.17.12",
|
|
37
|
+
"@dynamic-labs/utils": "0.17.12",
|
|
38
|
+
"@dynamic-labs/wallet-book": "0.17.12",
|
|
39
|
+
"@dynamic-labs/wallet-connector-core": "0.17.12"
|
|
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('
|
|
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 '
|
|
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 };
|
|
@@ -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,24 +41,39 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
35
41
|
if (provider === null || provider === void 0 ? void 0 : provider.uri) {
|
|
36
42
|
return;
|
|
37
43
|
}
|
|
38
|
-
|
|
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
|
-
//
|
|
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: [
|
|
62
|
+
events: [],
|
|
46
63
|
methods: [
|
|
47
|
-
'
|
|
64
|
+
'eth_signTypedData',
|
|
48
65
|
'eth_signTransaction',
|
|
49
66
|
'eth_sign',
|
|
50
67
|
'personal_sign',
|
|
51
|
-
'
|
|
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
|
}
|
|
@@ -68,11 +89,13 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
68
89
|
});
|
|
69
90
|
}
|
|
70
91
|
refreshSession() {
|
|
71
|
-
var _a, _b, _c, _d;
|
|
92
|
+
var _a, _b, _c, _d, _e;
|
|
72
93
|
if ((_b = (_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session) === null || _b === void 0 ? void 0 : _b.topic) {
|
|
73
94
|
if (localStorage.getItem(this.sessionTopicKey) ===
|
|
74
95
|
((_d = (_c = WalletConnectV2.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
|
|
75
96
|
this.session = WalletConnectV2.provider.session;
|
|
97
|
+
this.activeAccount =
|
|
98
|
+
(_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined;
|
|
76
99
|
}
|
|
77
100
|
}
|
|
78
101
|
}
|
|
@@ -80,11 +103,15 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
80
103
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
81
104
|
yield this.initProvider();
|
|
82
105
|
yield this.initConnection();
|
|
106
|
+
this.isInitialized = true;
|
|
83
107
|
});
|
|
84
108
|
}
|
|
85
109
|
get sessionTopicKey() {
|
|
86
110
|
return sessionTopicKey(this.key);
|
|
87
111
|
}
|
|
112
|
+
get activeAccountKey() {
|
|
113
|
+
return activeAccountKey(this.key);
|
|
114
|
+
}
|
|
88
115
|
supportsNetworkSwitching() {
|
|
89
116
|
return true;
|
|
90
117
|
}
|
|
@@ -100,18 +127,22 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
100
127
|
}
|
|
101
128
|
const { name, data } = params.event;
|
|
102
129
|
if (name === 'chainChanged') {
|
|
103
|
-
|
|
130
|
+
const chainId = parseIntSafe.parseIntSafe(data);
|
|
131
|
+
if (chainId === undefined) {
|
|
104
132
|
walletConnectorCore.logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
|
|
105
133
|
return;
|
|
106
134
|
}
|
|
107
|
-
(_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners,
|
|
135
|
+
(_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, String(chainId));
|
|
108
136
|
}
|
|
109
137
|
else if (name === 'accountsChanged') {
|
|
110
|
-
if (
|
|
138
|
+
if (!Array.isArray(data)) {
|
|
111
139
|
walletConnectorCore.logger.debug(`received unexpected data for accountsChanged: ${data} with type ${typeof data}}`);
|
|
112
140
|
return;
|
|
113
141
|
}
|
|
114
|
-
|
|
142
|
+
// eslint-disable-next-line prefer-destructuring
|
|
143
|
+
const account = data[0].split(':')[2];
|
|
144
|
+
this.setActiveAccount(account);
|
|
145
|
+
(_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, [account]);
|
|
115
146
|
}
|
|
116
147
|
});
|
|
117
148
|
WalletConnectV2.provider.client.on('session_delete', () => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -148,15 +179,25 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
148
179
|
return new ethers.ethers.providers.Web3Provider(WalletConnectV2.provider, 'any');
|
|
149
180
|
}
|
|
150
181
|
fetchPublicAddress(opts) {
|
|
182
|
+
var _a, _b;
|
|
151
183
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
152
|
-
if (this.
|
|
153
|
-
return this.
|
|
184
|
+
if (this.activeAccount) {
|
|
185
|
+
return this.activeAccount;
|
|
154
186
|
}
|
|
155
|
-
if (!WalletConnectV2.provider) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
187
|
+
if (!WalletConnectV2.provider || !((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri)) {
|
|
188
|
+
walletConnectorCore.logger.debug('No WC2 provider found, re-initializing...');
|
|
189
|
+
yield this.endSession();
|
|
190
|
+
yield this.init();
|
|
191
|
+
// sleep 1 s to wait for connect call to finish
|
|
192
|
+
// the connect call isn't await-ed because it only resolves once
|
|
193
|
+
// the connection is established, but we need to wait for it to
|
|
194
|
+
// finish setting up the connection URI and making it available
|
|
195
|
+
// on the provider
|
|
196
|
+
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
197
|
+
if (!WalletConnectV2.provider || !((_b = WalletConnectV2.provider) === null || _b === void 0 ? void 0 : _b.uri)) {
|
|
198
|
+
walletConnectorCore.logger.debug('No WC2 provider found, escaping and throwing error');
|
|
199
|
+
throw new utils.DynamicError('No provider found');
|
|
200
|
+
}
|
|
160
201
|
}
|
|
161
202
|
const metadata = walletBook.getWalletBookWallet(this.name);
|
|
162
203
|
walletConnectorCore.performPlatformSpecificConnectionMethod(WalletConnectV2.provider.uri, metadata, {
|
|
@@ -168,13 +209,21 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
168
209
|
reject(new utils.DynamicError('No provider found'));
|
|
169
210
|
return;
|
|
170
211
|
}
|
|
212
|
+
ee.on('walletconnect_connection_failed', () => {
|
|
213
|
+
const error = new utils.DynamicError('Connection rejected. Please try again.');
|
|
214
|
+
error.code = 'connection_rejected';
|
|
215
|
+
if (WalletConnectV2.provider) {
|
|
216
|
+
WalletConnectV2.provider.uri = undefined;
|
|
217
|
+
}
|
|
218
|
+
reject(error);
|
|
219
|
+
});
|
|
171
220
|
WalletConnectV2.provider.on('connect', ({ session }) => {
|
|
172
221
|
if (!session) {
|
|
173
222
|
reject(new utils.DynamicError('No session found'));
|
|
174
223
|
}
|
|
175
|
-
this.session
|
|
176
|
-
|
|
177
|
-
resolve(this.
|
|
224
|
+
this.setSession(session);
|
|
225
|
+
this.setActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
|
|
226
|
+
resolve(this.activeAccount);
|
|
178
227
|
});
|
|
179
228
|
});
|
|
180
229
|
});
|
|
@@ -194,34 +243,69 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
194
243
|
const deepLink = walletConnectorCore.getDeepLink({ metadata, mode: 'regular' });
|
|
195
244
|
window.location.href = deepLink;
|
|
196
245
|
}
|
|
197
|
-
// eslint-disable-next-line prefer-destructuring
|
|
198
|
-
const address = this.session.namespaces.eip155.accounts[0].split(':')[2];
|
|
199
246
|
const web3Provider = this.getWeb3Provider();
|
|
200
|
-
|
|
247
|
+
const response = web3Provider.send('personal_sign', [
|
|
201
248
|
walletConnectorCore.utf8ToHex(messageToSign, true),
|
|
202
|
-
|
|
249
|
+
this.activeAccount,
|
|
203
250
|
]);
|
|
251
|
+
try {
|
|
252
|
+
// A terrible hack to get MM to sign the message when it is on the wrong chain
|
|
253
|
+
// Since MM supports only one chain at a time, it just hangs when we call
|
|
254
|
+
// to sign, and it is not on Mainnet. For some magical reason,
|
|
255
|
+
// when we attempt to call again it just works.
|
|
256
|
+
if (this.key === 'metamask') {
|
|
257
|
+
yield this.promiseWithTimeout(7000, response);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
walletConnectorCore.logger.debug('metmask failed to sign message');
|
|
262
|
+
throw e;
|
|
263
|
+
}
|
|
264
|
+
return response;
|
|
204
265
|
});
|
|
205
266
|
}
|
|
267
|
+
clearActiveAccount() {
|
|
268
|
+
localStorage.removeItem(this.activeAccountKey);
|
|
269
|
+
this.activeAccount = undefined;
|
|
270
|
+
}
|
|
271
|
+
clearSession() {
|
|
272
|
+
localStorage.removeItem(this.sessionTopicKey);
|
|
273
|
+
this.session = undefined;
|
|
274
|
+
}
|
|
275
|
+
setActiveAccount(account) {
|
|
276
|
+
localStorage.setItem(this.activeAccountKey, account);
|
|
277
|
+
this.activeAccount = account;
|
|
278
|
+
}
|
|
279
|
+
setSession(session) {
|
|
280
|
+
localStorage.setItem(this.sessionTopicKey, session.topic);
|
|
281
|
+
this.session = session;
|
|
282
|
+
}
|
|
206
283
|
endSession() {
|
|
284
|
+
var _a;
|
|
207
285
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (!WalletConnectV2.provider) {
|
|
286
|
+
this.clearActiveAccount();
|
|
287
|
+
this.clearSession();
|
|
288
|
+
if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session)) {
|
|
212
289
|
return;
|
|
213
290
|
}
|
|
214
291
|
try {
|
|
215
292
|
yield WalletConnectV2.provider.disconnect();
|
|
216
293
|
WalletConnectV2.provider.uri = undefined;
|
|
217
|
-
localStorage.removeItem(this.sessionTopicKey);
|
|
218
|
-
this.session = undefined;
|
|
219
294
|
}
|
|
220
295
|
catch (e) {
|
|
221
296
|
walletConnectorCore.logger.debug(e);
|
|
222
297
|
}
|
|
223
298
|
});
|
|
224
299
|
}
|
|
300
|
+
getNetwork() {
|
|
301
|
+
const _super = Object.create(null, {
|
|
302
|
+
getNetwork: { get: () => super.getNetwork }
|
|
303
|
+
});
|
|
304
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
305
|
+
yield this.initProvider();
|
|
306
|
+
return _super.getNetwork.call(this);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
225
309
|
providerSwitchNetwork({ network, provider, }) {
|
|
226
310
|
const _super = Object.create(null, {
|
|
227
311
|
providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
|
|
@@ -244,14 +328,46 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
|
|
|
244
328
|
});
|
|
245
329
|
}
|
|
246
330
|
getConnectedAccounts() {
|
|
331
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
332
|
+
yield this.initProvider();
|
|
333
|
+
this.refreshSession();
|
|
334
|
+
this.isInitialized = true;
|
|
335
|
+
if (!this.activeAccount) {
|
|
336
|
+
return [];
|
|
337
|
+
}
|
|
338
|
+
return [this.activeAccount];
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
getSupportedNetworks() {
|
|
247
342
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
248
343
|
yield this.initProvider();
|
|
249
344
|
this.refreshSession();
|
|
250
345
|
if (!this.session) {
|
|
251
346
|
return [];
|
|
252
347
|
}
|
|
253
|
-
|
|
348
|
+
const chains = [];
|
|
349
|
+
// Some wallet (i.e ZenGo) use namespaces.account to list supported chains
|
|
350
|
+
// while others use keys within the namespaces object
|
|
351
|
+
Object.keys(this.session.namespaces).forEach((key) => {
|
|
352
|
+
if (key.startsWith('eip155:')) {
|
|
353
|
+
chains.push(key.split(':')[1]);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
this.session.namespaces.eip155.accounts.forEach((account) => chains.push(account.split(':')[1]));
|
|
357
|
+
return chains.length ? chains : undefined;
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// a HACK for MM to sign message when the selected chain is not mainnet
|
|
361
|
+
promiseWithTimeout(ms, promise) {
|
|
362
|
+
// Create a promise that rejects in <ms> milliseconds
|
|
363
|
+
const timeout = new Promise((_, reject) => {
|
|
364
|
+
const id = setTimeout(() => {
|
|
365
|
+
clearTimeout(id);
|
|
366
|
+
reject(new utils.DynamicError(undefined, 'metamask_timeout'));
|
|
367
|
+
}, ms);
|
|
254
368
|
});
|
|
369
|
+
// Returns a race between our timeout and the passed in promise
|
|
370
|
+
return Promise.race([promise, timeout]);
|
|
255
371
|
}
|
|
256
372
|
}
|
|
257
373
|
|
|
@@ -12,6 +12,8 @@ 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;
|
|
15
17
|
canConnectViaQrCode: boolean;
|
|
16
18
|
isWalletConnect: boolean;
|
|
17
19
|
private static provider;
|
|
@@ -22,6 +24,7 @@ export declare class WalletConnectV2 extends EthWalletConnector {
|
|
|
22
24
|
private refreshSession;
|
|
23
25
|
init(): Promise<void>;
|
|
24
26
|
get sessionTopicKey(): string;
|
|
27
|
+
get activeAccountKey(): string;
|
|
25
28
|
supportsNetworkSwitching(): boolean;
|
|
26
29
|
setupEventListeners(listeners: WalletEventListeners): void;
|
|
27
30
|
teardownEventListeners(): void;
|
|
@@ -29,10 +32,17 @@ export declare class WalletConnectV2 extends EthWalletConnector {
|
|
|
29
32
|
getWeb3Provider(): ethers.providers.Web3Provider;
|
|
30
33
|
fetchPublicAddress(opts?: FetchPublicAddressOpts): Promise<string | undefined>;
|
|
31
34
|
signMessage(messageToSign: string): Promise<string | undefined>;
|
|
35
|
+
private clearActiveAccount;
|
|
36
|
+
private clearSession;
|
|
37
|
+
private setActiveAccount;
|
|
38
|
+
private setSession;
|
|
32
39
|
endSession(): Promise<void>;
|
|
40
|
+
getNetwork(): Promise<number | undefined>;
|
|
33
41
|
providerSwitchNetwork({ network, provider, }: {
|
|
34
42
|
network: EvmNetwork;
|
|
35
43
|
provider: ethers.providers.Web3Provider;
|
|
36
44
|
}): Promise<void>;
|
|
37
45
|
getConnectedAccounts(): Promise<string[]>;
|
|
46
|
+
getSupportedNetworks(): Promise<string[] | undefined>;
|
|
47
|
+
private promiseWithTimeout;
|
|
38
48
|
}
|
|
@@ -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 EventEmitter from 'eventemitter3';
|
|
4
5
|
import { logger, getDeepLink, 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,24 +32,39 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
27
32
|
if (provider === null || provider === void 0 ? void 0 : provider.uri) {
|
|
28
33
|
return;
|
|
29
34
|
}
|
|
30
|
-
|
|
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
|
-
//
|
|
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: [
|
|
53
|
+
events: [],
|
|
38
54
|
methods: [
|
|
39
|
-
'
|
|
55
|
+
'eth_signTypedData',
|
|
40
56
|
'eth_signTransaction',
|
|
41
57
|
'eth_sign',
|
|
42
58
|
'personal_sign',
|
|
43
|
-
'
|
|
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
|
}
|
|
@@ -60,11 +80,13 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
60
80
|
});
|
|
61
81
|
}
|
|
62
82
|
refreshSession() {
|
|
63
|
-
var _a, _b, _c, _d;
|
|
83
|
+
var _a, _b, _c, _d, _e;
|
|
64
84
|
if ((_b = (_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session) === null || _b === void 0 ? void 0 : _b.topic) {
|
|
65
85
|
if (localStorage.getItem(this.sessionTopicKey) ===
|
|
66
86
|
((_d = (_c = WalletConnectV2.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
|
|
67
87
|
this.session = WalletConnectV2.provider.session;
|
|
88
|
+
this.activeAccount =
|
|
89
|
+
(_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined;
|
|
68
90
|
}
|
|
69
91
|
}
|
|
70
92
|
}
|
|
@@ -72,11 +94,15 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
72
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
95
|
yield this.initProvider();
|
|
74
96
|
yield this.initConnection();
|
|
97
|
+
this.isInitialized = true;
|
|
75
98
|
});
|
|
76
99
|
}
|
|
77
100
|
get sessionTopicKey() {
|
|
78
101
|
return sessionTopicKey(this.key);
|
|
79
102
|
}
|
|
103
|
+
get activeAccountKey() {
|
|
104
|
+
return activeAccountKey(this.key);
|
|
105
|
+
}
|
|
80
106
|
supportsNetworkSwitching() {
|
|
81
107
|
return true;
|
|
82
108
|
}
|
|
@@ -92,18 +118,22 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
92
118
|
}
|
|
93
119
|
const { name, data } = params.event;
|
|
94
120
|
if (name === 'chainChanged') {
|
|
95
|
-
|
|
121
|
+
const chainId = parseIntSafe(data);
|
|
122
|
+
if (chainId === undefined) {
|
|
96
123
|
logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
|
|
97
124
|
return;
|
|
98
125
|
}
|
|
99
|
-
(_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners,
|
|
126
|
+
(_a = listeners.onChainChange) === null || _a === void 0 ? void 0 : _a.call(listeners, String(chainId));
|
|
100
127
|
}
|
|
101
128
|
else if (name === 'accountsChanged') {
|
|
102
|
-
if (
|
|
129
|
+
if (!Array.isArray(data)) {
|
|
103
130
|
logger.debug(`received unexpected data for accountsChanged: ${data} with type ${typeof data}}`);
|
|
104
131
|
return;
|
|
105
132
|
}
|
|
106
|
-
|
|
133
|
+
// eslint-disable-next-line prefer-destructuring
|
|
134
|
+
const account = data[0].split(':')[2];
|
|
135
|
+
this.setActiveAccount(account);
|
|
136
|
+
(_b = listeners.onAccountChange) === null || _b === void 0 ? void 0 : _b.call(listeners, [account]);
|
|
107
137
|
}
|
|
108
138
|
});
|
|
109
139
|
WalletConnectV2.provider.client.on('session_delete', () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -140,15 +170,25 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
140
170
|
return new ethers.providers.Web3Provider(WalletConnectV2.provider, 'any');
|
|
141
171
|
}
|
|
142
172
|
fetchPublicAddress(opts) {
|
|
173
|
+
var _a, _b;
|
|
143
174
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
if (this.
|
|
145
|
-
return this.
|
|
175
|
+
if (this.activeAccount) {
|
|
176
|
+
return this.activeAccount;
|
|
146
177
|
}
|
|
147
|
-
if (!WalletConnectV2.provider) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
178
|
+
if (!WalletConnectV2.provider || !((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri)) {
|
|
179
|
+
logger.debug('No WC2 provider found, re-initializing...');
|
|
180
|
+
yield this.endSession();
|
|
181
|
+
yield this.init();
|
|
182
|
+
// sleep 1 s to wait for connect call to finish
|
|
183
|
+
// the connect call isn't await-ed because it only resolves once
|
|
184
|
+
// the connection is established, but we need to wait for it to
|
|
185
|
+
// finish setting up the connection URI and making it available
|
|
186
|
+
// on the provider
|
|
187
|
+
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
188
|
+
if (!WalletConnectV2.provider || !((_b = WalletConnectV2.provider) === null || _b === void 0 ? void 0 : _b.uri)) {
|
|
189
|
+
logger.debug('No WC2 provider found, escaping and throwing error');
|
|
190
|
+
throw new DynamicError('No provider found');
|
|
191
|
+
}
|
|
152
192
|
}
|
|
153
193
|
const metadata = getWalletBookWallet(this.name);
|
|
154
194
|
performPlatformSpecificConnectionMethod(WalletConnectV2.provider.uri, metadata, {
|
|
@@ -160,13 +200,21 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
160
200
|
reject(new DynamicError('No provider found'));
|
|
161
201
|
return;
|
|
162
202
|
}
|
|
203
|
+
ee.on('walletconnect_connection_failed', () => {
|
|
204
|
+
const error = new DynamicError('Connection rejected. Please try again.');
|
|
205
|
+
error.code = 'connection_rejected';
|
|
206
|
+
if (WalletConnectV2.provider) {
|
|
207
|
+
WalletConnectV2.provider.uri = undefined;
|
|
208
|
+
}
|
|
209
|
+
reject(error);
|
|
210
|
+
});
|
|
163
211
|
WalletConnectV2.provider.on('connect', ({ session }) => {
|
|
164
212
|
if (!session) {
|
|
165
213
|
reject(new DynamicError('No session found'));
|
|
166
214
|
}
|
|
167
|
-
this.session
|
|
168
|
-
|
|
169
|
-
resolve(this.
|
|
215
|
+
this.setSession(session);
|
|
216
|
+
this.setActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
|
|
217
|
+
resolve(this.activeAccount);
|
|
170
218
|
});
|
|
171
219
|
});
|
|
172
220
|
});
|
|
@@ -186,34 +234,69 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
186
234
|
const deepLink = getDeepLink({ metadata, mode: 'regular' });
|
|
187
235
|
window.location.href = deepLink;
|
|
188
236
|
}
|
|
189
|
-
// eslint-disable-next-line prefer-destructuring
|
|
190
|
-
const address = this.session.namespaces.eip155.accounts[0].split(':')[2];
|
|
191
237
|
const web3Provider = this.getWeb3Provider();
|
|
192
|
-
|
|
238
|
+
const response = web3Provider.send('personal_sign', [
|
|
193
239
|
utf8ToHex(messageToSign, true),
|
|
194
|
-
|
|
240
|
+
this.activeAccount,
|
|
195
241
|
]);
|
|
242
|
+
try {
|
|
243
|
+
// A terrible hack to get MM to sign the message when it is on the wrong chain
|
|
244
|
+
// Since MM supports only one chain at a time, it just hangs when we call
|
|
245
|
+
// to sign, and it is not on Mainnet. For some magical reason,
|
|
246
|
+
// when we attempt to call again it just works.
|
|
247
|
+
if (this.key === 'metamask') {
|
|
248
|
+
yield this.promiseWithTimeout(7000, response);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (e) {
|
|
252
|
+
logger.debug('metmask failed to sign message');
|
|
253
|
+
throw e;
|
|
254
|
+
}
|
|
255
|
+
return response;
|
|
196
256
|
});
|
|
197
257
|
}
|
|
258
|
+
clearActiveAccount() {
|
|
259
|
+
localStorage.removeItem(this.activeAccountKey);
|
|
260
|
+
this.activeAccount = undefined;
|
|
261
|
+
}
|
|
262
|
+
clearSession() {
|
|
263
|
+
localStorage.removeItem(this.sessionTopicKey);
|
|
264
|
+
this.session = undefined;
|
|
265
|
+
}
|
|
266
|
+
setActiveAccount(account) {
|
|
267
|
+
localStorage.setItem(this.activeAccountKey, account);
|
|
268
|
+
this.activeAccount = account;
|
|
269
|
+
}
|
|
270
|
+
setSession(session) {
|
|
271
|
+
localStorage.setItem(this.sessionTopicKey, session.topic);
|
|
272
|
+
this.session = session;
|
|
273
|
+
}
|
|
198
274
|
endSession() {
|
|
275
|
+
var _a;
|
|
199
276
|
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (!WalletConnectV2.provider) {
|
|
277
|
+
this.clearActiveAccount();
|
|
278
|
+
this.clearSession();
|
|
279
|
+
if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.session)) {
|
|
204
280
|
return;
|
|
205
281
|
}
|
|
206
282
|
try {
|
|
207
283
|
yield WalletConnectV2.provider.disconnect();
|
|
208
284
|
WalletConnectV2.provider.uri = undefined;
|
|
209
|
-
localStorage.removeItem(this.sessionTopicKey);
|
|
210
|
-
this.session = undefined;
|
|
211
285
|
}
|
|
212
286
|
catch (e) {
|
|
213
287
|
logger.debug(e);
|
|
214
288
|
}
|
|
215
289
|
});
|
|
216
290
|
}
|
|
291
|
+
getNetwork() {
|
|
292
|
+
const _super = Object.create(null, {
|
|
293
|
+
getNetwork: { get: () => super.getNetwork }
|
|
294
|
+
});
|
|
295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
yield this.initProvider();
|
|
297
|
+
return _super.getNetwork.call(this);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
217
300
|
providerSwitchNetwork({ network, provider, }) {
|
|
218
301
|
const _super = Object.create(null, {
|
|
219
302
|
providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
|
|
@@ -236,14 +319,46 @@ class WalletConnectV2 extends EthWalletConnector {
|
|
|
236
319
|
});
|
|
237
320
|
}
|
|
238
321
|
getConnectedAccounts() {
|
|
322
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
323
|
+
yield this.initProvider();
|
|
324
|
+
this.refreshSession();
|
|
325
|
+
this.isInitialized = true;
|
|
326
|
+
if (!this.activeAccount) {
|
|
327
|
+
return [];
|
|
328
|
+
}
|
|
329
|
+
return [this.activeAccount];
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
getSupportedNetworks() {
|
|
239
333
|
return __awaiter(this, void 0, void 0, function* () {
|
|
240
334
|
yield this.initProvider();
|
|
241
335
|
this.refreshSession();
|
|
242
336
|
if (!this.session) {
|
|
243
337
|
return [];
|
|
244
338
|
}
|
|
245
|
-
|
|
339
|
+
const chains = [];
|
|
340
|
+
// Some wallet (i.e ZenGo) use namespaces.account to list supported chains
|
|
341
|
+
// while others use keys within the namespaces object
|
|
342
|
+
Object.keys(this.session.namespaces).forEach((key) => {
|
|
343
|
+
if (key.startsWith('eip155:')) {
|
|
344
|
+
chains.push(key.split(':')[1]);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
this.session.namespaces.eip155.accounts.forEach((account) => chains.push(account.split(':')[1]));
|
|
348
|
+
return chains.length ? chains : undefined;
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// a HACK for MM to sign message when the selected chain is not mainnet
|
|
352
|
+
promiseWithTimeout(ms, promise) {
|
|
353
|
+
// Create a promise that rejects in <ms> milliseconds
|
|
354
|
+
const timeout = new Promise((_, reject) => {
|
|
355
|
+
const id = setTimeout(() => {
|
|
356
|
+
clearTimeout(id);
|
|
357
|
+
reject(new DynamicError(undefined, 'metamask_timeout'));
|
|
358
|
+
}, ms);
|
|
246
359
|
});
|
|
360
|
+
// Returns a race between our timeout and the passed in promise
|
|
361
|
+
return Promise.race([promise, timeout]);
|
|
247
362
|
}
|
|
248
363
|
}
|
|
249
364
|
|