Add initial create Eth wallet flow

This commit is contained in:
OmarHatem 2023-01-03 22:19:02 +02:00
parent 2c7883e099
commit 91ef1fdc7d
8 changed files with 208 additions and 14 deletions

View file

@ -1,7 +1,19 @@
import 'dart:convert';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_ethereum/ethereum_balance.dart'; import 'package:cw_ethereum/ethereum_balance.dart';
import 'package:cw_ethereum/ethereum_transaction_history.dart'; import 'package:cw_ethereum/ethereum_transaction_history.dart';
import 'package:cw_ethereum/ethereum_transaction_info.dart'; import 'package:cw_ethereum/ethereum_transaction_info.dart';
import 'package:cw_ethereum/ethereum_wallet_addresses.dart';
import 'package:cw_ethereum/file.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
part 'ethereum_wallet.g.dart'; part 'ethereum_wallet.g.dart';
@ -11,5 +23,87 @@ class EthereumWallet = EthereumWalletBase with _$EthereumWallet;
abstract class EthereumWalletBase abstract class EthereumWalletBase
extends WalletBase<EthereumBalance, EthereumTransactionHistory, EthereumTransactionInfo> extends WalletBase<EthereumBalance, EthereumTransactionHistory, EthereumTransactionInfo>
with Store { with Store {
EthereumWalletBase(super.walletInfo); EthereumWalletBase({
required WalletInfo walletInfo,
required this.mnemonic,
required this.privateKey,
required String password,
}) : syncStatus = NotConnectedSyncStatus(),
_password = password,
walletAddresses = EthereumWalletAddresses(walletInfo),
super(walletInfo) {
this.walletInfo = walletInfo;
transactionHistory = EthereumTransactionHistory();
}
final String mnemonic;
final String privateKey;
final String _password;
@override
SyncStatus syncStatus;
@override
ObservableMap<CryptoCurrency, EthereumBalance> get balance => throw UnimplementedError();
@override
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
throw UnimplementedError();
}
@override
Future<void> changePassword(String password) {
throw UnimplementedError();
}
@override
void close() {}
@override
Future<void> connectToNode({required Node node}) {
throw UnimplementedError();
}
@override
Future<PendingTransaction> createTransaction(Object credentials) {
throw UnimplementedError();
}
@override
Future<Map<String, EthereumTransactionInfo>> fetchTransactions() {
throw UnimplementedError();
}
@override
Object get keys => throw UnimplementedError();
@override
Future<void> rescan({required int height}) {
throw UnimplementedError();
}
@override
Future<void> save() async {
final path = await makePath();
await write(path: path, password: _password, data: toJSON());
await transactionHistory.save();
}
@override
String get seed => mnemonic;
@override
Future<void> startSync() {
throw UnimplementedError();
}
@override
WalletAddresses walletAddresses;
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
String toJSON() => json.encode({
'mnemonic': mnemonic,
// TODO: save other attributes
});
} }

View file

@ -0,0 +1,28 @@
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:mobx/mobx.dart';
part 'ethereum_wallet_addresses.g.dart';
class EthereumWalletAddresses = EthereumWalletAddressesBase with _$EthereumWalletAddresses;
abstract class EthereumWalletAddressesBase extends WalletAddresses with Store {
EthereumWalletAddressesBase(WalletInfo walletInfo)
: address = '',
super(walletInfo);
@override
String address;
@override
Future<void> init() {
// TODO: implement init
throw UnimplementedError();
}
@override
Future<void> updateAddressesInBox() {
// TODO: implement updateAddressesInBox
throw UnimplementedError();
}
}

View file

@ -10,7 +10,10 @@ import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:cw_ethereum/ethereum_wallet.dart'; import 'package:cw_ethereum/ethereum_wallet.dart';
import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart'; import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart';
import 'package:ed25519_hd_key/ed25519_hd_key.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:hex/hex.dart';
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials, class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> { EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
@ -20,13 +23,15 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
@override @override
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async { Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
final path = await pathForWallet(name: credentials.name, type: getType()); final mnemonic = bip39.generateMnemonic();
await monero_wallet_manager.createWallet( final privateKey = await getPrivateKey(mnemonic, credentials.password!);
path: path, final wallet = EthereumWallet(
password: credentials.password!, walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
privateKey: privateKey,
password: credentials.password!,
); );
final wallet = EthereumWallet(credentials.walletInfo!); await wallet.save();
await wallet.init();
return wallet; return wallet;
} }
@ -61,4 +66,12 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
// TODO: implement restoreFromSeed // TODO: implement restoreFromSeed
throw UnimplementedError(); throw UnimplementedError();
} }
Future<String> getPrivateKey(String mnemonic, String password) async {
final seed = bip39.mnemonicToSeedHex(mnemonic);
final master = await ED25519_HD_KEY.getMasterKeyFromSeed(HEX.decode(seed),
masterSecret: password);
final privateKey = HEX.encode(master.key);
return privateKey;
}
} }

39
cw_ethereum/lib/file.dart Normal file
View file

@ -0,0 +1,39 @@
import 'dart:io';
import 'package:cw_core/key.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
Future<void> write(
{required String path,
required String password,
required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);
final encrypted = await encode(key: key, iv: iv, data: data);
final f = File(path);
f.writeAsStringSync(encrypted);
}
Future<void> writeData(
{required String path,
required String password,
required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);
final encrypted = await encode(key: key, iv: iv, data: data);
final f = File(path);
f.writeAsStringSync(encrypted);
}
Future<String> read({required String path, required String password}) async {
final file = File(path);
if (!file.existsSync()) {
file.createSync();
}
final encrypted = file.readAsStringSync();
return decode(password: password, data: encrypted);
}

View file

@ -12,14 +12,19 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
web3dart: ^2.5.1 # web3dart: ^2.4.1
mobx: ^2.0.7+4 mobx: ^2.0.7+4
bip39: ^1.0.6
ed25519_hd_key: ^2.2.0
hex: ^0.2.0
cw_core: cw_core:
path: ../cw_core path: ../cw_core
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
build_runner: ^2.1.11
mobx_codegen: ^2.0.7
hive_generator: ^1.1.3 hive_generator: ^1.1.3
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the

View file

@ -2,11 +2,15 @@ part of 'ethereum.dart';
class CWEthereum extends Ethereum { class CWEthereum extends Ethereum {
@override @override
List<String> getEthereumWordList(String language) { List<String> getEthereumWordList(String language) => EthereumMnemonics.englishWordlist;
return EthereumMnemonics.englishWordlist;
}
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource) { WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource) =>
return EthereumWalletService(walletInfoSource); EthereumWalletService(walletInfoSource);
}
@override
WalletCredentials createEthereumNewWalletCredentials({
required String name,
WalletInfo? walletInfo,
}) =>
EthereumNewWalletCredentials(name: name, walletInfo: walletInfo);
} }

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
@ -41,6 +42,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
case WalletType.haven: case WalletType.haven:
return haven!.createHavenNewWalletCredentials( return haven!.createHavenNewWalletCredentials(
name: name, language: options as String); name: name, language: options as String);
case WalletType.ethereum:
return ethereum!.createEthereumNewWalletCredentials(name: name);
default: default:
throw Exception('Unexpected type: ${type.toString()}');; throw Exception('Unexpected type: ${type.toString()}');;
} }

View file

@ -477,12 +477,20 @@ Future<void> generateEthereum(bool hasImplementation) async {
const ethereumCommonHeaders = """ const ethereumCommonHeaders = """
"""; """;
const ethereumCWHeaders = """ const ethereumCWHeaders = """
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_ethereum/ethereum_mnemonics.dart'; import 'package:cw_ethereum/ethereum_mnemonics.dart';
import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart';
import 'package:cw_ethereum/ethereum_wallet_service.dart';
import 'package:hive/hive.dart';
"""; """;
const ethereumCwPart = "part 'cw_ethereum.dart';"; const ethereumCwPart = "part 'cw_ethereum.dart';";
const ethereumContent = """ const ethereumContent = """
abstract class Ethereum { abstract class Ethereum {
List<String> getEthereumWordList(String language); List<String> getEthereumWordList(String language);
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource);
WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo});
} }
"""; """;