Skip to content

Commit 3bd5d95

Browse files
committed
refactor: Lazy instantiation of adapters
1 parent 3b162c6 commit 3bd5d95

File tree

8 files changed

+159
-150
lines changed

8 files changed

+159
-150
lines changed

packages/assets/src/wallets/solflare.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,3 @@ export const metadata_Solflare: WalletMetadata = {
1818
},
1919
],
2020
};
21-
22-
export const metadata_SolflareMetaMaskSnap: WalletMetadata & { isMetaMaskSnap: true } = {
23-
...metadata_Solflare,
24-
isMetaMaskSnap: true,
25-
};

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface AntDesignWeb3ConfigProviderProps {
2525
availableChains: SolanaChainConfig[];
2626
balance?: boolean;
2727
currentChain?: SolanaChainConfig;
28-
availableWallets: Wallet[];
28+
availableWallets?: Wallet[];
2929
connectionError?: WalletConnectionError;
3030
autoAddRegisteredWallets?: boolean;
3131
onCurrentChainChange?: (chain?: SolanaChainConfig) => void;
@@ -137,8 +137,8 @@ export const AntDesignWeb3ConfigProvider: React.FC<
137137
.filter((item) => item !== null) as (Chain & SolanaChainConfig)[];
138138
}, [props.availableChains, props.chainAssets]);
139139

140-
const availableWallets = useMemo<Wallet[]>(() => {
141-
const providedWallets = props.availableWallets.map<Wallet>((w) => {
140+
const availableWallets = useMemo<Wallet[] | undefined>(() => {
141+
const providedWallets = props.availableWallets?.map<Wallet>((w) => {
142142
const adapter = wallets?.find((item) => item.adapter.name === w.name)?.adapter;
143143
const isWalletConnectAdapter = adapter instanceof WalletConnectWalletAdapter;
144144

@@ -161,10 +161,10 @@ export const AntDesignWeb3ConfigProvider: React.FC<
161161
return providedWallets;
162162
}
163163

164-
const providedWalletNames = providedWallets.map((w) => w.name);
164+
const providedWalletNames = providedWallets?.map((w) => w.name);
165165

166166
const autoRegisteredWallets = wallets
167-
.filter((w) => !providedWalletNames.includes(w.adapter.name))
167+
.filter((w) => !providedWalletNames?.includes(w.adapter.name))
168168
.map<Wallet>((w) => {
169169
const adapter = w.adapter;
170170

@@ -182,7 +182,7 @@ export const AntDesignWeb3ConfigProvider: React.FC<
182182
};
183183
});
184184

185-
return [...providedWallets, ...autoRegisteredWallets];
185+
return [...(providedWallets || []), ...(autoRegisteredWallets || [])];
186186
}, [props.availableWallets, wallets, props.autoAddRegisteredWallets]);
187187

188188
const currentChain = useMemo(() => {
Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { useMemo, useState, type FC, type PropsWithChildren } from 'react';
1+
import { useEffect, useMemo, useState, type FC, type PropsWithChildren } from 'react';
22
import { Solana, SolanaDevnet, SolanaTestnet } from '@ant-design/web3-assets/solana';
3-
import type { Locale } from '@ant-design/web3-common';
3+
import type { Locale, Wallet } from '@ant-design/web3-common';
44
import { WalletConnectionError } from '@solana/wallet-adapter-base';
55
import {
66
ConnectionProvider,
@@ -11,15 +11,15 @@ import {
1111
import { type UniversalProviderOpts } from '@walletconnect/universal-provider';
1212

1313
import { solana, type SolanaChainConfig } from '../chains';
14-
import { isAdapterWalletFactory, isWalletConnectFactory } from '../utils';
14+
import { isAdapterWallet, isWalletConnectWallet } from '../utils';
1515
import { type WalletFactory } from '../wallets/types';
1616
import { AntDesignWeb3ConfigProvider } from './config-provider';
1717
import { useWalletConnectProvider } from './useWalletConnectProvider';
1818

1919
export interface SolanaWeb3ConfigProviderProps {
2020
locale?: Locale;
2121
chains?: SolanaChainConfig[];
22-
wallets?: WalletFactory[];
22+
wallets: WalletFactory[];
2323
balance?: boolean;
2424

2525
autoAddRegisteredWallets?: boolean;
@@ -41,7 +41,7 @@ export interface SolanaWeb3ConfigProviderProps {
4141
export const SolanaWeb3ConfigProvider: FC<PropsWithChildren<SolanaWeb3ConfigProviderProps>> = ({
4242
locale,
4343
chains = [solana],
44-
wallets: walletFactories = [],
44+
wallets: walletFactories,
4545
balance,
4646
rpcProvider,
4747
connectionConfig,
@@ -55,6 +55,8 @@ export const SolanaWeb3ConfigProvider: FC<PropsWithChildren<SolanaWeb3ConfigProv
5555
const [connectionError, setConnectionError] = useState<WalletConnectionError>();
5656
const walletConnectProviderGetter = useWalletConnectProvider(walletConnect);
5757

58+
const [walletInstances, setWalletInstances] = useState<Wallet[]>();
59+
5860
const endpoint = useMemo(() => {
5961
if (typeof rpcProvider === 'function') {
6062
return rpcProvider(currentChain);
@@ -63,59 +65,57 @@ export const SolanaWeb3ConfigProvider: FC<PropsWithChildren<SolanaWeb3ConfigProv
6365
return (currentChain ?? solana).rpcUrls.default;
6466
}, [rpcProvider, currentChain]);
6567

66-
const availableWallets = walletFactories.map((factory) =>
67-
factory.create(walletConnectProviderGetter),
68-
);
68+
useEffect(() => {
69+
const allWallets = walletFactories.map((factory) => factory.create());
6970

70-
// Only filter out the wallets that have an adapter
71-
const walletAdapters = useMemo(
72-
() =>
73-
walletFactories
74-
.filter(isAdapterWalletFactory)
75-
76-
.map((w) => {
77-
if (isWalletConnectFactory(w)) {
78-
w.adapter.setWalletConnectProviderGetter(walletConnectProviderGetter);
79-
w.adapter.setWalletConnectConfigGetter(() => ({
80-
walletConnect,
81-
currentChain,
82-
rpcEndpoint: endpoint,
83-
}));
84-
}
85-
86-
return w.adapter;
87-
}),
88-
[currentChain, endpoint, walletConnect, walletConnectProviderGetter, walletFactories],
89-
);
71+
setWalletInstances(allWallets);
72+
}, [walletFactories]);
73+
74+
const availableWalletAdapters = useMemo(() => {
75+
return walletInstances?.filter(isAdapterWallet).map((w) => {
76+
if (isWalletConnectWallet(w)) {
77+
w.adapter.setWalletConnectProviderGetter(walletConnectProviderGetter);
78+
w.adapter.setWalletConnectConfigGetter(() => ({
79+
walletConnect,
80+
currentChain,
81+
rpcEndpoint: endpoint,
82+
}));
83+
}
84+
85+
return w.adapter!;
86+
});
87+
}, [currentChain, endpoint, walletConnect, walletConnectProviderGetter, walletInstances]);
9088

9189
return (
9290
<ConnectionProvider endpoint={endpoint} config={connectionConfig}>
93-
<WalletProvider
94-
wallets={walletAdapters}
95-
autoConnect={autoConnect}
96-
{...walletProviderProps}
97-
onError={(error, adapter) => {
98-
if (error instanceof WalletConnectionError) {
99-
setConnectionError(error);
100-
}
101-
102-
walletProviderProps?.onError?.(error, adapter);
103-
}}
104-
>
105-
<AntDesignWeb3ConfigProvider
106-
locale={locale}
107-
chainAssets={[Solana, SolanaDevnet, SolanaTestnet]}
108-
availableWallets={availableWallets}
109-
balance={balance}
110-
currentChain={currentChain}
111-
onCurrentChainChange={(chain) => setCurrentChain(chain)}
112-
availableChains={chains}
113-
connectionError={connectionError}
114-
autoAddRegisteredWallets={autoAddRegisteredWallets}
91+
{!!availableWalletAdapters && (
92+
<WalletProvider
93+
wallets={availableWalletAdapters}
94+
autoConnect={autoConnect}
95+
{...walletProviderProps}
96+
onError={(error, adapter) => {
97+
if (error instanceof WalletConnectionError) {
98+
setConnectionError(error);
99+
}
100+
101+
walletProviderProps?.onError?.(error, adapter);
102+
}}
115103
>
116-
{children}
117-
</AntDesignWeb3ConfigProvider>
118-
</WalletProvider>
104+
<AntDesignWeb3ConfigProvider
105+
locale={locale}
106+
chainAssets={[Solana, SolanaDevnet, SolanaTestnet]}
107+
availableWallets={walletInstances}
108+
balance={balance}
109+
currentChain={currentChain}
110+
onCurrentChainChange={(chain) => setCurrentChain(chain)}
111+
availableChains={chains}
112+
connectionError={connectionError}
113+
autoAddRegisteredWallets={autoAddRegisteredWallets}
114+
>
115+
{children}
116+
</AntDesignWeb3ConfigProvider>
117+
</WalletProvider>
118+
)}
119119
</ConnectionProvider>
120120
);
121121
};

packages/solana/src/utils.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1+
import type { Wallet } from '@ant-design/web3-common';
12
import { WalletReadyState } from '@solana/wallet-adapter-base';
23

34
import type {
4-
AdapterWalletFactory as AdapterWalletFactoryType,
5-
WalletConnectWalletFactory as WalletConnectWalletFactoryType,
5+
AdapterWallet,
6+
MetaMaskSnapWalletFactory as MetaMaskSnapWalletFactoryType,
7+
StandardWallet,
8+
WalletConnectWallet,
69
WalletFactory as WalletFactoryType,
710
} from './wallets/types';
811

912
export const hasWalletReady = (readyState?: WalletReadyState) =>
1013
readyState === WalletReadyState.Installed || readyState === WalletReadyState.Loadable;
1114

12-
export const isWalletConnectFactory = (
15+
export const isMetaMaskSnapWalletFactory = (
1316
factory: WalletFactoryType,
14-
): factory is WalletConnectWalletFactoryType =>
15-
!!(factory as WalletConnectWalletFactoryType).isWalletConnect;
17+
): factory is MetaMaskSnapWalletFactoryType => {
18+
return (factory as MetaMaskSnapWalletFactoryType).isMetaMaskSnap === true;
19+
};
1620

17-
export const isAdapterWalletFactory = (
18-
factory: WalletFactoryType,
19-
): factory is AdapterWalletFactoryType => {
20-
return (factory as AdapterWalletFactoryType).adapter !== undefined;
21+
export const isStandardWallet = (wallet: Wallet): wallet is StandardWallet => {
22+
return (wallet as StandardWallet).isStandardWallet === true;
23+
};
24+
25+
export const isAdapterWallet = (wallet: Wallet): wallet is AdapterWallet => {
26+
return (wallet as AdapterWallet).adapter !== undefined;
27+
};
28+
29+
export const isWalletConnectWallet = (wallet: Wallet): wallet is WalletConnectWallet => {
30+
return (wallet as WalletConnectWallet).isWalletConnect !== undefined;
2131
};

packages/solana/src/wallets/built-in.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,26 @@ import {
44
metadata_OkxWallet,
55
metadata_Phantom,
66
metadata_Solflare,
7-
metadata_SolflareMetaMaskSnap,
87
metadata_Trust,
98
metadata_WalletConnect,
109
} from '@ant-design/web3-assets';
11-
import {
12-
CoinbaseWalletAdapter,
13-
SolflareWalletAdapter,
14-
TrustWalletAdapter,
15-
} from '@solana/wallet-adapter-wallets';
10+
import { CoinbaseWalletAdapter, TrustWalletAdapter } from '@solana/wallet-adapter-wallets';
1611

1712
import { WalletConnectWalletAdapter } from '../wallet-connect-adapter';
1813
import { StandardWalletFactory, WalletConnectWalletFactory, WalletFactory } from './factory';
1914

20-
export const CoinbaseWallet = () =>
21-
WalletFactory(new CoinbaseWalletAdapter(), metadata_CoinbaseWallet);
22-
export const TrustWallet = () => WalletFactory(new TrustWalletAdapter(), metadata_Trust);
23-
export const SolflareMetaMaskSnapWallet = () =>
24-
WalletFactory(new SolflareWalletAdapter(), metadata_SolflareMetaMaskSnap);
15+
export const CoinbaseWallet = WalletFactory(
16+
() => new CoinbaseWalletAdapter(),
17+
metadata_CoinbaseWallet,
18+
);
19+
export const TrustWallet = WalletFactory(() => new TrustWalletAdapter(), metadata_Trust);
2520

26-
export const PhantomWallet = () => StandardWalletFactory(metadata_Phantom);
27-
export const OKXWallet = () => StandardWalletFactory(metadata_OkxWallet);
28-
export const BackpackWallet = () => StandardWalletFactory(metadata_Backpack);
29-
export const SolflareWallet = () => StandardWalletFactory(metadata_Solflare);
21+
export const PhantomWallet = StandardWalletFactory(metadata_Phantom);
22+
export const OKXWallet = StandardWalletFactory(metadata_OkxWallet);
23+
export const BackpackWallet = StandardWalletFactory(metadata_Backpack);
24+
export const SolflareWallet = StandardWalletFactory(metadata_Solflare);
3025

31-
export const WalletConnectWallet = () =>
32-
WalletConnectWalletFactory(new WalletConnectWalletAdapter(), metadata_WalletConnect);
26+
export const WalletConnectWallet = WalletConnectWalletFactory(
27+
new WalletConnectWalletAdapter(),
28+
metadata_WalletConnect,
29+
);

packages/solana/src/wallets/factory.ts

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,35 @@ import type {
44
WalletFactoryBuilder,
55
} from './types';
66

7-
export const WalletFactory: WalletFactoryBuilder = (adapter, metadata) => {
8-
return {
9-
adapter,
10-
create: () => {
11-
return {
12-
...metadata,
13-
name: adapter.name,
14-
remark: metadata.remark,
15-
adapter: adapter,
16-
};
17-
},
7+
export const WalletFactory: WalletFactoryBuilder = (adapterBuilder, metadata) => {
8+
return () => {
9+
return {
10+
// adapter,
11+
create: () => {
12+
const adapter = typeof adapterBuilder === 'function' ? adapterBuilder() : adapterBuilder;
13+
14+
return {
15+
...metadata,
16+
name: adapter.name,
17+
remark: metadata.remark,
18+
adapter: adapter,
19+
};
20+
},
21+
};
1822
};
1923
};
2024

2125
// For Standard wallets
2226
export const StandardWalletFactory: StandardWalletFactoryBuilder = (metadata) => {
23-
return {
24-
create: () => {
25-
return {
26-
...metadata,
27-
isStandardWallet: true,
28-
};
29-
},
27+
return () => {
28+
return {
29+
create: () => {
30+
return {
31+
...metadata,
32+
isStandardWallet: true,
33+
};
34+
},
35+
};
3036
};
3137
};
3238

@@ -35,32 +41,34 @@ export const WalletConnectWalletFactory: WalletConnectWalletFactoryBuilder = (
3541
adapter,
3642
metadata,
3743
) => {
38-
return {
39-
isWalletConnect: true,
40-
adapter,
41-
create: (getWalletConnectProvider) => {
42-
return {
43-
...metadata,
44-
name: adapter.name,
45-
remark: metadata.remark,
46-
adapter,
44+
return () => {
45+
return {
46+
create: (getWalletConnectProvider) => {
47+
return {
48+
...metadata,
49+
name: adapter.name,
50+
remark: metadata.remark,
4751

48-
getQrCode: getWalletConnectProvider
49-
? async () => {
50-
const walletConnectProvider = await getWalletConnectProvider();
52+
adapter,
53+
isWalletConnect: true,
5154

52-
if (!walletConnectProvider) {
53-
return Promise.reject(new Error('WalletConnect is not available'));
54-
}
55+
getQrCode: getWalletConnectProvider
56+
? async () => {
57+
const walletConnectProvider = await getWalletConnectProvider();
5558

56-
return new Promise((resolve) => {
57-
walletConnectProvider.on('display_uri', (uri: string) => {
58-
resolve({ uri });
59+
if (!walletConnectProvider) {
60+
return Promise.reject(new Error('WalletConnect is not available'));
61+
}
62+
63+
return new Promise((resolve) => {
64+
walletConnectProvider.on('display_uri', (uri: string) => {
65+
resolve({ uri });
66+
});
5967
});
60-
});
61-
}
62-
: undefined,
63-
};
64-
},
68+
}
69+
: undefined,
70+
};
71+
},
72+
};
6573
};
6674
};

0 commit comments

Comments
 (0)