Flutter and Blockchain – Hello World Dapp

11 May, 2022
Flutter and Blockchain
This tutorial will take you through the process of building your first mobile dapp – Hello World Dapp!
This tutorial is meant for those with a basic knowledge of Ethereum and smart contracts, who have some knowledge of the Flutter framework but are new to mobile dapps.
In this tutorial we will be covering:
Setting up the development environmentCreating a Truffle ProjectWriting your first Smart ContractCompiling and Migrating the Smart ContractTesting the Smart ContractContract linking with FlutterCreating a UI to interact with the smart contractInteracting with the complete Dapp
Setting up the development environment
Creating a Truffle Project
Writing your first Smart Contract
Compiling and Migrating the Smart Contract
Testing the Smart Contract
Contract linking with Flutter
Creating a UI to interact with the smart contract
Interacting with the complete Dapp
Truffle is the most popular development framework for Ethereum with a mission to make your life a whole lot easier. But before we install truffle make sure to install node .
Once we have node installed, we only need one command to install Truffle:
npm install -g truffle
We will also be using Ganache, a personal blockchain for Ethereum development you can use to deploy smart contracts, develop applications, and run tests. You can download Ganache by navigating to http://truffleframework.com/ganache and clicking the “Download” button.
Create a basic Flutter project in your favorite IDEInitialize Truffle in the flutter project directory by running
Create a basic Flutter project in your favorite IDE
Initialize Truffle in the flutter project directory by running
truffle init
contracts/ : Contains solidity contract file.
migrations/: Contains migration script files (Truffle uses a migration system to handle contract deployment).
test/ : Contains test script files.
truffle-config.js: Contains truffle deployment configurations information.
The Smart Contract actually acts as the back-end logic and storage for our Dapp.
Create a new file named HelloWorld.sol in the contracts/ directory.Add the following content to the file:
Create a new file named HelloWorld.sol in the contracts/ directory.
Add the following content to the file:
Solidity
pragma solidity ^0.5.9;  contract HelloWorld {  }
The minimum version of Solidity required is noted at the top of the contract: pragma solidity ^0.5.9;.
Statements are terminated with semicolons.
Add the following variable on the next line after contract HelloWorld { 
Add the following variable on the next line after contract HelloWorld { 
Solidity
string public yourName ;
We just defined a single variable yourName of type string, also yourName is a public modifier which means that we can access it from outside the smart contract.
Add the following constructor on the next line after string public yourName ;
Add the following constructor on the next line after string public yourName ;
Solidity
constructor() public {        yourName = "Unknown" ;}
Constructor in solidity executed only once, when a contract is created and it is used to initialize contract state. Here we’re just setting the initial value of variable yourName to “Unknown”.
Add the following function to the smart contract after the constructor declaration we set up above.
Add the following function to the smart contract after the constructor declaration we set up above.
Solidity
function setName(string memory nm) public{        yourName = nm ;}
In the above function, we’ll be taking in an nm(string) and setting the yourName variable to it.
Memory is the data location.
In a terminal, make sure you are in the root of the directory that contains the flutter and truffle project, Run the following command:
In a terminal, make sure you are in the root of the directory that contains the flutter and truffle project, Run the following command:
truffle compile
You should see output similar to the following:
truffle compile
You’ll see one JavaScript file already in the migrations/ directory: 1_initial_migration.js. This handles deploying the Migrations.sol contract to observe subsequent smart contract migrations, and ensures we don’t double-migrate unchanged contracts in the future.
Let’s create our own migration script :
Create a new file named 2_deploy_contracts.js in the migrations/ directory.Add the following content to the 2_deploy_contracts.js file:
Create a new file named 2_deploy_contracts.js in the migrations/ directory.
Add the following content to the 2_deploy_contracts.js file:
Javascript
const HelloWorld = artifacts.require("HelloWorld");  module.exports = function (deployer) {  deployer.deploy(HelloWorld);};
Before we can migrate our contract to the blockchain, we need to have a blockchain running. For this article, we’re going to use Ganache, a personal blockchain for Ethereum development you can use to deploy contracts, develop applications, and run tests. If you haven’t already, download Ganache and double-click the icon to launch the application. This will generate a blockchain running locally on port 7545.
Ganache
Add the following content to the truffle-config.js file:
Javascript
module.exports = {  networks: {     development: {      host: "127.0.0.1",     // Localhost (default: none)      port: 7545,            // Standard Ethereum port (default: none)      network_id: "*",       // Any network (default: none)     },  },    contracts_build_directory: "./src/artifacts/",        // Configure your compilers  compilers: {    solc: {                 // See the solidity docs for advice       // about optimization and evmVersion        optimizer: {          enabled: false,          runs: 200        },        evmVersion: "byzantium"    }  }};
Migrating the contract to the blockchain, run:
truffle migrate
You should see output similar to the following:
truffle migrate
Take a look into the Ganache, the first account originally had 100 ether, it is now lower, due to the transaction costs of migration.
In Truffle, we can write tests either in JavaScript or Solidity, In this article, we’ll be writing our tests in Javascript using the Chai and Mocha libraries.
Create a new file named helloWorld.js in the test/ directory.Add the following content to the helloWorld.js file:
Create a new file named helloWorld.js in the test/ directory.
Add the following content to the helloWorld.js file:
Javascript
const HelloWorld = artifacts.require("HelloWorld") ;  contract("HelloWorld" , () => {    it("Hello World Testing" , async () => {       const helloWorld = await HelloWorld.deployed() ;       await helloWorld.setName("User Name") ;       const result = await helloWorld.yourName() ;       assert(result === "User Name") ;    });});
HelloWorld: The smart contract we want to test, We begin our test by importing our HelloWorld contract using artifacts.require.
To test the setName function, recall that it accepts a name(string) as an argument.
Also, the yourName variable in our contract is using public modifier, which we can use as a getter from the outside function.
Truffle imports Chai so we can use the assert function. We pass the actual value and the expected value, To check that the name is set properly or not, assert(result === “User Name”) ;.
Running the test as:
truffle test
If all the test pass, you’ll see the console output similar to this:
truffle test
In the pubspec.yaml file import the following packages :
provider: ^4.3.3
web3dart: ^1.2.3
http: ^0.12.2
web_socket_channel: ^1.2.0
Also, add the asset src/artifacts/HelloWorld.json to pubspec.yaml file which is generated by truffle-config.js while we migrate our contract.
assets:
    - src/artifacts/HelloWorld.json
Create a new file named contract_linking.dart in the lib/ directory.Add the following content to the file:
Create a new file named contract_linking.dart in the lib/ directory.
Add the following content to the file:
Dart
import 'package:flutter/material.dart';  class ContractLinking extends ChangeNotifier {    }
Just a simple class with ChangeNotifier for state management.
Add the following variable on the next line after class ContractLinking extends ChangeNotifier {.
Dart
final String _rpcUrl = "http://10.0.2.2:7545";final String _wsUrl = "ws://10.0.2.2:7545/";final String _privateKey = "Enter Private Key";
The library web3dart won’t send signed transactions to miners itself. Instead, it relies on an RPC client to do that. For the WebSocket URL just modify the RPC URL. You can get the RPC URL from the ganache :
Ganache – RPC url
Get the Private Key from ganache:
Ganache – Private Key
Declare the following variables below :
Dart
Web3Client _client;bool isLoading = true;  String _abiCode;EthereumAddress _contractAddress;  Credentials _credentials;  DeployedContract _contract;ContractFunction _yourName;ContractFunction _setName;  String deployedName;
_client variable will be used to establish a connection to the ethereum rpc node with the help of WebSocket.isLoading variable will be used to check the state of the contract._abiCode variable will be used to, read the contract abi._contractAddress variable will be used to store the contract address of the deployed smart contract._credentials variable will store the credentials of the smart contract deployer._contract variable will be used to tell Web3dart where our contract is declared._yourName and _setName variable will be used to store the functions declared in our HelloWorld.sol smart contract.deployedName will hold the name from the smart contract.
_client variable will be used to establish a connection to the ethereum rpc node with the help of WebSocket.
isLoading variable will be used to check the state of the contract.
_abiCode variable will be used to, read the contract abi.
_contractAddress variable will be used to store the contract address of the deployed smart contract.
_credentials variable will store the credentials of the smart contract deployer.
_contract variable will be used to tell Web3dart where our contract is declared.
_yourName and _setName variable will be used to store the functions declared in our HelloWorld.sol smart contract.
deployedName will hold the name from the smart contract.
After declaring the above variable’s, Declare the following functions below it :
Dart
ContractLinking() {    initialSetup();  }    initialSetup() async {          // establish a connection to the ethereum rpc node. The socketConnector    // property allows more efficient event streams over websocket instead of    // http-polls. However, the socketConnector property is experimental.    _client = Web3Client(_rpcUrl, Client(), socketConnector: () {      return IOWebSocketChannel.connect(_wsUrl).cast<String>();    });      await getAbi();    await getCredentials();    await getDeployedContract();  }    Future<void> getAbi() async {          // Reading the contract abi    String abiStringFile =        await rootBundle.loadString("src/artifacts/HelloWorld.json");    var jsonAbi = jsonDecode(abiStringFile);    _abiCode = jsonEncode(jsonAbi["abi"]);      _contractAddress =        EthereumAddress.fromHex(jsonAbi["networks"]["5777"]["address"]);  }    Future<void> getCredentials() async {    _credentials = await _client.credentialsFromPrivateKey(_privateKey);  }    Future<void> getDeployedContract() async {          // Telling Web3dart where our contract is declared.    _contract = DeployedContract(        ContractAbi.fromJson(_abiCode, "HelloWorld"), _contractAddress);      // Extracting the functions, declared in contract.    _yourName = _contract.function("yourName");    _setName = _contract.function("setName");    getName();  }    getName() async {          // Getting the current name declared in the smart contract.    var currentName = await _client        .call(contract: _contract, function: _yourName, params: []);    deployedName = currentName[0];    isLoading = false;    notifyListeners();  }    setName(String nameToSet) async {          // Setting the name to nameToSet(name defined by user)    isLoading = true;    notifyListeners();    await _client.sendTransaction(        _credentials,        Transaction.callContract(            contract: _contract, function: _setName, parameters: [nameToSet]));    getName();  }
Create a new file named helloUI.dart in the lib/ directory.Add the following content to the file:
Create a new file named helloUI.dart in the lib/ directory.
Add the following content to the file:
Dart
import 'package:flutter/material.dart';import 'package:hello_world/contract_linking.dart';import 'package:provider/provider.dart';  class HelloUI extends StatelessWidget {  @override  Widget build(BuildContext context) {          // Getting the value and object or contract_linking    var contractLink = Provider.of<ContractLinking>(context);      TextEditingController yourNameController = TextEditingController();      return Scaffold(      appBar: AppBar(        title: Text("Hello World !"),        centerTitle: true,      ),      body: Container(        padding: EdgeInsets.symmetric(horizontal: 20),        child: Center(          child: contractLink.isLoading              ? CircularProgressIndicator()              : SingleChildScrollView(            child: Form(              child: Column(                children: [                  Row(                    mainAxisAlignment: MainAxisAlignment.center,                    children: [                      Text(                        "Hello ",                        style: TextStyle(                            fontWeight: FontWeight.bold, fontSize: 52),                      ),                      Text(                        contractLink.deployedName,                        style: TextStyle(                            fontWeight: FontWeight.bold,                            fontSize: 52,                            color: Colors.tealAccent),                      ),                    ],                  ),                  Padding(                    padding: EdgeInsets.only(top: 29),                    child: TextFormField(                      controller: yourNameController,                      decoration: InputDecoration(                          border: OutlineInputBorder(),                          labelText: "Your Name",                          hintText: "What is your name ?",                          icon: Icon(Icons.drive_file_rename_outline)),                    ),                  ),                  Padding(                    padding: EdgeInsets.only(top: 30),                    child: ElevatedButton(                      child: Text(                        'Set Name',                        style: TextStyle(fontSize: 30),                      ),                      style: ElevatedButton.styleFrom(                        primary: Colors.green,                      ),                      onPressed: () {                        contractLink.setName(yourNameController.text);                        yourNameController.clear();                      },                    ),                  )                ],              ),            ),          ),        ),      ),    );  }}
Update the main.dart as :
Dart
import 'package:flutter/material.dart';import 'package:hello_world/contract_linking.dart';import 'package:hello_world/helloUI.dart';import 'package:provider/provider.dart';  void main() {  runApp(MyApp());}  class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {          // Inserting Provider as a parent of HelloUI()    return ChangeNotifierProvider<ContractLinking>(      create: (_) => ContractLinking(),      child: MaterialApp(        title: "Hello World",        theme: ThemeData(            brightness: Brightness.dark,            primaryColor: Colors.cyan[400],            accentColor: Colors.deepOrange[200]),        home: HelloUI(),      ),    );  }}
Now we’re ready to use our dapp!
Just RUN the Flutter Project.
Hello World Dapp
As you can see the Hello Unknown, in the UI is actually coming from the smart contract, variable yourName .
When you type your name into the TextFormField and Press `Set Name` ElevatedButton, it will invoke the setName function from contract_linking.dart which will directly invoke the setName function of our smart contract (HelloWorld.sol).
Hello World Dapp
Hello World Dapp
Hello World Dapp
Congratulations! You have taken a huge step to become a full-fledged mobile dapp developer. For developing locally, you have all the tools you need to start making more advanced dapps.
If you stuck somewhere, do check out the GitHub repository for complete code.
Blockchain
Dart
Flutter
Solidity
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.