Skip to content

Get started

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.

Installation

To use the Variance SDK in your Flutter project, open your terminal and run the following command:

flutter pub add variance_dart
flutter pub add web3_signers
flutter pub add web3dart

Chain Configuration

First, import the necessary classes and configure the EVM network you want to work with:

import 'package:web3_signers/web3_signers.dart';
import 'package:variance_dart/variance_dart.dart';
import 'package:web3dart/web3dart.dart';
 
// Configure the chain
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)
    // For Safe Accounts, use `Constants.safeProxyFactoryAddress` as the account factory.
    ..accountFactory = Constants.lightAccountFactoryAddressv07
    ..bundlerUrl = rpc
    ..paymasterUrl = rpc;

The Chains class provides a list of available networks, including ethereum, polygon, optimism, base, arbitrum, linea, fuse, scroll, and testnets like sepolia and baseTestnet.

Signer Setup

The Variance SDK supports various types of signers, which are responsible for signing UserOperation hashes to be verified on-chain. The signers are managed in a separate package called web3signers, which provides the following functionalities:

PrivateKey Signer

The PrivateKeySigner is the most basic signer and conforms to the multi-signer interface. You can create a random private key or load it from an encrypted backup:

// Create a random private key
final PrivateKeySigner signer = PrivateKeySigner.createRandom("password");
 
// Load from an encrypted backup
final PrivateKeySigner signer = PrivateKeySigner.fromJson("source", "password");

Passkey Signer

The PassKeySigner conforms to the multi-signer interface and allows you to sign payloads using your device's passkeys. It falls under the secp256r1 category and can be verified on-chain using a P256 Verifier on-chain:

final options = PassKeysOptions(
        name: "variance", // Replace with your relying party name
        namespace: "variance.space", // Replace with your relying party ID (domain name)
        origin: "https://variance.space", // Replace with your relying party origin
        userVerification: "required",
        requireResidentKey: true,
        sharedWebauthnSigner: EthereumAddress.fromHex("0xfD90FAd33ee8b58f32c00aceEad1358e4AFC23f9"));
 
final PassKeySigner signer = PassKeySigner(options);
 
// Register a new passkey
PassKeyPair pkp = await pkpSigner.register("user@variance.space", "test user");

The PassKeySigner supports various signing methods, including personalSign, signToEc, and signToPasskeySignature.

EOA Wallet (Seed Phrases)

The EOAWallet signer allows you to sign transactions using seed phrases (also known as mnemonics). It conforms to the multi-signer interface and can be used with simple smart accounts and safe accounts. Once you have set up the appropriate signer, you can create a SmartWalletFactory instance and proceed with creating and interacting with smart wallets.

final signer = EOAWallet.createWallet();

A note on prefix: SignatureOptions is used to specify a prefix for the specific signer. This is required for alchemy light accounts. It is not required for safe smart accounts.

Smart Wallet Factory

With the chain configuration and signer set up, you can create a SmartWalletFactory instance:

final SmartWalletFactory smartWalletFactory = SmartWalletFactory(chain, signer);

Creating a Smart Wallet

The SmartWalletFactory class provides methods to create different types of smart wallets, such as AlchemyLightAccount, SafeAccountWithPasskey, and SafeAccount. Here's an example of creating a simple smart account:

final salt = Uint256.zero;
final SmartWallet wallet = await smartWalletFactory.createSafeAccount(salt);
print("Simple wallet address: ${wallet.address.hex}");

Interacting with the Smart Wallet

Once you have a SmartWallet instance, you can interact with it using various methods:

Retrieve the balance

final EtherAmount balance = await wallet.balance;
print("Account balance: ${balance.getInWei}");

Retrieve the account nonce

final Uint256 nonce = await wallet.nonce;
print("Account nonce: ${nonce.toInt()}");

Check if the wallet is deployed

final bool deployed = await wallet.deployed;
print("Account deployed: $deployed");

Get the init code

final String initCode = wallet.initCode;
print("Account init code: $initCode");

Send ether to another account

await wallet.send(
  EthereumAddress.fromHex("0x5bb137D4b0FDCD49DcA30c7CF57E578a026d2789"), // Recipient address
  EtherAmount.fromInt(EtherUnit.ether, 0.7142), // Amount in ether
);