Skip to content

Commit

Permalink
feat: onConnected callback support provider account (#933)
Browse files Browse the repository at this point in the history
* feat: onConnected callback support provider account

* chore: add changelog

* fix: test

* chore: update demo

* test: improve test coverage

* fix: eslint issue

---------

Co-authored-by: tingzhao.ytz <tingzhao.ytz@antgroup.com>
Co-authored-by: thinkasany <480968828@qq.com>
  • Loading branch information
3 people committed Jun 12, 2024
1 parent c7aef8f commit 4abe7c0
Show file tree
Hide file tree
Showing 18 changed files with 139 additions and 29 deletions.
7 changes: 7 additions & 0 deletions .changeset/serious-ducks-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@ant-design/web3-common': minor
'@ant-design/web3-wagmi': minor
'@ant-design/web3': minor
---

feat: onConnected callback support provider account
2 changes: 1 addition & 1 deletion packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export interface UniversalWeb3ProviderInterface {
/** Such as `0x` */
addressPrefix?: string | false;

connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void>;
connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void | Account>;
disconnect?: () => Promise<void>;
switchChain?: (chain: Chain) => Promise<void>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ vi.mock('wagmi', async () => {
return {
connectAsync: async (...args: any[]) => {
mockConnectAsync(...args);
return {};
},
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe('WagmiWeb3ConfigProvider with EIP6963 Wallet', () => {
return {
connectAsync: async (...args: any[]) => {
mockConnectAsync(...args);
return {};
},
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ vi.mock('wagmi', () => {
connectAsync: (options: any) => {
connectAsync(options);
event.emit('connectChanged', true);
return {};
},
};
},
Expand Down
18 changes: 15 additions & 3 deletions packages/wagmi/src/wagmi-provider/__tests__/connect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,15 @@ vi.mock('wagmi', () => {
useConnect: () => {
return {
connectors: [mockConnector],
connectAsync: () => {
connectAsync: async () => {
connectAsync();
event.emit('connectChanged', true);
return {
accounts: [
'0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
'0x0212f0974d53a6e96eF05d7B324a9803735fFd3B',
],
};
},
};
},
Expand All @@ -78,18 +84,20 @@ vi.mock('wagmi', () => {

describe('WagmiWeb3ConfigProvider connect', () => {
it('connect', async () => {
const onConnected = vi.fn();
const CustomConnector = () => {
const { connect, account, disconnect } = useProvider();
return (
<div>
<div
className="custom-text"
onClick={() => {
onClick={async () => {
if (account) {
disconnect?.();
return;
}
connect?.(MetaMask().create([mockConnector]));
const res = await connect?.(MetaMask().create([mockConnector]));
onConnected(res);
}}
>
{account ? account?.address : 'Connect'}
Expand Down Expand Up @@ -119,6 +127,10 @@ describe('WagmiWeb3ConfigProvider connect', () => {
);
});

expect(onConnected).toBeCalledWith({
address: '0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
});

fireEvent.click(baseElement.querySelector('.custom-text')!);
await vi.waitFor(() => {
expect(disconnectAsync).toBeCalled();
Expand Down
4 changes: 3 additions & 1 deletion packages/wagmi/src/wagmi-provider/__tests__/ens.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ vi.mock('wagmi', () => {
useConnect: () => {
return {
connectors: [],
connectAsync: () => {},
connectAsync: async () => {
return {};
},
};
},
useDisconnect: () => {
Expand Down
4 changes: 3 additions & 1 deletion packages/wagmi/src/wagmi-provider/__tests__/nft.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ vi.mock('wagmi', () => {
useConnect: () => {
return {
connectors: [],
connectAsync: () => {},
connectAsync: async () => {
return {};
},
};
},
useDisconnect: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ vi.mock('wagmi', () => {
useConnect: () => {
return {
connectors: [mockConnector],
connectAsync: () => {},
connectAsync: async () => {
return {};
},
};
},
useDisconnect: () => {
Expand Down
5 changes: 4 additions & 1 deletion packages/wagmi/src/wagmi-provider/config-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,13 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
if (!connector) {
throw new Error(`Can not find connector for ${wallet?.name}`);
}
await connectAsync({
const { accounts } = await connectAsync({
connector,
chainId: currentChain?.id,
});
return {
address: accounts?.[0],
};
}}
disconnect={async () => {
// await disconnectAsync();
Expand Down
80 changes: 76 additions & 4 deletions packages/web3/src/connector/__tests__/basic.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe('Connector', () => {
</Button>
);
};
const onConnected = vi.fn();
const onConnected = vi.fn((account) => account);

const App = () => {
const [account, setAccount] = React.useState<Account | undefined>();
Expand All @@ -136,14 +136,17 @@ describe('Connector', () => {
setAccount({
address: '0x1234567890',
});
return {
address: '0x1234567890',
};
}}
disconnect={async () => {
setAccount(undefined);
}}
onDisconnected={onDisconnected}
onDisconnect={onDisconnect}
onConnected={() => {
onConnected();
onConnected={(a) => {
onConnected(a);
}}
>
<CustomButton>children</CustomButton>
Expand All @@ -161,7 +164,7 @@ describe('Connector', () => {

await vi.waitFor(() => {
expect(onConnectCallTest).toBeCalled();
expect(onConnected).toBeCalled();
expect(onConnected).toBeCalledWith({ address: '0x1234567890' });
});

fireEvent.click(baseElement.querySelector('.ant-modal-close')!);
Expand All @@ -180,6 +183,75 @@ describe('Connector', () => {
expect(baseElement.querySelector('.ant-btn')?.textContent).toBe('children');
});

it('connect without return account info', async () => {
const onConnectCallTest = vi.fn();
const onDisconnected = vi.fn();
const onDisconnect = vi.fn();
const CustomButton: React.FC<React.PropsWithChildren<ConnectorTriggerProps>> = (props) => {
const { account, onConnectClick, onDisconnectClick, children } = props;
return (
<Button
onClick={() => {
if (account) {
onDisconnectClick?.();
} else {
onConnectClick?.();
}
}}
>
{account?.address ?? children}
</Button>
);
};
const onConnected = vi.fn((account) => account);

const App = () => {
const [account, setAccount] = React.useState<Account | undefined>();
return (
<Connector
account={account}
availableWallets={[
{
...metadata_MetaMask,
hasWalletReady: async () => {
return true;
},
},
]}
onConnect={onConnectCallTest}
connect={async () => {
setAccount({
address: '0x1234567890',
});
}}
disconnect={async () => {
setAccount(undefined);
}}
onDisconnected={onDisconnected}
onDisconnect={onDisconnect}
onConnected={(a) => {
onConnected(a);
}}
>
<CustomButton>children</CustomButton>
</Connector>
);
};
const { baseElement } = render(<App />);
expect(baseElement.querySelector('.ant-btn')?.textContent).toBe('children');
fireEvent.click(baseElement.querySelector('.ant-btn')!);

await vi.waitFor(() => {
expect(baseElement.querySelector('.ant-web3-connect-modal-wallet-item')).toBeTruthy();
});
fireEvent.click(baseElement.querySelector('.ant-web3-connect-modal-wallet-item')!);

await vi.waitFor(() => {
expect(onConnectCallTest).toBeCalled();
expect(onConnected).toBeCalledWith(undefined);
});
});

it('should support controlled loading', async () => {
const App = () => {
const [account, setAccount] = React.useState<Account | undefined>();
Expand Down
4 changes: 2 additions & 2 deletions packages/web3/src/connector/connector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const Connector: React.FC<ConnectorProps> = (props) => {
onConnect?.();
try {
setConnecting(true);
await connect?.(wallet, options);
onConnected?.();
const connectedAccount = await connect?.(wallet, options);
onConnected?.(connectedAccount ? connectedAccount : undefined);
setOpen(false);
} catch (e: any) {
if (typeof onConnectError === 'function') {
Expand Down
10 changes: 5 additions & 5 deletions packages/web3/src/connector/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ In addition, `Connector` is usually used with [adapter](../../guide/adapter). Th
| --- | --- | --- | --- | --- |
| children | Connection control, typically a `ConnectButton` | `React.ReactNode` | - | - |
| modalProps | Properties passed through to `ConnectModal`. | `ModalProps` | - | - |
| onConnect | Callback when triggering the connection. | `() => Promise<void>` | - | - |
| onDisconnect | Callback when triggering the disconnection. | `() => Promise<void>` | - | - |
| onConnected | Callback when the connection is successful. | `() => Promise<void>` | - | - |
| onDisconnected | Callback when the connection is disconnected. | `() => Promise<void>` | - | - |
| onChainSwitched | Callback when switching networks. | `(chain: Chain) => Promise<void>` | - | - |
| onConnect | Callback when triggering the connection. | `() => void` | - | - |
| onDisconnect | Callback when triggering the disconnection. | `() => void` | - | - |
| onConnected | Callback when the connection is successful. The availability of `account` depends on the adapter implementation. | `(account?: Account) => void` | - | - |
| onDisconnected | Callback when the connection is disconnected. | `() => void` | - | - |
| onChainSwitched | Callback when switching networks. | `(chain: Chain) => void` | - | - |
| availableWallets | Available aallet list | `Wallet[]` | - | - |
| account | Current connected account | `Account` | - | - |
| availableChains | List of available chains | `Chain[]` | - | - |
Expand Down
10 changes: 5 additions & 5 deletions packages/web3/src/connector/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ group: UI 组件
| --- | --- | --- | --- | --- |
| children | 连接控件,通常是 `ConnectButton` | `React.ReactNode` | - | - |
| modalProps | 透传给 `ConnectModal` 的属性 | `ModalProps` | - | - |
| onConnect | 触发连接时的回调 | `() => Promise<void>` | - | - |
| onDisconnect | 触发断开连接时的回调 | `() => Promise<void>` | - | - |
| onConnected | 连接成功时的回调 | `() => Promise<void>` | - | - |
| onDisconnected | 断开连接时的回调 | `() => Promise<void>` | - | - |
| onChainSwitched | 切换网络时的回调 | `(chain: Chain) => Promise<void>` | - | - |
| onConnect | 触发连接时的回调 | `() => void` | - | - |
| onDisconnect | 触发断开连接时的回调 | `() => void` | - | - |
| onConnected | 连接成功时的回调`account` 是否可用取决于适配器实现 | `(account?: Account) => void` | - | - |
| onDisconnected | 断开连接时的回调 | `() => void` | - | - |
| onChainSwitched | 切换网络时的回调 | `(chain: Chain) => void` | - | - |
| availableWallets | 钱包列表 | `Wallet[]` | - | - |
| account | 当前连接账号 | `Account[]` | - | - |
| availableChains | 可以连接的链列表 | `Chain[]` | - | - |
Expand Down
4 changes: 2 additions & 2 deletions packages/web3/src/connector/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface ConnectorProps {
modalProps?: ConnectModalProps;
onConnect?: () => void;
onDisconnect?: () => void;
onConnected?: () => void;
onConnected?: (account?: Account) => void;
onDisconnected?: () => void;
onChainSwitched?: (chain?: Chain) => void;
onConnectError?: (error?: Error) => void;
Expand All @@ -17,7 +17,7 @@ export interface ConnectorProps {
availableChains?: Chain[];
availableWallets?: Wallet[];

connect?: (wallet?: Wallet) => Promise<void>;
connect?: (wallet?: Wallet) => Promise<void | Account>;
disconnect?: () => Promise<void>;
switchChain?: (chain: Chain) => Promise<void>;
}
9 changes: 8 additions & 1 deletion packages/web3/src/ethereum/demos/eip6963.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ConnectButton, Connector } from '@ant-design/web3';
import { MetaMask, WagmiWeb3ConfigProvider } from '@ant-design/web3-wagmi';
import { message } from 'antd';
import { createConfig, http } from 'wagmi';
import { mainnet } from 'wagmi/chains';

Expand All @@ -11,6 +12,7 @@ const config = createConfig({
});

const App: React.FC = () => {
const [messageApi, contextHolder] = message.useMessage();
return (
<WagmiWeb3ConfigProvider
config={config}
Expand All @@ -19,9 +21,14 @@ const App: React.FC = () => {
}}
wallets={[MetaMask()]}
>
<Connector>
<Connector
onConnected={(account) => {
messageApi.success(`Connected to ${account?.address}`);
}}
>
<ConnectButton />
</Connector>
{contextHolder}
</WagmiWeb3ConfigProvider>
);
};
Expand Down
2 changes: 1 addition & 1 deletion packages/web3/src/types/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ This is an enum type that contains the IDs of some commonly used chains. Its val
| chain | Current chain | [Chain](#chain) | - | - |
| availableChains | List of available chains | [Chain](#chain)\[] | - | - |
| availableWallets | List of available wallets | [Wallet](#wallet)\[] | - | - |
| connect | Connect to the wallet | `(wallet: Wallet, options?: ConnectOptions) => Promise<void>` | - | - |
| connect | Connect to the wallet | `(wallet: Wallet, options?: ConnectOptions) => Promise<void \| Account>` | - | - |
| disconnect | Disconnect from the chain | `() => Promise<void>` | - | - |
| switchChain | Switch to another chain | `(chainId: ChainIds) => Promise<void>` | - | - |
| getNFTMetadata | Get the metadata of the NFT | `(contractAddress: string, tokenId?: string) => Promise<NFTMetadata>` | - | - |
Expand Down
2 changes: 1 addition & 1 deletion packages/web3/src/types/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ order: 3
| chain | 当前链 | [Chain](#chain) | - | - |
| availableChains | 可以连接的链列表 | [Chain](#chain)[] | - | - |
| availableWallets | 可用的钱包列表 | [Wallet](#wallet)[] | - | - |
| connect | 连接钱包 | `(wallet: Wallet, options?: ConnectOptions) => Promise<void>` | - | - |
| connect | 连接钱包 | `(wallet: Wallet, options?: ConnectOptions) => Promise<void \| Account>` | - | - |
| disconnect | 断开钱包连接 | `() => Promise<void>` | - | - |
| switchChain | 切换链 | `(chain: Chain) => Promise<void>` | - | - |
| getNFTMetadata | 获取 NFT 的元数据 | `(params: { address: string; tokenId?: bigint \| number }) => Promise<NFTMetadata>` | - | - |
Expand Down

0 comments on commit 4abe7c0

Please sign in to comment.