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_info.dart';
import 'package:cw_ethereum/ethereum_balance.dart';
import 'package:cw_ethereum/ethereum_transaction_history.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';
part 'ethereum_wallet.g.dart';
@ -11,5 +23,87 @@ class EthereumWallet = EthereumWalletBase with _$EthereumWallet;
abstract class EthereumWalletBase
extends WalletBase<EthereumBalance, EthereumTransactionHistory, EthereumTransactionInfo>
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_ethereum/ethereum_wallet.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:bip39/bip39.dart' as bip39;
import 'package:hex/hex.dart';
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
@ -20,13 +23,15 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
@override
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
final path = await pathForWallet(name: credentials.name, type: getType());
await monero_wallet_manager.createWallet(
path: path,
password: credentials.password!,
final mnemonic = bip39.generateMnemonic();
final privateKey = await getPrivateKey(mnemonic, credentials.password!);
final wallet = EthereumWallet(
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
privateKey: privateKey,
password: credentials.password!,
);
final wallet = EthereumWallet(credentials.walletInfo!);
await wallet.init();
await wallet.save();
return wallet;
}
@ -61,4 +66,12 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
// TODO: implement restoreFromSeed
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:
flutter:
sdk: flutter
web3dart: ^2.5.1
# web3dart: ^2.4.1
mobx: ^2.0.7+4
bip39: ^1.0.6
ed25519_hd_key: ^2.2.0
hex: ^0.2.0
cw_core:
path: ../cw_core
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.1.11
mobx_codegen: ^2.0.7
hive_generator: ^1.1.3
# 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 {
@override
List<String> getEthereumWordList(String language) {
return EthereumMnemonics.englishWordlist;
}
List<String> getEthereumWordList(String language) => EthereumMnemonics.englishWordlist;
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource) {
return EthereumWalletService(walletInfoSource);
}
WalletService createEthereumWalletService(Box<WalletInfo> 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:hive/hive.dart';
import 'package:mobx/mobx.dart';
@ -41,6 +42,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
case WalletType.haven:
return haven!.createHavenNewWalletCredentials(
name: name, language: options as String);
case WalletType.ethereum:
return ethereum!.createEthereumNewWalletCredentials(name: name);
default:
throw Exception('Unexpected type: ${type.toString()}');;
}

View file

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