Variance is an Account Abstraction Developer toolkit that is designed to simplify the development of Ethereum smart accounts and Entrypoint interactions. It relies on the Web3dart library.
- ABI Encoding/Decoding: Easily encode and decode ABI data for Ethereum smart contract and Entrypoint interactions.
- Transaction Handling: Simplify the process of creating and sending UserOperations.
- Token Operations: Work with ERC20 and ERC721 tokens, including transfer and approval functionalities.
- Web3 Functionality: Interact with Ethereum nodes and bundlers.
- SecP256r1 Signatures: Sign transactions with Passkeys.
open your terminal and run the following command:
flutter pub add variance_dart
flutter pub add web3_signers
flutter pub add web3dart
// Import the packages
import 'package:web3_signers/web3_signers.dart';
import 'package:variance_dart/variance_dart.dart';
import 'package:web3dart/web3dart.dart';
static const rpc = "https://api.pimlico.io/v2/84532/rpc?apikey=API_KEY";
final Uint256 salt = Uint256.zero;
final Chain chain = Chains.getChain(Network.baseTestnet)
..accountFactory = Constants.lightAccountFactoryAddressv07
..bundlerUrl = rpc
..paymasterUrl = rpc;
For Safe Accounts, use
Constants.safeProxyFactoryAddress
as the account factory. There are 8 available networks: ethereum, polygon, optimism, base, arbitrum, linea, fuse and scroll. 2 available testnets: sepolia and baseTestent.
Additionally, you can specify a different Entrypoint address. By default, the entrypoin v0.7 is used. If you wish to use v0.6, you can do so as follows:
final EntryPointAddress entrypointAddress = EntryPointAddress.v06;
chain.entrypoint = entrypointAddress;
// OR append it to the chain
..entrypoint = EntryPointAddress.v06;
By default the paymaster is set to null. If wish to use paymasters with your smart wallet you can do so by specifying the rpc endpoint of the paymaster. This would add a paymaster Plugin to the smart wallet.
If you have additional context for the paymaster, you will be able to add it to the smart wallet after creation or before initiating a transaction.
wallet.plugin<Paymaster>('paymaster').context = {'key': 'value'};
In order to create a smart wallet client you need to set up a signer, which will sign useroperation hashes to be verified onchain. Only signers available in the web3signers package can be used.
You have to use the correct signer for the type of account you want to create.
PrivateKeys
- use with light accounts and safe accountsPasskey
- use with safe Passkey accounts onlyEOA Wallet
- use with light smart accounts and safe accounts
For more information, please check out the web3signers package documentation.
- The
PrivateKey
signer generates only a single private key for use with a smart account. The private key requires a password, and the private key can be serialized into JSON format for storage. - The
EOA Wallet
signer generates a HD wallet with multiple accounts for use with a smart account. Additionally theEOA Wallet
signer allows the smart account to sign transactions with different accounts by specifying the account index.
With
EOA Wallet
signer, users receive the mnemonic phrase but withPrivateKey
signer they dont.
The smart wallet factory handles the creation of smart wallet instances. Make sure you have created a signer from the previous step.
final SmartWalletFactory smartWalletFactory = SmartWalletFactory(chain, signer);
The Alchemy Light Account requires the signer to have a prefix. When creating a web3_signer for your smart wallet make sure to provide a Uint8
value prefix. This will be appended to the signature generated by the signers.
Example:
const prefix = const SignatureOptions(prefix: [0])
final signer = EOAWallet.createWallet(WordLength.word_12, prefix);
final smartWalletFactory = SmartWalletFactory(chain, signer);
final Smartwallet wallet = await smartWalletFactory.createAlchemyLightAccount(salt);
print("light account wallet address: ${wallet.address.hex}");
To create a Safe Smart Account
// No prefix is required. word_12 is the default
final signer = EOAWallet.createWallet();
final smartWalletFactory = SmartWalletFactory(chain, signer);
final Smartwallet wallet = await smartWalletFactory.createSafeAccount(salt);
print("safe wallet address: ${wallet.address.hex}");
To create a Safe Smart Account with Passkey
final sharedWebauthnSigner = EthereumAddress.fromHex("0xfD90FAd33ee8b58f32c00aceEad1358e4AFC23f9");
final options = PassKeysOptions(
...
sharedWebauthnSigner: sharedWebauthnSigner,);
final signer = PassKeySigner(options: options);
final smartWalletFactory = SmartWalletFactory(chain, signer);
final keypair = await signer.register(name, displayName); // email can be used in place of name
final Smartwallet wallet = await smartWalletFactory.createSafeAccountWithPasskey(
keypair, salt, sharedWebauthnSigner);
print("p256 wallet address: ${wallet.address.hex}");
Your keypair must be a
PassKeyPair
object received when registering with yourPasskeySigner
signer. Keypair can serialized and stored by the app
Additionally, you can pass a p256Verifier
address to the createSafeAccountWithPasskey
method, by default the RIP-7212 precompile is used.
final Smartwallet wallet = await smartWalletFactory.createSafeAccountWithPasskey(
keypair, salt, sharedWebauthnSigner, p256Verifier);
print("p256 wallet address: ${wallet.address.hex}");
// retrieve the balance of a smart wallet
final EtherAmount balance = await wallet.balance;
print("account balance: ${balance.getInWei}");
// retrive the account nonce
final Uint256 nonce = await wallet.nonce;
print("account nonce: ${nonce.toInt()}");
// check if a smart wallet has been deployed
final bool deployed = await wallet.deployed;
print("account deployed: $deployed");
// get the init code of the smart wallet
final String initCode = wallet.initCode;
print("account init code: $initCode");
// perform a simple transaction (send ether to another account)
// account must be prefunded with native token. paymaster is not yet implemented
await wallet.send(
EthereumAddress.fromHex(
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"), // receive address
EtherAmount.fromInt(EtherUnit.ether, 0.7142), // 0.7142 ether
);
For detailed usage and examples, refer to the documentation. Additional refer to the example for use in a flutter app.
Detailed API reference and examples can be found in the API reference.
We are committed to maintaining variance as an open source sdk, take a look at existing issues, open a pull request etc.
This project is licensed under the BSD-3-Clause - see the LICENSE file for details.