Contract linking with Flutter
- 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 country_pickers: ^1.3.0
- Also, add the asset src/artifacts/Population.json to pubspec.yaml file which is generated by truffle-config.js while we migrate our contract.
assets: - src/artifacts/Population.json
- Create a new file named contract_linking.dart in the lib/ directory.
- Add the following content to the file:
Dart
import 'package:flutter/foundation.dart' ; class ContractLinking extends ChangeNotifier { } |
Variables
- 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 :
- Get the Private Key from ganache:
- Declare the following variable’s below :
Dart
Web3Client _client; bool isLoading = true ; String _abiCode; EthereumAddress _contractAddress; Credentials _credentials; DeployedContract _contract; ContractFunction _countryName; ContractFunction _currentPopulation; ContractFunction _set; ContractFunction _decrement; ContractFunction _increment; String countryName; String currentPopulation; |
- _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 smart contract is declared.
- _countryName , _currentPopulation , _set , _decrement , and _increment variables will be used to hold the functions declared in our Population.sol smart contract.
- countryName and currentPopulation will hold the exact name and population from the smart contract.
Functions
- 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 final abiStringFile = await rootBundle.loadString( "src/artifacts/Population.json" ); final 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, "Population" ), _contractAddress); // Extracting the functions, declared in contract. _countryName = _contract.function( "countryName" ); _currentPopulation = _contract.function( "currentPopulation" ); _set = _contract.function( "set" ); _decrement = _contract.function( "decrement" ); _increment = _contract.function( "increment" ); getData(); } getData() async { // Getting the current name and population declared in the smart contract. List name = await _client .call(contract: _contract, function: _countryName, params: []); List population = await _client .call(contract: _contract, function: _currentPopulation, params: []); countryName = name[0]; currentPopulation = population[0].toString(); print( "$countryName , $currentPopulation" ); isLoading = false ; notifyListeners(); } addData(String nameData, BigInt countData) async { // Setting the countryName and currentPopulation defined by the user isLoading = true ; notifyListeners(); await _client.sendTransaction( _credentials, Transaction.callContract( contract: _contract, function: _set, parameters: [nameData, countData])); getData(); } increasePopulation( int incrementBy) async { // Increasing the currentPopulation isLoading = true ; notifyListeners(); await _client.sendTransaction( _credentials, Transaction.callContract( contract: _contract, function: _increment, parameters: [BigInt.from(incrementBy)])); getData(); } decreasePopulation( int decrementBy) async { // Decreasing the currentPopulation isLoading = true ; notifyListeners(); await _client.sendTransaction( _credentials, Transaction.callContract( contract: _contract, function: _decrement, parameters: [BigInt.from(decrementBy)])); getData(); } |
Flutter and Blockchain – Population Dapp
Before checking out this article, Do take a look at Flutter and Blockchain – Hello World Dapp. This tutorial will take you through the process of building your mobile dapp – Population on Blockchain!
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 environment
- Creating a Truffle Project
- Writing the 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
Description
Population on blockchain is a simple decentralized application, which will allow you to store a specific country population on the blockchain, you can increment as well as decrement the population based on the current condition of the country.
Output: