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 shareprivateKey
, used for making credentials forweb3dart
, at various places in the codes below.
Chain Details for Ethereum
- Mainnet
- Testnet
- 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
- Chain ID: 0xaa36a7
- Public RPC URL: https://rpc.ankr.com/eth_sepolia (Avoid using public rpcTarget in production, use services like Infura, Quicknode etc)
- Display Name: Ethereum Sepolia Testnet
- Block Explorer Link: https://sepolia.etherscan.io
- Ticker: ETH
- Ticker Name: Sepolia
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");