-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from vaariance/fix/useroperations
Fix/useroperations
- Loading branch information
Showing
52 changed files
with
2,173 additions
and
877 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
get_dependencies: | ||
name: "Get dependencies" | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: dart-lang/setup-dart@v1 | ||
- name: "Print Dart SDK Version" | ||
run: dart --version | ||
- uses: actions/cache@v2 | ||
with: | ||
path: .dart_tool | ||
key: dart-dependencies-${{ hashFiles('pubspec.yaml') }} | ||
- name: "Get dependencies" | ||
env: | ||
PUB_CACHE: ".dart_tool/pub_cache" | ||
run: dart pub upgrade | ||
|
||
analyze: | ||
name: "Analysis" | ||
needs: get_dependencies | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/cache@v2 | ||
with: | ||
path: .dart_tool | ||
key: dart-dependencies-${{ hashFiles('pubspec.yaml') }} | ||
- uses: dart-lang/setup-dart@v1 | ||
- run: "dart format --output=none --set-exit-if-changed ." | ||
- run: dart analyze --fatal-infos |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name: Publish to pub.dev | ||
|
||
on: | ||
push: | ||
tags: | ||
- "v[0-9]+.[0-9]+.[0-9]+*" | ||
|
||
jobs: | ||
publish: | ||
permissions: | ||
id-token: write # Required for authentication using OIDC | ||
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,181 @@ | ||
# 4337 Dart | ||
# Variance SDK | ||
|
||
Account Abstraction SDK written in dart. Build Cross Platform Native Ethereum dApps easily. | ||
Variance is a Dart SDK designed to simplify interaction with Ethereum-based blockchains and enables flutter developers to implement account abstraction with minimal efforts. It provides functionalities such as encoding and decoding ABI data, handling Ethereum transactions, working with ERC20 and ERC721 tokens, and managing Ethereum smart accounts. | ||
|
||
supports: | ||
## Features | ||
|
||
- [x] multi-signatures | ||
- - [x] passkeys (secp256r1) | ||
- - [x] default (secp256k1) | ||
- - [x] DIY (custom schemes) | ||
- [] safe core protocol | ||
- [x] SDK plugins | ||
- **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. | ||
|
||
## Getting Started | ||
|
||
### Installation | ||
|
||
```yml | ||
// Add this line to your pubspec.yaml file | ||
|
||
dependencies: | ||
variance_dart: ^0.0.4 | ||
``` | ||
Then run: | ||
```sh | ||
flutter pub get | ||
``` | ||
|
||
### Usage | ||
|
||
```dart | ||
// Import the package | ||
import 'package:variance_dart/utils.dart'; | ||
import 'package:variance_dart/variance.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. | ||
|
||
```dart | ||
Chain chain; | ||
// manually | ||
const String rpcUrl = 'http://localhost:8545'; | ||
const String bundlerUrl = 'http://localhost:3000/rpc'; | ||
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 | ||
..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: | ||
|
||
- passkeys | ||
- hd wallet | ||
- simple credential (privatekey) | ||
|
||
> 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. | ||
```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()}"); | ||
``` | ||
|
||
Optionally the credentials returned from the signer instances can be securely saved on device android encrypted shared preferences or ios keychain using the `SecureStorageMiddleware`. | ||
|
||
```dart | ||
// save a signer credential to device | ||
await hd | ||
.withSecureStorage(FlutterSecureStorage()) | ||
.saveCredential(CredentialType.hdwallet); | ||
await pkp | ||
.withSecureStorage(FlutterSecureStorage()) | ||
.saveCredential(CredentialType.passkeypair); | ||
// load a credential from the device | ||
final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage()); | ||
final hdInstance = | ||
await HDWalletSigner.loadFromSecureStorage(storageMiddleware: ss); | ||
print("pkp: ${hdInstance?.exportMnemonic()}"); | ||
// NOTE: interactions with securestorage can be authenticated when using `SecureStorageMiddleware` | ||
final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage(), authMiddleware: AuthenticationMiddleware()); | ||
// then used with `SecureStorageMiddleware` in the following way | ||
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 | ||
``` | ||
|
||
Interacting with the smart wallet: | ||
|
||
```dart | ||
// create a smart wallet client | ||
final walletClient = SmartWallet( | ||
chain: chain, | ||
signer: hd, | ||
bundler: BundlerProvider(chain, RPCProvider(chain.bundlerUrl!)), | ||
); | ||
// create a simple account based on hd | ||
final SmartWallet simpleSmartAccount = | ||
await walletClient.createSimpleAccount(salt); | ||
print("simple account address: ${simpleSmartAccount.address}"); | ||
// create a simple account based on pkp | ||
final SmartWallet simplePkpAccount = | ||
await walletClient.createSimplePasskeyAccount(pkp, salt); | ||
print("simple pkp account address: ${simplePkpAccount.address}"); | ||
// retrieve the balance of a smart wallet | ||
final EtherAmount balance = await simpleSmartAccount.balance; | ||
print("account balance: ${balance.getInWei}"); | ||
// retrive the account nonce | ||
final Uint256 nonce = await simpleSmartAccount.nonce; | ||
print("account nonce: ${nonce.toInt()}"); | ||
// check if a smart wallet has been deployed | ||
final bool deployed = await simpleSmartAccount.deployed; | ||
print("account deployed: $deployed"); | ||
// get the init code of the smart wallet | ||
final String initCode = simpleSmartAccount.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( | ||
EthereumAddress.fromHex( | ||
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"), // receive address | ||
getConversion("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. | ||
|
||
## API Reference | ||
|
||
Detailed API reference and examples can be found in the [API reference](https://pub.dev/documentation/variance_dart/latest/variance/variance-library.html). | ||
|
||
## Contributing | ||
|
||
We are committed to maintaining variance as an open source sdk, take a look at existing issues, open a pull request etc. | ||
|
||
## License | ||
|
||
This project is licensed under the **BSD-3-Clause** - see the [LICENSE](./LICENSE) file for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// ignore_for_file: public_member_api_docs | ||
|
||
import 'dart:math'; | ||
|
||
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; | ||
import 'package:variance_dart/utils.dart'; | ||
import 'package:variance_dart/variance.dart'; | ||
import 'package:web3dart/web3dart.dart'; | ||
|
||
const String rpcUrl = 'http://localhost:8545'; | ||
const String bundlerUrl = 'http://localhost:3000/rpc'; | ||
|
||
Future<void> main() async { | ||
final Uint256 salt = Uint256.zero; | ||
|
||
// configure your chain | ||
final Chain chain = Chain( | ||
ethRpcUrl: rpcUrl, | ||
bundlerUrl: bundlerUrl, | ||
entrypoint: Constants.entrypoint, | ||
accountFactory: Constants.accountFactory, | ||
chainId: 1337, | ||
explorer: ""); | ||
|
||
// 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()}"); | ||
|
||
// save a signer credential to device | ||
await hd | ||
.withSecureStorage(FlutterSecureStorage()) | ||
.saveCredential(CredentialType.hdwallet); | ||
|
||
// load a credential from the device | ||
final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage()); | ||
final hdInstance = | ||
await HDWalletSigner.loadFromSecureStorage(storageMiddleware: ss); | ||
print("pkp: ${hdInstance?.exportMnemonic()}"); | ||
|
||
// NOTE: interactions with securestorage can be authenticated when using `SecureStorageMiddleware` | ||
// | ||
// final ss = SecureStorageMiddleware(secureStorage: FlutterSecureStorage(), authMiddleware: AuthenticationMiddleware()); | ||
// then used with `SecureStorageMiddleware` in the following way | ||
// | ||
// 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 | ||
//; | ||
|
||
// create a smart wallet client | ||
final walletClient = SmartWallet( | ||
chain: chain, | ||
signer: hd, | ||
bundler: BundlerProvider(chain, RPCProvider(chain.bundlerUrl!)), | ||
); | ||
|
||
// create a simple account based on hd | ||
final SmartWallet simpleSmartAccount = | ||
await walletClient.createSimpleAccount(salt); | ||
print("simple account address: ${simpleSmartAccount.address}"); | ||
|
||
// create a simple account based on pkp | ||
final SmartWallet simplePkpAccount = | ||
await walletClient.createSimplePasskeyAccount(pkp, salt); | ||
print("simple pkp account address: ${simplePkpAccount.address}"); | ||
|
||
// retrieve the balance of a smart wallet | ||
final EtherAmount balance = await simpleSmartAccount.balance; | ||
print("account balance: ${balance.getInWei}"); | ||
|
||
// retrive the account nonce | ||
final Uint256 nonce = await simpleSmartAccount.nonce; | ||
print("account nonce: ${nonce.toInt()}"); | ||
|
||
// check if a smart wallet has been deployed | ||
final bool deployed = await simpleSmartAccount.deployed; | ||
print("account deployed: $deployed"); | ||
|
||
// get the init code of the smart wallet | ||
final String initCode = simpleSmartAccount.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( | ||
EthereumAddress.fromHex( | ||
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"), // receive address | ||
getConversion("0.7142"), // 0.7142 ether | ||
); | ||
} | ||
|
||
EtherAmount getConversion(String amount) { | ||
final amtToDb = double.parse(amount); | ||
return EtherAmount.fromBigInt( | ||
EtherUnit.wei, BigInt.from(amtToDb * pow(10, 18))); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
name: example | ||
publish_to: none | ||
version: 0.0.1 | ||
homepage: https://variance.space | ||
repository: https://github.com/vaariance/variance-dart | ||
|
||
environment: | ||
sdk: ">=2.12.0 <4.0.0" | ||
|
||
dependencies: | ||
variance_dart: | ||
path: ../ | ||
|
||
dev_dependencies: | ||
coverage: ^1.1.0 | ||
lints: ^2.0.0 |
Oops, something went wrong.