@dynamic-labs/ethereum 0.17.17 → 0.17.19

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,15 @@
1
1
 
2
+ ### [0.17.19](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.18...v0.17.19) (2023-07-02)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * log out if there's any session sync issue ([#2548](https://github.com/dynamic-labs/DynamicAuth/issues/2548)) ([3f92bab](https://github.com/dynamic-labs/DynamicAuth/commit/3f92bab1b6b317f4a024a68d4d220921bad3437c))
8
+ * WC2 sign-message on non-selected chain ([#2551](https://github.com/dynamic-labs/DynamicAuth/issues/2551)) ([c455e53](https://github.com/dynamic-labs/DynamicAuth/commit/c455e530c964b2865ffd29529546faddf2a57096)), closes [#2544](https://github.com/dynamic-labs/DynamicAuth/issues/2544) [#2552](https://github.com/dynamic-labs/DynamicAuth/issues/2552) [#2525](https://github.com/dynamic-labs/DynamicAuth/issues/2525) [#2500](https://github.com/dynamic-labs/DynamicAuth/issues/2500) [#2546](https://github.com/dynamic-labs/DynamicAuth/issues/2546)
9
+ * **wcv2:** don't force required chain to eth in case is not enabled ([#2538](https://github.com/dynamic-labs/DynamicAuth/issues/2538)) ([933dc20](https://github.com/dynamic-labs/DynamicAuth/commit/933dc20b300f0740a438810b9e65d693aae61689))
10
+
11
+ ### [0.17.18](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.17...v0.17.18) (2023-06-29)
12
+
2
13
  ### [0.17.17](https://github.com/dynamic-labs/DynamicAuth/compare/v0.17.16...v0.17.17) (2023-06-29)
3
14
 
4
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/ethereum",
3
- "version": "0.17.17",
3
+ "version": "0.17.19",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/dynamic-labs/DynamicAuth.git",
@@ -32,11 +32,11 @@
32
32
  "ethers": "5.7.2",
33
33
  "eventemitter3": "5.0.1",
34
34
  "buffer": "6.0.3",
35
- "@dynamic-labs/rpc-providers": "0.17.17",
36
- "@dynamic-labs/types": "0.17.17",
37
- "@dynamic-labs/utils": "0.17.17",
38
- "@dynamic-labs/wallet-book": "0.17.17",
39
- "@dynamic-labs/wallet-connector-core": "0.17.17"
35
+ "@dynamic-labs/rpc-providers": "0.17.19",
36
+ "@dynamic-labs/types": "0.17.19",
37
+ "@dynamic-labs/utils": "0.17.19",
38
+ "@dynamic-labs/wallet-book": "0.17.19",
39
+ "@dynamic-labs/wallet-connector-core": "0.17.19"
40
40
  },
41
41
  "peerDependencies": {}
42
42
  }
@@ -141,6 +141,12 @@ class WalletConnect extends EthWalletConnector.EthWalletConnector {
141
141
  return client.accounts;
142
142
  });
143
143
  }
144
+ getSession() {
145
+ var _a;
146
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
147
+ return (_a = this.client) === null || _a === void 0 ? void 0 : _a.session;
148
+ });
149
+ }
144
150
  }
145
151
 
146
152
  exports.WalletConnect = WalletConnect;
@@ -3,6 +3,19 @@ import { ethers } from 'ethers';
3
3
  import { Chain, FetchPublicAddressOpts, WalletEventListeners } from '@dynamic-labs/wallet-connector-core';
4
4
  import { EvmNetwork } from '@dynamic-labs/types';
5
5
  import { EthWalletConnector, EthWalletConnectorOpts } from '../EthWalletConnector';
6
+ type ConnectorSession = {
7
+ connected: boolean;
8
+ accounts: string[];
9
+ chainId: number;
10
+ bridge: string;
11
+ key: string;
12
+ clientId: string;
13
+ clientMeta: any;
14
+ peerId: string;
15
+ peerMeta: any;
16
+ handshakeId: number;
17
+ handshakeTopic: string;
18
+ };
6
19
  export type WalletConnectOpts = EthWalletConnectorOpts & {
7
20
  walletConnectV1Bridge: string;
8
21
  walletName: string;
@@ -32,4 +45,6 @@ export declare class WalletConnect extends EthWalletConnector {
32
45
  provider: ethers.providers.Web3Provider;
33
46
  }): Promise<void>;
34
47
  getConnectedAccounts(): Promise<string[]>;
48
+ getSession(): Promise<ConnectorSession | undefined>;
35
49
  }
50
+ export {};
@@ -133,6 +133,12 @@ class WalletConnect extends EthWalletConnector {
133
133
  return client.accounts;
134
134
  });
135
135
  }
136
+ getSession() {
137
+ var _a;
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ return (_a = this.client) === null || _a === void 0 ? void 0 : _a.session;
140
+ });
141
+ }
136
142
  }
137
143
 
138
144
  export { WalletConnect };
@@ -32,6 +32,7 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
32
32
  this.projectId = opts.projectId;
33
33
  }
34
34
  initConnection() {
35
+ var _a;
35
36
  return _tslib.__awaiter(this, void 0, void 0, function* () {
36
37
  const { provider } = WalletConnectV2;
37
38
  if (!provider) {
@@ -41,7 +42,9 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
41
42
  if (provider === null || provider === void 0 ? void 0 : provider.uri) {
42
43
  return;
43
44
  }
44
- const defaultChain = 1;
45
+ const defaultChain = ((_a = this.evmNetworks) === null || _a === void 0 ? void 0 : _a.length)
46
+ ? this.evmNetworks[0].chainId
47
+ : 1;
45
48
  provider
46
49
  .connect({
47
50
  namespaces: {
@@ -81,6 +84,7 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
81
84
  createInitProviderPromise() {
82
85
  return _tslib.__awaiter(this, void 0, void 0, function* () {
83
86
  const provider = yield Provider__default["default"].init({
87
+ logger: walletConnectorCore.logger.logLevel.toLowerCase() === 'debug' ? 'debug' : undefined,
84
88
  projectId: this.projectId,
85
89
  });
86
90
  WalletConnectV2.provider = provider;
@@ -167,6 +171,21 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
167
171
  WalletConnectV2.provider.client.removeAllListeners('session_event');
168
172
  WalletConnectV2.provider.client.removeAllListeners('session_delete');
169
173
  }
174
+ getDeepLink() {
175
+ var _a, _b;
176
+ if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri))
177
+ return;
178
+ const wallet = walletBook.getWalletBookWallet(this.name);
179
+ if (!utils.isMobile() && !((_b = wallet.desktop) === null || _b === void 0 ? void 0 : _b.native)) {
180
+ return undefined;
181
+ }
182
+ return walletConnectorCore.getDeepLink({
183
+ isWC2: true,
184
+ metadata: wallet,
185
+ mode: 'regular',
186
+ uri: WalletConnectV2.provider.uri,
187
+ });
188
+ }
170
189
  getWeb3Provider() {
171
190
  if (!WalletConnectV2.provider) {
172
191
  return;
@@ -223,8 +242,36 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
223
242
  });
224
243
  });
225
244
  }
245
+ /**
246
+ * WalletConnect V2 will fail to send the sign message request if the chainId
247
+ * is not the same as the one in the session. This method will wait for the
248
+ * chainId to change and then retry the sign message request.
249
+ *
250
+ * Otherwise it will just return the result of the sign message request.
251
+ *
252
+ * @param signMessageFn - Function to sign message with provider
253
+ * @param messageToSign - Message to sign
254
+ * @returns
255
+ */
256
+ waitForSignMessage(signMessageFn, messageToSign) {
257
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
258
+ const raceConditionPromise = new Promise((resolve) => {
259
+ // Create listener for chain change event
260
+ this.setupEventListeners({
261
+ onChainChange: () => _tslib.__awaiter(this, void 0, void 0, function* () {
262
+ resolve({ success: false });
263
+ }),
264
+ });
265
+ signMessageFn(messageToSign).then((result) => resolve({ signedMessage: result, success: true }));
266
+ });
267
+ const signedMessageResult = yield raceConditionPromise;
268
+ if (signedMessageResult.success === false) {
269
+ return signMessageFn(messageToSign);
270
+ }
271
+ return signedMessageResult.signedMessage;
272
+ });
273
+ }
226
274
  signMessage(messageToSign) {
227
- var _a, _b;
228
275
  return _tslib.__awaiter(this, void 0, void 0, function* () {
229
276
  if (!this.session) {
230
277
  throw new utils.DynamicError('no session');
@@ -234,30 +281,27 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
234
281
  }
235
282
  const metadata = walletBook.getWalletBookWallet(this.name);
236
283
  if (utils.isMobile()) {
237
- const deepLink = ((_a = metadata['mobile']) === null || _a === void 0 ? void 0 : _a.native) || ((_b = metadata['mobile']) === null || _b === void 0 ? void 0 : _b.universal) || '';
284
+ // for sign message, no uri is needed because the uri encodes connection details,
285
+ // and at this point we are already connected
286
+ const deepLink = walletConnectorCore.getDeepLink({
287
+ isWC2: true,
288
+ metadata,
289
+ mode: 'regular',
290
+ uri: WalletConnectV2.provider.uri,
291
+ });
238
292
  window.location.href = deepLink;
239
293
  }
240
294
  const web3Provider = this.getWeb3Provider();
241
295
  if (!web3Provider) {
242
296
  throw new utils.DynamicError('No web3 provider found');
243
297
  }
244
- const response = web3Provider.send('personal_sign', [
245
- walletConnectorCore.utf8ToHex(messageToSign, true),
246
- this.activeAccount,
247
- ]);
248
- try {
249
- // A terrible hack to get MM to sign the message when it is on the wrong chain
250
- // Since MM supports only one chain at a time, it just hangs when we call
251
- // to sign, and it is not on Mainnet. For some magical reason,
252
- // when we attempt to call again it just works.
253
- if (this.key === 'metamask') {
254
- yield this.promiseWithTimeout(7000, response);
255
- }
256
- }
257
- catch (e) {
258
- walletConnectorCore.logger.debug('metmask failed to sign message');
259
- throw e;
260
- }
298
+ const signMessageFn = (messageToSign) => _tslib.__awaiter(this, void 0, void 0, function* () {
299
+ return web3Provider.send('personal_sign', [
300
+ walletConnectorCore.utf8ToHex(messageToSign, true),
301
+ this.activeAccount,
302
+ ]);
303
+ });
304
+ const response = yield this.waitForSignMessage(signMessageFn, messageToSign);
261
305
  return response;
262
306
  });
263
307
  }
@@ -287,7 +331,9 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
287
331
  }
288
332
  try {
289
333
  yield WalletConnectV2.provider.disconnect();
290
- WalletConnectV2.provider.uri = undefined;
334
+ // We must unset provider on logout so that a new session can be established
335
+ // If we don't then the provider will still have the old session and will hang
336
+ WalletConnectV2.provider = undefined;
291
337
  }
292
338
  catch (e) {
293
339
  walletConnectorCore.logger.debug(e);
@@ -354,18 +400,6 @@ class WalletConnectV2 extends EthWalletConnector.EthWalletConnector {
354
400
  return chains.length ? chains : undefined;
355
401
  });
356
402
  }
357
- // a HACK for MM to sign message when the selected chain is not mainnet
358
- promiseWithTimeout(ms, promise) {
359
- // Create a promise that rejects in <ms> milliseconds
360
- const timeout = new Promise((_, reject) => {
361
- const id = setTimeout(() => {
362
- clearTimeout(id);
363
- reject(new utils.DynamicError(undefined, 'metamask_timeout'));
364
- }, ms);
365
- });
366
- // Returns a race between our timeout and the passed in promise
367
- return Promise.race([promise, timeout]);
368
- }
369
403
  }
370
404
 
371
405
  exports.WalletConnectV2 = WalletConnectV2;
@@ -30,8 +30,21 @@ export declare class WalletConnectV2 extends EthWalletConnector {
30
30
  supportsNetworkSwitching(): boolean;
31
31
  setupEventListeners(listeners: WalletEventListeners): void;
32
32
  teardownEventListeners(): void;
33
+ getDeepLink(): string | undefined;
33
34
  getWeb3Provider(): ethers.providers.Web3Provider | undefined;
34
35
  fetchPublicAddress(opts?: FetchPublicAddressOpts): Promise<string | undefined>;
36
+ /**
37
+ * WalletConnect V2 will fail to send the sign message request if the chainId
38
+ * is not the same as the one in the session. This method will wait for the
39
+ * chainId to change and then retry the sign message request.
40
+ *
41
+ * Otherwise it will just return the result of the sign message request.
42
+ *
43
+ * @param signMessageFn - Function to sign message with provider
44
+ * @param messageToSign - Message to sign
45
+ * @returns
46
+ */
47
+ protected waitForSignMessage(signMessageFn: (messageToSign: string) => Promise<string | undefined>, messageToSign: string): Promise<string | undefined>;
35
48
  signMessage(messageToSign: string): Promise<string | undefined>;
36
49
  private clearActiveAccount;
37
50
  private clearSession;
@@ -45,5 +58,4 @@ export declare class WalletConnectV2 extends EthWalletConnector {
45
58
  }): Promise<void>;
46
59
  getConnectedAccounts(): Promise<string[]>;
47
60
  getSupportedNetworks(): Promise<string[] | undefined>;
48
- private promiseWithTimeout;
49
61
  }
@@ -2,7 +2,7 @@ import { __awaiter } from '../../_virtual/_tslib.js';
2
2
  import Provider from '@walletconnect/universal-provider';
3
3
  import { ethers } from 'ethers';
4
4
  import EventEmitter from 'eventemitter3';
5
- import { logger, performPlatformSpecificConnectionMethod, utf8ToHex } from '@dynamic-labs/wallet-connector-core';
5
+ import { logger, getDeepLink, performPlatformSpecificConnectionMethod, utf8ToHex } from '@dynamic-labs/wallet-connector-core';
6
6
  import { getWalletBookWallet } from '@dynamic-labs/wallet-book';
7
7
  import { DynamicError, isMobile } from '@dynamic-labs/utils';
8
8
  import { EthWalletConnector } from '../EthWalletConnector.js';
@@ -23,6 +23,7 @@ class WalletConnectV2 extends EthWalletConnector {
23
23
  this.projectId = opts.projectId;
24
24
  }
25
25
  initConnection() {
26
+ var _a;
26
27
  return __awaiter(this, void 0, void 0, function* () {
27
28
  const { provider } = WalletConnectV2;
28
29
  if (!provider) {
@@ -32,7 +33,9 @@ class WalletConnectV2 extends EthWalletConnector {
32
33
  if (provider === null || provider === void 0 ? void 0 : provider.uri) {
33
34
  return;
34
35
  }
35
- const defaultChain = 1;
36
+ const defaultChain = ((_a = this.evmNetworks) === null || _a === void 0 ? void 0 : _a.length)
37
+ ? this.evmNetworks[0].chainId
38
+ : 1;
36
39
  provider
37
40
  .connect({
38
41
  namespaces: {
@@ -72,6 +75,7 @@ class WalletConnectV2 extends EthWalletConnector {
72
75
  createInitProviderPromise() {
73
76
  return __awaiter(this, void 0, void 0, function* () {
74
77
  const provider = yield Provider.init({
78
+ logger: logger.logLevel.toLowerCase() === 'debug' ? 'debug' : undefined,
75
79
  projectId: this.projectId,
76
80
  });
77
81
  WalletConnectV2.provider = provider;
@@ -158,6 +162,21 @@ class WalletConnectV2 extends EthWalletConnector {
158
162
  WalletConnectV2.provider.client.removeAllListeners('session_event');
159
163
  WalletConnectV2.provider.client.removeAllListeners('session_delete');
160
164
  }
165
+ getDeepLink() {
166
+ var _a, _b;
167
+ if (!((_a = WalletConnectV2.provider) === null || _a === void 0 ? void 0 : _a.uri))
168
+ return;
169
+ const wallet = getWalletBookWallet(this.name);
170
+ if (!isMobile() && !((_b = wallet.desktop) === null || _b === void 0 ? void 0 : _b.native)) {
171
+ return undefined;
172
+ }
173
+ return getDeepLink({
174
+ isWC2: true,
175
+ metadata: wallet,
176
+ mode: 'regular',
177
+ uri: WalletConnectV2.provider.uri,
178
+ });
179
+ }
161
180
  getWeb3Provider() {
162
181
  if (!WalletConnectV2.provider) {
163
182
  return;
@@ -214,8 +233,36 @@ class WalletConnectV2 extends EthWalletConnector {
214
233
  });
215
234
  });
216
235
  }
236
+ /**
237
+ * WalletConnect V2 will fail to send the sign message request if the chainId
238
+ * is not the same as the one in the session. This method will wait for the
239
+ * chainId to change and then retry the sign message request.
240
+ *
241
+ * Otherwise it will just return the result of the sign message request.
242
+ *
243
+ * @param signMessageFn - Function to sign message with provider
244
+ * @param messageToSign - Message to sign
245
+ * @returns
246
+ */
247
+ waitForSignMessage(signMessageFn, messageToSign) {
248
+ return __awaiter(this, void 0, void 0, function* () {
249
+ const raceConditionPromise = new Promise((resolve) => {
250
+ // Create listener for chain change event
251
+ this.setupEventListeners({
252
+ onChainChange: () => __awaiter(this, void 0, void 0, function* () {
253
+ resolve({ success: false });
254
+ }),
255
+ });
256
+ signMessageFn(messageToSign).then((result) => resolve({ signedMessage: result, success: true }));
257
+ });
258
+ const signedMessageResult = yield raceConditionPromise;
259
+ if (signedMessageResult.success === false) {
260
+ return signMessageFn(messageToSign);
261
+ }
262
+ return signedMessageResult.signedMessage;
263
+ });
264
+ }
217
265
  signMessage(messageToSign) {
218
- var _a, _b;
219
266
  return __awaiter(this, void 0, void 0, function* () {
220
267
  if (!this.session) {
221
268
  throw new DynamicError('no session');
@@ -225,30 +272,27 @@ class WalletConnectV2 extends EthWalletConnector {
225
272
  }
226
273
  const metadata = getWalletBookWallet(this.name);
227
274
  if (isMobile()) {
228
- const deepLink = ((_a = metadata['mobile']) === null || _a === void 0 ? void 0 : _a.native) || ((_b = metadata['mobile']) === null || _b === void 0 ? void 0 : _b.universal) || '';
275
+ // for sign message, no uri is needed because the uri encodes connection details,
276
+ // and at this point we are already connected
277
+ const deepLink = getDeepLink({
278
+ isWC2: true,
279
+ metadata,
280
+ mode: 'regular',
281
+ uri: WalletConnectV2.provider.uri,
282
+ });
229
283
  window.location.href = deepLink;
230
284
  }
231
285
  const web3Provider = this.getWeb3Provider();
232
286
  if (!web3Provider) {
233
287
  throw new DynamicError('No web3 provider found');
234
288
  }
235
- const response = web3Provider.send('personal_sign', [
236
- utf8ToHex(messageToSign, true),
237
- this.activeAccount,
238
- ]);
239
- try {
240
- // A terrible hack to get MM to sign the message when it is on the wrong chain
241
- // Since MM supports only one chain at a time, it just hangs when we call
242
- // to sign, and it is not on Mainnet. For some magical reason,
243
- // when we attempt to call again it just works.
244
- if (this.key === 'metamask') {
245
- yield this.promiseWithTimeout(7000, response);
246
- }
247
- }
248
- catch (e) {
249
- logger.debug('metmask failed to sign message');
250
- throw e;
251
- }
289
+ const signMessageFn = (messageToSign) => __awaiter(this, void 0, void 0, function* () {
290
+ return web3Provider.send('personal_sign', [
291
+ utf8ToHex(messageToSign, true),
292
+ this.activeAccount,
293
+ ]);
294
+ });
295
+ const response = yield this.waitForSignMessage(signMessageFn, messageToSign);
252
296
  return response;
253
297
  });
254
298
  }
@@ -278,7 +322,9 @@ class WalletConnectV2 extends EthWalletConnector {
278
322
  }
279
323
  try {
280
324
  yield WalletConnectV2.provider.disconnect();
281
- WalletConnectV2.provider.uri = undefined;
325
+ // We must unset provider on logout so that a new session can be established
326
+ // If we don't then the provider will still have the old session and will hang
327
+ WalletConnectV2.provider = undefined;
282
328
  }
283
329
  catch (e) {
284
330
  logger.debug(e);
@@ -345,18 +391,6 @@ class WalletConnectV2 extends EthWalletConnector {
345
391
  return chains.length ? chains : undefined;
346
392
  });
347
393
  }
348
- // a HACK for MM to sign message when the selected chain is not mainnet
349
- promiseWithTimeout(ms, promise) {
350
- // Create a promise that rejects in <ms> milliseconds
351
- const timeout = new Promise((_, reject) => {
352
- const id = setTimeout(() => {
353
- clearTimeout(id);
354
- reject(new DynamicError(undefined, 'metamask_timeout'));
355
- }, ms);
356
- });
357
- // Returns a race between our timeout and the passed in promise
358
- return Promise.race([promise, timeout]);
359
- }
360
394
  }
361
395
 
362
396
  export { WalletConnectV2 };