Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/blue-games-live.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: support sign and unsign
1 change: 1 addition & 0 deletions packages/common/src/locale/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const localeValues: RequiredLocale = {
walletAddress: 'Wallet address',
moreWallets: 'More Wallets',
sign: 'Sign',
profile: 'Profile',
},
ConnectModal: {
title: 'Connect Wallet',
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/locale/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const localeValues: RequiredLocale = {
walletAddress: '钱包地址',
moreWallets: '更多钱包',
sign: '签名',
profile: '我的资料',
},
ConnectModal: {
title: '连接钱包',
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export type WalletExtensionItem = {
* @desc 支持的浏览器的 key
* @descEn The key of the supported browser
*/
// eslint-disable-next-line @typescript-eslint/ban-types
key: 'Chrome' | 'Firefox' | 'Edge' | 'Safari' | (string & {});
/**
* @desc 浏览器扩展程序的链接
Expand Down Expand Up @@ -276,6 +277,7 @@ export interface RequiredLocale {
walletAddress: string;
moreWallets: string;
sign: string;
profile: string;
};
ConnectModal: {
title: string;
Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/utils/__tests__/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ describe('request', () => {
expect(getWeb3AssetUrl('')).toEqual('');
expect(getWeb3AssetUrl('ipfs://test.com/xxxxx')).toEqual('https://ipfs.io/ipfs/test.com/xxxxx');
});
it('requestWeb3Asset', () => {
it('requestWeb3Asset', async () => {
const res = { test: 'test' };
mockFetch(res);
expect(requestWeb3Asset('')).rejects.toThrowError('URL not set');
expect(requestWeb3Asset('ipfs://test.com/xxxxx')).resolves.toMatchObject(res);
await expect(requestWeb3Asset('')).rejects.toThrowError('URL not set');
await expect(requestWeb3Asset('ipfs://test.com/xxxxx')).resolves.toMatchObject(res);
});
});
3 changes: 2 additions & 1 deletion packages/ethers-v5/src/hooks/use-ethers-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { providers } from 'ethers';
import type { Chain, Client, Transport } from 'viem';
import { useClient, type Config } from 'wagmi';

/* v8 ignore next 15 */
export function clientToProvider(client: Client<Transport, Chain>) {
const { chain, transport } = client;
const network = {
chainId: chain.id,
name: chain.name,
ensAddress: chain.contracts?.ensRegistry?.address,
};

if (transport.type === 'fallback')
/* v8 ignore next 5 */
return new providers.FallbackProvider(
(transport.transports as ReturnType<Transport>[]).map(
({ value }) => new providers.JsonRpcProvider(value?.url, network),
Expand Down
2 changes: 1 addition & 1 deletion packages/ethers/src/hooks/use-ethers-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FallbackProvider, JsonRpcProvider } from 'ethers';
import type { Chain, Client, Transport } from 'viem';
import { useClient, type Config } from 'wagmi';

/* v8 ignore next 15 */
export function clientToProvider(client: Client<Transport, Chain>) {
const { chain, transport } = client;
const network = {
Expand All @@ -11,7 +12,6 @@ export function clientToProvider(client: Client<Transport, Chain>) {
ensAddress: chain.contracts?.ensRegistry?.address,
};

/* v8 ignore next 7 */
if (transport.type === 'fallback') {
const providers = (transport.transports as ReturnType<Transport>[]).map(
({ value }) => new JsonRpcProvider(value?.url, network),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ describe('Solana Connect', () => {

const pluginCheck = selector('.plugin-check')!;

await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(pluginCheck.textContent).toBe('true');
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe('SolanaWeb3ConfigProvider standard mobile wallet adapter', () => {
expect(connectBtnDom).not.toBeNull();

// check wallet-connect config can be created
await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(namesDom.textContent).toBe(MWA_WALLET_NAME);

expect(readyDom.textContent).toBe('true');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('SolanaWeb3ConfigProvider Standard wallet', () => {
const readyDom = selector('.is-ready')!;

// check wallet-connect config can be created
await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(readyDom.textContent).toBe('ready:true');
});
});
Expand Down Expand Up @@ -192,7 +192,7 @@ describe('SolanaWeb3ConfigProvider Standard wallet', () => {
const extInstalledDom = selector('.added-ext-installed')!;

// check wallet-connect config can be created
await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(namesDom.textContent).toBe('Phantom, OKX Wallet');

expect(readyDom.textContent).toBe('true');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,14 @@ describe('SolanaWeb3ConfigProvider WalletConnect', () => {
const btn = selector('button')!;
expect(btn.textContent).toBe('Click to connect');

await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(mockWalletConnectConfig).toBeCalledWith(true);
});

fireEvent.click(btn);

// check wallet-connect config can be created
await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(mockSelectFn).toBeCalledTimes(2);
});
});
Expand Down Expand Up @@ -206,7 +206,7 @@ describe('SolanaWeb3ConfigProvider WalletConnect', () => {

const dom = selector('.plugin-check')!;

await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(dom.textContent).toBe('true');
});
});
Expand Down
6 changes: 3 additions & 3 deletions packages/sui/src/sui-provider/__tests__/balance.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { useProvider } from '@ant-design/web3';
import { describe, expect, it, vi } from 'vitest';

Expand Down Expand Up @@ -41,7 +41,7 @@ describe('SuiWeb3ConfigProvider balance tests', () => {
},

useSuiClientQuery: (method: keyof typeof mockedQueryFetch, params?: any, options?: any) => {
const [data, setData] = useState(null);
const [data, setData] = React.useState(null);
const fetcher = mockedQueryFetch[method];

const fetchRunner = React.useCallback(async () => {
Expand All @@ -55,7 +55,7 @@ describe('SuiWeb3ConfigProvider balance tests', () => {
setData(selectedResult);
}, [fetcher, options, params]);

useEffect(() => {
React.useEffect(() => {
fetchRunner();
}, [method, params, fetchRunner]);

Expand Down
2 changes: 1 addition & 1 deletion packages/ton/src/ton-provider/__tests__/sdk.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('TonSDK', () => {
);
};

expect(errorThrowingFunctionWithUrl()).rejects.toThrow();
await expect(errorThrowingFunctionWithUrl()).rejects.toThrow();
const balance = await connector.getBalance();
expect(balance).toBe(0n);
});
Expand Down
70 changes: 65 additions & 5 deletions packages/wagmi/src/wagmi-provider/__tests__/siwe.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react';
import { ConnectButton, Connector } from '@ant-design/web3';
import { Mainnet } from '@ant-design/web3-assets';
import { fireEvent, render, waitFor } from '@testing-library/react';
Expand All @@ -10,7 +11,7 @@ import { MetaMask } from '../../wallets';
import { AntDesignWeb3ConfigProvider } from '../config-provider';

let locationSpy: ReturnType<typeof vi.spyOn> = undefined as any;
const createMessage = vi.fn(() => 'message');
const mockSignMessageAsync = vi.fn(async () => '0x123456789');

vi.mock('wagmi', async (importOriginal) => {
const actual = await importOriginal<typeof Wagmi>();
Expand All @@ -27,7 +28,7 @@ vi.mock('wagmi', async (importOriginal) => {
address: '0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
};
},
useSignMessage: () => ({ signMessageAsync: createMessage }),
useSignMessage: () => ({ signMessageAsync: mockSignMessageAsync }),
};
});

Expand All @@ -43,6 +44,7 @@ describe('Wagmi siwe sign', () => {
});

const getNonce = vi.fn(async () => '1');
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);

const config = createConfig({
Expand Down Expand Up @@ -75,7 +77,7 @@ describe('Wagmi siwe sign', () => {
'Sign: 0x21CD...Fd3B',
);

fireEvent.click(baseElement.querySelector('.ant-web3-connect-button')!);
fireEvent.click(baseElement.querySelector('.ant-btn-compact-first-item')!);

await waitFor(() => {
expect(getNonce).toBeCalled();
Expand All @@ -96,6 +98,7 @@ describe('Wagmi siwe sign', () => {
const { createConfig, http } = await import('wagmi');

const getNonce = vi.fn(async () => '1');
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);

const config = createConfig({
Expand Down Expand Up @@ -134,7 +137,7 @@ describe('Wagmi siwe sign', () => {
);
const { baseElement } = render(<App />);

fireEvent.click(baseElement.querySelector('.ant-web3-connect-button')!);
fireEvent.click(baseElement.querySelector('.ant-btn-compact-first-item')!);

await waitFor(() => {
expect(createMessage).toBeCalledWith({
Expand All @@ -152,6 +155,7 @@ describe('Wagmi siwe sign', () => {
const { createConfig, http } = await import('wagmi');

const getNonce = vi.fn(async () => '1');
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);

const config = createConfig({
Expand Down Expand Up @@ -190,7 +194,7 @@ describe('Wagmi siwe sign', () => {
);
const { baseElement } = render(<App />);

fireEvent.click(baseElement.querySelector('.ant-web3-connect-button')!);
fireEvent.click(baseElement.querySelector('.ant-btn-compact-first-item')!);

await waitFor(() => {
expect(createMessage).toBeCalledWith({
Expand Down Expand Up @@ -239,6 +243,7 @@ describe('Wagmi siwe sign', () => {
const getNonce = vi.fn(() => {
throw new Error('signAddress is required');
});
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);

const renderText = vi.fn((defaultDom, account) => `Custom Sign: ${account.address}`);
Expand Down Expand Up @@ -281,6 +286,7 @@ describe('Wagmi siwe sign', () => {
const { createConfig, http } = await import('wagmi');

const getNonce = vi.fn(async () => '1');
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);

const config = createConfig({
Expand Down Expand Up @@ -321,4 +327,58 @@ describe('Wagmi siwe sign', () => {
'0x21CD...Fd3B & Custom Sign: 0x21CDf0974d53a6e96eF05d7B324a9803735fFd3B',
);
});

it('test signOut function', async () => {
const { createConfig, http } = await import('wagmi');
const { useProvider } = await import('@ant-design/web3');

const getNonce = vi.fn(async () => '1');
const createMessage = vi.fn(() => 'message');
const verifyMessage = vi.fn(async () => true);
const fakeSignout = vi.fn();

const config = createConfig({
chains: [mainnet],
transports: {
[mainnet.id]: http(),
},
connectors: [],
});

const TestComponent = () => {
const { sign } = useProvider();

React.useEffect(() => {
if (sign?.signOut) {
sign.signOut().then(() => {
fakeSignout();
});
}
}, [sign]);

return <div data-testid="test-component">Test</div>;
};

const App = () => (
<AntDesignWeb3ConfigProvider
walletFactories={[MetaMask()]}
chainAssets={[Mainnet]}
wagimConfig={config}
siwe={{
getNonce,
createMessage,
verifyMessage,
}}
>
<TestComponent />
</AntDesignWeb3ConfigProvider>
);

const { getByTestId } = render(<App />);

await waitFor(() => {
expect(getByTestId('test-component')).toBeTruthy();
expect(fakeSignout).toHaveBeenCalled();
});
});
});
5 changes: 5 additions & 0 deletions packages/wagmi/src/wagmi-provider/config-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
[siwe, currentChain, signMessageAsync],
);

const signOut = async () => {
setStatus(ConnectStatus.Connected);
};

return (
<Web3ConfigProvider
locale={locale}
Expand All @@ -247,6 +251,7 @@ export const AntDesignWeb3ConfigProvider: React.FC<AntDesignWeb3ConfigProviderPr
sign={
siwe && {
signIn,
signOut,
}
}
balance={
Expand Down
2 changes: 1 addition & 1 deletion packages/web3/src/address/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('Address', () => {
);
expect(baseElement.querySelector('.ant-web3-address')?.textContent).toBe('0x21CD...Fd3B');
fireEvent.click(baseElement.querySelector('.anticon-copy')!);
await vi.waitFor(async () => {
await vi.waitFor(() => {
expect(baseElement.querySelector('.anticon-check')).not.toBeNull();
expect(baseElement.querySelector('.anticon-copy')).toBeNull();
expect(baseElement.querySelector('.ant-typography-copy')?.getAttribute('aria-label')).toBe(
Expand Down
Loading