Skip to content

Commit

Permalink
fix(solana): Some wallets cannot connect again (#1331)
Browse files Browse the repository at this point in the history
* fix(solana): Some wallets cannot connect again

* refactor: comments

* test: update test case
  • Loading branch information
gin-lsl authored Jan 27, 2025
1 parent b5532ab commit c8aaacc
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/hip-vans-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ant-design/web3-solana': patch
---

fix(solana): Some wallets cannot connect again
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ vi.mock('@solana/wallet-adapter-react', async () => {
mockThrowWalletConnectionError();
onError?.(new WalletConnectionError('mock error'));
}
}, [mockThrowError, onError]);
}, [mockThrowError]);
return <>{children}</>;
};

Expand Down
70 changes: 43 additions & 27 deletions packages/solana/src/solana-provider/__tests__/connect.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useProvider } from '@ant-design/web3';
import { WalletReadyState } from '@solana/wallet-adapter-base';
import type { ConnectionContextState } from '@solana/wallet-adapter-react';
Expand Down Expand Up @@ -66,7 +66,7 @@ vi.mock('@solana/wallet-adapter-react', async () => {
connectedRef.value = true;
setConnected((p) => p + 1);
}
}, [currentWallet]);
}, [currentWallet?.adapter?.name]);

useEffect(() => {
if (connecting) {
Expand All @@ -76,22 +76,34 @@ vi.mock('@solana/wallet-adapter-react', async () => {
}
}, [connecting]);

const selectCallback = useCallback((walletName: string | null) => {
mockSelectWalletFnNotWalletName(walletName);
const mockWalletAdapter = {
adapter: { name: walletName, readyState: WalletReadyState.Installed },
};
currentWalletRef.value = mockWalletAdapter;
setCurrentWallet(mockWalletAdapter);
mockSelectWalletFn();
}, []);

const connectCallback = useCallback(async () => {
setConnected(0);
setConnecting(true);
await new Promise((resolve) => {
setTimeout(() => {
resolve(0);
}, 100);
});
setConnecting(false);
setConnected((p) => p + 1);
}, []);

return {
publicKey,
connecting,
connected: connected,
connect: async () => {
setConnecting(true);
},
select: (walletName: string | null) => {
mockSelectWalletFnNotWalletName(walletName);
const mockWalletAdapter = {
adapter: { name: walletName, readyState: WalletReadyState.Installed },
};
currentWalletRef.value = mockWalletAdapter;
setCurrentWallet(mockWalletAdapter);
mockSelectWalletFn();
},
connected: !!connected,
connect: connectCallback,
select: selectCallback,
disconnect: () => {},
wallet: currentWalletRef.value,
wallets: [
Expand Down Expand Up @@ -161,6 +173,7 @@ describe('Solana Connect', () => {
<div className="custom-connectbtn">
<button
className="btn-switchwallet"
type="button"
onClick={() => {
switchWalletRunned();
}}
Expand All @@ -169,6 +182,7 @@ describe('Solana Connect', () => {
</button>
<button
className="btn-connect"
type="button"
onClick={async () => {
await connectWallet();
// mock connect twice
Expand Down Expand Up @@ -226,20 +240,16 @@ describe('Solana Connect', () => {
expect(mockSelectWalletFn).toBeCalledTimes(3);
});

await vi.waitFor(
() => {
expect(connectRunned).toBeCalled();
expect(shownConnectRunDone.textContent).toBe('true');
expect(gotAddressAfterConnect).toBeCalledWith(mockedData.address.value);
},
{
timeout: 5000,
},
);
await vi.waitFor(() => {
expect(connectRunned).toBeCalled();
expect(shownConnectRunDone.textContent).toBe('true');
expect(gotAddressAfterConnect).toBeCalledWith(mockedData.address.value);
});
});

it('call connect but not provide wallet', async () => {
const { useWallet } = await import('@solana/wallet-adapter-react');
const prepareConnectRunned = vi.fn();
const connectRunned = vi.fn();

const CustomConnectBtn: React.FC = () => {
Expand All @@ -250,13 +260,15 @@ describe('Solana Connect', () => {
<div className="custom-connectbtn">
<button
className="btn-connect"
type="button"
onClick={async () => {
prepareConnectRunned();
await connectWallet();
connect?.();
connectRunned();
}}
>
Connect
Connect1
</button>
</div>
);
Expand All @@ -281,7 +293,11 @@ describe('Solana Connect', () => {

fireEvent.click(connectBtn);
await vi.waitFor(() => {
expect(connectRunned).toBeCalled();
expect(prepareConnectRunned).toBeCalled();
expect(connectRunned).not.toBeCalled();
});

await vi.waitFor(() => {
expect(mockSelectWalletFnNotWalletName).toBeCalledWith(null);
});
});
Expand Down
14 changes: 13 additions & 1 deletion packages/solana/src/solana-provider/config-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export interface AntDesignWeb3ConfigProviderProps {
export const AntDesignWeb3ConfigProvider: React.FC<
React.PropsWithChildren<AntDesignWeb3ConfigProviderProps>
> = (props) => {
const mountRef = useRef(false);

const {
publicKey,
connected,
Expand All @@ -45,7 +47,6 @@ export const AntDesignWeb3ConfigProvider: React.FC<
} = useWallet();

const { connection } = useConnection();

const connectAsyncRef = useRef<ConnectAsync>();

const [balanceData, setBalanceData] = useState<bigint>();
Expand Down Expand Up @@ -98,6 +99,11 @@ export const AntDesignWeb3ConfigProvider: React.FC<

// connect/disconnect wallet
useEffect(() => {
// 初始化时跳过,避免与 wallet-adapter 的自动连接逻辑冲突
if (!mountRef.current) {
return;
}

if (wallet?.adapter?.name) {
// if wallet is not ready, need clear selected wallet
if (!hasWalletReady(wallet.adapter.readyState)) {
Expand All @@ -113,6 +119,12 @@ export const AntDesignWeb3ConfigProvider: React.FC<
}
}, [wallet?.adapter?.name, connected]);

useEffect(() => {
if (!mountRef.current) {
mountRef.current = true;
}
}, []);

const chainList = useMemo(() => {
return props.availableChains
.map((item) => {
Expand Down

0 comments on commit c8aaacc

Please sign in to comment.