@dynamic-labs/wagmi-connector 3.0.0-alpha.9 → 3.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.
@@ -3,18 +3,16 @@ import { __awaiter } from '../../_virtual/_tslib.js';
3
3
  import { createConnector } from '@wagmi/core';
4
4
  import { getAddress, createWalletClient, custom } from 'viem';
5
5
 
6
- const getCreateConnectorFn = (parameters) => createConnector((config) => ({
6
+ /* eslint-disable prefer-arrow/prefer-arrow-functions */
7
+ const getCreateConnectorFn = ({ connectorId, wallet, }) => createConnector((config) => ({
7
8
  connect() {
8
9
  return __awaiter(this, void 0, void 0, function* () {
9
- if (!parameters.walletConnector) {
10
+ if (!wallet.connector) {
10
11
  throw new Error('WalletConnector is not defined');
11
12
  }
12
- parameters.walletConnector.on('accountChange', ({ accounts }) => {
13
- const handler = this.onAccountsChanged.bind(this);
14
- handler(accounts);
15
- });
16
- parameters.walletConnector.on('chainChange', ({ chain }) => this.onChainChanged(chain));
17
- parameters.walletConnector.on('disconnect', this.onDisconnect.bind(this));
13
+ wallet.connector.on('accountChange', this.handleAccountsChange.bind(this));
14
+ wallet.connector.on('chainChange', this.handleChainChange.bind(this));
15
+ wallet.connector.on('disconnect', this.onDisconnect.bind(this));
18
16
  const accounts = yield this.getAccounts();
19
17
  return {
20
18
  accounts,
@@ -24,38 +22,19 @@ const getCreateConnectorFn = (parameters) => createConnector((config) => ({
24
22
  },
25
23
  disconnect() {
26
24
  return __awaiter(this, void 0, void 0, function* () {
27
- if (!parameters.preventWagmiSyncFromCallingLogout.current) {
28
- yield parameters.walletConnector.endSession();
29
- yield parameters.handleLogOut();
30
- }
31
- parameters.walletConnector.off('accountChange');
32
- parameters.walletConnector.off('chainChange');
33
- parameters.walletConnector.off('disconnect');
34
- /**
35
- * In our own Dynamic Wagmi sync component, we will flip the flag to true before calling disconnect,
36
- * and here it automatically flips back to false afterwards. This will prevent the Connector from
37
- * calling handleLogOut when we are the ones calling disconnect, but will preserve the existing behavior
38
- * for customers who use useDisconnect directly.
39
- */
40
- parameters.preventWagmiSyncFromCallingLogout.current = false;
25
+ wallet.connector.off('accountChange', this.handleAccountsChange.bind(this));
26
+ wallet.connector.off('chainChange', this.handleChainChange.bind(this));
27
+ wallet.connector.off('disconnect', this.onDisconnect.bind(this));
41
28
  });
42
29
  },
43
30
  getAccounts() {
44
31
  return __awaiter(this, void 0, void 0, function* () {
45
- var _a;
46
- const address = yield ((_a = parameters.walletConnector) === null || _a === void 0 ? void 0 : _a.getAddress());
47
- if (!address) {
48
- throw new Error('Not connected');
49
- }
50
- return [getAddress(address)];
32
+ return [getAddress(wallet.address)];
51
33
  });
52
34
  },
53
35
  getChainId() {
54
36
  return __awaiter(this, void 0, void 0, function* () {
55
- if (!parameters.walletConnector) {
56
- throw new Error('WalletConnector is not defined');
57
- }
58
- const network = yield parameters.walletConnector.getNetwork();
37
+ const network = yield wallet.connector.getNetwork();
59
38
  if (!network) {
60
39
  throw new Error('Network is not defined');
61
40
  }
@@ -65,37 +44,43 @@ const getCreateConnectorFn = (parameters) => createConnector((config) => ({
65
44
  getClient(args) {
66
45
  return __awaiter(this, void 0, void 0, function* () {
67
46
  var _a, _b;
68
- const signer = yield parameters.walletConnector.getSigner();
69
- if (signer.account && signer.chain) {
70
- return signer;
47
+ const walletClient = yield wallet.getWalletClient();
48
+ if (walletClient.account && walletClient.chain) {
49
+ return walletClient;
71
50
  }
72
- const walletClient = createWalletClient({
73
- account: (_a = (yield this.getAccounts())) === null || _a === void 0 ? void 0 : _a[0],
74
- chain: (_b = config.chains.find((chain) => chain.id === (args === null || args === void 0 ? void 0 : args.chainId))) !== null && _b !== void 0 ? _b : config.chains[0],
75
- transport: custom(signer),
51
+ const client = createWalletClient({
52
+ account: walletClient.account || ((_a = (yield this.getAccounts())) === null || _a === void 0 ? void 0 : _a[0]),
53
+ chain: (_b = (walletClient.chain ||
54
+ config.chains.find((chain) => chain.id === (args === null || args === void 0 ? void 0 : args.chainId)))) !== null && _b !== void 0 ? _b : config.chains[0],
55
+ transport: custom(walletClient),
76
56
  });
77
- return walletClient;
57
+ return client;
78
58
  });
79
59
  },
80
60
  getProvider() {
81
61
  return __awaiter(this, void 0, void 0, function* () {
82
- var _a;
83
- return (_a = parameters.walletConnector) === null || _a === void 0 ? void 0 : _a.getWalletClient();
62
+ return wallet.getWalletClient();
84
63
  });
85
64
  },
86
- id: parameters.connectorId,
65
+ handleAccountsChange({ accounts }) {
66
+ this.onAccountsChanged(accounts);
67
+ },
68
+ handleChainChange({ chain }) {
69
+ this.onChainChanged(chain);
70
+ },
71
+ id: connectorId,
87
72
  isAuthorized() {
88
73
  return __awaiter(this, void 0, void 0, function* () {
89
74
  var _a, _b;
90
- const accounts = (_b = (yield ((_a = parameters.walletConnector) === null || _a === void 0 ? void 0 : _a.getConnectedAccounts()))) !== null && _b !== void 0 ? _b : [];
91
- return accounts.length > 0;
75
+ const accounts = (_b = (yield ((_a = wallet.connector) === null || _a === void 0 ? void 0 : _a.getConnectedAccounts()))) !== null && _b !== void 0 ? _b : [];
76
+ return accounts.includes(wallet.address);
92
77
  });
93
78
  },
94
79
  name: 'Dynamic',
95
- onAccountsChanged(accounts) {
96
- config.emitter.emit('change', {
97
- accounts: [getAddress(accounts[0])],
98
- });
80
+ onAccountsChanged(_) {
81
+ // this changes the active account on wagmi, but we don't want to do that
82
+ // we want the active account to always match the primary wallet
83
+ // so we should not emit this event on the wagmi config
99
84
  },
100
85
  onChainChanged(chainId) {
101
86
  config.emitter.emit('change', {
@@ -105,14 +90,11 @@ const getCreateConnectorFn = (parameters) => createConnector((config) => ({
105
90
  onDisconnect() { },
106
91
  switchChain(_a) {
107
92
  return __awaiter(this, arguments, void 0, function* ({ chainId }) {
108
- var _b;
109
93
  const chain = config.chains.find((x) => x.id === chainId);
110
94
  if (!chain) {
111
95
  throw new Error(`Chain ${chainId} is not supported`);
112
96
  }
113
- yield ((_b = parameters.walletConnector) === null || _b === void 0 ? void 0 : _b.switchNetwork({
114
- networkChainId: chainId,
115
- }));
97
+ yield wallet.switchNetwork(chainId);
116
98
  return chain;
117
99
  });
118
100
  },
@@ -1,27 +1,27 @@
1
1
  'use client'
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useRef, useMemo, useEffect } from 'react';
3
+ import { useMemo, useEffect } from 'react';
4
4
  import { useConfig } from 'wagmi';
5
- import { ErrorBoundaryInclude, useDynamicContext, useUserWallets, ErrorBoundaryExclude } from '@dynamic-labs/sdk-react-core';
5
+ import { ErrorBoundaryInclude, useDynamicContext, ErrorBoundaryExclude } from '@dynamic-labs/sdk-react-core';
6
+ import { isEthereumWallet } from '@dynamic-labs/ethereum-core';
6
7
  import { getCreateConnectorFn } from './Connector.js';
7
8
  import { SyncDynamicWagmi } from './SyncDynamicWagmi.js';
8
9
  import { useChainMismatchLogger } from './useChainMismatchLogger.js';
9
- import { useFindEvmWallet } from './hooks/useFindEvmWallet/useFindEvmWallet.js';
10
10
  import { useConnectorId } from './hooks/useConnectorId/useConnectorId.js';
11
11
 
12
- const DynamicWagmiConnector = ({ suppressChainMismatchError = false, children, }) => (jsx(ErrorBoundaryInclude, { children: jsx(DynamicWagmiConnectorInner, { suppressChainMismatchError: true, children: children }) }));
12
+ const DynamicWagmiConnector = ({ suppressChainMismatchError = false, children, }) => (jsx(ErrorBoundaryInclude, { children: jsx(DynamicWagmiConnectorInner, { suppressChainMismatchError: suppressChainMismatchError, children: children }) }));
13
+ const getEvmWallet = (wallet) => {
14
+ if (!wallet || !isEthereumWallet(wallet)) {
15
+ return null;
16
+ }
17
+ return wallet;
18
+ };
13
19
  const DynamicWagmiConnectorInner = ({ suppressChainMismatchError = false, children }) => {
14
20
  const config = useConfig();
15
- const { handleLogOut, primaryWallet } = useDynamicContext();
16
- const wallets = useUserWallets();
17
- useChainMismatchLogger({ throwOnMismatch: !suppressChainMismatchError });
18
- const evmWallet = useFindEvmWallet(primaryWallet, wallets);
21
+ const { primaryWallet } = useDynamicContext();
22
+ useChainMismatchLogger({ suppress: suppressChainMismatchError });
23
+ const evmWallet = getEvmWallet(primaryWallet);
19
24
  const getConnectorId = useConnectorId();
20
- /**
21
- * This will prevent the wagmi Connector from calling handleLogOut when we are the ones calling disconnect
22
- * as a result of a handleLogOut call (see SyncDynamicWagmi), but will preserve the existing behavior for customers.
23
- */
24
- const preventWagmiSyncFromCallingLogout = useRef(false);
25
25
  const connector = useMemo(() => {
26
26
  if (!evmWallet) {
27
27
  return;
@@ -29,11 +29,9 @@ const DynamicWagmiConnectorInner = ({ suppressChainMismatchError = false, childr
29
29
  const connectorId = getConnectorId(evmWallet.connector);
30
30
  return config._internal.connectors.setup(getCreateConnectorFn({
31
31
  connectorId,
32
- handleLogOut,
33
- preventWagmiSyncFromCallingLogout,
34
- walletConnector: evmWallet.connector,
32
+ wallet: evmWallet,
35
33
  }));
36
- }, [config._internal.connectors, getConnectorId, handleLogOut, evmWallet]);
34
+ }, [config._internal.connectors, getConnectorId, evmWallet]);
37
35
  /**
38
36
  * Updating the wagmi config must be done in a useEffect because
39
37
  * when setting the public client and connectors, wagmi will fire
@@ -44,7 +42,7 @@ const DynamicWagmiConnectorInner = ({ suppressChainMismatchError = false, childr
44
42
  useEffect(() => {
45
43
  config._internal.connectors.setState(connector ? [connector] : []);
46
44
  }, [config._internal.connectors, connector]);
47
- return (jsx(SyncDynamicWagmi, { connector: connector, preventWagmiSyncFromCallingLogout: preventWagmiSyncFromCallingLogout, wallets: wallets, children: jsx(ErrorBoundaryExclude, { children: children }) }));
45
+ return (jsx(SyncDynamicWagmi, { connector: connector, wallet: evmWallet, children: jsx(ErrorBoundaryExclude, { children: children }) }));
48
46
  };
49
47
 
50
48
  export { DynamicWagmiConnector, DynamicWagmiConnectorInner };
@@ -1,9 +1,8 @@
1
- import React, { MutableRefObject } from 'react';
1
+ import React from 'react';
2
2
  import { Connector } from 'wagmi';
3
3
  import { Wallet } from '@dynamic-labs/sdk-react-core';
4
4
  export type SyncDynamicWagmiProps = React.PropsWithChildren<{
5
5
  connector: Connector | undefined;
6
- wallets: Wallet[];
7
- preventWagmiSyncFromCallingLogout: MutableRefObject<boolean>;
6
+ wallet: Wallet | null;
8
7
  }>;
9
- export declare const SyncDynamicWagmi: ({ children, connector, wallets, preventWagmiSyncFromCallingLogout, }: SyncDynamicWagmiProps) => JSX.Element;
8
+ export declare const SyncDynamicWagmi: ({ children, connector, wallet, }: SyncDynamicWagmiProps) => JSX.Element;
@@ -1,58 +1,67 @@
1
1
  'use client'
2
+ import { __awaiter } from '../../_virtual/_tslib.js';
2
3
  import { jsx, Fragment } from 'react/jsx-runtime';
3
- import { useRef, useEffect } from 'react';
4
+ import { useRef, useCallback, useEffect } from 'react';
4
5
  import { useConfig, useConnect, useDisconnect } from 'wagmi';
5
- import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
6
+ import { useWalletConnectorEvent } from '@dynamic-labs/sdk-react-core';
7
+ import { logger } from '@dynamic-labs/wallet-connector-core';
6
8
 
7
- const SyncDynamicWagmi = ({ children, connector, wallets, preventWagmiSyncFromCallingLogout, }) => {
9
+ const SyncDynamicWagmi = ({ children, connector, wallet, }) => {
8
10
  const { state: { status: clientStatus }, } = useConfig();
9
11
  const { connect } = useConnect();
10
12
  const { disconnect } = useDisconnect();
11
- const { walletConnector } = useDynamicContext();
12
- const lastConnectedConnectorId = useRef(undefined);
13
- useEffect(() => {
14
- const isConnected = Boolean(lastConnectedConnectorId.current);
15
- /**
16
- * Disconnects from Wagmi when no more wallets are available
17
- * and returns early to prevent re-connecting to the same connector
18
- */
19
- if (!wallets.length) {
20
- /**
21
- * Check if the connector is already disconnected to prevent
22
- * disconnecting in a page transition on NextJS with multiple
23
- * layouts
24
- */
25
- if (isConnected) {
26
- /**
27
- * This will prevent the Connector from calling handleLogOut when we are the ones calling disconnect,
28
- * but will preserve the existing behavior for customers who use useDisconnect directly.
29
- */
30
- preventWagmiSyncFromCallingLogout.current = true;
31
- disconnect();
32
- lastConnectedConnectorId.current = undefined;
33
- }
13
+ const lastConnectedWalletId = useRef(undefined);
14
+ const hasPreviousConnection = Boolean(lastConnectedWalletId.current);
15
+ const disconnectWagmi = useCallback(() => {
16
+ logger.debug('[SyncDynamicWagmi] disconnecting wagmi - previous status: ', clientStatus);
17
+ if (clientStatus === 'disconnected') {
18
+ return;
19
+ }
20
+ disconnect();
21
+ lastConnectedWalletId.current = undefined;
22
+ }, [disconnect, clientStatus]);
23
+ const connectWagmi = useCallback((connector, newId, forceConnect) => {
24
+ logger.debug('[SyncDynamicWagmi] connecting wagmi - previous status: ', clientStatus);
25
+ if (clientStatus !== 'disconnected' && !forceConnect) {
26
+ return;
27
+ }
28
+ lastConnectedWalletId.current = newId;
29
+ connect({ connector });
30
+ }, [connect, clientStatus]);
31
+ const sync = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
32
+ // if there's no connector, disconnect wagmi
33
+ if (!connector || !(wallet === null || wallet === void 0 ? void 0 : wallet.address)) {
34
+ disconnectWagmi();
35
+ return;
36
+ }
37
+ const newId = `${connector.id}-${wallet.address}`;
38
+ // if the connector hasn't changed since the last connection, do nothing
39
+ if (newId === lastConnectedWalletId.current) {
34
40
  return;
35
41
  }
36
- /**
37
- * Connects to Wagmi when a connector is available and
38
- * the connector has changed since the last connection
39
- */
40
- if (walletConnector &&
41
- connector &&
42
- (connector === null || connector === void 0 ? void 0 : connector.id) !== lastConnectedConnectorId.current) {
43
- lastConnectedConnectorId.current = connector.id;
44
- connect({ connector });
42
+ // if has a previous connection, disconnect wagmi
43
+ if (hasPreviousConnection) {
44
+ disconnectWagmi();
45
45
  }
46
- }, [
47
- clientStatus,
48
- connect,
46
+ // and then (re)connect wagmi
47
+ // force reconnect if has disconnected in the preivous step
48
+ // in case the clientStatus takes a while to update
49
+ connectWagmi(connector, newId, hasPreviousConnection);
50
+ }), [
51
+ connectWagmi,
49
52
  connector,
50
- disconnect,
51
- lastConnectedConnectorId,
52
- preventWagmiSyncFromCallingLogout,
53
- walletConnector,
54
- wallets,
53
+ disconnectWagmi,
54
+ hasPreviousConnection,
55
+ wallet === null || wallet === void 0 ? void 0 : wallet.address,
55
56
  ]);
57
+ // this is for handling the scenario where the user unlocks the wallet,
58
+ // as well as changes to a linked wallet
59
+ useWalletConnectorEvent(wallet === null || wallet === void 0 ? void 0 : wallet.connector, 'accountChange', () => {
60
+ sync();
61
+ });
62
+ useEffect(() => {
63
+ sync();
64
+ }, [sync, clientStatus]);
56
65
  // eslint-disable-next-line react/jsx-no-useless-fragment
57
66
  return jsx(Fragment, { children: children });
58
67
  };
@@ -1,3 +1,3 @@
1
- export declare const useChainMismatchLogger: ({ throwOnMismatch, }?: {
2
- throwOnMismatch: boolean;
1
+ export declare const useChainMismatchLogger: ({ suppress, }?: {
2
+ suppress: boolean;
3
3
  }) => void;
@@ -5,11 +5,11 @@ import { Logger } from '@dynamic-labs/logger';
5
5
  import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
6
6
 
7
7
  const logger = new Logger('DynamicWagmiConnector');
8
- const useChainMismatchLogger = ({ throwOnMismatch, } = { throwOnMismatch: true }) => {
8
+ const useChainMismatchLogger = ({ suppress, } = { suppress: false }) => {
9
9
  const config = useConfig();
10
10
  const { networkConfigurations } = useDynamicContext();
11
11
  useEffect(() => {
12
- if (!(networkConfigurations === null || networkConfigurations === void 0 ? void 0 : networkConfigurations.evm))
12
+ if (!(networkConfigurations === null || networkConfigurations === void 0 ? void 0 : networkConfigurations.evm) || suppress)
13
13
  return;
14
14
  const wagmiChains = config.chains;
15
15
  const wagmiChainIds = wagmiChains.map((chain) => chain.id);
@@ -20,10 +20,6 @@ const useChainMismatchLogger = ({ throwOnMismatch, } = { throwOnMismatch: true }
20
20
  const message = `Chain (id: ${chain.id} name: ${chain.name}) is present in the Wagmi config, but is not present in the Dynamic configuration.` +
21
21
  ' Please make sure to enable the chain in your Dynamic Dashboard, or add it to the evmNetworks prop on DynamicContextProvider.' +
22
22
  ' For more information, see: https://docs.dynamic.xyz/guides/frameworks/wagmi-v2#chain-configuration';
23
- if (throwOnMismatch) {
24
- throw new Error(message +
25
- ' \n\nTo suppress this error, pass `suppressChainMismatchError` to `DynamicWagmiConnector`: `<DynamicWagmiConnector suppressChainMismatchError>`');
26
- }
27
23
  logger.warn(message);
28
24
  }
29
25
  });
@@ -32,14 +28,10 @@ const useChainMismatchLogger = ({ throwOnMismatch, } = { throwOnMismatch: true }
32
28
  const message = `Chain (id: ${chain.chainId} name: ${chain.name}) is present in the Dynamic config, but is not present in the Wagmi configuration.` +
33
29
  ' Please make sure to add the chain to the chains prop on the Wagmi createConfig function.' +
34
30
  ' For more information, see: https://docs.dynamic.xyz/guides/frameworks/wagmi-v2#chain-configuration';
35
- if (throwOnMismatch) {
36
- throw new Error(message +
37
- ' \n\nTo suppress this error, pass `suppressChainMismatchError` to `DynamicWagmiConnector`: `<DynamicWagmiConnector suppressChainMismatchError>`');
38
- }
39
31
  logger.warn(message);
40
32
  }
41
33
  });
42
- }, [config.chains, networkConfigurations, throwOnMismatch]);
34
+ }, [config.chains, networkConfigurations, suppress]);
43
35
  };
44
36
 
45
37
  export { useChainMismatchLogger };
@@ -1 +0,0 @@
1
- export { useFindEvmWallet } from './useFindEvmWallet';
@@ -1,2 +0,0 @@
1
- import { Wallet } from '@dynamic-labs/sdk-react-core';
2
- export declare const useFindEvmWallet: (primaryWallet: Wallet | null, wallets: Wallet[]) => Wallet | undefined;
@@ -1,22 +0,0 @@
1
- 'use client'
2
- const isEvmWallet = (wallet) => wallet.connector.connectedChain === 'EVM';
3
- const isWalletConnected = (wallet) => wallet.connected;
4
- const useFindEvmWallet = (primaryWallet, wallets) => {
5
- /**
6
- * If the primary wallet is an EVM wallet and is connected, return it.
7
- */
8
- if (primaryWallet &&
9
- isEvmWallet(primaryWallet) &&
10
- isWalletConnected(primaryWallet)) {
11
- return primaryWallet;
12
- }
13
- /**
14
- * If the primary wallet is not connected, find the first connected EVM wallet.
15
- */
16
- const connectedEvmWallets = wallets
17
- .filter(isEvmWallet)
18
- .filter(isWalletConnected);
19
- return connectedEvmWallets[0];
20
- };
21
-
22
- export { useFindEvmWallet };