mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-23 03:05:11 +00:00
Add initial create Eth wallet flow
This commit is contained in:
parent
2c7883e099
commit
91ef1fdc7d
8 changed files with 208 additions and 14 deletions
|
@ -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
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
28
cw_ethereum/lib/ethereum_wallet_addresses.dart
Normal file
28
cw_ethereum/lib/ethereum_wallet_addresses.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
39
cw_ethereum/lib/file.dart
Normal 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);
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()}');;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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});
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue