Implement open wallet functionality

This commit is contained in:
OmarHatem 2023-01-05 21:05:44 +02:00
parent 73680a96e2
commit e1639cdc34
3 changed files with 78 additions and 27 deletions

View file

@ -4,7 +4,7 @@ import 'package:cw_core/balance.dart';
import 'package:web3dart/web3dart.dart';
class EthereumBalance extends Balance {
EthereumBalance(super.available, super.additional);
EthereumBalance({required int available, required int additional}) : super(available, additional);
@override
String get formattedAdditionalBalance {
@ -18,4 +18,17 @@ class EthereumBalance extends Balance {
EtherAmount.fromUnitAndValue(EtherUnit.ether, available.toString()).getInEther.toString();
String toJSON() => json.encode({'available': available, 'additional': additional});
static EthereumBalance? fromJSON(String? jsonSource) {
if (jsonSource == null) {
return null;
}
final decoded = json.decode(jsonSource) as Map;
return EthereumBalance(
available: decoded['available'] as int? ?? 0,
additional: decoded['additional'] as int? ?? 0,
);
}
}

View file

@ -18,6 +18,9 @@ import 'package:cw_ethereum/ethereum_wallet_addresses.dart';
import 'package:cw_ethereum/file.dart';
import 'package:mobx/mobx.dart';
import 'package:web3dart/web3dart.dart';
import 'package:ed25519_hd_key/ed25519_hd_key.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:hex/hex.dart';
part 'ethereum_wallet.g.dart';
@ -28,25 +31,24 @@ abstract class EthereumWalletBase
with Store {
EthereumWalletBase({
required WalletInfo walletInfo,
required this.mnemonic,
required this.privateKey,
required String mnemonic,
required String password,
EthereumBalance? initialBalance,
}) : syncStatus = NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
walletAddresses = EthereumWalletAddresses(walletInfo),
balance = ObservableMap<CryptoCurrency, EthereumBalance>.of(
{CryptoCurrency.eth: initialBalance ?? EthereumBalance(0, 0)}),
{CryptoCurrency.eth: initialBalance ?? EthereumBalance(available: 0, additional: 0)}),
super(walletInfo) {
this.walletInfo = walletInfo;
transactionHistory = EthereumTransactionHistory();
walletAddresses.address = EthPrivateKey.fromHex(privateKey).address.toString();
}
final String mnemonic;
final String privateKey;
final String _mnemonic;
final String _password;
late final String privateKey;
late EthereumClient _client;
EtherAmount? _gasPrice;
@ -61,6 +63,12 @@ abstract class EthereumWalletBase
@observable
late ObservableMap<CryptoCurrency, EthereumBalance> balance;
Future<void> init() async {
privateKey = await getPrivateKey(_mnemonic, _password);
transactionHistory = EthereumTransactionHistory();
walletAddresses.address = EthPrivateKey.fromHex(privateKey).address.toString();
}
@override
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
throw UnimplementedError("calculateEstimatedFee");
@ -119,7 +127,7 @@ abstract class EthereumWalletBase
}
@override
String get seed => mnemonic;
String get seed => _mnemonic;
@override
Future<void> startSync() async {
@ -150,11 +158,31 @@ abstract class EthereumWalletBase
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
String toJSON() => json.encode({
'mnemonic': mnemonic,
'mnemonic': _mnemonic,
'balance': balance[currency]!.toJSON(),
// TODO: save other attributes
});
static Future<EthereumWallet> open({
required String name,
required String password,
required WalletInfo walletInfo,
}) async {
final path = await pathForWallet(name: name, type: walletInfo.type);
final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map;
final mnemonic = data['mnemonic'] as String;
final balance = EthereumBalance.fromJSON(data['balance'] as String) ??
EthereumBalance(available: 0, additional: 0);
return EthereumWallet(
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
initialBalance: balance,
);
}
Future<void> _updateBalance() async {
balance[currency] = await _fetchBalances();
await save();
@ -163,6 +191,17 @@ abstract class EthereumWalletBase
Future<EthereumBalance> _fetchBalances() async {
final balance = await _client.getBalance(privateKey);
return EthereumBalance(balance.getInEther.toInt(), balance.getInEther.toInt());
return EthereumBalance(
available: balance.getInEther.toInt(),
additional: balance.getInEther.toInt(),
);
}
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;
}
}

View file

@ -10,10 +10,8 @@ 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> {
@ -24,13 +22,13 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
@override
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
final mnemonic = bip39.generateMnemonic();
final privateKey = await getPrivateKey(mnemonic, credentials.password!);
final wallet = EthereumWallet(
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
privateKey: privateKey,
password: credentials.password!,
);
await wallet.init();
await wallet.save();
return wallet;
@ -44,10 +42,19 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
File(await pathForWallet(name: name, type: getType())).existsSync();
@override
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> openWallet(
String name, String password) {
// TODO: implement openWallet
throw UnimplementedError();
Future<EthereumWallet> openWallet(String name, String password) async {
final walletInfo =
walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
final wallet = await EthereumWalletBase.open(
name: name,
password: password,
walletInfo: walletInfo,
);
await wallet.init();
await wallet.save();
return wallet;
}
@override
@ -66,12 +73,4 @@ 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;
}
}