Connect to Solana using Node.js
Get started with MetaMask Connect Solana in a Node.js application. The SDK displays a QR code in the terminal that you scan with MetaMask Mobile 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.
- MetaMask Mobile 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 } 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: {
mainnet: 'https://solana-mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
},
},
})
createSolanaClient is asynccreateSolanaClient 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 MetaMask Mobile:
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 } 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: {
mainnet: 'https://solana-mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
},
},
})
// Connect -- scan the QR code with MetaMask Mobile
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 SDK to connect to both EVM and Solana from a single session