Flutter3 & Web3 | Metamask Integration

Muhammad Hamza
5 min readSep 20, 2022

The “3” always fascinates either you are a flutter developer or a web developer. So, today let’s combine the “3” from both of the sides and create something new!

So, have you ever wondered how to accept crypto payments in your web app? Fear not! I’m going to show you how to integrate Metamask with Flutter web to accept Ethereum payments.

Table of Contents

  • Metamask
  • Flutter setup
  • Required packages
  • Coding
  • Creating the Provider Class
  • Connecting Metamask
  • Initializing Metamask
  • Flutter Integration
  • Done’n Dusted! 👏

🎭 Metamask

Metamask is a cryptocurrency wallet that allows you to transact with the Ethereum blockchain. It’s simply your wallet available through their browser extensions and applications, which you can connect to sites that support payment via Metmask. It really is that simple, and that’s all you need to know for this article, but if you’re interested in learning more, check out their official site.

🛠 Flutter Setup

The Flutter web setup should be quite easy. Just make sure that Flutter Web is enabled for the project; this shouldn’t be an issue if you’re already using Flutter 3.0. Simply create a new project:

flutter create — org com.hmz flutter_metamask

Done! Well, not really. You have your Flutter project setup though.

📦 Required packages

Of course, hats off to the Flutter community for making our tasks easy! We will be using the following package to implement our Metamask integration:

And that’s it! That’s pretty much all you need to get into the world of Web3 via Flutter3.

🧑🏻‍💻 Coding

Ready? Here we go!

First, we will be setting up our provider for Metamask. Start here:

Creating the Provider Class

class MetaMaskProvider extends ChangeNotifier {
// rest of the code
}

We’ll be needing the following variables to manage various scenarios:

int currentChain = -1;String currentAddress = '';static const operatingChain = 4;bool get isEnabled => ethereum != null;bool get isInOperatingChain => currentChain == operatingChain;bool get isConnected => isEnabled && currentAddress.isNotEmpty;

Don’t worry! I’ll explain all of this!

  1. currentChain → We set this variable to -1 so that we do not immediately connect to a chain when the wallet connects. Starting from which chain are we, keeping it -1 meaning we won’t jump into some chain the moment our wallet connects.
  2. currentAddress → The present address of our Metamask.
  3. operatingChain → The Ethereum chain we’ll be operating on. For now, it will be test networks, so we set it to 4 (Rinkeby Test Network)
  4. isEnabled → Checks whether the browser supports Metamask
  5. isInOperatingChain → A bool variable that tells, whether we are connect to correct chain or not. Do I need to explain? I guess not
  6. isConnected → A state that shows whether Metamask has been connected or not

The code will be now like this:

class MetaMaskProvider extends ChangeNotifier {
int currentChain = -1;
String currentAddress = ''; static const operatingChain = 4; bool get isEnabled => ethereum != null; bool get isInOperatingChain => currentChain == operatingChain; bool get isConnected => isEnabled && currentAddress.isNotEmpty;
}

Connecting Metamask

We will be making a function that connects to Metamask if the following requirements are achieved:

Future<void> connect() async {
if (isEnabled) {
final accs = await ethereum!.requestAccount();
if (accs.isNotEmpty) currentAddress = accs.first;
currentChain = await ethereum!.getChainId();
notifyListeners();
}
}

Let me break it down for you:

  1. Check if Web3 is enabled on the browser
  2. Get the accounts on Ethereum
  3. If the accounts are not empty, get the first address
  4. Get the ID of the current chain.

🏁 Initializing Metamask

To initialize, we need to clear the currentAddress and reset the currentChain for two conditions every time:

  1. If the account changed
  2. If the chain itself changed
init() {
/// in both the cases we clear the data and re-sign in the metamask
if (isEnabled) {
// whenever the account is changed
ethereum!.onAccountsChanged((accounts) {
clear();
});
// whenever the chain is changed
ethereum!.onChainChanged((chainId) {
clear();
});
}
}
// clear method
clear() {
currentAddress = '';
currentChain = -1;
notifyListeners();
}

We’re done with one “3” — the Web3 part. Now it’s time for Flutter3.

👉 Flutter

Put the providers in the MultiProvider as we always do, but this time simply call the init() method that we wrote above.

return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => MetaMaskProvider()..init()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,

...
...
);

Now, we’ll make a button to start connecting to Metamask with conditions.

MaterialButton(
child: Consumer<MetaMaskProvider>(
builder: (context, meta, child) {
String text = '';

if (meta.isConnected && meta.isInOperatingChain){
text = "Metamask Connected!";
} else if (meta.isConnected && !meta.isInOperatingChain){
text = "Wrong Operating Chain";
} else if (meta.isEnabled) {
return Text("Connect Metamask");
} else {
text = 'Unsupported browser!';
}
return Text(text);
onPressed: () {
final meta = context.read<MetaMaskProvider>();
meta.connect();
},
)

Now, sadly Metamask doesn’t work in the debug mode, so you have to run the web server for Flutter web and visit the URL.

In case you want to hot reload/restart, after pressing “r” in the terminal, make sure to reload the web browser yourself.

flutter run -d web-server

And we have…🥁🥁🥁

Metamask in Flutter web 🔥

Yay!! You did it. I hope you’ve learned something. Make sure to drop your reviews and suggestions!

Just incase you don’t know, you can give 50 claps 👏 on Medium!

💻 GitHub Repohttps://github.com/mhmzdev/flutter-metamask

Thanks y’all & #happyfluttering 💙

--

--

Muhammad Hamza

Student forever | Leading @Flutter Islamabad | Find me @mhmzdev