Metamask: React dapp using same previous account (from ganache) even though changed in metamask
Metamask Issue: Stuck on Previous Account Even After Switching
As a developer building a React dapp, interacting with Ethereum contracts deployed on the local Ganache blockchain is a common challenge. One such issue that has plagued many developers is being able to switch between different accounts in MetaMask while still accessing previously accessed functions and assets.
In this article, we’ll explore why it’s happening and how to resolve it.
The Problem:
When you create a new account using Metamask, the Ethereum wallet app creates a new account with an initial balance of 0 Ether (ETH) and no transactions. However, if you’ve already interacted with a contract or accessed assets on another account, those interactions will persist even after switching to a new account.
For example, if you’ve deployed an ERC-20 token using the Solidity compiler in Ganache, and then switched to a different wallet, but still have the same contract deployed, interacting with it through your React dapp code will result in errors or unexpected behavior due to the persisted state of the contract.
The Solution:
To resolve this issue, we’ll explore two solutions:
- Using
eth.accounts
instead of changing accounts: Instead of switching between accounts using MetaMask’s account selector feature, we can use a more modern approach by leveraging theeth.accounts
object.
- Setting up a separate contract and storage for each wallet: We’ll create a separate contract instance with the same function signature but different storage locations to avoid conflicts when switching between wallets.
Solution 1: Using eth.accounts
instead of changing accounts
In your React dapp, you’re likely using something like this:
import { connect } from 'react-redux';
import { getAccount, interactWithContract } from './actions';
const mapStateToProps = state => {
return {
account: getAccount(state)
};
};
const mapDispatchToProps = dispatch => {
return {
interactWithContract: (contractAddress, args) => dispatch(interactWithContract(contractAddress, args))
}
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
In this example, getAccount
returns the current Ethereum account ID. Since we’re using a single contract instance and passing it to interactWithContract
, changes to the account will affect all interactions.
Solution 2: Using separate contract and storage for each wallet
Here’s an updated example that separates the contract and storage:
// contracts/MyContract.sol
pragma solidity ^0.6.0;
contract MyContract {
// ... contract implementation ...
mapping(address => uint256) public balances;
}
// app.js (React dapp)
import React from 'react';
import { connect } from 'react-redux';
const mapStateToProps = state => {
return {
balance: state.balance
};
};
const mapDispatchToProps = dispatch => {
return {
updateBalance: (newBalance) => dispatch(updateBalance(newBalance))
}
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
In this example, we’re using the MyContract
contract with separate storage for each wallet. When switching between wallets, you’ll need to create a new instance of the contract and update its storage.
Conclusion:
To resolve the issue of interacting with previously accessed functions and assets on different Ethereum accounts in your React dapp, try using eth.accounts
instead of changing accounts or setting up separate contracts and storage for each wallet. This approach will allow you to maintain a consistent state across different wallets while still accessing functions and assets from other wallets.
Leave a Reply