mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Fix Wallet Loading issues (basic_string & input_stream) (#1059)
* Recover from wallet loading exceptions (basic_string & input_stream) Recover from removed cached wallets * Fix restoring as Monero wallets Fix restoring wallets with invalid files * Add coin control missing changes for macos monero files * Add same key for cached dependencies [skip ci]
This commit is contained in:
parent
fff5a1c419
commit
1cc2c645fa
5 changed files with 279 additions and 32 deletions
2
.github/workflows/cache_dependencies.yml
vendored
2
.github/workflows/cache_dependencies.yml
vendored
|
@ -45,7 +45,7 @@ jobs:
|
||||||
/opt/android/cake_wallet/cw_monero/android/.cxx
|
/opt/android/cake_wallet/cw_monero/android/.cxx
|
||||||
/opt/android/cake_wallet/cw_monero/ios/External
|
/opt/android/cake_wallet/cw_monero/ios/External
|
||||||
/opt/android/cake_wallet/cw_shared_external/ios/External
|
/opt/android/cake_wallet/cw_shared_external/ios/External
|
||||||
key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }}
|
key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh', '**/monero_api.cpp') }}
|
||||||
|
|
||||||
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
|
||||||
name: Generate Externals
|
name: Generate Externals
|
||||||
|
|
|
@ -57,7 +57,7 @@ class MoneroWalletService extends WalletService<
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
||||||
|
|
||||||
static bool walletFilesExist(String path) =>
|
static bool walletFilesExist(String path) =>
|
||||||
!File(path).existsSync() && !File('$path.keys').existsSync();
|
!File(path).existsSync() && !File('$path.keys').existsSync();
|
||||||
|
|
||||||
|
@ -124,13 +124,20 @@ class MoneroWalletService extends WalletService<
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Implement Exception for wallet list service.
|
// TODO: Implement Exception for wallet list service.
|
||||||
|
|
||||||
if ((e.toString().contains('bad_alloc') ||
|
final bool isBadAlloc = e.toString().contains('bad_alloc') ||
|
||||||
(e is WalletOpeningException &&
|
(e is WalletOpeningException &&
|
||||||
(e.message == 'std::bad_alloc' ||
|
(e.message == 'std::bad_alloc' || e.message.contains('bad_alloc')));
|
||||||
e.message.contains('bad_alloc')))) ||
|
|
||||||
(e.toString().contains('does not correspond') ||
|
final bool doesNotCorrespond = e.toString().contains('does not correspond') ||
|
||||||
(e is WalletOpeningException &&
|
(e is WalletOpeningException && e.message.contains('does not correspond'));
|
||||||
e.message.contains('does not correspond')))) {
|
|
||||||
|
final bool isMissingCacheFilesIOS = e.toString().contains('basic_string') ||
|
||||||
|
(e is WalletOpeningException && e.message.contains('basic_string'));
|
||||||
|
|
||||||
|
final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') ||
|
||||||
|
(e is WalletOpeningException && e.message.contains('input_stream'));
|
||||||
|
|
||||||
|
if (isBadAlloc || doesNotCorrespond || isMissingCacheFilesIOS || isMissingCacheFilesAndroid) {
|
||||||
await restoreOrResetWalletFiles(name);
|
await restoreOrResetWalletFiles(name);
|
||||||
return openWallet(name, password);
|
return openWallet(name, password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <list>
|
||||||
#include "thread"
|
#include "thread"
|
||||||
#include "CwWalletListener.h"
|
#include "CwWalletListener.h"
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
|
@ -137,7 +139,7 @@ extern "C"
|
||||||
int8_t direction;
|
int8_t direction;
|
||||||
int8_t isPending;
|
int8_t isPending;
|
||||||
uint32_t subaddrIndex;
|
uint32_t subaddrIndex;
|
||||||
|
|
||||||
char *hash;
|
char *hash;
|
||||||
char *paymentId;
|
char *paymentId;
|
||||||
|
|
||||||
|
@ -152,7 +154,7 @@ extern "C"
|
||||||
std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin();
|
std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin();
|
||||||
subaddrIndex = *it;
|
subaddrIndex = *it;
|
||||||
confirmations = transaction->confirmations();
|
confirmations = transaction->confirmations();
|
||||||
datetime = static_cast<int64_t>(transaction->timestamp());
|
datetime = static_cast<int64_t>(transaction->timestamp());
|
||||||
direction = transaction->direction();
|
direction = transaction->direction();
|
||||||
isPending = static_cast<int8_t>(transaction->isPending());
|
isPending = static_cast<int8_t>(transaction->isPending());
|
||||||
std::string *hash_str = new std::string(transaction->hash());
|
std::string *hash_str = new std::string(transaction->hash());
|
||||||
|
@ -181,6 +183,62 @@ extern "C"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CoinsInfoRow
|
||||||
|
{
|
||||||
|
uint64_t blockHeight;
|
||||||
|
char *hash;
|
||||||
|
uint64_t internalOutputIndex;
|
||||||
|
uint64_t globalOutputIndex;
|
||||||
|
bool spent;
|
||||||
|
bool frozen;
|
||||||
|
uint64_t spentHeight;
|
||||||
|
uint64_t amount;
|
||||||
|
bool rct;
|
||||||
|
bool keyImageKnown;
|
||||||
|
uint64_t pkIndex;
|
||||||
|
uint32_t subaddrIndex;
|
||||||
|
uint32_t subaddrAccount;
|
||||||
|
char *address;
|
||||||
|
char *addressLabel;
|
||||||
|
char *keyImage;
|
||||||
|
uint64_t unlockTime;
|
||||||
|
bool unlocked;
|
||||||
|
char *pubKey;
|
||||||
|
bool coinbase;
|
||||||
|
char *description;
|
||||||
|
|
||||||
|
CoinsInfoRow(Monero::CoinsInfo *coinsInfo)
|
||||||
|
{
|
||||||
|
blockHeight = coinsInfo->blockHeight();
|
||||||
|
std::string *hash_str = new std::string(coinsInfo->hash());
|
||||||
|
hash = strdup(hash_str->c_str());
|
||||||
|
internalOutputIndex = coinsInfo->internalOutputIndex();
|
||||||
|
globalOutputIndex = coinsInfo->globalOutputIndex();
|
||||||
|
spent = coinsInfo->spent();
|
||||||
|
frozen = coinsInfo->frozen();
|
||||||
|
spentHeight = coinsInfo->spentHeight();
|
||||||
|
amount = coinsInfo->amount();
|
||||||
|
rct = coinsInfo->rct();
|
||||||
|
keyImageKnown = coinsInfo->keyImageKnown();
|
||||||
|
pkIndex = coinsInfo->pkIndex();
|
||||||
|
subaddrIndex = coinsInfo->subaddrIndex();
|
||||||
|
subaddrAccount = coinsInfo->subaddrAccount();
|
||||||
|
address = strdup(coinsInfo->address().c_str()) ;
|
||||||
|
addressLabel = strdup(coinsInfo->addressLabel().c_str());
|
||||||
|
keyImage = strdup(coinsInfo->keyImage().c_str());
|
||||||
|
unlockTime = coinsInfo->unlockTime();
|
||||||
|
unlocked = coinsInfo->unlocked();
|
||||||
|
pubKey = strdup(coinsInfo->pubKey().c_str());
|
||||||
|
coinbase = coinsInfo->coinbase();
|
||||||
|
description = strdup(coinsInfo->description().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnlocked(bool unlocked);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Monero::Coins *m_coins;
|
||||||
|
|
||||||
Monero::Wallet *m_wallet;
|
Monero::Wallet *m_wallet;
|
||||||
Monero::TransactionHistory *m_transaction_history;
|
Monero::TransactionHistory *m_transaction_history;
|
||||||
MoneroWalletListener *m_listener;
|
MoneroWalletListener *m_listener;
|
||||||
|
@ -188,6 +246,7 @@ extern "C"
|
||||||
Monero::SubaddressAccount *m_account;
|
Monero::SubaddressAccount *m_account;
|
||||||
uint64_t m_last_known_wallet_height;
|
uint64_t m_last_known_wallet_height;
|
||||||
uint64_t m_cached_syncing_blockchain_height = 0;
|
uint64_t m_cached_syncing_blockchain_height = 0;
|
||||||
|
std::list<Monero::CoinsInfo*> m_coins_info;
|
||||||
std::mutex store_lock;
|
std::mutex store_lock;
|
||||||
bool is_storing = false;
|
bool is_storing = false;
|
||||||
|
|
||||||
|
@ -195,7 +254,7 @@ extern "C"
|
||||||
{
|
{
|
||||||
m_wallet = wallet;
|
m_wallet = wallet;
|
||||||
m_listener = nullptr;
|
m_listener = nullptr;
|
||||||
|
|
||||||
|
|
||||||
if (wallet != nullptr)
|
if (wallet != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -223,6 +282,17 @@ extern "C"
|
||||||
{
|
{
|
||||||
m_subaddress = nullptr;
|
m_subaddress = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_coins_info = std::list<Monero::CoinsInfo*>();
|
||||||
|
|
||||||
|
if (wallet != nullptr)
|
||||||
|
{
|
||||||
|
m_coins = wallet->coins();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_coins = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::Wallet *get_current_wallet()
|
Monero::Wallet *get_current_wallet()
|
||||||
|
@ -405,13 +475,14 @@ extern "C"
|
||||||
return is_connected;
|
return is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error)
|
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error)
|
||||||
{
|
{
|
||||||
nice(19);
|
nice(19);
|
||||||
Monero::Wallet *wallet = get_current_wallet();
|
Monero::Wallet *wallet = get_current_wallet();
|
||||||
|
|
||||||
std::string _login = "";
|
std::string _login = "";
|
||||||
std::string _password = "";
|
std::string _password = "";
|
||||||
|
std::string _socksProxyAddress = "";
|
||||||
|
|
||||||
if (login != nullptr)
|
if (login != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -423,7 +494,12 @@ extern "C"
|
||||||
_password = std::string(password);
|
_password = std::string(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet);
|
if (socksProxyAddress != nullptr)
|
||||||
|
{
|
||||||
|
_socksProxyAddress = std::string(socksProxyAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress);
|
||||||
|
|
||||||
if (!inited)
|
if (!inited)
|
||||||
{
|
{
|
||||||
|
@ -480,10 +556,19 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transaction_create(char *address, char *payment_id, char *amount,
|
bool transaction_create(char *address, char *payment_id, char *amount,
|
||||||
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
uint8_t priority_raw, uint32_t subaddr_account,
|
||||||
|
char **preferred_inputs, uint32_t preferred_inputs_size,
|
||||||
|
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
||||||
{
|
{
|
||||||
nice(19);
|
nice(19);
|
||||||
|
|
||||||
|
std::set<std::string> _preferred_inputs;
|
||||||
|
|
||||||
|
for (int i = 0; i < preferred_inputs_size; i++) {
|
||||||
|
_preferred_inputs.insert(std::string(*preferred_inputs));
|
||||||
|
preferred_inputs++;
|
||||||
|
}
|
||||||
|
|
||||||
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
||||||
std::string _payment_id;
|
std::string _payment_id;
|
||||||
Monero::PendingTransaction *transaction;
|
Monero::PendingTransaction *transaction;
|
||||||
|
@ -496,13 +581,13 @@ extern "C"
|
||||||
if (amount != nullptr)
|
if (amount != nullptr)
|
||||||
{
|
{
|
||||||
uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount));
|
uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount));
|
||||||
transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account);
|
transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account);
|
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = transaction->status();
|
int status = transaction->status();
|
||||||
|
|
||||||
if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
|
if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
|
||||||
|
@ -520,7 +605,9 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size,
|
bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size,
|
||||||
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
uint8_t priority_raw, uint32_t subaddr_account,
|
||||||
|
char **preferred_inputs, uint32_t preferred_inputs_size,
|
||||||
|
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
|
||||||
{
|
{
|
||||||
nice(19);
|
nice(19);
|
||||||
|
|
||||||
|
@ -534,6 +621,13 @@ extern "C"
|
||||||
amounts++;
|
amounts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<std::string> _preferred_inputs;
|
||||||
|
|
||||||
|
for (int i = 0; i < preferred_inputs_size; i++) {
|
||||||
|
_preferred_inputs.insert(std::string(*preferred_inputs));
|
||||||
|
preferred_inputs++;
|
||||||
|
}
|
||||||
|
|
||||||
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
|
||||||
std::string _payment_id;
|
std::string _payment_id;
|
||||||
Monero::PendingTransaction *transaction;
|
Monero::PendingTransaction *transaction;
|
||||||
|
@ -793,6 +887,91 @@ extern "C"
|
||||||
return m_wallet->trustedDaemon();
|
return m_wallet->trustedDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoinsInfoRow* coin(int index)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < m_coins_info.size()) {
|
||||||
|
std::list<Monero::CoinsInfo*>::iterator it = m_coins_info.begin();
|
||||||
|
std::advance(it, index);
|
||||||
|
Monero::CoinsInfo* element = *it;
|
||||||
|
std::cout << "Element at index " << index << ": " << element << std::endl;
|
||||||
|
return new CoinsInfoRow(element);
|
||||||
|
} else {
|
||||||
|
std::cout << "Invalid index." << std::endl;
|
||||||
|
return nullptr; // Return a default value (nullptr) for invalid index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh_coins(uint32_t accountIndex)
|
||||||
|
{
|
||||||
|
m_coins_info.clear();
|
||||||
|
|
||||||
|
m_coins->refresh();
|
||||||
|
for (const auto i : m_coins->getAll()) {
|
||||||
|
if (i->subaddrAccount() == accountIndex && !(i->spent())) {
|
||||||
|
m_coins_info.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t coins_count()
|
||||||
|
{
|
||||||
|
return m_coins_info.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinsInfoRow** coins_from_account(uint32_t accountIndex)
|
||||||
|
{
|
||||||
|
std::vector<CoinsInfoRow*> matchingCoins;
|
||||||
|
|
||||||
|
for (int i = 0; i < coins_count(); i++) {
|
||||||
|
CoinsInfoRow* coinInfo = coin(i);
|
||||||
|
if (coinInfo->subaddrAccount == accountIndex) {
|
||||||
|
matchingCoins.push_back(coinInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()];
|
||||||
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinsInfoRow** coins_from_txid(const char* txid, size_t* count)
|
||||||
|
{
|
||||||
|
std::vector<CoinsInfoRow*> matchingCoins;
|
||||||
|
|
||||||
|
for (int i = 0; i < coins_count(); i++) {
|
||||||
|
CoinsInfoRow* coinInfo = coin(i);
|
||||||
|
if (std::string(coinInfo->hash) == txid) {
|
||||||
|
matchingCoins.push_back(coinInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = matchingCoins.size();
|
||||||
|
CoinsInfoRow** result = new CoinsInfoRow*[*count];
|
||||||
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count)
|
||||||
|
{
|
||||||
|
std::vector<CoinsInfoRow*> matchingCoins;
|
||||||
|
|
||||||
|
for (int i = 0; i < coins_count(); i++) {
|
||||||
|
CoinsInfoRow* coinsInfoRow = coin(i);
|
||||||
|
for (size_t j = 0; j < keyimageCount; j++) {
|
||||||
|
if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) {
|
||||||
|
matchingCoins.push_back(coinsInfoRow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = matchingCoins.size();
|
||||||
|
CoinsInfoRow** result = new CoinsInfoRow*[*count];
|
||||||
|
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import 'dart:io' show File, Platform;
|
import 'dart:io' show Directory, File, Platform;
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
@ -28,7 +27,7 @@ const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002';
|
||||||
const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
|
const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
|
||||||
const ethereumDefaultNodeUri = 'ethereum.publicnode.com';
|
const ethereumDefaultNodeUri = 'ethereum.publicnode.com';
|
||||||
|
|
||||||
Future defaultSettingsMigration(
|
Future<void> defaultSettingsMigration(
|
||||||
{required int version,
|
{required int version,
|
||||||
required SharedPreferences sharedPreferences,
|
required SharedPreferences sharedPreferences,
|
||||||
required FlutterSecureStorage secureStorage,
|
required FlutterSecureStorage secureStorage,
|
||||||
|
@ -43,6 +42,8 @@ Future defaultSettingsMigration(
|
||||||
// check current nodes for nullability regardless of the version
|
// check current nodes for nullability regardless of the version
|
||||||
await checkCurrentNodes(nodes, sharedPreferences);
|
await checkCurrentNodes(nodes, sharedPreferences);
|
||||||
|
|
||||||
|
await _validateWalletInfoBoxData(walletInfoSource);
|
||||||
|
|
||||||
final isNewInstall = sharedPreferences
|
final isNewInstall = sharedPreferences
|
||||||
.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
|
.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
|
||||||
|
|
||||||
|
@ -179,6 +180,66 @@ Future defaultSettingsMigration(
|
||||||
PreferencesKey.currentDefaultSettingsMigrationVersion, version);
|
PreferencesKey.currentDefaultSettingsMigrationVersion, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async {
|
||||||
|
final root = await getApplicationDocumentsDirectory();
|
||||||
|
|
||||||
|
for (var type in WalletType.values) {
|
||||||
|
if (type == WalletType.none) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String prefix = walletTypeToString(type).toLowerCase();
|
||||||
|
Directory walletsDir = Directory('${root.path}/wallets/$prefix/');
|
||||||
|
|
||||||
|
if (!walletsDir.existsSync()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList();
|
||||||
|
|
||||||
|
for (var name in walletNames) {
|
||||||
|
final dir = Directory(await pathForWalletDir(name: name, type: type));
|
||||||
|
|
||||||
|
final walletFiles = dir.listSync();
|
||||||
|
final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name"));
|
||||||
|
|
||||||
|
if (!hasCacheFile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == WalletType.monero || type == WalletType.haven) {
|
||||||
|
final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys"));
|
||||||
|
|
||||||
|
if (!hasKeysFile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final id = prefix + '_' + name;
|
||||||
|
final exist = walletInfoSource.values.any((el) => el.id == id);
|
||||||
|
|
||||||
|
if (exist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final walletInfo = WalletInfo.external(
|
||||||
|
id: id,
|
||||||
|
type: type,
|
||||||
|
name: name,
|
||||||
|
isRecovery: true,
|
||||||
|
restoreHeight: 0,
|
||||||
|
date: DateTime.now(),
|
||||||
|
dirPath: dir.path,
|
||||||
|
path: '${dir.path}/$name',
|
||||||
|
address: '',
|
||||||
|
showIntroCakePayCard: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
walletInfoSource.add(walletInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
|
Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
|
||||||
if (bitcoin == null) {
|
if (bitcoin == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -226,7 +287,7 @@ Future<void> changeMoneroCurrentNodeToDefault(
|
||||||
{required SharedPreferences sharedPreferences,
|
{required SharedPreferences sharedPreferences,
|
||||||
required Box<Node> nodes}) async {
|
required Box<Node> nodes}) async {
|
||||||
final node = getMoneroDefaultNode(nodes: nodes);
|
final node = getMoneroDefaultNode(nodes: nodes);
|
||||||
final nodeId = node?.key as int ?? 0; // 0 - England
|
final nodeId = node.key as int? ?? 0; // 0 - England
|
||||||
|
|
||||||
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, nodeId);
|
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, nodeId);
|
||||||
}
|
}
|
||||||
|
@ -279,7 +340,7 @@ Future<void> changeBitcoinCurrentElectrumServerToDefault(
|
||||||
{required SharedPreferences sharedPreferences,
|
{required SharedPreferences sharedPreferences,
|
||||||
required Box<Node> nodes}) async {
|
required Box<Node> nodes}) async {
|
||||||
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
||||||
final serverId = server?.key as int ?? 0;
|
final serverId = server?.key as int? ?? 0;
|
||||||
|
|
||||||
await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId);
|
await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId);
|
||||||
}
|
}
|
||||||
|
@ -288,7 +349,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault(
|
||||||
{required SharedPreferences sharedPreferences,
|
{required SharedPreferences sharedPreferences,
|
||||||
required Box<Node> nodes}) async {
|
required Box<Node> nodes}) async {
|
||||||
final server = getLitecoinDefaultElectrumServer(nodes: nodes);
|
final server = getLitecoinDefaultElectrumServer(nodes: nodes);
|
||||||
final serverId = server?.key as int ?? 0;
|
final serverId = server?.key as int? ?? 0;
|
||||||
|
|
||||||
await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId);
|
await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId);
|
||||||
}
|
}
|
||||||
|
@ -297,7 +358,7 @@ Future<void> changeHavenCurrentNodeToDefault(
|
||||||
{required SharedPreferences sharedPreferences,
|
{required SharedPreferences sharedPreferences,
|
||||||
required Box<Node> nodes}) async {
|
required Box<Node> nodes}) async {
|
||||||
final node = getHavenDefaultNode(nodes: nodes);
|
final node = getHavenDefaultNode(nodes: nodes);
|
||||||
final nodeId = node?.key as int ?? 0;
|
final nodeId = node?.key as int? ?? 0;
|
||||||
|
|
||||||
await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, nodeId);
|
await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, nodeId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,11 +57,11 @@ DEPENDENCIES:
|
||||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||||
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
||||||
- package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`)
|
- package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`)
|
||||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`)
|
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
|
- platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
|
||||||
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`)
|
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`)
|
||||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
- wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`)
|
- wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`)
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ EXTERNAL SOURCES:
|
||||||
package_info:
|
package_info:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||||
platform_device_id:
|
platform_device_id:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos
|
||||||
platform_device_id_macos:
|
platform_device_id_macos:
|
||||||
|
@ -95,7 +95,7 @@ EXTERNAL SOURCES:
|
||||||
share_plus_macos:
|
share_plus_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
wakelock_macos:
|
wakelock_macos:
|
||||||
|
|
Loading…
Reference in a new issue