@dynamic-labs/ethereum 2.0.0-alpha.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/package.json +10 -9
  3. package/src/EthWalletConnector.cjs +12 -1
  4. package/src/EthWalletConnector.d.ts +13 -10
  5. package/src/EthWalletConnector.js +12 -1
  6. package/src/coinbase/client/client.cjs +14 -14
  7. package/src/coinbase/client/client.d.ts +5 -4
  8. package/src/coinbase/client/client.js +13 -13
  9. package/src/coinbase/client/types.d.ts +6 -3
  10. package/src/coinbase/coinbase.cjs +30 -13
  11. package/src/coinbase/coinbase.d.ts +5 -4
  12. package/src/coinbase/coinbase.js +31 -14
  13. package/src/ethProviderHelper.cjs +11 -6
  14. package/src/ethProviderHelper.d.ts +6 -4
  15. package/src/ethProviderHelper.js +11 -6
  16. package/src/index.cjs +3 -1
  17. package/src/index.d.ts +1 -0
  18. package/src/index.js +3 -2
  19. package/src/injected/InjectedWalletBase.cjs +28 -11
  20. package/src/injected/InjectedWalletBase.d.ts +2 -2
  21. package/src/injected/InjectedWalletBase.js +28 -11
  22. package/src/injected/PhantomEvm.cjs +3 -3
  23. package/src/injected/PhantomEvm.d.ts +1 -1
  24. package/src/injected/PhantomEvm.js +3 -3
  25. package/src/injected/Zerion.cjs +38 -0
  26. package/src/injected/Zerion.d.ts +10 -0
  27. package/src/injected/Zerion.js +34 -0
  28. package/src/injected/fetchInjectedWalletConnectors.cjs +25 -0
  29. package/src/injected/fetchInjectedWalletConnectors.js +25 -0
  30. package/src/utils/index.d.ts +1 -0
  31. package/src/utils/isEthWalletConnector/index.d.ts +1 -0
  32. package/src/utils/isEthWalletConnector/isEthWalletConnector.cjs +7 -0
  33. package/src/utils/isEthWalletConnector/isEthWalletConnector.d.ts +3 -0
  34. package/src/utils/isEthWalletConnector/isEthWalletConnector.js +3 -0
  35. package/src/walletConnect/index.d.ts +1 -1
  36. package/src/walletConnect/walletConnect.cjs +114 -75
  37. package/src/walletConnect/walletConnect.d.ts +19 -18
  38. package/src/walletConnect/walletConnect.js +113 -74
@@ -1,10 +1,11 @@
1
1
  import { __awaiter } from '../../_virtual/_tslib.js';
2
- import Provider from '@walletconnect/universal-provider';
2
+ import EthereumProvider from '@walletconnect/ethereum-provider';
3
3
  import EventEmitter from 'eventemitter3';
4
4
  import { createWalletClient, custom } from 'viem';
5
- import { DynamicError, sleep, isMobile } from '@dynamic-labs/utils';
6
- import { getWalletBookWallet } from '@dynamic-labs/wallet-book';
7
5
  import { logger, performPlatformSpecificConnectionMethod, getDeepLink } from '@dynamic-labs/wallet-connector-core';
6
+ import { getWalletBookWallet } from '@dynamic-labs/wallet-book';
7
+ import { DynamicError, sleep, isMobile } from '@dynamic-labs/utils';
8
+ import { chainsMap } from '@dynamic-labs/viem-utils';
8
9
  import { EthWalletConnector } from '../EthWalletConnector.js';
9
10
  import { parseIntSafe } from '../utils/parseIntSafe.js';
10
11
 
@@ -26,6 +27,8 @@ class WalletConnect extends EthWalletConnector {
26
27
  // When trying to switch network for MetaMask, the switch promise gets stuck
27
28
  // if the switch got trigged once already, so we need to keep track of that
28
29
  this._hasSwitchedNetwork = false;
30
+ this.sessionEventHandler = () => { };
31
+ this.sessionDeleteHandler = () => { };
29
32
  this.name = opts.walletName;
30
33
  this.projectId = opts.projectId;
31
34
  this.deepLinkPreference = opts.deepLinkPreference || 'native';
@@ -47,7 +50,7 @@ class WalletConnect extends EthWalletConnector {
47
50
  const allChains = this.getMappedChains();
48
51
  const reorderedChains = this.preferredChains.filter((chain) => allChains.includes(chain));
49
52
  const remainingChains = allChains.filter((chain) => !this.preferredChains.includes(chain));
50
- return [...reorderedChains, ...remainingChains];
53
+ return [...reorderedChains, ...remainingChains].map((chain) => Number(chain.split(':')[1]));
51
54
  }
52
55
  initConnection() {
53
56
  return __awaiter(this, void 0, void 0, function* () {
@@ -56,43 +59,51 @@ class WalletConnect extends EthWalletConnector {
56
59
  throw new DynamicError('No provider found (init connection)');
57
60
  }
58
61
  // this means there is already a connection in progress, so don't call connect again
59
- if (provider === null || provider === void 0 ? void 0 : provider.uri) {
62
+ if (provider === null || provider === void 0 ? void 0 : provider.signer.uri) {
60
63
  return;
61
64
  }
62
- const optionalNamespaces = {
63
- eip155: {
64
- chains: this.getMappedChainsByPreferredOrder(),
65
- events: ['chainChanged', 'accountsChanged'],
66
- methods: [
67
- 'eth_chainId',
68
- 'eth_signTypedData',
69
- 'eth_signTransaction',
70
- 'eth_sign',
71
- 'personal_sign',
72
- 'eth_sendTransaction',
73
- 'eth_signTypedData_v4',
74
- 'wallet_switchEthereumChain',
75
- 'wallet_addEthereumChain',
76
- ],
77
- rpcMap: this.evmNetworkRpcMap(),
78
- },
79
- };
80
- provider
81
- .connect({
82
- optionalNamespaces,
83
- })
84
- .catch((e) => {
65
+ provider.connect().catch((e) => {
85
66
  logger.error(e);
86
67
  ee.emit('walletconnect_connection_failed', e);
87
68
  });
88
69
  });
89
70
  }
90
- createInitProviderPromise() {
71
+ createProvider() {
91
72
  return __awaiter(this, void 0, void 0, function* () {
92
- WalletConnect.provider = yield Provider.init({
93
- logger: logger.logLevel.toLowerCase() === 'debug' ? 'debug' : undefined,
73
+ return EthereumProvider.init({
74
+ events: ['chainChanged', 'accountsChanged'],
75
+ methods: [],
76
+ optionalChains: this.getMappedChainsByPreferredOrder(),
77
+ optionalMethods: [
78
+ 'eth_chainId',
79
+ 'eth_signTypedData',
80
+ 'eth_signTransaction',
81
+ 'eth_sign',
82
+ 'personal_sign',
83
+ 'eth_sendTransaction',
84
+ 'eth_signTypedData_v4',
85
+ 'wallet_switchEthereumChain',
86
+ 'wallet_addEthereumChain',
87
+ ],
94
88
  projectId: this.projectId,
89
+ rpcMap: this.evmNetworkRpcMap(),
90
+ showQrModal: false,
91
+ });
92
+ });
93
+ }
94
+ getWalletClientFromInitializedProvider() {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ const walletConnect = this.createProvider();
97
+ const walletClient = createWalletClient({
98
+ account: this.getActiveAccount(),
99
+ transport: custom(yield walletConnect),
95
100
  });
101
+ return walletClient;
102
+ });
103
+ }
104
+ createInitProviderPromise() {
105
+ return __awaiter(this, void 0, void 0, function* () {
106
+ WalletConnect.provider = yield this.createProvider();
96
107
  this.teardownEventListeners();
97
108
  this.setupEventListeners();
98
109
  });
@@ -117,7 +128,7 @@ class WalletConnect extends EthWalletConnector {
117
128
  if (localStorage.getItem(this.sessionTopicKey) ===
118
129
  ((_d = (_c = WalletConnect.provider) === null || _c === void 0 ? void 0 : _c.session) === null || _d === void 0 ? void 0 : _d.topic)) {
119
130
  this.session = WalletConnect.provider.session;
120
- this.activeAccount = ((_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined);
131
+ this.setActiveAccount(((_e = localStorage.getItem(this.activeAccountKey)) !== null && _e !== void 0 ? _e : undefined));
121
132
  }
122
133
  }
123
134
  }
@@ -171,7 +182,7 @@ class WalletConnect extends EthWalletConnector {
171
182
  if (!WalletConnect.provider) {
172
183
  return;
173
184
  }
174
- WalletConnect.provider.client.on('session_event', ({ params }) => {
185
+ this.sessionEventHandler = ({ params, }) => {
175
186
  logger.debug('session_event was called', { params });
176
187
  if (!params || !params.event) {
177
188
  logger.debug('session_event was called without params or params.event');
@@ -180,12 +191,17 @@ class WalletConnect extends EthWalletConnector {
180
191
  const { name, data } = params.event;
181
192
  if (name === 'chainChanged') {
182
193
  const chainId = parseIntSafe(data);
194
+ if (chainId === this.currentChainId) {
195
+ logger.debug(`ignoring chainChanged event with same chain id as current chain id: ${chainId}`);
196
+ return;
197
+ }
183
198
  if (chainId === undefined) {
184
199
  logger.debug(`received unexpected data for chainChanged: ${data} with type ${typeof data}}`);
185
200
  return;
186
201
  }
187
202
  this.currentChainId = chainId;
188
203
  this.emit('chainChange', { chain: String(chainId) });
204
+ this.hasSwitchedNetwork = true;
189
205
  // When a user switches network from their wallet, we need the provider to change network
190
206
  // such that any future calls to `getNetwork` will return the correct network
191
207
  this.switchNetwork({ networkChainId: chainId });
@@ -197,36 +213,41 @@ class WalletConnect extends EthWalletConnector {
197
213
  }
198
214
  // eslint-disable-next-line prefer-destructuring
199
215
  const account = data[0].split(':')[2];
200
- this.setActiveAccount(account);
216
+ this.setWCActiveAccount(account);
201
217
  }
202
- });
203
- WalletConnect.provider.client.on('session_delete', () => __awaiter(this, void 0, void 0, function* () {
218
+ };
219
+ WalletConnect.provider.on('session_event', this.sessionEventHandler);
220
+ this.sessionDeleteHandler = () => __awaiter(this, void 0, void 0, function* () {
204
221
  this.endSession();
205
222
  this.emit('disconnect');
206
- }));
223
+ });
224
+ WalletConnect.provider.on('session_delete', this.sessionDeleteHandler);
207
225
  }
208
226
  teardownEventListeners() {
209
227
  if (!WalletConnect.provider) {
210
228
  return;
211
229
  }
212
- WalletConnect.provider.client.removeAllListeners('session_event');
213
- WalletConnect.provider.client.removeAllListeners('session_delete');
230
+ WalletConnect.provider.off('session_event', this.sessionEventHandler);
231
+ WalletConnect.provider.off('session_delete', this.sessionDeleteHandler);
214
232
  }
215
- getWalletClient() {
233
+ getWalletClient(chainId) {
216
234
  if (!WalletConnect.provider) {
217
235
  return;
218
236
  }
219
237
  return createWalletClient({
238
+ account: this.getActiveAccount(),
239
+ chain: chainsMap[chainId !== null && chainId !== void 0 ? chainId : String(this.currentChainId)],
220
240
  transport: custom(WalletConnect.provider),
221
241
  });
222
242
  }
223
- fetchPublicAddress(opts) {
243
+ getAddress(opts) {
224
244
  var _a, _b;
225
245
  return __awaiter(this, void 0, void 0, function* () {
226
- if (this.activeAccount) {
227
- return this.activeAccount;
246
+ const activeAccount = this.getActiveAccount();
247
+ if (activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.address) {
248
+ return activeAccount.address;
228
249
  }
229
- if (!WalletConnect.provider || !((_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.uri)) {
250
+ if (!WalletConnect.provider || !((_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.signer.uri)) {
230
251
  logger.debug('No WC2 provider found, re-initializing...');
231
252
  yield this.endSession();
232
253
  yield this.init();
@@ -236,13 +257,13 @@ class WalletConnect extends EthWalletConnector {
236
257
  // finish setting up the connection URI and making it available
237
258
  // on the provider
238
259
  yield sleep(1000);
239
- if (!WalletConnect.provider || !((_b = WalletConnect.provider) === null || _b === void 0 ? void 0 : _b.uri)) {
260
+ if (!WalletConnect.provider || !((_b = WalletConnect.provider) === null || _b === void 0 ? void 0 : _b.signer.uri)) {
240
261
  logger.debug('No WC2 provider found, escaping and throwing error');
241
262
  throw new DynamicError('No provider found');
242
263
  }
243
264
  }
244
- const metadata = getWalletBookWallet(this.walletBook, this.key);
245
- performPlatformSpecificConnectionMethod(WalletConnect.provider.uri, metadata, {
265
+ const metadata = getWalletBookWallet(this.walletBook, this.key, this.walletFallback);
266
+ performPlatformSpecificConnectionMethod(WalletConnect.provider.signer.uri, metadata, {
246
267
  onDesktopUri: opts === null || opts === void 0 ? void 0 : opts.onDesktopUri,
247
268
  onDisplayUri: opts === null || opts === void 0 ? void 0 : opts.onDisplayUri,
248
269
  }, this.deepLinkPreference);
@@ -255,7 +276,7 @@ class WalletConnect extends EthWalletConnector {
255
276
  const error = new DynamicError('Connection rejected. Please try again.');
256
277
  error.code = 'connection_rejected';
257
278
  if (WalletConnect.provider) {
258
- WalletConnect.provider.uri = undefined;
279
+ WalletConnect.provider.signer.uri = undefined;
259
280
  // this is needed for mobile to work when using universal links.
260
281
  // if the user cancels the connection, we need to re-initialize the provider
261
282
  // so that the async work is done ahead of time, before the user tries to connect again,
@@ -267,13 +288,20 @@ class WalletConnect extends EthWalletConnector {
267
288
  // whenever the connection attempt either succeeds or fails
268
289
  cleanupListeners();
269
290
  };
270
- const onConnect = ({ session }) => {
291
+ const onConnect = () => {
292
+ var _a;
293
+ const session = (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.session;
271
294
  if (!session) {
272
295
  reject(new DynamicError('No session found'));
296
+ return;
273
297
  }
274
298
  this.setSession(session);
275
- this.setActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
276
- resolve(this.activeAccount);
299
+ this.setWCActiveAccount(session.namespaces.eip155.accounts[0].split(':')[2]);
300
+ this.getNetwork().then((chainId) => {
301
+ var _a;
302
+ this.currentChainId = chainId;
303
+ resolve((_a = this.getActiveAccount()) === null || _a === void 0 ? void 0 : _a.address);
304
+ });
277
305
  // We must clean up the onConnect and onFail listeners
278
306
  // whenever the connection attempt either succeeds or fails
279
307
  cleanupListeners();
@@ -301,10 +329,12 @@ class WalletConnect extends EthWalletConnector {
301
329
  */
302
330
  waitForSignMessage(signMessageFn, messageToSign) {
303
331
  return __awaiter(this, void 0, void 0, function* () {
304
- const raceConditionPromise = new Promise((resolve) => {
332
+ const raceConditionPromise = new Promise((resolve, reject) => {
305
333
  // Create listener for chain change event
306
334
  this.on('chainChange', () => resolve({ success: false }));
307
- signMessageFn(messageToSign).then((result) => resolve({ signedMessage: result, success: true }));
335
+ signMessageFn(messageToSign)
336
+ .then((result) => resolve({ signedMessage: result, success: true }))
337
+ .catch(reject);
308
338
  });
309
339
  const signedMessageResult = yield raceConditionPromise;
310
340
  if (signedMessageResult.success === false) {
@@ -323,7 +353,7 @@ class WalletConnect extends EthWalletConnector {
323
353
  metadata,
324
354
  mode: 'regular',
325
355
  preference: this.deepLinkPreference,
326
- uri: (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.uri,
356
+ uri: (_a = WalletConnect.provider) === null || _a === void 0 ? void 0 : _a.signer.uri,
327
357
  });
328
358
  if (!deepLink) {
329
359
  return;
@@ -337,20 +367,17 @@ class WalletConnect extends EthWalletConnector {
337
367
  if (!this.session) {
338
368
  throw new DynamicError('no session');
339
369
  }
340
- const web3Provider = this.getWalletClient();
341
- if (!web3Provider) {
342
- throw new DynamicError('No WalletConnect provider found to handle signing');
343
- }
344
370
  const deepLink = this.getDeepLink();
345
371
  if (isMobile() && deepLink) {
346
372
  window.location.href = deepLink;
347
373
  }
348
374
  const signMessageFn = (messageToSign) => __awaiter(this, void 0, void 0, function* () {
349
- const { activeAccount } = this;
375
+ const activeAccount = this.getActiveAccount();
350
376
  if (!activeAccount) {
351
377
  return;
352
378
  }
353
- return web3Provider.signMessage({
379
+ const walletClient = yield this.getWalletClientFromInitializedProvider();
380
+ return walletClient.signMessage({
354
381
  account: activeAccount,
355
382
  message: messageToSign,
356
383
  });
@@ -361,15 +388,15 @@ class WalletConnect extends EthWalletConnector {
361
388
  }
362
389
  clearActiveAccount() {
363
390
  localStorage.removeItem(this.activeAccountKey);
364
- this.activeAccount = undefined;
391
+ this.setActiveAccount(undefined);
365
392
  }
366
393
  clearSession() {
367
394
  localStorage.removeItem(this.sessionTopicKey);
368
395
  this.session = undefined;
369
396
  }
370
- setActiveAccount(account) {
397
+ setWCActiveAccount(account) {
371
398
  localStorage.setItem(this.activeAccountKey, account);
372
- this.activeAccount = account;
399
+ this.setActiveAccount(account);
373
400
  this.emit('accountChange', { accounts: [account] });
374
401
  }
375
402
  setSession(session) {
@@ -409,11 +436,17 @@ class WalletConnect extends EthWalletConnector {
409
436
  return _super.getNetwork.call(this);
410
437
  });
411
438
  }
412
- providerSwitchNetwork({ network, provider, }) {
439
+ providerSwitchNetwork({ network, }) {
413
440
  const _super = Object.create(null, {
414
441
  providerSwitchNetwork: { get: () => super.providerSwitchNetwork }
415
442
  });
416
443
  return __awaiter(this, void 0, void 0, function* () {
444
+ const supportedNetworks = yield this.getSupportedNetworks();
445
+ if (!(supportedNetworks === null || supportedNetworks === void 0 ? void 0 : supportedNetworks.includes(network.chainId.toString()))) {
446
+ const error = new DynamicError('Network switching is not available at this time. The user should manually switch network in their wallet');
447
+ error.code = 'network_switching_only_available_in_wallet';
448
+ throw error;
449
+ }
417
450
  const currentNetworkId = yield this.getNetwork();
418
451
  if (currentNetworkId && currentNetworkId === network.chainId) {
419
452
  return;
@@ -424,10 +457,14 @@ class WalletConnect extends EthWalletConnector {
424
457
  if (!this.supportsNetworkSwitching()) {
425
458
  throw new DynamicError('Network switching not supported');
426
459
  }
427
- if (!provider) {
428
- throw new DynamicError('Provider not found');
460
+ const walletClient = yield this.getWalletClientFromInitializedProvider();
461
+ if (this.isMetaMask()) {
462
+ const deepLink = this.getDeepLink();
463
+ if (deepLink) {
464
+ window.location.href = deepLink;
465
+ }
429
466
  }
430
- yield _super.providerSwitchNetwork.call(this, { network, provider });
467
+ yield _super.providerSwitchNetwork.call(this, { network, provider: walletClient });
431
468
  this.currentChainId = network.chainId;
432
469
  this.hasSwitchedNetwork = true;
433
470
  this.emit('chainChange', { chain: String(network.chainId) });
@@ -440,10 +477,11 @@ class WalletConnect extends EthWalletConnector {
440
477
  this.refreshSession();
441
478
  this.isInitialized = true;
442
479
  }
443
- if (!this.activeAccount) {
480
+ const activeAccount = this.getActiveAccount();
481
+ if (!(activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.address)) {
444
482
  return [];
445
483
  }
446
- return [this.activeAccount];
484
+ return [activeAccount.address];
447
485
  });
448
486
  }
449
487
  isMetaMask() {
@@ -453,13 +491,14 @@ class WalletConnect extends EthWalletConnector {
453
491
  getSupportedNetworks() {
454
492
  var _a;
455
493
  return __awaiter(this, void 0, void 0, function* () {
456
- // MM allows you to switch to any network the first time, even if it's not enabled in MM
457
- // so we should consider all networks as supported if network switching hasn't been triggered yet
458
- if (this.isMetaMask() && !this.hasSwitchedNetwork) {
459
- return this.evmNetworks.map((network) => network.chainId.toString());
460
- }
461
494
  yield this.initProvider();
462
495
  this.refreshSession();
496
+ if (this.isMetaMask()) {
497
+ if (this.hasSwitchedNetwork) {
498
+ return [String(this.currentChainId)];
499
+ }
500
+ return this.evmNetworks.map((network) => network.chainId.toString());
501
+ }
463
502
  if (!this.session) {
464
503
  return [];
465
504
  }