mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
Add Encryption file utils to Ethereum (#1025)
This commit is contained in:
parent
5ce1fbb1e4
commit
cb295333af
8 changed files with 89 additions and 16 deletions
42
cw_ethereum/lib/encryption_file_utils.dart
Normal file
42
cw_ethereum/lib/encryption_file_utils.dart
Normal file
|
@ -0,0 +1,42 @@
|
|||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:cw_ethereum/file.dart' as ef;
|
||||
import 'package:cake_backup/backup.dart' as cwb;
|
||||
|
||||
EncryptionFileUtils encryptionFileUtilsFor(bool direct)
|
||||
=> direct
|
||||
? XChaCha20EncryptionFileUtils()
|
||||
: Salsa20EncryhptionFileUtils();
|
||||
|
||||
abstract class EncryptionFileUtils {
|
||||
Future<void> write({required String path, required String password, required String data});
|
||||
Future<String> read({required String path, required String password});
|
||||
}
|
||||
|
||||
class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
|
||||
// Requires legacy complex key + iv as password
|
||||
@override
|
||||
Future<void> write({required String path, required String password, required String data}) async
|
||||
=> await ef.write(path: path, password: password, data: data);
|
||||
|
||||
// Requires legacy complex key + iv as password
|
||||
@override
|
||||
Future<String> read({required String path, required String password}) async
|
||||
=> await ef.read(path: path, password: password);
|
||||
}
|
||||
|
||||
class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
|
||||
@override
|
||||
Future<void> write({required String path, required String password, required String data}) async {
|
||||
final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
|
||||
await File(path).writeAsBytes(encrypted);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> read({required String path, required String password}) async {
|
||||
final file = File(path);
|
||||
final encrypted = await file.readAsBytes();
|
||||
final bytes = await cwb.decrypt(password, encrypted);
|
||||
return String.fromCharCodes(bytes);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import 'dart:convert';
|
|||
import 'dart:core';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_ethereum/file.dart';
|
||||
import 'package:cw_ethereum/encryption_file_utils.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_info.dart';
|
||||
|
@ -15,12 +15,16 @@ class EthereumTransactionHistory = EthereumTransactionHistoryBase with _$Ethereu
|
|||
|
||||
abstract class EthereumTransactionHistoryBase
|
||||
extends TransactionHistoryBase<EthereumTransactionInfo> with Store {
|
||||
EthereumTransactionHistoryBase({required this.walletInfo, required String password})
|
||||
: _password = password {
|
||||
EthereumTransactionHistoryBase({
|
||||
required this.walletInfo,
|
||||
required String password,
|
||||
required this.encryptionFileUtils,
|
||||
}) : _password = password {
|
||||
transactions = ObservableMap<String, EthereumTransactionInfo>();
|
||||
}
|
||||
|
||||
final WalletInfo walletInfo;
|
||||
final EncryptionFileUtils encryptionFileUtils;
|
||||
String _password;
|
||||
|
||||
Future<void> init() async => await _load();
|
||||
|
@ -31,7 +35,7 @@ abstract class EthereumTransactionHistoryBase
|
|||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||
final path = '$dirPath/$transactionsHistoryFileName';
|
||||
final data = json.encode({'transactions': transactions});
|
||||
await writeData(path: path, password: _password, data: data);
|
||||
await encryptionFileUtils.write(path: path, password: _password, data: data);
|
||||
} catch (e, s) {
|
||||
print('Error while save ethereum transaction history: ${e.toString()}');
|
||||
print(s);
|
||||
|
@ -48,7 +52,7 @@ abstract class EthereumTransactionHistoryBase
|
|||
Future<Map<String, dynamic>> _read() async {
|
||||
final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
|
||||
final path = '$dirPath/$transactionsHistoryFileName';
|
||||
final content = await read(path: path, password: _password);
|
||||
final content = await encryptionFileUtils.read(path: path, password: _password);
|
||||
if (content.isEmpty) {
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ 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/default_erc20_tokens.dart';
|
||||
import 'package:cw_ethereum/encryption_file_utils.dart';
|
||||
import 'package:cw_ethereum/erc20_balance.dart';
|
||||
import 'package:cw_ethereum/ethereum_client.dart';
|
||||
import 'package:cw_ethereum/ethereum_exceptions.dart';
|
||||
|
@ -45,18 +46,24 @@ abstract class EthereumWalletBase
|
|||
required WalletInfo walletInfo,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
required EncryptionFileUtils encryptionFileUtils,
|
||||
ERC20Balance? initialBalance,
|
||||
}) : syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_mnemonic = mnemonic,
|
||||
_isTransactionUpdating = false,
|
||||
_encryptionFileUtils = encryptionFileUtils,
|
||||
_client = EthereumClient(),
|
||||
walletAddresses = EthereumWalletAddresses(walletInfo),
|
||||
balance = ObservableMap<CryptoCurrency, ERC20Balance>.of(
|
||||
{CryptoCurrency.eth: initialBalance ?? ERC20Balance(BigInt.zero)}),
|
||||
super(walletInfo) {
|
||||
this.walletInfo = walletInfo;
|
||||
transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password);
|
||||
transactionHistory = EthereumTransactionHistory(
|
||||
walletInfo: walletInfo,
|
||||
password: password,
|
||||
encryptionFileUtils: encryptionFileUtils,
|
||||
);
|
||||
|
||||
if (!Hive.isAdapterRegistered(Erc20Token.typeId)) {
|
||||
Hive.registerAdapter(Erc20TokenAdapter());
|
||||
|
@ -68,6 +75,8 @@ abstract class EthereumWalletBase
|
|||
final String _mnemonic;
|
||||
final String _password;
|
||||
|
||||
final EncryptionFileUtils _encryptionFileUtils;
|
||||
|
||||
late final Box<Erc20Token> erc20TokensBox;
|
||||
|
||||
late final EthPrivateKey _privateKey;
|
||||
|
@ -282,7 +291,7 @@ abstract class EthereumWalletBase
|
|||
Future<void> save() async {
|
||||
await walletAddresses.updateAddressesInBox();
|
||||
final path = await makePath();
|
||||
await write(path: path, password: _password, data: toJSON());
|
||||
await _encryptionFileUtils.write(path: path, password: _password, data: toJSON());
|
||||
await transactionHistory.save();
|
||||
}
|
||||
|
||||
|
@ -321,9 +330,10 @@ abstract class EthereumWalletBase
|
|||
required String name,
|
||||
required String password,
|
||||
required WalletInfo walletInfo,
|
||||
required EncryptionFileUtils encryptionFileUtils,
|
||||
}) async {
|
||||
final path = await pathForWallet(name: name, type: walletInfo.type);
|
||||
final jsonSource = await read(path: path, password: password);
|
||||
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
|
||||
final data = json.decode(jsonSource) as Map;
|
||||
final mnemonic = data['mnemonic'] as String;
|
||||
final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero);
|
||||
|
@ -333,6 +343,7 @@ abstract class EthereumWalletBase
|
|||
password: password,
|
||||
mnemonic: mnemonic,
|
||||
initialBalance: balance,
|
||||
encryptionFileUtils: encryptionFileUtils,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cw_core/wallet_base.dart';
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_ethereum/encryption_file_utils.dart';
|
||||
import 'package:cw_ethereum/ethereum_mnemonics.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart';
|
||||
|
@ -14,9 +15,10 @@ import 'package:collection/collection.dart';
|
|||
|
||||
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
||||
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
|
||||
EthereumWalletService(this.walletInfoSource);
|
||||
EthereumWalletService(this.walletInfoSource, this.isDirect);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
final bool isDirect;
|
||||
|
||||
@override
|
||||
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
|
||||
|
@ -25,6 +27,7 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
walletInfo: credentials.walletInfo!,
|
||||
mnemonic: mnemonic,
|
||||
password: credentials.password!,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
@ -49,6 +52,7 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
name: name,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
@ -60,8 +64,8 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
@override
|
||||
Future<void> remove(String wallet) async {
|
||||
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
|
||||
final walletInfo = walletInfoSource.values.firstWhereOrNull(
|
||||
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
|
||||
final walletInfo = walletInfoSource.values
|
||||
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
|
||||
await walletInfoSource.delete(walletInfo.key);
|
||||
}
|
||||
|
||||
|
@ -81,6 +85,7 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
password: credentials.password!,
|
||||
mnemonic: credentials.mnemonic,
|
||||
walletInfo: credentials.walletInfo!,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
@ -95,7 +100,11 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
final currentWalletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||
final currentWallet = await EthereumWalletBase.open(
|
||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
||||
password: password,
|
||||
name: currentName,
|
||||
walletInfo: currentWalletInfo,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||
);
|
||||
|
||||
await currentWallet.renameWalletFiles(newName);
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@ dependencies:
|
|||
shared_preferences: ^2.0.15
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
cake_backup:
|
||||
git:
|
||||
url: https://github.com/cake-tech/cake_backup.git
|
||||
ref: main
|
||||
version: 1.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -768,7 +768,9 @@ Future setup({
|
|||
_walletInfoSource, _unspentCoinsInfoSource!,
|
||||
SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumWalletService(_walletInfoSource);
|
||||
return ethereum!.createEthereumWalletService(
|
||||
_walletInfoSource,
|
||||
SettingsStoreBase.walletPasswordDirectInput);
|
||||
default:
|
||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ class CWEthereum extends Ethereum {
|
|||
@override
|
||||
List<String> getEthereumWordList(String language) => EthereumMnemonics.englishWordlist;
|
||||
|
||||
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource) =>
|
||||
EthereumWalletService(walletInfoSource);
|
||||
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
|
||||
EthereumWalletService(walletInfoSource, isDirect);
|
||||
|
||||
@override
|
||||
WalletCredentials createEthereumNewWalletCredentials({
|
||||
|
|
|
@ -507,7 +507,7 @@ import 'package:cw_ethereum/ethereum_transaction_priority.dart';
|
|||
const ethereumContent = """
|
||||
abstract class Ethereum {
|
||||
List<String> getEthereumWordList(String language);
|
||||
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource);
|
||||
WalletService createEthereumWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
|
||||
WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password});
|
||||
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
|
||||
String getAddress(WalletBase wallet);
|
||||
|
|
Loading…
Reference in a new issue