mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-12 22:04:54 +00:00
Implement open wallet functionality
This commit is contained in:
parent
73680a96e2
commit
e1639cdc34
3 changed files with 78 additions and 27 deletions
|
@ -4,7 +4,7 @@ import 'package:cw_core/balance.dart';
|
||||||
import 'package:web3dart/web3dart.dart';
|
import 'package:web3dart/web3dart.dart';
|
||||||
|
|
||||||
class EthereumBalance extends Balance {
|
class EthereumBalance extends Balance {
|
||||||
EthereumBalance(super.available, super.additional);
|
EthereumBalance({required int available, required int additional}) : super(available, additional);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get formattedAdditionalBalance {
|
String get formattedAdditionalBalance {
|
||||||
|
@ -18,4 +18,17 @@ class EthereumBalance extends Balance {
|
||||||
EtherAmount.fromUnitAndValue(EtherUnit.ether, available.toString()).getInEther.toString();
|
EtherAmount.fromUnitAndValue(EtherUnit.ether, available.toString()).getInEther.toString();
|
||||||
|
|
||||||
String toJSON() => json.encode({'available': available, 'additional': additional});
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ import 'package:cw_ethereum/ethereum_wallet_addresses.dart';
|
||||||
import 'package:cw_ethereum/file.dart';
|
import 'package:cw_ethereum/file.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:web3dart/web3dart.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';
|
part 'ethereum_wallet.g.dart';
|
||||||
|
|
||||||
|
@ -28,25 +31,24 @@ abstract class EthereumWalletBase
|
||||||
with Store {
|
with Store {
|
||||||
EthereumWalletBase({
|
EthereumWalletBase({
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required this.mnemonic,
|
required String mnemonic,
|
||||||
required this.privateKey,
|
|
||||||
required String password,
|
required String password,
|
||||||
EthereumBalance? initialBalance,
|
EthereumBalance? initialBalance,
|
||||||
}) : syncStatus = NotConnectedSyncStatus(),
|
}) : syncStatus = NotConnectedSyncStatus(),
|
||||||
_password = password,
|
_password = password,
|
||||||
|
_mnemonic = mnemonic,
|
||||||
walletAddresses = EthereumWalletAddresses(walletInfo),
|
walletAddresses = EthereumWalletAddresses(walletInfo),
|
||||||
balance = ObservableMap<CryptoCurrency, EthereumBalance>.of(
|
balance = ObservableMap<CryptoCurrency, EthereumBalance>.of(
|
||||||
{CryptoCurrency.eth: initialBalance ?? EthereumBalance(0, 0)}),
|
{CryptoCurrency.eth: initialBalance ?? EthereumBalance(available: 0, additional: 0)}),
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = EthereumTransactionHistory();
|
|
||||||
walletAddresses.address = EthPrivateKey.fromHex(privateKey).address.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String mnemonic;
|
final String _mnemonic;
|
||||||
final String privateKey;
|
|
||||||
final String _password;
|
final String _password;
|
||||||
|
|
||||||
|
late final String privateKey;
|
||||||
|
|
||||||
late EthereumClient _client;
|
late EthereumClient _client;
|
||||||
|
|
||||||
EtherAmount? _gasPrice;
|
EtherAmount? _gasPrice;
|
||||||
|
@ -61,6 +63,12 @@ abstract class EthereumWalletBase
|
||||||
@observable
|
@observable
|
||||||
late ObservableMap<CryptoCurrency, EthereumBalance> balance;
|
late ObservableMap<CryptoCurrency, EthereumBalance> balance;
|
||||||
|
|
||||||
|
Future<void> init() async {
|
||||||
|
privateKey = await getPrivateKey(_mnemonic, _password);
|
||||||
|
transactionHistory = EthereumTransactionHistory();
|
||||||
|
walletAddresses.address = EthPrivateKey.fromHex(privateKey).address.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
||||||
throw UnimplementedError("calculateEstimatedFee");
|
throw UnimplementedError("calculateEstimatedFee");
|
||||||
|
@ -119,7 +127,7 @@ abstract class EthereumWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get seed => mnemonic;
|
String get seed => _mnemonic;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> startSync() async {
|
Future<void> startSync() async {
|
||||||
|
@ -150,11 +158,31 @@ abstract class EthereumWalletBase
|
||||||
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||||
|
|
||||||
String toJSON() => json.encode({
|
String toJSON() => json.encode({
|
||||||
'mnemonic': mnemonic,
|
'mnemonic': _mnemonic,
|
||||||
'balance': balance[currency]!.toJSON(),
|
'balance': balance[currency]!.toJSON(),
|
||||||
// TODO: save other attributes
|
// 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 {
|
Future<void> _updateBalance() async {
|
||||||
balance[currency] = await _fetchBalances();
|
balance[currency] = await _fetchBalances();
|
||||||
await save();
|
await save();
|
||||||
|
@ -163,6 +191,17 @@ abstract class EthereumWalletBase
|
||||||
Future<EthereumBalance> _fetchBalances() async {
|
Future<EthereumBalance> _fetchBalances() async {
|
||||||
final balance = await _client.getBalance(privateKey);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,8 @@ 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:bip39/bip39.dart' as bip39;
|
||||||
import 'package:hex/hex.dart';
|
|
||||||
|
|
||||||
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
||||||
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
|
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
|
||||||
|
@ -24,13 +22,13 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
||||||
@override
|
@override
|
||||||
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
|
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
|
||||||
final mnemonic = bip39.generateMnemonic();
|
final mnemonic = bip39.generateMnemonic();
|
||||||
final privateKey = await getPrivateKey(mnemonic, credentials.password!);
|
|
||||||
final wallet = EthereumWallet(
|
final wallet = EthereumWallet(
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
privateKey: privateKey,
|
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wallet.init();
|
||||||
await wallet.save();
|
await wallet.save();
|
||||||
|
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -44,10 +42,19 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
||||||
File(await pathForWallet(name: name, type: getType())).existsSync();
|
File(await pathForWallet(name: name, type: getType())).existsSync();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> openWallet(
|
Future<EthereumWallet> openWallet(String name, String password) async {
|
||||||
String name, String password) {
|
final walletInfo =
|
||||||
// TODO: implement openWallet
|
walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
||||||
throw UnimplementedError();
|
final wallet = await EthereumWalletBase.open(
|
||||||
|
name: name,
|
||||||
|
password: password,
|
||||||
|
walletInfo: walletInfo,
|
||||||
|
);
|
||||||
|
|
||||||
|
await wallet.init();
|
||||||
|
await wallet.save();
|
||||||
|
|
||||||
|
return wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -66,12 +73,4 @@ 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue