Use the Wallet Adapter
Solana's Wallet Adapter is the standard way for Solana dapps to discover and connect to wallets. MetaMask Connect Solana implements the Wallet Standard, so it works with the Wallet Adapter out-of-the-box.
This guide shows you how to set up the Wallet Adapter with MetaMask in a React dapp. You can also use the
create-solana-dapp CLI tool to generate
a new project with the Wallet Adapter built in.
Prerequisites
- Node.js version 19 or later
- A package manager such as npm, Yarn, pnpm, or bun
- A React or Next.js project
Steps
1. Install dependencies
Install MetaMask Connect Solana and the Wallet Adapter packages:
npm install @metamask/connect-solana \
@solana/web3.js \
@solana/wallet-adapter-base \
@solana/wallet-adapter-react \
@solana/wallet-adapter-react-ui \
@solana/wallet-adapter-wallets
2. Create the Solana provider
Create a SolanaProvider component that initializes MetaMask Connect Solana and wraps the Wallet Adapter
providers:
'use client';
import React, { FC, ReactNode, useEffect, useMemo } from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { clusterApiUrl } from '@solana/web3.js';
import { createSolanaClient } from '@metamask/connect-solana';
import '@solana/wallet-adapter-react-ui/styles.css';
interface SolanaProviderProps {
children: ReactNode;
}
export const SolanaProvider: FC<SolanaProviderProps> = ({ children }) => {
const network = WalletAdapterNetwork.Devnet;
const endpoint = useMemo(() => clusterApiUrl(network), [network]);
useEffect(() => {
createSolanaClient({
dapp: {
name: 'My Solana Dapp',
url: window.location.origin,
},
});
}, []);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={[]} autoConnect>
<WalletModalProvider>{children}</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
};
Calling createSolanaClient registers MetaMask with
the Wallet Standard registry.
This displays MetaMask as a connection option in the wallet modal, even if the user doesn't have
MetaMask installed.
The useEffect pattern above works because createSolanaClient typically resolves before the user
opens the wallet modal.
If MetaMask does not appear in the wallet list, ensure createSolanaClient has resolved before the
WalletProvider renders.
One approach is to await the client in your app's entry point before calling createRoot().render().
See Troubleshooting: MetaMask wallet not appearing
for details.
3. Add the provider to your root layout
Wrap your application with SolanaProvider so all components can access the wallet context:
import './globals.css';
import '@solana/wallet-adapter-react-ui/styles.css';
import { SolanaProvider } from '@/components/SolanaProvider';
export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html>
<body>
<SolanaProvider>{children}</SolanaProvider>
</body>
</html>
);
}
4. Add a connect button
Use the Wallet Adapter's WalletMultiButton component to add a connect button to your dapp:
'use client';
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
export const ConnectWallet = () => {
return <WalletMultiButton />;
};
The button automatically displays a wallet selection modal that includes MetaMask.
There is a known issue with @solana/wallet-adapter-react on Chrome Android when used with the
Wallet Standard provider from @metamask/connect-solana.
Test Solana Wallet Adapter flows on desktop Chrome and the MetaMask browser extension before
targeting mobile.
See Troubleshooting for details.
Next steps
See how to send a legacy transaction and a versioned transaction.