eth_accounts to Retrieve User AccountsMetaMask is more than just a popular crypto wallet—it functions as a gateway for web applications (dApps) to interact with Ethereum and other EVM-compatible blockchains. For developers building on top of MetaMask, understanding how to work with its injected provider, detect account changes, and manage connections is critical.
In my experience building and testing dApps, MetaMask’s JavaScript API offers a streamlined approach but also introduces nuances that, if overlooked, can cause a poor user experience or security gaps. So, let’s carefully unpack these core aspects.
At the heart of the MetaMask extension or mobile app is the injected provider (window.ethereum). This object serves as an interface between your dApp and the user's MetaMask wallet. It allows your application to request account access, send transactions, and listen to events such as account or network changes.
Think of window.ethereum as the translator between your code and the blockchain—a bridge that facilitates non-custodial access without exposing private keys.
For any MetaMask developer account, the first step usually involves checking for this provider’s presence before attempting wallet interactions:
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask is installed!');
} else {
console.warn('MetaMask not detected');
}
A common developer challenge is responding dynamically when users switch accounts inside their MetaMask wallet. This is crucial for dApps that track user balances or permissions.
MetaMask emits the accountsChanged event whenever the active account changes. You can listen to this event via the provider:
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
// User has locked or disconnected MetaMask
console.log('Please connect your wallet.');
} else {
console.log('Active account changed to:', accounts[0]);
// Update your app state accordingly
}
});
What I've found is that failing to handle this properly leads to stale or insecure dApp states. Always assume users can switch accounts any moment and refresh relevant data accordingly.
eth_accounts to Retrieve User Accountseth_accounts is a JSON-RPC method that returns an array of user Ethereum addresses currently authorized to your dApp. Unlike eth_requestAccounts, it does not prompt the user but simply returns what the app already has permission for.
A typical snippet:
const accounts = await window.ethereum.request({ method: 'eth_accounts' });
if (accounts.length > 0) {
console.log('Connected accounts:', accounts);
} else {
console.log('No accounts authorized');
}
Why does this matter? It lets your dApp check connection status silently, improving UX by avoiding unnecessary permission popups.
For full connection flow, you’d normally combine eth_accounts with eth_requestAccounts to request permission when no accounts exist.
MetaMask does not currently provide a direct disconnect method in the injected provider API. But the concept of "disconnect" exists from the dApp perspective as user revoking or dropping connection.
In practice, the metamask_disconnect event can be emitted by the extension to notify dApps, but support varies. Developers should design their applications to:
accountsChanged with empty array).eth_requestAccounts.Here’s a guarded approach:
window.ethereum.on('disconnect', (error) => {
console.log('MetaMask disconnected', error);
// Clear app state and ask for reconnection
});
If you want users to actively "disconnect" their wallet, this generally happens client-side simply by removing authorization or state. It's more manual compared to some other wallet APIs.
Besides account changes, detecting network changes is equally important. When the user switches from Ethereum mainnet to, say, Polygon or Binance Smart Chain, your dApp must update accordingly.
MetaMask emits a chainChanged event:
window.ethereum.on('chainChanged', (chainId) => {
console.log('Chain changed to:', chainId);
// Refresh or reset dApp state
window.location.reload(); // Some apps reload for simplicity
});
Also, connect and disconnect events are useful during initial connection and teardown, adding resiliency to your dApp user experience.
Always check for provider availability: Not all browsers or users have MetaMask installed.
Handle permissions gracefully: Use eth_accounts to check connection without annoying prompts.
Update UI reactively: Listeners for accountsChanged and chainChanged should update state seamlessly.
Beware of race conditions: Account or network changes can happen at any time; your app should be fault-tolerant.
Respect privacy: Do not save user accounts or private info without explicit consent.
These steps make the difference between a robust dApp and one that frustrates users.
Accounts not updating: Ensure your event listeners are correctly set up and your app state refreshes on accountsChanged.
Missing injected provider: Remind users to install MetaMask or fallback gracefully.
No accounts returned: Check if user has connected the wallet; use eth_requestAccounts to prompt if necessary.
Network mismatch errors: Confirm your app supports the active chain ID or prompt network switch.
Phishing warnings: MetaMask may block certain sites; always encourage users to double-check URLs.
To wrap up, the MetaMask injected provider API is powerful but requires thoughtful integration. Detecting account changes (metamask detect account change), using eth_accounts properly, and responding to disconnect events form the core of solid wallet handling.
For developers preparing to integrate more complex features like swaps, staking, or multi-chain support, understanding these basics up front saves headaches later.
If you want practical setup guides on connecting wallets or managing transactions, check out our MetaMask Mobile Guide and Connecting to dApps pages. Curious about integrating hardware wallets? See Ledger Setup and Hardware Wallet Integration.
Becoming confident with the MetaMask developer account environment takes some testing, but it’s well worth it for building smooth, secure crypto applications.
Happy coding and safe signing!