Connect to Solana - Node.js quickstart
Get started with MetaMask Connect Solana in a Node.js application. The SDK displays a QR code in the terminal that you scan with the MetaMask mobile app to establish a connection.
Wallet Standard features (getWallet(),
wallet.features[...]) are designed for browser environments.
In Node.js, use the multichain core directly via client.core.connect() and
client.core.invokeMethod() to interact with Solana.
Prerequisites
- Node.js version 20 or later installed.
- A package manager installed, such as npm, Yarn, or pnpm.
- The MetaMask mobile app installed on your phone.
- An Infura API key from the MetaMask Developer dashboard.
Steps
1. Install dependencies
- npm
- Yarn
- pnpm
- Bun
npm install @metamask/connect-solana
yarn add @metamask/connect-solana
pnpm add @metamask/connect-solana
bun add @metamask/connect-solana
2. Initialize the Solana client
Create a file (for example, index.mjs) and initialize the client.
In Node.js, there is no window.location, so you must set dapp.url explicitly.
The supportedNetworks map uses network names (mainnet, devnet) as keys:
import { createSolanaClient, getInfuraRpcUrls } from '@metamask/connect-solana'
const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
const solanaClient = await createSolanaClient({
dapp: {
name: 'My Node.js Solana App',
url: 'https://myapp.com',
},
api: {
supportedNetworks: getInfuraRpcUrls({
infuraApiKey: 'YOUR_INFURA_API_KEY',
networks: ['mainnet'],
}),
},
})
createSolanaClient returns a promise. Always await it before using the client.
The client uses a singleton multichain core under the hood — calling it multiple times
returns the same underlying session.
3. Connect to MetaMask
Use the multichain core to connect with a Solana scope. A QR code appears in the terminal — scan it with the MetaMask mobile app:
await solanaClient.core.connect([SOLANA_MAINNET], [])
const session = await solanaClient.core.getSession()
const accounts = session?.sessionScopes?.[SOLANA_MAINNET]?.accounts ?? []
const address = accounts[0]?.split(':').pop()
console.log('Connected Solana address:', address)
4. Sign a message
Use invokeMethod to call the signMessage method on the Solana scope:
const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64')
const result = await solanaClient.core.invokeMethod({
scope: SOLANA_MAINNET,
request: {
method: 'signMessage',
params: {
account: { address },
message,
},
},
})
console.log('Signature:', result)
5. Disconnect
await solanaClient.disconnect()
console.log('Disconnected')
Listen for session events
Use the wallet_sessionChanged event on the multichain core to track session state:
solanaClient.core.on('wallet_sessionChanged', (session) => {
if (session?.sessionScopes) {
const solanaAccounts = session.sessionScopes[SOLANA_MAINNET]?.accounts ?? []
console.log('Solana accounts:', solanaAccounts)
} else {
console.log('Session ended')
}
})
Solana CAIP-2 scope reference
| Network | CAIP-2 scope |
|---|---|
| Mainnet | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
| Devnet | solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 |
Devnet and testnet require MetaMask Flask. Production MetaMask only supports Solana mainnet.
Full example
import { createSolanaClient, getInfuraRpcUrls } from '@metamask/connect-solana'
const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
const solanaClient = await createSolanaClient({
dapp: {
name: 'My Node.js Solana App',
url: 'https://myapp.com',
},
api: {
supportedNetworks: getInfuraRpcUrls({
infuraApiKey: 'YOUR_INFURA_API_KEY',
networks: ['mainnet'],
}),
},
})
// Connect — scan the QR code with the MetaMask mobile app
await solanaClient.core.connect([SOLANA_MAINNET], [])
const session = await solanaClient.core.getSession()
const accounts = session?.sessionScopes?.[SOLANA_MAINNET]?.accounts ?? []
const address = accounts[0]?.split(':').pop()
console.log('Connected:', address)
// Sign a message
const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64')
const result = await solanaClient.core.invokeMethod({
scope: SOLANA_MAINNET,
request: {
method: 'signMessage',
params: {
account: { address },
message,
},
},
})
console.log('Signature:', result)
// Disconnect
await solanaClient.disconnect()
console.log('Disconnected')
Run it with:
node index.mjs
Next steps
- Send a legacy Solana transaction.
- Send a versioned Solana transaction.
- Sign a Solana message.
- Use the multichain client to connect to both EVM and Solana from a single session.