Skip to content

Commit

Permalink
Merge pull request #17 from vaariance/refactoring
Browse files Browse the repository at this point in the history
Refactoring
  • Loading branch information
code-z2 authored Apr 8, 2024
2 parents 81a1098 + 9513740 commit 78de37e
Show file tree
Hide file tree
Showing 172 changed files with 6,821 additions and 11,073 deletions.
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
## 0.1.0

* Training wheel support for entrypoint v0.7.0 via pimlico bundler
* Fix issue with gas multiplier
* Added safe4337module abi for v0.7.0
* Add support for custom paymaster address

## 0.1.0-r3

* Add mutisend address to constants
* Add support for Safe account batch transactions

## 0.1.0-r2

* Fix safe transaction encoding
* Remove _checkDeployment function in counterfactual creation
* Add getBlockInformation in JsonRPCProvider

## 0.1.0-r1

* Mainnet Pre-release
* refactor sdk to use the factory method for creating smart-accounts
* add safe smart accounts via safe plugin
* reduce external dependencies to 3
* implement custom errors and add logger for debugging
* update contract abis, adding more erc20/erc721 abi snippets
* fix paymaster plugin context incompatibility
* add utility for packing and unpacking uint256 values
* update chain configuration to surpport minimal modest chains
* update example to a real flutter example
* rename library name from variance to variance_dart for consistency
* update API refs and README to reflect new changes

## 0.0.9

* Add support for entrypoint v0.7 in parrallel.

## 0.0.8

* Add paymaster as a plugin
* Rename plugins.dart to mixins
* Improve gas and nonce calculation process.

## 0.0.7

* Deprecate passing wallet address via constructor as fields will be made final
* Enable global gas settings and fee % multiplier
* Introduce userOp retry mechanism

## 0.0.6

* Sunset all goerli chains

## 0.0.5

* Added missing required blockParam to `eth_call`

* Reduced default callgasLimit and verificationGasLimit to 250K and 750k respectively in `eth_estimateUserOperationGas`

* Prevent redundant eth_call's in fetching nonce/deployment status

* Reduced strict internal op callGasLimit validation from 21k gas 12k gas requirement

## 0.0.4

* Added a Secure Storage Repository for saving credentials to encrypted android shared-preference and iOS keychain
Expand Down
172 changes: 77 additions & 95 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,166 +7,148 @@ Variance is a Dart SDK designed to simplify interaction with Ethereum-based bloc
- **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.
- **Secure Storage:** Securely store and manage sensitive data such as private keys and credentials.
- **Web3 Functionality:** Interact with Ethereum nodes and bundlers using web3 functions like `eth_call`, `eth_sendTransaction`, `eth_sendUserOperation`, etc.
- **PassKeyPair and HDWalletSigner:** Manage smart accounts signers using Passkeys or Seed Phrases.
- **Web3 Functionality:** Interact with Ethereum nodes and bundlers using abstracted methods over, `eth_sendTransaction`, and `eth_sendUserOperation`.
- **SecP256r1 Signatures:** Sign transactions with SecP256r1 signatures.

## Getting Started

### Installation

```yml
// Add this line to your pubspec.yaml file

dependencies:
variance_dart: ^0.0.4
```
Then run:
open your terminal and run the following command:

```sh
flutter pub get
flutter pub add variance_dart
flutter pub add web3_signers

# optionally
flutter pub add web3dart
```

### Usage

```dart
// Import the package
import 'package:variance_dart/utils.dart';
import 'package:variance_dart/variance.dart';
import 'package:web3_signers/web3_signers.dart';
import 'package:variance_dart/variance_dart.dart';
// optionally
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:web3dart/web3dart.dart';
```

configure your chains: there are 2 ways to get the chain configuration. either manually or using the already supported configurations.
### Chain Configuration

```dart
Chain chain;
// manually
const String rpcUrl = 'http://localhost:8545';
const String bundlerUrl = 'http://localhost:3000/rpc';
const Uint256 salt = const Uint256.zero;
chain = Chain(
ethRpcUrl: rpcUrl,
bundlerUrl: bundlerUrl,
entrypoint: Constants.entrypoint,
accountFactory: Constants.accountFactory,
chainId: 1337,
explorer: "");
// using pre configured chain
chain = Chains.getChain(Network.localhost)
..ethRpcUrl = rpcUrl
final Chain chain = Chains.getChain(Network.localhost)
..jsonRpcUrl = rpcUrl
..bundlerUrl = bundlerUrl;
```

In order to create a smart wallet client you need to set up a signer, which will sign useroperation hashes to be verified onchain.
there are 3 available signers:
> There are 8 available networks: ethereum, polygon, optimism, base, arbitrumOne, linea, opBnB and scroll. 3 available testnets: sepolia, mumbai and baseTestent. You can also develop on localHost.
Additionally, you can specify a different Entrypoint address. By default, the entrypoin v0.6 is used.

- passkeys
- hd wallet
- simple credential (privatekey)
```dart
final EntryPointAddress entrypointAddress = EntryPointAddress.v07;
chain.entrypoint = entrypointAddress;
```

> Variance SDK can be used to create both EOA and Smart Wallets. the `HD wallet signer` itself is a fully featured EOA wallet that can be used to build any EOA wallet like metamask. it can also be used as an account signer for a smart wallet.
Also if wish to use paymasters with your smart wallet you can do so by specifying the endpoint of the paymaster. By default the paymaster is set to null. This would add a paymaster Plugin to the smart wallet.

```dart
// create smart wallet signer based of seed phrase
final HDWalletSigner hd = HDWalletSigner.createWallet();
print("mnemonic: ${hd.exportMnemonic()}");
// create a smart wallet signer based on passkeys
// this operation requires biometrics verification from the user
final PassKeyPair pkp =
await PassKeySigner("myapp.xyz", "myapp", "https://myapp.xyz")
.register("<user name>", true);
print("pkp: ${pkp.toJson()}");
final String paymasterUrl = 'https://api.pimlico.io/v2/84532/rpc?apikey=...';
chain.paymasterUrl = paymasterUrl;
```

Optionally the credentials returned from the signer instances can be securely saved on device android encrypted shared preferences or ios keychain using the `SecureStorageMiddleware`.
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.

```dart
// save a signer credential to device
await hd
.withSecureStorage(FlutterSecureStorage())
.saveCredential(CredentialType.hdwallet);
wallet.plugin<Paymaster>('paymaster').context = {'key': 'value'};
```

### Signers

await pkp
.withSecureStorage(FlutterSecureStorage())
.saveCredential(CredentialType.passkeypair);
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](https://pub.dev/packages/web3_signers) package can be used.

// load a credential from the device
final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage());
final hdInstance =
await HDWalletSigner.loadFromSecureStorage(storageMiddleware: ss);
print("pkp: ${hdInstance?.exportMnemonic()}");
> You have to use the correct signer for the type of account you want to create.
// NOTE: interactions with securestorage can be authenticated when using `SecureStorageMiddleware`
1. `PrivateKeys` - use with simple accounts and safe accounts only
2. `Passkey` - use with p256 smart accounts and safe Passkey accounts only
3. `EOA Wallet (Seed Phrases)` - use with simple smart accounts and safe accounts only
4. `HardWare Signers (Secure Enclave/Keystore)` - use with p256 smart accounts only

final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage(), authMiddleware: AuthenticationMiddleware());
// then used with `SecureStorageMiddleware` in the following way
### Smart Wallet Factory

ss.save("key", "value", options: SSAuthOperationOptions(requiresAuth: true, authReason: "reason"));
ss.read("key"); // default options are used i.e requiresAuth: false
ss.delete("key", options: SSAuthOperationOptions(requiresAuth: false)); // explicitly reject authentication
The smart wallet factory handles the creation of smart wallet instances. Make sure you have created a signer from the previous step.

```dart
final SmartWalletFactory smartWalletFactory = SmartWalletFactory(chain, signer);
```

Interacting with the smart wallet:
#### To Create a Simple Smart Account

```dart
// create a smart wallet client
final walletClient = SmartWallet(
chain: chain,
signer: hd,
bundler: BundlerProvider(chain, RPCProvider(chain.bundlerUrl!)),
);
final Smartwallet wallet = await smartWalletFactory.createSimpleAccount(salt);
print("simple wallet address: ${wallet.address.hex}");
```

// create a simple account based on hd
final SmartWallet simpleSmartAccount =
await walletClient.createSimpleAccount(salt);
print("simple account address: ${simpleSmartAccount.address}");
#### To create a P256 Smart Account (Secure Enclave/Keystore)

// create a simple account based on pkp
final SmartWallet simplePkpAccount =
await walletClient.createSimplePasskeyAccount(pkp, salt);
print("simple pkp account address: ${simplePkpAccount.address}");
```dart
final Smartwallet wallet = await smartWalletFactory.createP256Account(keypair, salt);
print("p256 wallet address: ${wallet.address.hex}");
```

Your keypair must be either be the `PassKeyPair` or `P256Credential` return when registering with your secp256r1 signer.
Additionally, you can pass a recovery address to the `createP256Account` method.

```dart
final Smartwallet wallet = await smartWalletFactory.createP256Account(keypair, salt, recoveryAddress);
print("p256 wallet address: ${wallet.address.hex}");
```

#### To create a [Safe](https://safe.global) Smart Account

```dart
final Smartwallet wallet = await smartWalletFactory
.createSafeAccount(salt);
print("safe wallet address: ${wallet.address.hex}");
```

> Safe SecP256r1 signers can not be used with this SDK yet.
### Interacting with the Smart Wallet

```dart
// retrieve the balance of a smart wallet
final EtherAmount balance = await simpleSmartAccount.balance;
final EtherAmount balance = await wallet.balance;
print("account balance: ${balance.getInWei}");
// retrive the account nonce
final Uint256 nonce = await simpleSmartAccount.nonce;
final Uint256 nonce = await wallet.nonce;
print("account nonce: ${nonce.toInt()}");
// check if a smart wallet has been deployed
final bool deployed = await simpleSmartAccount.deployed;
final bool deployed = await wallet.deployed;
print("account deployed: $deployed");
// get the init code of the smart wallet
final String initCode = simpleSmartAccount.initCode;
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 simpleSmartAccount.send(
await wallet.send(
EthereumAddress.fromHex(
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"), // receive address
getConversion("0.7142"), // 0.7142 ether
EtherAmount.fromInt(EtherUnit.ether, 0.7142), // 0.7142 ether
);
// utility function to convert eth amount from string to wei
EtherAmount getConversion(String amount) {
final amtToDb = double.parse(amount);
return EtherAmount.fromBigInt(
EtherUnit.wei, BigInt.from(amtToDb * pow(10, 18)));
}
```

For detailed usage and examples, refer to the [documentation](https://docs.variance.space). Additional refer to the [demo](https://github.com/vaariance/variancedemo) for use in a flutter app.
For detailed usage and examples, refer to the [documentation](https://docs.variance.space). Additional refer to the [example](./example/) for use in a flutter app.

## API Reference

Expand Down
43 changes: 43 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
30 changes: 30 additions & 0 deletions example/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "41456452f29d64e8deb623a3c927524bcf9f111b"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
- platform: android
create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b
base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
Loading

0 comments on commit 78de37e

Please sign in to comment.