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