mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
Merge remote-tracking branch 'origin/main' into electrum-sp-refactors
This commit is contained in:
commit
860d882c41
8 changed files with 130 additions and 339 deletions
|
@ -162,7 +162,8 @@ class $BackupService {
|
||||||
|
|
||||||
final data = json.decode(preferencesFile.readAsStringSync()) as Map<String, dynamic>;
|
final data = json.decode(preferencesFile.readAsStringSync()) as Map<String, dynamic>;
|
||||||
|
|
||||||
try { // shouldn't throw an error but just in case, so it doesn't stop the backup restore
|
try {
|
||||||
|
// shouldn't throw an error but just in case, so it doesn't stop the backup restore
|
||||||
for (var entry in data.entries) {
|
for (var entry in data.entries) {
|
||||||
String key = entry.key;
|
String key = entry.key;
|
||||||
dynamic value = entry.value;
|
dynamic value = entry.value;
|
||||||
|
@ -180,7 +181,8 @@ class $BackupService {
|
||||||
await sharedPreferences.setStringList(key, value);
|
await sharedPreferences.setStringList(key, value);
|
||||||
} else {
|
} else {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
printV('Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
|
printV(
|
||||||
|
'Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,15 +265,23 @@ class $BackupService {
|
||||||
{String keychainSalt = secrets.backupKeychainSalt}) async {
|
{String keychainSalt = secrets.backupKeychainSalt}) async {
|
||||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||||
final wallets = await Future.wait(walletInfoSource.values.map((walletInfo) async {
|
final wallets = await Future.wait(walletInfoSource.values.map((walletInfo) async {
|
||||||
return {
|
try {
|
||||||
'name': walletInfo.name,
|
return {
|
||||||
'type': walletInfo.type.toString(),
|
'name': walletInfo.name,
|
||||||
'password': await keyService.getWalletPassword(walletName: walletInfo.name)
|
'type': walletInfo.type.toString(),
|
||||||
};
|
'password': await keyService.getWalletPassword(walletName: walletInfo.name)
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return {'name': walletInfo.name, 'type': walletInfo.type.toString(), 'password': ''};
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||||
final backupPassword = await _secureStorage.read(key: backupPasswordKey);
|
final backupPassword = await _secureStorage.read(key: backupPasswordKey);
|
||||||
final data = utf8.encode(json.encode({'wallets': wallets, backupPasswordKey: backupPassword}));
|
final data = utf8.encode(json.encode({
|
||||||
|
'wallets': wallets,
|
||||||
|
backupPasswordKey: backupPassword,
|
||||||
|
'_all': await _secureStorage.readAll()
|
||||||
|
}));
|
||||||
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
|
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
|
||||||
|
|
||||||
return encrypted;
|
return encrypted;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||||
import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
|
import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
|
||||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||||
|
import 'package:cake_wallet/haven/cw_haven.dart';
|
||||||
import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
|
import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
|
||||||
import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
|
import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
|
import 'package:cake_wallet/src/screens/settings/background_sync_page.dart';
|
||||||
|
@ -1144,8 +1145,9 @@ Future<void> setup({
|
||||||
return zano!.createZanoWalletService(_walletInfoSource);
|
return zano!.createZanoWalletService(_walletInfoSource);
|
||||||
case WalletType.decred:
|
case WalletType.decred:
|
||||||
return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
return decred!.createDecredWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||||
case WalletType.none:
|
|
||||||
case WalletType.haven:
|
case WalletType.haven:
|
||||||
|
return HavenWalletService(_walletInfoSource);
|
||||||
|
case WalletType.none:
|
||||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,8 +41,8 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
|
||||||
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
|
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
|
||||||
static const sending = TradeState(raw: 'sending', title: 'Sending');
|
static const sending = TradeState(raw: 'sending', title: 'Sending');
|
||||||
static const success = TradeState(raw: 'success', title: 'Success');
|
static const success = TradeState(raw: 'success', title: 'Success');
|
||||||
static TradeState deserialize({required String raw}) {
|
|
||||||
|
|
||||||
|
static TradeState deserialize({required String raw}) {
|
||||||
switch (raw) {
|
switch (raw) {
|
||||||
case '1':
|
case '1':
|
||||||
return unpaid;
|
return unpaid;
|
||||||
|
@ -138,7 +138,7 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
|
||||||
case 'awaiting':
|
case 'awaiting':
|
||||||
return awaiting;
|
return awaiting;
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected token: $raw in TradeState deserialize');
|
return TradeState(raw: raw, title: raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,348 +1,78 @@
|
||||||
part of 'haven.dart';
|
import 'dart:io';
|
||||||
|
|
||||||
class CWHavenAccountList extends HavenAccountList {
|
import 'package:cw_core/balance.dart';
|
||||||
CWHavenAccountList(this._wallet);
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
|
import 'package:cw_core/transaction_history.dart';
|
||||||
|
import 'package:cw_core/transaction_info.dart';
|
||||||
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
import 'package:cw_core/wallet_credentials.dart';
|
||||||
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
import 'package:cw_core/wallet_service.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
final Object _wallet;
|
class HavenWalletService extends WalletService {
|
||||||
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
|
||||||
|
HavenWalletService(this.walletInfoSource);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@computed
|
WalletType getType() => WalletType.haven;
|
||||||
ObservableList<Account> get accounts {
|
|
||||||
final havenWallet = _wallet as HavenWallet;
|
|
||||||
final accounts = havenWallet.walletAddresses.accountList.accounts
|
|
||||||
.map((acc) => Account(id: acc.id, label: acc.label))
|
|
||||||
.toList();
|
|
||||||
return ObservableList<Account>.of(accounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(Object wallet) {
|
Future<void> remove(String wallet) async {
|
||||||
final havenWallet = wallet as HavenWallet;
|
final path = await pathForWalletDir(name: wallet, type: WalletType.haven);
|
||||||
havenWallet.walletAddresses.accountList.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
final file = Directory(path);
|
||||||
void refresh(Object wallet) {
|
final isExist = file.existsSync();
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
havenWallet.walletAddresses.accountList.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
if (isExist) {
|
||||||
List<Account> getAll(Object wallet) {
|
await file.delete(recursive: true);
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
return havenWallet.walletAddresses.accountList
|
|
||||||
.getAll()
|
|
||||||
.map((acc) => Account(id: acc.id, label: acc.label))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> addAccount(Object wallet, {required String label}) async {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
await havenWallet.walletAddresses.accountList.addAccount(label: label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setLabelAccount(Object wallet,
|
|
||||||
{required int accountIndex, required String label}) async {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
await havenWallet.walletAddresses.accountList
|
|
||||||
.setLabelAccount(accountIndex: accountIndex, label: label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CWHavenSubaddressList extends MoneroSubaddressList {
|
|
||||||
CWHavenSubaddressList(this._wallet);
|
|
||||||
|
|
||||||
final Object _wallet;
|
|
||||||
|
|
||||||
@override
|
|
||||||
@computed
|
|
||||||
ObservableList<Subaddress> get subaddresses {
|
|
||||||
final havenWallet = _wallet as HavenWallet;
|
|
||||||
final subAddresses = havenWallet.walletAddresses.subaddressList.subaddresses
|
|
||||||
.map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
|
|
||||||
.toList();
|
|
||||||
return ObservableList<Subaddress>.of(subAddresses);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void update(Object wallet, {required int accountIndex}) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
havenWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void refresh(Object wallet, {required int accountIndex}) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
havenWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Subaddress> getAll(Object wallet) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
return havenWallet.walletAddresses.subaddressList
|
|
||||||
.getAll()
|
|
||||||
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> addSubaddress(Object wallet,
|
|
||||||
{required int accountIndex, required String label}) async {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
await havenWallet.walletAddresses.subaddressList
|
|
||||||
.addSubaddress(accountIndex: accountIndex, label: label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setLabelSubaddress(Object wallet,
|
|
||||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
await havenWallet.walletAddresses.subaddressList
|
|
||||||
.setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CWHavenWalletDetails extends HavenWalletDetails {
|
|
||||||
CWHavenWalletDetails(this._wallet);
|
|
||||||
|
|
||||||
final Object _wallet;
|
|
||||||
|
|
||||||
@computed
|
|
||||||
@override
|
|
||||||
Account get account {
|
|
||||||
final havenWallet = _wallet as HavenWallet;
|
|
||||||
final acc = havenWallet.walletAddresses.account as monero_account.Account;
|
|
||||||
return Account(id: acc.id, label: acc.label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed
|
|
||||||
@override
|
|
||||||
HavenBalance get balance {
|
|
||||||
final havenWallet = _wallet as HavenWallet;
|
|
||||||
final balance = havenWallet.balance;
|
|
||||||
throw Exception('Unimplemented');
|
|
||||||
//return HavenBalance(
|
|
||||||
// fullBalance: balance.fullBalance,
|
|
||||||
// unlockedBalance: balance.unlockedBalance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CWHaven extends Haven {
|
|
||||||
@override
|
|
||||||
HavenAccountList getAccountList(Object wallet) {
|
|
||||||
return CWHavenAccountList(wallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
MoneroSubaddressList getSubaddressList(Object wallet) {
|
|
||||||
return CWHavenSubaddressList(wallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
TransactionHistoryBase getTransactionHistory(Object wallet) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
return havenWallet.transactionHistory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
HavenWalletDetails getMoneroWalletDetails(Object wallet) {
|
|
||||||
return CWHavenWalletDetails(wallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int getHeightByDate({required DateTime date}) => getHavenHeightByDate(date: date);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<int> getCurrentHeight() => getHavenCurrentHeight();
|
|
||||||
|
|
||||||
@override
|
|
||||||
TransactionPriority getDefaultTransactionPriority() {
|
|
||||||
return MoneroTransactionPriority.automatic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
|
|
||||||
return MoneroTransactionPriority.deserialize(raw: raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<TransactionPriority> getTransactionPriorities() {
|
|
||||||
return MoneroTransactionPriority.all;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<String> getMoneroWordList(String language) {
|
|
||||||
switch (language.toLowerCase()) {
|
|
||||||
case 'english':
|
|
||||||
return EnglishMnemonics.words;
|
|
||||||
case 'chinese (simplified)':
|
|
||||||
return ChineseSimplifiedMnemonics.words;
|
|
||||||
case 'dutch':
|
|
||||||
return DutchMnemonics.words;
|
|
||||||
case 'german':
|
|
||||||
return GermanMnemonics.words;
|
|
||||||
case 'japanese':
|
|
||||||
return JapaneseMnemonics.words;
|
|
||||||
case 'portuguese':
|
|
||||||
return PortugueseMnemonics.words;
|
|
||||||
case 'russian':
|
|
||||||
return RussianMnemonics.words;
|
|
||||||
case 'spanish':
|
|
||||||
return SpanishMnemonics.words;
|
|
||||||
case 'french':
|
|
||||||
return FrenchMnemonics.words;
|
|
||||||
case 'italian':
|
|
||||||
return ItalianMnemonics.words;
|
|
||||||
default:
|
|
||||||
return EnglishMnemonics.words;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final walletInfo = walletInfoSource.values
|
||||||
|
.firstWhere((info) => info.id == WalletBase.idFor(wallet, getType()));
|
||||||
|
await walletInfoSource.delete(walletInfo.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletCredentials createHavenRestoreWalletFromKeysCredentials(
|
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(
|
||||||
{required String name,
|
WalletCredentials credentials,
|
||||||
required String spendKey,
|
{bool? isTestnet}) {
|
||||||
required String viewKey,
|
throw UnimplementedError();
|
||||||
required String address,
|
|
||||||
required String password,
|
|
||||||
required String language,
|
|
||||||
required int height}) {
|
|
||||||
return HavenRestoreWalletFromKeysCredentials(
|
|
||||||
name: name,
|
|
||||||
spendKey: spendKey,
|
|
||||||
viewKey: viewKey,
|
|
||||||
address: address,
|
|
||||||
password: password,
|
|
||||||
language: language,
|
|
||||||
height: height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletCredentials createHavenRestoreWalletFromSeedCredentials(
|
Future<bool> isWalletExit(String name) {
|
||||||
{required String name,
|
throw UnimplementedError();
|
||||||
required String password,
|
|
||||||
required int height,
|
|
||||||
required String mnemonic}) {
|
|
||||||
return HavenRestoreWalletFromSeedCredentials(
|
|
||||||
name: name, password: password, height: height, mnemonic: mnemonic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletCredentials createHavenNewWalletCredentials(
|
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> openWallet(
|
||||||
{required String name, required String language, String? password}) {
|
String name, String password) {
|
||||||
return HavenNewWalletCredentials(name: name, password: password, language: language);
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, String> getKeys(Object wallet) {
|
Future<void> rename(String currentName, String password, String newName) {
|
||||||
final havenWallet = wallet as HavenWallet;
|
throw UnimplementedError();
|
||||||
final keys = havenWallet.keys;
|
|
||||||
return <String, String>{
|
|
||||||
'privateSpendKey': keys.privateSpendKey,
|
|
||||||
'privateViewKey': keys.privateViewKey,
|
|
||||||
'publicSpendKey': keys.publicSpendKey,
|
|
||||||
'publicViewKey': keys.publicViewKey
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Object createHavenTransactionCreationCredentials(
|
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
|
||||||
{required List<Output> outputs,
|
restoreFromHardwareWallet(WalletCredentials credentials) {
|
||||||
required TransactionPriority priority,
|
throw UnimplementedError();
|
||||||
required String assetType}) {
|
|
||||||
return HavenTransactionCreationCredentials(
|
|
||||||
outputs: outputs
|
|
||||||
.map((out) => OutputInfo(
|
|
||||||
fiatAmount: out.fiatAmount,
|
|
||||||
cryptoAmount: out.cryptoAmount,
|
|
||||||
address: out.address,
|
|
||||||
note: out.note,
|
|
||||||
sendAll: out.sendAll,
|
|
||||||
extractedAddress: out.extractedAddress,
|
|
||||||
isParsedAddress: out.isParsedAddress,
|
|
||||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
|
||||||
.toList(),
|
|
||||||
priority: priority as MoneroTransactionPriority,
|
|
||||||
assetType: assetType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String formatterMoneroAmountToString({required int amount}) {
|
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
|
||||||
return moneroAmountToString(amount: amount);
|
restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) {
|
||||||
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double formatterMoneroAmountToDouble({required int amount}) {
|
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
|
||||||
return moneroAmountToDouble(amount: amount);
|
restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) {
|
||||||
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
int formatterMoneroParseAmount({required String amount}) {
|
|
||||||
return moneroParseAmount(amount: amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Account getCurrentAccount(Object wallet) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
final acc = havenWallet.walletAddresses.account as monero_account.Account;
|
|
||||||
return Account(id: acc.id, label: acc.label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void setCurrentAccount(Object wallet, int id, String label) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
havenWallet.walletAddresses.account = monero_account.Account(id: id, label: label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onStartup() {
|
|
||||||
monero_wallet_api.onStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int getTransactionInfoAccountId(TransactionInfo tx) {
|
|
||||||
final havenTransactionInfo = tx as HavenTransactionInfo;
|
|
||||||
return havenTransactionInfo.accountIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> backupHavenSeeds(Box<HavenSeedStore> havenSeedStore) async {
|
|
||||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
|
||||||
final wallets = walletInfoSource.values
|
|
||||||
.where((element) => element.type == WalletType.haven);
|
|
||||||
for (var w in wallets) {
|
|
||||||
final walletService = HavenWalletService(walletInfoSource);
|
|
||||||
final flutterSecureStorage = secureStorageShared;
|
|
||||||
final keyService = KeyService(flutterSecureStorage);
|
|
||||||
final password = await keyService.getWalletPassword(walletName: w.name);
|
|
||||||
final wallet = await walletService.openWallet(w.name, password);
|
|
||||||
await havenSeedStore.add(HavenSeedStore(id: wallet.id, seed: wallet.seed));
|
|
||||||
wallet.close();
|
|
||||||
}
|
|
||||||
await havenSeedStore.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
WalletService createHavenWalletService(Box<WalletInfo> walletInfoSource) {
|
|
||||||
return HavenWalletService(walletInfoSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
|
|
||||||
final havenWallet = wallet as HavenWallet;
|
|
||||||
return havenWallet.getTransactionAddress(accountIndex, addressIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
CryptoCurrency assetOfTransaction(TransactionInfo tx) {
|
|
||||||
final transaction = tx as HavenTransactionInfo;
|
|
||||||
final asset = CryptoCurrency.fromString(transaction.assetType);
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<AssetRate> getAssetRate() =>
|
|
||||||
getRate().map((rate) => AssetRate(rate.getAssetType(), rate.getRate())).toList();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,11 +490,19 @@ class BuySellPage extends BasePage {
|
||||||
return DesktopExchangeCardsSection(
|
return DesktopExchangeCardsSection(
|
||||||
firstExchangeCard: fiatExchangeCard,
|
firstExchangeCard: fiatExchangeCard,
|
||||||
secondExchangeCard: cryptoExchangeCard,
|
secondExchangeCard: cryptoExchangeCard,
|
||||||
|
onBuyTap: () => null,
|
||||||
|
onSellTap: () =>
|
||||||
|
buySellViewModel.isBuyAction ? buySellViewModel.changeBuySellAction() : null,
|
||||||
|
isBuySellOption: true,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return DesktopExchangeCardsSection(
|
return DesktopExchangeCardsSection(
|
||||||
firstExchangeCard: cryptoExchangeCard,
|
firstExchangeCard: cryptoExchangeCard,
|
||||||
secondExchangeCard: fiatExchangeCard,
|
secondExchangeCard: fiatExchangeCard,
|
||||||
|
onBuyTap: () =>
|
||||||
|
!buySellViewModel.isBuyAction ? buySellViewModel.changeBuySellAction() : null,
|
||||||
|
onSellTap: () => null,
|
||||||
|
isBuySellOption: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
|
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DesktopExchangeCardsSection extends StatelessWidget {
|
class DesktopExchangeCardsSection extends StatelessWidget {
|
||||||
final Widget firstExchangeCard;
|
|
||||||
final Widget secondExchangeCard;
|
|
||||||
|
|
||||||
const DesktopExchangeCardsSection({
|
const DesktopExchangeCardsSection({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.firstExchangeCard,
|
required this.firstExchangeCard,
|
||||||
required this.secondExchangeCard,
|
required this.secondExchangeCard,
|
||||||
|
this.isBuySellOption = false,
|
||||||
|
this.onBuyTap,
|
||||||
|
this.onSellTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final Widget firstExchangeCard;
|
||||||
|
final Widget secondExchangeCard;
|
||||||
|
final bool isBuySellOption;
|
||||||
|
final VoidCallback? onBuyTap;
|
||||||
|
final VoidCallback? onSellTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FocusTraversalGroup(
|
return FocusTraversalGroup(
|
||||||
|
@ -18,7 +25,18 @@ class DesktopExchangeCardsSection extends StatelessWidget {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 55, left: 24, right: 24),
|
padding: EdgeInsets.only(top: 55, left: 24, right: 24),
|
||||||
child: firstExchangeCard,
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (isBuySellOption)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
BuySellOptionButtons(onBuyTap: onBuyTap, onSellTap: onSellTap),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
firstExchangeCard,
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
||||||
|
|
|
@ -38,6 +38,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
static const fourPinLength = 4;
|
static const fourPinLength = 4;
|
||||||
final _gridViewKey = GlobalKey();
|
final _gridViewKey = GlobalKey();
|
||||||
final _key = GlobalKey<ScaffoldState>();
|
final _key = GlobalKey<ScaffoldState>();
|
||||||
|
late final FocusNode _focusNode;
|
||||||
|
|
||||||
int pinLength;
|
int pinLength;
|
||||||
String pin;
|
String pin;
|
||||||
|
@ -54,7 +55,17 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
pin = '';
|
pin = '';
|
||||||
title = S.current.enter_your_pin;
|
title = S.current.enter_your_pin;
|
||||||
_aspectRatio = 0;
|
_aspectRatio = 0;
|
||||||
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
|
_focusNode = FocusNode();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_focusNode.requestFocus();
|
||||||
|
_afterLayout(_);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_focusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTitle(String title) => setState(() => this.title = title);
|
void setTitle(String title) => setState(() => this.title = title);
|
||||||
|
@ -120,8 +131,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
);
|
);
|
||||||
|
|
||||||
return KeyboardListener(
|
return KeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: _focusNode,
|
||||||
autofocus: true,
|
autofocus: false,
|
||||||
onKeyEvent: (keyEvent) {
|
onKeyEvent: (keyEvent) {
|
||||||
if (keyEvent is KeyDownEvent) {
|
if (keyEvent is KeyDownEvent) {
|
||||||
if (keyEvent.logicalKey.keyLabel == "Backspace") {
|
if (keyEvent.logicalKey.keyLabel == "Backspace") {
|
||||||
|
@ -144,8 +155,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color:
|
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
||||||
Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
|
||||||
Spacer(flex: 8),
|
Spacer(flex: 8),
|
||||||
Container(
|
Container(
|
||||||
width: 180,
|
width: 180,
|
||||||
|
@ -162,7 +172,9 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: isFilled
|
color: isFilled
|
||||||
? Theme.of(context).extension<CakeTextTheme>()!.titleColor
|
? Theme.of(context).extension<CakeTextTheme>()!.titleColor
|
||||||
: Theme.of(context).extension<PinCodeTheme>()!.indicatorsColor
|
: Theme.of(context)
|
||||||
|
.extension<PinCodeTheme>()!
|
||||||
|
.indicatorsColor
|
||||||
.withOpacity(0.25),
|
.withOpacity(0.25),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
|
@ -225,7 +237,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => _pop(),
|
onPressed: () => _pop(),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.background,
|
||||||
shape: CircleBorder(),
|
shape: CircleBorder(),
|
||||||
),
|
),
|
||||||
child: deleteIconImage,
|
child: deleteIconImage,
|
||||||
|
@ -250,7 +263,9 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 25.0,
|
fontSize: 25.0,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)),
|
color: Theme.of(context)
|
||||||
|
.extension<CakeTextTheme>()!
|
||||||
|
.titleColor)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1680,6 +1680,7 @@ abstract class SecureStorage {
|
||||||
Future<void> delete({required String key});
|
Future<void> delete({required String key});
|
||||||
// Legacy
|
// Legacy
|
||||||
Future<String?> readNoIOptions({required String key});
|
Future<String?> readNoIOptions({required String key});
|
||||||
|
Future<Map<String, String>> readAll();
|
||||||
}""";
|
}""";
|
||||||
const defaultSecureStorage = """
|
const defaultSecureStorage = """
|
||||||
class DefaultSecureStorage extends SecureStorage {
|
class DefaultSecureStorage extends SecureStorage {
|
||||||
|
@ -1718,6 +1719,11 @@ class DefaultSecureStorage extends SecureStorage {
|
||||||
iOptions: useNoIOptions ? IOSOptions() : null,
|
iOptions: useNoIOptions ? IOSOptions() : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Map<String, String>> readAll() async {
|
||||||
|
return await _secureStorage.readAll();
|
||||||
|
}
|
||||||
}""";
|
}""";
|
||||||
const fakeSecureStorage = """
|
const fakeSecureStorage = """
|
||||||
class FakeSecureStorage extends SecureStorage {
|
class FakeSecureStorage extends SecureStorage {
|
||||||
|
@ -1729,6 +1735,8 @@ class FakeSecureStorage extends SecureStorage {
|
||||||
Future<void> delete({required String key}) async {}
|
Future<void> delete({required String key}) async {}
|
||||||
@override
|
@override
|
||||||
Future<String?> readNoIOptions({required String key}) async => null;
|
Future<String?> readNoIOptions({required String key}) async => null;
|
||||||
|
@override
|
||||||
|
Future<Map<String, String>> readAll() async => {};
|
||||||
}""";
|
}""";
|
||||||
final outputFile = File(secureStoragePath);
|
final outputFile = File(secureStoragePath);
|
||||||
final header = hasFlutterSecureStorage
|
final header = hasFlutterSecureStorage
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue