Skip to main content

Integrate Web3Auth with the Ethereum Blockchain in Flutter

While using the Web3Auth Flutter SDK, you get the private key within the user scope. This private key can interact with Ethereum to make any blockchain calls, like getting user's account, fetch balance, sign transaction, send transaction, read from and write to the smart contract, etc. We have highlighted a few here for getting you started quickly on that.

Installation

To interact with the Ethereum blockchain in Flutter, you can use any EIP1193 compatible package. Here, we're using web3dart to demonstrate how to make blockchain calls using it with Web3Auth.

flutter pub add web3dart shared_preferences

Note: We will also be using shared_preferences package to share privateKey, used for making credentials for web3dart, at various places in the codes below.

Chain Details for Ethereum

  • Chain ID: 0x1
  • Public RPC URL: https://rpc.ankr.com/eth (Avoid using public rpcTarget in production, use services like Infura, Quicknode etc)
  • Display Name: Ethereum Mainnet
  • Block Explorer Link: https://etherscan.io
  • Ticker: ETH
  • Ticker Name: Ethereum

Initialize

import 'package:flutter/material.dart';
import 'package:web3auth_flutter/web3auth_flutter.dart';
import 'package:web3auth_flutter/enums.dart';
import 'package:web3auth_flutter/input.dart';
import 'package:web3auth_flutter/output.dart';
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatefulWidget {

_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

String rpcUrl = ""; // EVM chain RPC URL


void initState() {
super.initState();
initPlatformState();
}

Future<void> initPlatformState() async {
Uri redirectUrl;
if (Platform.isAndroid) {
redirectUrl = Uri.parse('{SCHEME}://{HOST}/auth');
// w3a://com.example.w3aflutter/auth
} else if (Platform.isIOS) {
redirectUrl = Uri.parse('{bundleId}://auth');
// com.example.w3aflutter://openlogin
} else {
throw UnKnownException('Unknown platform');
}

await Web3AuthFlutter.init(Web3AuthOptions(
clientId: 'WEB3AUTH_CLIENT_ID_FROM_DASHBOARD',
network: Network.testnet,
redirectUrl: redirectUrl));
}


Widget build(BuildContext context) {
// Your page
}
}

Get User Info

You get the user information after a successful login returned from the login method. The userInfo object contains the user information, whereas the privKey object contains the private key that can be used to make blockchain calls.

// Use codes from Initialization here,
// and replace the `Widget build` from the below code:


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
// Get Account
ElevatedButton(
onPressed: () async {
// Upon ligin, gets the UserInfo along with priavteKey.
final response = await Web3AuthFlutter.login(
LoginParams(loginProvider: Provider.google)
);
debugPrint("UserInfo, ${response?.userinfo?.toString()}");
final prefs = await SharedPreferences.getInstance();
await prefs.setString('privateKey', response?.privKey.toString());
// Setting the privateKey to shared_preferences
},
child: const Text('Login'),
),
])));
}

Get Account

// Use codes from Initialization here,
// and replace the `Widget build` from the below code:


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
// Get Account
ElevatedButton(
onPressed: () async {
final credentials = EthPrivateKey.fromHex(privateKey);
final address = credentials.address;
debugPrint("Account, ${address.hexEip55}");
},
child: const Text('Get Address'),
),
])));
}

Get Balance

// Use codes from Initialization here,
// and replace the `Widget build` from the below code:


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
// Get Balance
ElevatedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
final privateKey = prefs.getString('privateKey') ?? '0';
final credentials = EthPrivateKey.fromHex(privateKey);
final client = Web3Client(rpcUrl, Client());
final credentials = EthPrivateKey.fromHex(privateKey);
final address = credentials.address;
final balance = await client.getBalance(address);
debugPrint("Balance, ${balance}");
},
child: const Text('Get Balance'),
),
])));
}

Send Transaction

// Use codes from Initialization here,
// and replace the `Widget build` from the below code:


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
// Send Transaction
ElevatedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
final privateKey = prefs.getString('privateKey') ?? '0';
final client = Web3Client(rpcUrl, Client());
final credentials = EthPrivateKey.fromHex(privateKey);
final address = credentials.address;
final receipt = await client.sendTransaction(
credentials,
Transaction(
from: address,
to: EthereumAddress.fromHex(
'0x809D4310d578649D8539e718030EE11e603Ee8f3'),
value: EtherAmount.fromUnitAndValue(
EtherUnit.gwei, 50000000), // 0.05 ETH
),
chainId: 5); // change chainId as per your chain.
debugPrint("Receipt, ${receipt}");
},
child: const Text('Send Transaction'),
),
])));
}

Sign Transaction

// Use codes from Initialization here,
// and replace the `Widget build` from the below code:


Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
// Send Transaction
ElevatedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
final privateKey = prefs.getString('privateKey') ?? '0';
final client = Web3Client(rpcUrl, Client());
final credentials = EthPrivateKey.fromHex(privateKey);
final address = credentials.address;
final receipt = await client.signTransaction(
credentials,
Transaction(
from: address,
to: EthereumAddress.fromHex(
'0x809D4310d578649D8539e718030EE11e603Ee8f3'),
value: EtherAmount.fromUnitAndValue(
EtherUnit.gwei, 50000000), // 0.05 ETH
),
chainId: 5); // change chainId as per your chain.
debugPrint("Receipt, ${receipt}");
},
child: const Text('Sign Transaction'),
),
])));
}

Smart Contract

In this example, we'll be demonstrating how to use Web3Auth with web3dart to interact with Solidity Smart Contracts. The simple Hello World contract allows anyone to read and write a message to it.

pragma solidity ^0.5.10;

contract HelloWorld {

string public message;

constructor(string memory initMessage) public {
message = initMessage;
}

function update(string memory newMessage) public {
message = newMessage;
}
}
class TestContract {
static final deployedAddress =
EthereumAddress.fromHex("0x1dce94bb358785c2fa27b74551f8aea24d3d0afe");
static const contractAbi = '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
static const byteCode =
"0x608060405234801561001057600080fd5b506040516104623803806104628339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b61030b806101576000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633d7403a31461003b578063e21f37ce146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe610193565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f929190610231565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102295780601f106101fe57610100808354040283529160200191610229565b820191906000526020600020905b81548152906001019060200180831161020c57829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061027257805160ff19168380011785556102a0565b828001600101855582156102a0579182015b8281111561029f578251825591602001919060010190610284565b5b5090506102ad91906102b1565b5090565b6102d391905b808211156102cf5760008160009055506001016102b7565b5090565b9056fea265627a7a72305820a58716d2c2342b3cc5028e49842810b98f5c3f2c1591e8c7f3ec916096f6a03264736f6c634300050a0032";
}

Deploy Contract

final prefs = await SharedPreferences.getInstance();
final privateKey = prefs.getString('privateKey') ?? '0';
final client = Web3Client(rpcUrl, Client());
final credential = EthPrivateKey.fromHex(privateKey);

var list = utf8.encode(TestContract.byteCode);
Uint8List payload = Uint8List.fromList(list);
final Transaction transaction = Transaction(
to: null,
from: credential.address,
data: payload,
maxGas: 2000000);
final String transactionId =
await client.sendTransaction(credential, transaction);

Read From Contract

final client = Web3Client(rpcUrl, Client());

final contract = DeployedContract(
ContractAbi.fromJson(TestContract.contractAbi, ''),
TestContract.deployedAddress);
final messageFunction = contract.function('message');
var message = await client.call(
contract: contract, function: messageFunction, params: []);
debugPrint("Contract Read Message, $message");

Write to Contract

final prefs = await SharedPreferences.getInstance();
final privateKey = prefs.getString('privateKey') ?? '0';
final client = Web3Client(rpcUrl, Client());
final credential = EthPrivateKey.fromHex(privateKey);

final contract = DeployedContract(
ContractAbi.fromJson(TestContract.contractAbi, ''),
TestContract.deployedAddress);
final updateFunction = contract.function('update');
var transactionId = await client.sendTransaction(
credential,
Transaction.callContract(
contract: contract,
function: updateFunction,
parameters: ["NEW_MESSAGE"]));
debugPrint("Transaction Id, $transactionId");