Skip to main content

Connect to EVM - Node.js quickstart

Get started with MetaMask Connect EVM 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.

No polyfills required

Node.js has native support for Buffer, crypto, stream, and other modules that require polyfilling in browser or React Native environments.

Prerequisites

Steps

1. Install MetaMask Connect EVM

Install MetaMask Connect EVM and MetaMask Connect Multichain:

npm install @metamask/connect-evm @metamask/connect-multichain

@metamask/connect-multichain provides the getInfuraRpcUrls helper for generating RPC URLs.

2. Initialize MetaMask Connect EVM

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:

index.mjs
import { createEVMClient } from '@metamask/connect-evm'
import { getInfuraRpcUrls } from '@metamask/connect-multichain'

const evmClient = await createEVMClient({
dapp: {
name: 'My Node.js App',
url: 'https://myapp.com',
},
api: {
supportedNetworks: getInfuraRpcUrls({
infuraApiKey: 'YOUR_INFURA_API_KEY',
}),
},
})
createEVMClient is async

createEVMClient returns a promise. Always await it before using the client. The client is a singleton — calling createEVMClient again returns the same instance.

3. Connect to MetaMask

Call connect() to start the connection flow. A QR code appears in the terminal — scan it with the MetaMask mobile app:

try {
const { accounts, chainId } = await evmClient.connect({
chainIds: ['0x1'],
})
console.log('Connected account:', accounts[0])
console.log('Active chain:', chainId)
} catch (error) {
if (error.code === 4001) {
console.log('User rejected the connection request')
} else if (error.code === -32002) {
console.log('Connection request already pending')
} else {
console.error('Connection failed:', error)
}
}

4. Use the provider

Get the EIP-1193 provider and make JSON-RPC requests:

const provider = evmClient.getProvider()

const balance = await provider.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest'],
})
console.log('Balance (wei):', balance)

5. Sign a message

Use personal_sign to request a signature from the connected wallet:

const message = '0x' + Buffer.from('Hello from Node.js!', 'utf8').toString('hex')

const signature = await provider.request({
method: 'personal_sign',
params: [message, accounts[0]],
})
console.log('Signature:', signature)

6. Disconnect

await evmClient.disconnect()
console.log('Disconnected')

Listen for events

Use eventHandlers in the client configuration to react to connection state changes:

const evmClient = await createEVMClient({
dapp: {
name: 'My Node.js App',
url: 'https://myapp.com',
},
api: {
supportedNetworks: getInfuraRpcUrls({
infuraApiKey: 'YOUR_INFURA_API_KEY',
}),
},
eventHandlers: {
connect: ({ accounts, chainId }) => {
console.log('Connected:', accounts, 'on chain', chainId)
},
disconnect: () => {
console.log('Disconnected')
},
accountsChanged: (accounts) => {
console.log('Accounts changed:', accounts)
},
chainChanged: (chainId) => {
console.log('Chain changed:', chainId)
},
},
})

Full example

index.mjs
import { createEVMClient } from '@metamask/connect-evm'
import { getInfuraRpcUrls } from '@metamask/connect-multichain'

const evmClient = await createEVMClient({
dapp: {
name: 'My Node.js App',
url: 'https://myapp.com',
},
api: {
supportedNetworks: getInfuraRpcUrls({
infuraApiKey: 'YOUR_INFURA_API_KEY',
}),
},
})

// Connect — scan the QR code with the MetaMask mobile app
const { accounts, chainId } = await evmClient.connect({ chainIds: ['0x1'] })
console.log('Connected:', accounts[0], 'on', chainId)

// Get balance
const provider = evmClient.getProvider()
const balance = await provider.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest'],
})
console.log('Balance:', balance)

// Sign a message
const message = '0x' + Buffer.from('Hello from Node.js!', 'utf8').toString('hex')
const signature = await provider.request({
method: 'personal_sign',
params: [message, accounts[0]],
})
console.log('Signature:', signature)

// Disconnect
await evmClient.disconnect()
console.log('Disconnected')

Run it with:

node index.mjs

Next steps