Skip to content

Commit

Permalink
Merge pull request #23 from vaariance/feat/safe-passkey
Browse files Browse the repository at this point in the history
Feat/safe-passkey
  • Loading branch information
code-z2 authored Oct 11, 2024
2 parents 1bb53b2 + 8c7ff08 commit 1229fde
Show file tree
Hide file tree
Showing 26 changed files with 347 additions and 545 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.1.4

* add surpport for web3_signers v0.1+
* add create safe account with passkeys method in accounts factory
* modify getSafeSignature to support hybrid signatures (private key + passkey)
* update default singleton to safeL2
* refactor safe inititializer
* fix issue that causes create2salt to result in a different safe address
* fetch the smart account balance from the entrypoint
* fix issue where empty amounts array throws a light account ArrayLengthMismatch() error during batch transactions

## 0.1.3

* replace Simple account with Alchemy light account
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '2.0.20'
repositories {
google()
mavenCentral()
Expand Down
3 changes: 3 additions & 0 deletions example/devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
109 changes: 36 additions & 73 deletions example/lib/providers/wallet_provider.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:web3_signers/web3_signers.dart';
import 'package:variance_dart/variance_dart.dart';
import 'package:web3dart/credentials.dart';
import 'package:web3dart/web3dart.dart' as w3d;
import 'package:web3dart/crypto.dart' as w3d;

class WalletProvider extends ChangeNotifier {
final Chain _chain;
Expand All @@ -23,67 +20,56 @@ class WalletProvider extends ChangeNotifier {
final EthereumAddress erc20 =
EthereumAddress.fromHex("0xAEaF19097D8a8da728438D6B57edd9Bc5DAc4795");
final EthereumAddress deployer =
EthereumAddress.fromHex("0x218F6Bbc32Ef28F547A67c70AbCF8c2ea3b468BA");
EthereumAddress.fromHex("0xf5bb7f874d8e3f41821175c0aa9910d30d10e193");

final salt = Uint256.zero;
static const rpc =
"https://api.pimlico.io/v2/84532/rpc?apikey=pim_NuuL4a9tBdyfoogF5LtP5A";

WalletProvider()
: _chain = Chain(
chainId: 31337,
explorer: "https://sepolia.etherscan.io/",
entrypoint: EntryPointAddress(
0.6,
EthereumAddress.fromHex(
"0x5165c9e79213e2208947589c6e1dcc80ee8d3d00")))
..accountFactory = EthereumAddress.fromHex(
"0x0ce83Bf5d20c539E77e1E607B8349E26c6b20133") // v07 p256 factory address
..jsonRpcUrl = "http://127.0.0.1:8545"
..bundlerUrl = "http://localhost:3000/rpc";
// ..paymasterUrl =
// "https://api.pimlico.io/v2/11155111/rpc?apikey=875f3458-a37c-4187-8ac5-d08bbfa0d501";

// "0x402A266e92993EbF04a5B3fd6F0e2b21bFC83070" v06 p256 factory address
: _chain = Chains.getChain(Network.baseTestnet)
..accountFactory = Constants.lightAccountFactoryAddressv07
..bundlerUrl = rpc
..paymasterUrl = rpc;

Future<void> registerWithPassKey(String name,
{bool? requiresUserVerification}) async {
final pkpSigner =
PassKeySigner("webauthn.io", "webauthn", "https://webauthn.io");
final hwdSigner = HardwareSigner.withTag(name);
_chain.accountFactory = Constants.safeProxyFactoryAddress;

final salt = Uint256.zero;
Uint256.fromHex(
hexlify(w3d.keccak256(Uint8List.fromList(utf8.encode(name)))));
final options = PassKeysOptions(
name: "variance",
namespace: "variance.space",
origin: "https://variance.space",
userVerification: "required",
requireResidentKey: true,
sharedWebauthnSigner: EthereumAddress.fromHex(
"0xfD90FAd33ee8b58f32c00aceEad1358e4AFC23f9"));
final pkpSigner = PassKeySigner(options: options);

try {
// uses passkeys on android, secure enclave on iOS
if (Platform.isAndroid) {
final SmartWalletFactory walletFactory =
SmartWalletFactory(_chain, pkpSigner);
final keypair = await pkpSigner.register(name, name);
_wallet =
await walletFactory.createP256Account<PassKeyPair>(keypair, salt);
} else if (Platform.isIOS) {
final SmartWalletFactory walletFactory =
SmartWalletFactory(_chain, hwdSigner);
final keypair = await hwdSigner.generateKeyPair();
_wallet = await walletFactory.createP256Account<P256Credential>(
keypair, salt);
}
final SmartWalletFactory walletFactory =
SmartWalletFactory(_chain, pkpSigner);
final keypair = await pkpSigner.register(
"${DateTime.timestamp().millisecondsSinceEpoch}@variance.space",
name);
_wallet = await walletFactory.createSafeAccountWithPasskey(
keypair, salt, options.sharedWebauthnSigner);

log("wallet created ${_wallet?.address.hex} ");
} catch (e) {
_errorMessage = e.toString();
notifyListeners();
log("something happened: $e");
rethrow;
}
}

Future<void> createEOAWallet() async {
_chain.accountFactory = Constants.lightAccountFactoryAddressv06;

final signer = EOAWallet.createWallet();
final signer = EOAWallet.createWallet(
WordLength.word_12, const SignatureOptions(prefix: [0]));
log("signer: ${signer.getAddress()}");

final SmartWalletFactory walletFactory = SmartWalletFactory(_chain, signer);
final salt = Uint256.fromHex(hexlify(w3d
.keccak256(EthereumAddress.fromHex(signer.getAddress()).addressBytes)));

try {
_wallet = await walletFactory.createAlchemyLightAccount(salt);
Expand All @@ -99,17 +85,13 @@ class WalletProvider extends ChangeNotifier {
final random = math.Random.secure();
final privateKey = EthPrivateKey.createRandom(random);

final signer = PrivateKeySigner.create(privateKey, "123456", random);
final signer = PrivateKeySigner.create(privateKey, "123456", random,
options: const SignatureOptions(prefix: [0]));
log("signer: ${signer.getAddress()}");
log("pk: ${hexlify(privateKey.privateKey)}");

final SmartWalletFactory walletFactory = SmartWalletFactory(_chain, signer);

final salt = Uint256.fromHex(hexlify(w3d
.keccak256(EthereumAddress.fromHex(signer.getAddress()).addressBytes)));

log("pk salt: ${salt.toHex()}");

try {
_wallet = await walletFactory.createAlchemyLightAccount(salt);
log("pk wallet created ${_wallet?.address.hex} ");
Expand All @@ -128,11 +110,6 @@ class WalletProvider extends ChangeNotifier {

final SmartWalletFactory walletFactory = SmartWalletFactory(_chain, signer);

final salt = Uint256.fromHex(hexlify(w3d
.keccak256(EthereumAddress.fromHex(signer.getAddress()).addressBytes)));

log("salt: ${salt.toHex()}");

try {
_wallet = await walletFactory.createSafeAccount(salt);
log("safe created ${_wallet?.address.hex} ");
Expand Down Expand Up @@ -180,30 +157,16 @@ class WalletProvider extends ChangeNotifier {

Future<void> sendTransaction(String recipient, String amount) async {
if (_wallet != null) {
final response = await transferToken(
EthereumAddress.fromHex(recipient),
w3d.EtherAmount.fromBigInt(
w3d.EtherUnit.wei, BigInt.from(20 * math.pow(10, 6))));

// final etherAmount = w3d.EtherAmount.fromBigInt(w3d.EtherUnit.wei,
// BigInt.from(double.parse(amount) * math.pow(10, 18)));
final etherAmount = w3d.EtherAmount.fromBigInt(w3d.EtherUnit.wei,
BigInt.from(double.parse(amount) * math.pow(10, 18)));

// final response =
// await _wallet?.send(EthereumAddress.fromHex(recipient), etherAmount);
final response =
await _wallet?.send(EthereumAddress.fromHex(recipient), etherAmount);
final receipt = await response?.wait();

log("Transaction receipt Hash: ${receipt?.userOpHash}");
} else {
log("No wallet available to send transaction");
}
}

Future<UserOperationResponse?> transferToken(
EthereumAddress recipient, w3d.EtherAmount amount) async {
final erc20 =
EthereumAddress.fromHex("0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9");

return await _wallet?.sendTransaction(
erc20, Contract.encodeERC20TransferCall(erc20, recipient, amount));
}
}
44 changes: 42 additions & 2 deletions example/lib/screens/create_account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,48 @@ class _CreateAccountScreenState extends State<CreateAccountScreen> {
}
},
icon: const Icon(Icons.key),
label: const Text('Create Safe Smart Account')),
)
label: const Text(
'Create Alchemy Light Account with private key')),
),
18.verticalSpace,
Container(
margin: const EdgeInsets.only(left: 135),
child: Text('OR', style: TextStyle(fontSize: 18.sp))),
24.verticalSpace,
Container(
margin: const EdgeInsets.only(left: 30),
child: TextButton.icon(
onPressed: () {
try {
context.read<WalletProvider>().createEOAWallet();
Navigator.pushNamed(context, '/home');
} catch (e) {
'Something went wrong: $e';
}
},
icon: const Icon(Icons.key),
label: const Text(
'Create Alchemy Light Account with seed phrase')),
),
18.verticalSpace,
Container(
margin: const EdgeInsets.only(left: 135),
child: Text('OR', style: TextStyle(fontSize: 18.sp))),
24.verticalSpace,
Container(
margin: const EdgeInsets.only(left: 30),
child: TextButton.icon(
onPressed: () {
try {
context.read<WalletProvider>().createSafeWallet();
Navigator.pushNamed(context, '/home');
} catch (e) {
'Something went wrong: $e';
}
},
icon: const Icon(Icons.key),
label: const Text('Create default Safe Account')),
),
],
),
);
Expand Down
5 changes: 0 additions & 5 deletions example/lib/screens/home/home_screen.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
import 'package:variancedemo/providers/wallet_provider.dart';
Expand Down Expand Up @@ -167,9 +165,6 @@ class NFT extends StatelessWidget {

@override
Widget build(BuildContext context) {
final wallet = context.select(
(WalletProvider provider) => provider.wallet,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expand Down
34 changes: 17 additions & 17 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.4"
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
Expand Down Expand Up @@ -340,18 +340,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.8.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.12.0"
version: "1.15.0"
nested:
dependency: transitive
description:
Expand Down Expand Up @@ -641,10 +641,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.2"
typed_data:
dependency: transitive
description:
Expand Down Expand Up @@ -683,7 +683,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.1.3"
version: "0.1.4"
vector_math:
dependency: transitive
description:
Expand All @@ -696,10 +696,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "14.2.5"
wallet:
dependency: transitive
description:
Expand All @@ -720,10 +720,10 @@ packages:
dependency: "direct main"
description:
name: web3_signers
sha256: "455acf0207ef6edc5937a73edd57ce94f028b41856c07193be23e282d542d625"
sha256: cb07808a4add7119f07c5c696db242a78df0c6c45a414ff8f1333b747b811b21
url: "https://pub.dev"
source: hosted
version: "0.0.14-alpha-01"
version: "0.1.6"
web3dart:
dependency: "direct main"
description:
Expand Down Expand Up @@ -757,5 +757,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.4.0 <4.0.0"
flutter: ">=3.22.0"
dart: ">=3.5.0 <4.0.0"
flutter: ">=3.24.3"
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ dependencies:
google_fonts: 6.1.0
flutter_screenutil: ^5.9.0
qr_flutter: ^4.1.0
web3dart: ^2.7.2
web3dart: ^2.7.3
shared_preferences: ^2.2.2
path_provider: ^2.1.1
fluttertoast: ^8.2.4
variance_dart:
path: ../
web3_signers: ^0.0.14-alpha-01
web3_signers: ^0.1.6

dev_dependencies:
flutter_test:
Expand Down
Loading

0 comments on commit 1229fde

Please sign in to comment.