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.
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.
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;
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.
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/
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);
}
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;
}
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;
}
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;
}
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(() {});
}
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;
}
That concludes our logic, when you run your project, you should have something like this.
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
Top comments (1)
I've been exploring the idea of building a crypto wallet DApp using Flutter and Solidity too! It's a pretty exciting space, especially when considering the best decentralized crypto wallet options out there. I think the multi-currency aspect is super important for reaching a broader user base. Speaking of which, I’ve been using NonBank to manage my crypto and bank accounts in one app. I also recommend to read best crypto wallet reddit reviews to know more. It’s like having the best of Web2 and Web3 in one place. How do you guys usually set up a crypto wallet in your DApps? Any tips for integrating a multi-currency wallet?