Skip to content

Commit

Permalink
fix(wagmi): solve react max update depth exceeded issue (#884)
Browse files Browse the repository at this point in the history
* fix(wagmi): max update depth exceeded

* chore(wagmi): add changeset

* fix(wagmi): test case

* test(wagmi): fix ci

* test(wagmi): vitest cases

* feat(ethersjs): support storage props

* feat(web3js): support storage props

* chore(web3): update demos for storage

* chore: add changeset

* test: add coverage

* chore(wagmi): mock use disconnect

* refactor(wagmi): use low-level disconnect instead

* chore(wagmi): rm unused code

Co-authored-by: kiner-tang <1127031143@qq.com>

* docs: add storage config for ethereum adapters

* chore(ethers): add storage for minor upgrade

---------

Co-authored-by: kiner-tang <1127031143@qq.com>
  • Loading branch information
jeasonstudio and kiner-tang committed May 21, 2024
1 parent b12a0e9 commit 518fd83
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 53 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-pugs-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ant-design/web3-wagmi": patch
---

fix(wagmi): react max depth update exceeded
8 changes: 8 additions & 0 deletions .changeset/yellow-cameras-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@ant-design/web3-eth-web3js": minor
"@ant-design/web3-ethers": minor
"@ant-design/web3-wagmi": patch
"@ant-design/web3": patch
---

chore: add storage props to config
24 changes: 24 additions & 0 deletions packages/eth-web3js/src/web3js-provider/web3js-provider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useProvider } from '@ant-design/web3';
import { Mainnet, Optimism } from '@ant-design/web3-assets';
import { render } from '@testing-library/react';
import { describe, expect, test } from 'vitest';
import { createStorage } from 'wagmi';

import { MetaMask, TokenPocket } from '../wallets';
import { EthWeb3jsConfigProvider } from './web3js-provider';
Expand Down Expand Up @@ -102,4 +103,27 @@ describe('web3js-provider', async () => {
const { baseElement } = render(<App />);
expect(baseElement.querySelector('.wallets-name')?.textContent).toBe('MetaMask,WalletConnect');
});

test('storage', async () => {
const CustomConnector: React.FC = () => {
const { availableChains } = useProvider();
return (
<div className="chains-name">{availableChains?.map((item) => item.name).join(',')}</div>
);
};

const App = ({ storage }: any) => (
<EthWeb3jsConfigProvider storage={storage}>
<CustomConnector />
</EthWeb3jsConfigProvider>
);
expect(
render(<App storage={false} />).baseElement.querySelector('.chains-name')?.textContent,
).toBe('Ethereum');
expect(
render(<App storage={createStorage({ storage: localStorage })} />).baseElement.querySelector(
'.chains-name',
)?.textContent,
).toBe('Ethereum');
});
});
14 changes: 10 additions & 4 deletions packages/eth-web3js/src/web3js-provider/web3js-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
type WagmiWeb3ConfigProviderProps,
} from '@ant-design/web3-wagmi';
import type { Chain } from 'viem';
import { createConfig, http, type CreateConfigParameters } from 'wagmi';
import { createConfig, http, type CreateConfigParameters, type Storage } from 'wagmi';
import * as wagmiChains from 'wagmi/chains';
import * as wagmiConnectors from 'wagmi/connectors';
import type { WalletConnectParameters } from 'wagmi/connectors';
Expand All @@ -27,11 +27,12 @@ export interface WalletConnectOptions

export interface EthWeb3jsConfigProviderProps extends Omit<WagmiWeb3ConfigProviderProps, 'config'> {
walletConnect?: false | WalletConnectOptions;
storage?: Storage | false;
}

export const EthWeb3jsConfigProvider: React.FC<
React.PropsWithChildren<EthWeb3jsConfigProviderProps>
> = ({ children, walletConnect, ...props }) => {
> = ({ children, walletConnect, storage, ...props }) => {
const chains = React.useMemo(
() =>
(props.chains ?? [Mainnet])
Expand Down Expand Up @@ -71,8 +72,13 @@ export const EthWeb3jsConfigProvider: React.FC<
}),
);
}
return createConfig({ chains, transports, connectors });
}, [chains, walletConnect, props.wallets]);
return createConfig({
chains,
transports,
connectors,
storage: storage === false ? null : storage,
});
}, [chains, walletConnect, props.wallets, storage]);

return (
<WagmiWeb3ConfigProvider {...props} config={wagmiConfig} wallets={wallets}>
Expand Down
24 changes: 24 additions & 0 deletions packages/ethers/src/ethers-provider/ethers-provider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useProvider } from '@ant-design/web3';
import { Mainnet, Optimism } from '@ant-design/web3-assets';
import { render } from '@testing-library/react';
import { describe, expect, test } from 'vitest';
import { createStorage } from 'wagmi';

import { MetaMask, TokenPocket } from '../wallets';
import { EthersWeb3ConfigProvider } from './ethers-provider';
Expand Down Expand Up @@ -102,4 +103,27 @@ describe('ethers-provider', async () => {
const { baseElement } = render(<App />);
expect(baseElement.querySelector('.wallets-name')?.textContent).toBe('MetaMask,WalletConnect');
});

test('storage', async () => {
const CustomConnector: React.FC = () => {
const { availableChains } = useProvider();
return (
<div className="chains-name">{availableChains?.map((item) => item.name).join(',')}</div>
);
};

const App = ({ storage }: any) => (
<EthersWeb3ConfigProvider storage={storage}>
<CustomConnector />
</EthersWeb3ConfigProvider>
);
expect(
render(<App storage={false} />).baseElement.querySelector('.chains-name')?.textContent,
).toBe('Ethereum');
expect(
render(<App storage={createStorage({ storage: localStorage })} />).baseElement.querySelector(
'.chains-name',
)?.textContent,
).toBe('Ethereum');
});
});
14 changes: 10 additions & 4 deletions packages/ethers/src/ethers-provider/ethers-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
type WagmiWeb3ConfigProviderProps,
} from '@ant-design/web3-wagmi';
import type { Chain } from 'viem';
import { createConfig, http, type CreateConfigParameters } from 'wagmi';
import { createConfig, http, type CreateConfigParameters, type Storage } from 'wagmi';
import * as wagmiChains from 'wagmi/chains';
import * as wagmiConnectors from 'wagmi/connectors';
import type { WalletConnectParameters } from 'wagmi/connectors';
Expand All @@ -28,11 +28,12 @@ export interface WalletConnectOptions
export interface EthersWeb3ConfigProviderProps
extends Omit<WagmiWeb3ConfigProviderProps, 'config'> {
walletConnect?: false | WalletConnectOptions;
storage?: Storage | false;
}

export const EthersWeb3ConfigProvider: React.FC<
React.PropsWithChildren<EthersWeb3ConfigProviderProps>
> = ({ children, walletConnect, ...props }) => {
> = ({ children, walletConnect, storage, ...props }) => {
const chains = React.useMemo(
() =>
(props.chains ?? [Mainnet])
Expand Down Expand Up @@ -72,8 +73,13 @@ export const EthersWeb3ConfigProvider: React.FC<
}),
);
}
return createConfig({ chains, transports, connectors });
}, [chains, walletConnect, props.wallets]);
return createConfig({
chains,
transports,
connectors,
storage: storage === false ? null : storage,
});
}, [chains, walletConnect, props.wallets, storage]);

return (
<WagmiWeb3ConfigProvider {...props} config={wagmiConfig} wallets={wallets}>
Expand Down
5 changes: 5 additions & 0 deletions packages/wagmi/src/wagmi-provider/__tests__/balance.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const mockConnector = {
name: 'MetaMask',
};

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ const event = new EventEmitter();
const connectAsync = vi.fn();
const disconnectAsync = vi.fn();

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {
disconnectAsync();
event.emit('connectChanged', false);
},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/wagmi/src/wagmi-provider/__tests__/connect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ const event = new EventEmitter();
const connectAsync = vi.fn();
const disconnectAsync = vi.fn();

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {
disconnectAsync();
event.emit('connectChanged', false);
},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/wagmi/src/wagmi-provider/__tests__/ens.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ vi.mock('@wagmi/core', () => {
}
return null;
},
getAccount: () => ({}),
disconnect: () => {},
};
});

Expand Down
14 changes: 7 additions & 7 deletions packages/wagmi/src/wagmi-provider/__tests__/nft.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { mainnet } from 'wagmi/chains';
import { MetaMask } from '../../wallets';
import { AntDesignWeb3ConfigProvider } from '../config-provider';

vi.mock('@wagmi/core', () => {
return {
readContract: async () => {
return 'http://nft-metadata.com';
},
};
});
vi.mock('@wagmi/core', () => ({
readContract: async () => {
return 'http://nft-metadata.com';
},
getAccount: () => ({}),
disconnect: () => {},
}));

vi.mock('wagmi', () => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const mockConnector = {
name: 'MetaMask',
};

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ const mockConnector = {
name: 'MetaMask',
};

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const mockConnector = {
name: 'MetaMask',
};

vi.mock('@wagmi/core', () => ({
getAccount: () => ({}),
disconnect: () => {},
}));

vi.mock('wagmi', () => {
return {
useConfig: () => {
Expand Down
71 changes: 33 additions & 38 deletions packages/wagmi/src/wagmi-provider/config-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type Locale,
type Wallet,
} from '@ant-design/web3-common';
import { disconnect, getAccount } from '@wagmi/core';
import type { Chain as WagmiChain } from 'viem';
import {
useAccount,
useBalance,
useConfig,
useConnect,
useDisconnect,
useSwitchChain,
type Connector as WagmiConnector,
} from 'wagmi';
Expand Down Expand Up @@ -52,27 +52,25 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
const [account, setAccount] = React.useState<Account | undefined>();
const { connectAsync } = useConnect();
const { switchChain } = useSwitchChain();
const { disconnectAsync } = useDisconnect();
const [currentChain, setCurrentChain] = React.useState<Chain | undefined>(undefined);
const { data: balanceData } = useBalance({
address: balance && account ? fillAddressWith0x(account.address) : undefined,
});

React.useEffect(() => {
if (!address || isDisconnected) {
setAccount(undefined);
return;
}
const updateAccounts = async () => {
const a = {
address,
} else {
const updateAccounts = async () => {
const a = {
address,
};
setAccount(a);
if (ens) {
setAccount(await addNameToAccount(config, a));
}
};
setAccount(a);
if (ens) {
setAccount(await addNameToAccount(config, a));
}
};
updateAccounts();
updateAccounts();
}
}, [address, isDisconnected, chain, ens]);

const findConnectorByName = (name: string): WagmiConnector | undefined => {
Expand Down Expand Up @@ -162,25 +160,20 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
.filter((item) => item !== null) as Chain[];
}, [availableChains, chainAssets]);

const chainId = chain?.id || availableChains?.[0]?.id;
const chainName = chain?.name || availableChains?.[0]?.name;
const [currentChain, setCurrentChain] = React.useState<Chain | undefined>(undefined);

React.useEffect(() => {
if (!chain && currentChain) {
setCurrentChain((prevChain) => {
// not connected any chain, keep current chain
return;
}
const currentWagmiChain = chain ?? availableChains[0];
if (!currentWagmiChain) {
return;
}
let c = chainAssets?.find((item) => (item as Chain).id === currentWagmiChain?.id) as Chain;
if (!c?.id) {
c = {
id: currentWagmiChain.id,
name: currentWagmiChain.name,
};
}
setCurrentChain(c);
return;
}, [chain, chainAssets, availableChains, currentChain]);
let newChain = chainAssets?.find((item) => item?.id === chainId);
if (!newChain && chainId) {
newChain = { id: chainId, name: chainName };
}
return newChain || prevChain;
});
}, [chainAssets, availableChains, chainId, chainName]);

const currency = currentChain?.nativeCurrency;

Expand Down Expand Up @@ -222,17 +215,19 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
});
}}
disconnect={async () => {
await disconnectAsync();
// await disconnectAsync();
// TODO@jeasonstudio: wagmi useDisconnect hook 在处理多实例(config)共存时,
// 存在一些状态处理的 bug,暂时用更低阶 API 代替。
const { connector } = getAccount(config);
await disconnect(config, { connector });
}}
switchChain={async (c: Chain) => {
switchChain={async (newChain: Chain) => {
if (!chain) {
// hava not connected any chain
setCurrentChain(c);
return;
setCurrentChain(newChain);
} else {
switchChain?.({ chainId: newChain.id });
}
switchChain?.({
chainId: c.id,
});
}}
getNFTMetadata={getNFTMetadataFunc}
>
Expand Down
1 change: 1 addition & 0 deletions packages/web3/src/ethereum-ethersjs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ const App = () => {
| locale | Multilingual settings | [Locale](https://github.com/ant-design/ant-design-web3/blob/main/packages/common/src/locale/en_US.ts) | - | - |
| eip6963 | Whether to use EIP6963 protocol wallet and related configurations | `boolean` \| `EIP6963Config` | `false` | |
| walletConnect | Whether to use the Wallet Connect protocol | `false` \| [WalletConnectOptions](https://wagmi.sh/core/api/connectors/walletConnect#parameters) | `false` | |
| storage | Persists config's state between sessions. | `false` \| [WagmiStorage](https://wagmi.sh/core/api/createStorage) | - | `next` |
Loading

0 comments on commit 518fd83

Please sign in to comment.