Skip to content

Commit c8aaacc

Browse files
authored
fix(solana): Some wallets cannot connect again (#1331)
* fix(solana): Some wallets cannot connect again * refactor: comments * test: update test case
1 parent b5532ab commit c8aaacc

File tree

4 files changed

+62
-29
lines changed

4 files changed

+62
-29
lines changed

.changeset/hip-vans-laugh.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@ant-design/web3-solana': patch
3+
---
4+
5+
fix(solana): Some wallets cannot connect again

packages/solana/src/solana-provider/__tests__/connect-error.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ vi.mock('@solana/wallet-adapter-react', async () => {
7777
mockThrowWalletConnectionError();
7878
onError?.(new WalletConnectionError('mock error'));
7979
}
80-
}, [mockThrowError, onError]);
80+
}, [mockThrowError]);
8181
return <>{children}</>;
8282
};
8383

packages/solana/src/solana-provider/__tests__/connect.test.tsx

+43-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useCallback, useEffect, useState } from 'react';
22
import { useProvider } from '@ant-design/web3';
33
import { WalletReadyState } from '@solana/wallet-adapter-base';
44
import type { ConnectionContextState } from '@solana/wallet-adapter-react';
@@ -66,7 +66,7 @@ vi.mock('@solana/wallet-adapter-react', async () => {
6666
connectedRef.value = true;
6767
setConnected((p) => p + 1);
6868
}
69-
}, [currentWallet]);
69+
}, [currentWallet?.adapter?.name]);
7070

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

79+
const selectCallback = useCallback((walletName: string | null) => {
80+
mockSelectWalletFnNotWalletName(walletName);
81+
const mockWalletAdapter = {
82+
adapter: { name: walletName, readyState: WalletReadyState.Installed },
83+
};
84+
currentWalletRef.value = mockWalletAdapter;
85+
setCurrentWallet(mockWalletAdapter);
86+
mockSelectWalletFn();
87+
}, []);
88+
89+
const connectCallback = useCallback(async () => {
90+
setConnected(0);
91+
setConnecting(true);
92+
await new Promise((resolve) => {
93+
setTimeout(() => {
94+
resolve(0);
95+
}, 100);
96+
});
97+
setConnecting(false);
98+
setConnected((p) => p + 1);
99+
}, []);
100+
79101
return {
80102
publicKey,
81103
connecting,
82-
connected: connected,
83-
connect: async () => {
84-
setConnecting(true);
85-
},
86-
select: (walletName: string | null) => {
87-
mockSelectWalletFnNotWalletName(walletName);
88-
const mockWalletAdapter = {
89-
adapter: { name: walletName, readyState: WalletReadyState.Installed },
90-
};
91-
currentWalletRef.value = mockWalletAdapter;
92-
setCurrentWallet(mockWalletAdapter);
93-
mockSelectWalletFn();
94-
},
104+
connected: !!connected,
105+
connect: connectCallback,
106+
select: selectCallback,
95107
disconnect: () => {},
96108
wallet: currentWalletRef.value,
97109
wallets: [
@@ -161,6 +173,7 @@ describe('Solana Connect', () => {
161173
<div className="custom-connectbtn">
162174
<button
163175
className="btn-switchwallet"
176+
type="button"
164177
onClick={() => {
165178
switchWalletRunned();
166179
}}
@@ -169,6 +182,7 @@ describe('Solana Connect', () => {
169182
</button>
170183
<button
171184
className="btn-connect"
185+
type="button"
172186
onClick={async () => {
173187
await connectWallet();
174188
// mock connect twice
@@ -226,20 +240,16 @@ describe('Solana Connect', () => {
226240
expect(mockSelectWalletFn).toBeCalledTimes(3);
227241
});
228242

229-
await vi.waitFor(
230-
() => {
231-
expect(connectRunned).toBeCalled();
232-
expect(shownConnectRunDone.textContent).toBe('true');
233-
expect(gotAddressAfterConnect).toBeCalledWith(mockedData.address.value);
234-
},
235-
{
236-
timeout: 5000,
237-
},
238-
);
243+
await vi.waitFor(() => {
244+
expect(connectRunned).toBeCalled();
245+
expect(shownConnectRunDone.textContent).toBe('true');
246+
expect(gotAddressAfterConnect).toBeCalledWith(mockedData.address.value);
247+
});
239248
});
240249

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

245255
const CustomConnectBtn: React.FC = () => {
@@ -250,13 +260,15 @@ describe('Solana Connect', () => {
250260
<div className="custom-connectbtn">
251261
<button
252262
className="btn-connect"
263+
type="button"
253264
onClick={async () => {
265+
prepareConnectRunned();
254266
await connectWallet();
255267
connect?.();
256268
connectRunned();
257269
}}
258270
>
259-
Connect
271+
Connect1
260272
</button>
261273
</div>
262274
);
@@ -281,7 +293,11 @@ describe('Solana Connect', () => {
281293

282294
fireEvent.click(connectBtn);
283295
await vi.waitFor(() => {
284-
expect(connectRunned).toBeCalled();
296+
expect(prepareConnectRunned).toBeCalled();
297+
expect(connectRunned).not.toBeCalled();
298+
});
299+
300+
await vi.waitFor(() => {
285301
expect(mockSelectWalletFnNotWalletName).toBeCalledWith(null);
286302
});
287303
});

packages/solana/src/solana-provider/config-provider.tsx

+13-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export interface AntDesignWeb3ConfigProviderProps {
3434
export const AntDesignWeb3ConfigProvider: React.FC<
3535
React.PropsWithChildren<AntDesignWeb3ConfigProviderProps>
3636
> = (props) => {
37+
const mountRef = useRef(false);
38+
3739
const {
3840
publicKey,
3941
connected,
@@ -45,7 +47,6 @@ export const AntDesignWeb3ConfigProvider: React.FC<
4547
} = useWallet();
4648

4749
const { connection } = useConnection();
48-
4950
const connectAsyncRef = useRef<ConnectAsync>();
5051

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

99100
// connect/disconnect wallet
100101
useEffect(() => {
102+
// 初始化时跳过,避免与 wallet-adapter 的自动连接逻辑冲突
103+
if (!mountRef.current) {
104+
return;
105+
}
106+
101107
if (wallet?.adapter?.name) {
102108
// if wallet is not ready, need clear selected wallet
103109
if (!hasWalletReady(wallet.adapter.readyState)) {
@@ -113,6 +119,12 @@ export const AntDesignWeb3ConfigProvider: React.FC<
113119
}
114120
}, [wallet?.adapter?.name, connected]);
115121

122+
useEffect(() => {
123+
if (!mountRef.current) {
124+
mountRef.current = true;
125+
}
126+
}, []);
127+
116128
const chainList = useMemo(() => {
117129
return props.availableChains
118130
.map((item) => {

0 commit comments

Comments
 (0)