DEV Community

Cover image for CRYPTO WALLET DAPP WITH FLUTTER AND SOLIDITY
tedTecch
tedTecch

Posted on • Updated on

CRYPTO WALLET DAPP WITH FLUTTER AND SOLIDITY

Introduction

The evolution of web3 has been growing at a very fast pace, with a lot of products and tools coming out making it easy to understand and perform transactions on the blockchain. The use of blockchain technologies to develop web apps and mobile apps, also known as decentralised applications (Dapps), like our crypto wallets (trust wallet, metamask), pancake swap, etc., is also growing at a very fast pace. Therefore, anyone who intends to stay current and ahead of the growth should learn how to use and integrate this technology.

In this article, I’ll show you how to connect your Solidity smart contract to a flutter application and perform basic CRUD operations. This article is a continuation of my previous article on creating an ERC20 token on a polygon network. In the article, I explain some basic terminologies that won't be repeated in this article, so check it out Here.

We’ll cover the following in details:

  • Connecting to a smart contract
  • Getting the balance of an address
  • Fetching data from the blockchain, e.g., name, symbol, e.t.c.
  • Transfer our token from one address to another
  • Mint tokens to our address

Prerequisites

To understand and follow through this article, you need to have:

  • Flutter pre-installed
  • Basic understanding of flutter and dart
  • Code editor
  • Web Browser(chrome)

Getting started

After writing, compiling, and deploying the smart contract, we need a blockchain server to run it on. There are some platforms that offer this service, like Infura, Alchemy, etc. We will be using Alchemy for its simplicity and also because it provides us access to different blockchain networks.
Simply create an account and create a new app on the platform, enter project details, then you can select the chain, in this case, polygon and network in polygon Mumbai.
Image description

After creating the app, click on "view key," which would give us a key and two links, as in the image below. You can pick any of the links, but we would use the http link by copying it.
Image description

The next thing is to create a new Flutter project and develop a basic design for our app with three buttons: send, receive, and a floating action button (to refresh our screen). The send and receive buttons provide a cupertino alert dialog where we can input an address and amount.
But before we start coding the logic of the app, we need to add some packages.

The first package we require is web3dart, which is a dart library that connects to the Ethereum blockchain. It connects to an Ethereum node to send transactions, interact with smart contracts, and much more. And the second package is http, which is used for making https requests in a flutter.

We start by creating the following variables below. We also paste our metamask address, the http link provided by Alchemy in the blockchain url, and declare a variable dec, which represent 10^18 which is the erc20 decimal standard.


 late Client httpClient;
  late Web3Client ethClient;
  //Polygon address
  final String myAddress = "0x4818569AA9dE13d3cC1D702Cd10a95932799a674";
  //url from alchemy
  final String blockchainUrl = "https://polygon-mumbai.g.alchemy.com/v2/xhOSAQIFW6H_-NjxcSrpa1vJbwckXTUC";
  bool data = false;
  int myAmount = 0;
  int amt = 0;
  var addressTo = "";
  var dec = pow(10, 18);
  var mydata;
  var mybalance;
  late String transHash;
  var balance;
  var name;
  var symbol;
Enter fullscreen mode Exit fullscreen mode

After that, we head back to our Remix IDE, and in the Solidity compiler tab, we copy the ABI of our smart contract as shown in the image below, marked by the red arrow. Also, ensure the contract file is our created contract as marked with the blue arrow.
Image description

Then in our flutter project, we create an assets folder in our root folder and within it we create a file named ‘token.json’, in this file, we paste the copied abi. We can then move to our pubspec.yaml file and uncomment, adding assets to our application looking like the code below. Then we can run flutter pub get command.

 assets:
    - assets/
Enter fullscreen mode Exit fullscreen mode

In our initState callback, we will initialize our httpClient and Web3client, as well as call a method to retrieve the name, symbol, and balance values from our smart contract:

@override
  void initState() {
    httpClient = Client();
    ethClient = Web3Client(blockchainUrl, httpClient);
    super.initState();
    getName();
    getSymbol();
    getBalance(myAddress);
  }
Enter fullscreen mode Exit fullscreen mode

Connect Smart Contract

We declare a contract using the DeployedContract class from our web3dart package, which takes in the ABI file, the name of our smart contract, which in our case is FirstToken, and the contract address and returns it from our function.

Future<DeployedContract> getContract() async {
    String abiFile = await rootBundle.loadString("assets/token.json");
    String contractAddress = "0x50338cAF974F2ec1869020e83eF48E36aCE93caf";
    final contract = DeployedContract(
        ContractAbi.fromJson(abiFile, "FirstToken"),
        EthereumAddress.fromHex(contractAddress));
    return contract;
  }
Enter fullscreen mode Exit fullscreen mode

Fetch Data From TheBlockchain

The next function, query is used to call a function inside our smart contract, I used it mainly for read operations. This function connects to our smart contract using the call extension from the web3dart EthereumClient class, we will be calling this function in another function.

Future<List<dynamic>> query(String functionName, List<dynamic> args) async {
    //
    final contract = await getContract();
    final ethFunction = contract.function(functionName);
    // This line below doesn't work.
    final result = await ethClient.call(
        contract: contract, function: ethFunction, params: args);
    // print(result.toString());
    return result;
  }
Enter fullscreen mode Exit fullscreen mode

Write To The Blockchain

In this submit function we are performing a write operation to the blockchain therefore it requires our private key which you can get from metamask, but in a normal wallet, this private key is stored securely in the app when you import or generate a wallet, take note that you should not reveal your private key under any circumstances.

Also, we used a Transaction.callContract to pass in our gotten contract, the function we are requesting in our smart contract, the parameters imputed in the function and maximum gas fee, after we used sendTransaction from web3dart to pass in our private key, the transaction object and fetchChainIdFromNetworkId.

Future<String> submit(String functionName, List<dynamic> args) async {
    DeployedContract contract = await getContract();
    final ethFunction = contract.function(functionName);
    snackBar(label: "Recording tranction");
    EthPrivateKey key = EthPrivateKey.fromHex(
        "5288***********************************60ffbd08");
    Transaction transaction = await Transaction.callContract(
        contract: contract,
        function: ethFunction,
        parameters: args,
        maxGas: 100000);
    print(transaction.nonce);
    final result = await ethClient.sendTransaction(key, transaction,
        fetchChainIdFromNetworkId: true, chainId: null);
    print(result);
    ScaffoldMessenger.of(context).removeCurrentSnackBar();
    snackBar(label: "verifying transaction");
    //set a 20 seconds delay to allow the transaction to be verified before trying to retrieve the balance
    Future.delayed(const Duration(seconds: 20), () {
      ScaffoldMessenger.of(context).removeCurrentSnackBar();
      snackBar(label: "retriving balance");
      getBalance(myAddress);
      ScaffoldMessenger.of(context).clearSnackBars();
    });
    return result;
  }
Enter fullscreen mode Exit fullscreen mode

We set a 20-sec delay before calling our getBalance function to ensure that the transaction has been executed because it takes a while, we also add some snackBar to make sure a user knows what is going on.

Moving forward we have the main getBalance, getName and getSymbol function, these functions calls the query read request function explained above, pass the function name as it is written in solidity and save it as a variable in our flutter app.

Future<void> getBalance(String targetAddress) async {
    EthereumAddress address = EthereumAddress.fromHex(targetAddress);
    // print('In getGreeting');
    List<dynamic> result = await query('balanceOf', [address]);
    print('In getGreeting');
    print(result[0]);
    mybalance = result[0];
    var div = BigInt.from(dec);
    balance = BigInt.from(mybalance / div);

    print("balance: $balance");
    data = true;
    setState(() {});
  }
  Future<void> getName() async {
    // print('In getGreeting');
    List<dynamic> result = await query('name', []);
    print(result[0]);
    name = result[0];
    data = true;
    print(name);
    setState(() {});
  }
  Future<void> getSymbol() async {
    List<dynamic> result = await query('symbol', []);
    print(result[0]);
    symbol = result[0];
    data = true;
    setState(() {});
  }
Enter fullscreen mode Exit fullscreen mode

Finally, we have our ‘sendCoin’ and ‘recieveCoin’ functions, these functions use the ‘submit’ function explained earlier passing the function name as it is in solidity, also the address it should be sent to and the amount.

Future<String> reciveCoin() async {
    EthereumAddress addressTo =
        EthereumAddress.fromHex("0x4818569AA9dE13d3cC1D702Cd10a95932799a674");
    var bigAmount = BigInt.from(myAmount);
    var response = await submit('mint', [addressTo, bigAmount]);
    print('Recieved');
    transHash = response;
    setState(() {});
    return response;
  }
  Future<String> transferCoin() async {
    var amount = BigInt.from(amt *dec);
    EthereumAddress to = EthereumAddress.fromHex(addressTo);
    print("amo: $amount");
    var response = await submit('transfer', [to, amount]);
    print('Transfered');
    transHash = response;
    setState(() {});
    return response;
  }

Enter fullscreen mode Exit fullscreen mode

That concludes our logic, when you run your project, you should have something like this.

Image description

Conclusion

This smart integration has covered enough to help you understand and execute read and write operations to the block chain using flutter which is relatively new, so keep exploring and experimenting. Keep in mind there is no learning without practice.
Check out the link below to access the project's repository.
https://github.com/lyon-zas/ERC-20-wallet

Discussion (0)