mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Generic fixes (#1154)
* Fix White screen issue Bypass node certificate issue * check on Fiat currency only with fiat templates * Add possible missing cache file android error * Dispose exchange state reaction when page is closed * Fix minor chinese translation * Temp remove BCH from robinhood * Minor fixes
This commit is contained in:
parent
ca6ccf1cf9
commit
37c2ee9e9e
10 changed files with 98 additions and 77 deletions
|
@ -162,6 +162,9 @@ class Node extends HiveObject with Keyable {
|
||||||
try {
|
try {
|
||||||
final authenticatingClient = HttpClient();
|
final authenticatingClient = HttpClient();
|
||||||
|
|
||||||
|
authenticatingClient.badCertificateCallback =
|
||||||
|
((X509Certificate cert, String host, int port) => true);
|
||||||
|
|
||||||
authenticatingClient.addCredentials(
|
authenticatingClient.addCredentials(
|
||||||
rpcUri,
|
rpcUri,
|
||||||
realm,
|
realm,
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
@ -135,9 +135,18 @@ class MoneroWalletService extends WalletService<
|
||||||
(e is WalletOpeningException && e.message.contains('basic_string'));
|
(e is WalletOpeningException && e.message.contains('basic_string'));
|
||||||
|
|
||||||
final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') ||
|
final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') ||
|
||||||
(e is WalletOpeningException && e.message.contains('input_stream'));
|
e.toString().contains('input stream error') ||
|
||||||
|
(e is WalletOpeningException &&
|
||||||
|
(e.message.contains('input_stream') || e.message.contains('input stream error')));
|
||||||
|
|
||||||
if (isBadAlloc || doesNotCorrespond || isMissingCacheFilesIOS || isMissingCacheFilesAndroid) {
|
final bool invalidSignature = e.toString().contains('invalid signature') ||
|
||||||
|
(e is WalletOpeningException && e.message.contains('invalid signature'));
|
||||||
|
|
||||||
|
if (isBadAlloc ||
|
||||||
|
doesNotCorrespond ||
|
||||||
|
isMissingCacheFilesIOS ||
|
||||||
|
isMissingCacheFilesAndroid ||
|
||||||
|
invalidSignature) {
|
||||||
await restoreOrResetWalletFiles(name);
|
await restoreOrResetWalletFiles(name);
|
||||||
return openWallet(name, password);
|
return openWallet(name, password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,7 +283,7 @@ SPEC CHECKSUMS:
|
||||||
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
|
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
|
||||||
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
||||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||||
fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c
|
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
|
||||||
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
||||||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||||
|
@ -302,7 +302,7 @@ SPEC CHECKSUMS:
|
||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86
|
||||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class RobinhoodBuyProvider {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
||||||
default:
|
default:
|
||||||
throw Exception("WalletType is not available for Robinhood");
|
throw Exception("WalletType is not available for Robinhood ${_wallet.type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,63 +191,70 @@ Future<void> defaultSettingsMigration(
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async {
|
Future<void> _validateWalletInfoBoxData(Box<WalletInfo> walletInfoSource) async {
|
||||||
final root = await getApplicationDocumentsDirectory();
|
try {
|
||||||
|
final root = await getApplicationDocumentsDirectory();
|
||||||
|
|
||||||
for (var type in WalletType.values) {
|
for (var type in WalletType.values) {
|
||||||
if (type == WalletType.none) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == WalletType.monero || type == WalletType.haven) {
|
String prefix = walletTypeToString(type).toLowerCase();
|
||||||
final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys"));
|
Directory walletsDir = Directory('${root.path}/wallets/$prefix/');
|
||||||
|
|
||||||
if (!hasKeysFile) {
|
if (!walletsDir.existsSync()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList();
|
||||||
|
|
||||||
|
for (var name in walletNames) {
|
||||||
|
final Directory dir;
|
||||||
|
try {
|
||||||
|
dir = Directory(await pathForWalletDir(name: name, type: type));
|
||||||
|
} catch (_) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
|
Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class MainActions {
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
case WalletType.bitcoinCash:
|
// case WalletType.bitcoinCash: // TODO: add sign message function to BCH first
|
||||||
switch (defaultBuyProvider) {
|
switch (defaultBuyProvider) {
|
||||||
case BuyProviderType.AskEachTime:
|
case BuyProviderType.AskEachTime:
|
||||||
Navigator.pushNamed(context, Routes.buy);
|
Navigator.pushNamed(context, Routes.buy);
|
||||||
|
|
|
@ -91,6 +91,8 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
||||||
|
|
||||||
bool _effectsInstalled = false;
|
bool _effectsInstalled = false;
|
||||||
|
|
||||||
|
ReactionDisposer? _exchangeStateReaction;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -103,8 +105,9 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
|
||||||
widget.exchangeTradeViewModel.timer?.cancel();
|
widget.exchangeTradeViewModel.timer?.cancel();
|
||||||
|
_exchangeStateReaction?.reaction.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -229,7 +232,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reaction((_) => this.widget.exchangeTradeViewModel.sendViewModel.state,
|
_exchangeStateReaction = reaction((_) => this.widget.exchangeTradeViewModel.sendViewModel.state,
|
||||||
(ExecutionState state) {
|
(ExecutionState state) {
|
||||||
if (state is FailureState) {
|
if (state is FailureState) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
|
|
@ -13,8 +13,7 @@ import 'package:cake_wallet/store/authentication_store.dart';
|
||||||
import 'package:cake_wallet/entities/qr_scanner.dart';
|
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:uni_links/uni_links.dart';
|
import 'package:uni_links/uni_links.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
||||||
import '../setup_2fa/setup_2fa_enter_code_page.dart';
|
|
||||||
|
|
||||||
class Root extends StatefulWidget {
|
class Root extends StatefulWidget {
|
||||||
Root({
|
Root({
|
||||||
|
|
|
@ -413,39 +413,39 @@ class SendPage extends BasePage {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showPopUp<void>(
|
showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext _dialogContext) {
|
||||||
return ConfirmSendingAlert(
|
return ConfirmSendingAlert(
|
||||||
alertTitle: S.of(context).confirm_sending,
|
alertTitle: S.of(_dialogContext).confirm_sending,
|
||||||
amount: S.of(context).send_amount,
|
amount: S.of(_dialogContext).send_amount,
|
||||||
amountValue: sendViewModel.pendingTransaction!.amountFormatted,
|
amountValue: sendViewModel.pendingTransaction!.amountFormatted,
|
||||||
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
|
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
|
||||||
fee: S.of(context).send_fee,
|
fee: S.of(_dialogContext).send_fee,
|
||||||
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
|
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
|
||||||
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
|
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
|
||||||
outputs: sendViewModel.outputs,
|
outputs: sendViewModel.outputs,
|
||||||
rightButtonText: S.of(context).ok,
|
rightButtonText: S.of(_dialogContext).ok,
|
||||||
leftButtonText: S.of(context).cancel,
|
leftButtonText: S.of(_dialogContext).cancel,
|
||||||
actionRightButton: () {
|
actionRightButton: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(_dialogContext).pop();
|
||||||
sendViewModel.commitTransaction();
|
sendViewModel.commitTransaction();
|
||||||
showPopUp<void>(
|
showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext _dialogContext) {
|
||||||
return Observer(builder: (_) {
|
return Observer(builder: (_) {
|
||||||
final state = sendViewModel.state;
|
final state = sendViewModel.state;
|
||||||
|
|
||||||
if (state is FailureState) {
|
if (state is FailureState) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(_dialogContext).pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is TransactionCommitted) {
|
if (state is TransactionCommitted) {
|
||||||
return AlertWithOneAction(
|
return AlertWithOneAction(
|
||||||
alertTitle: '',
|
alertTitle: '',
|
||||||
alertContent: S.of(context).send_success(
|
alertContent: S.of(_dialogContext).send_success(
|
||||||
sendViewModel.selectedCryptoCurrency.toString()),
|
sendViewModel.selectedCryptoCurrency.toString()),
|
||||||
buttonText: S.of(context).ok,
|
buttonText: S.of(_dialogContext).ok,
|
||||||
buttonAction: () {
|
buttonAction: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(_dialogContext).pop();
|
||||||
RequestReviewHandler.requestReview();
|
RequestReviewHandler.requestReview();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -454,7 +454,7 @@ class SendPage extends BasePage {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
actionLeftButton: () => Navigator.of(context).pop());
|
actionLeftButton: () => Navigator.of(_dialogContext).pop());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -472,15 +472,15 @@ class SendPage extends BasePage {
|
||||||
|
|
||||||
Future<void> _setInputsFromTemplate(BuildContext context,
|
Future<void> _setInputsFromTemplate(BuildContext context,
|
||||||
{required Output output, required Template template}) async {
|
{required Output output, required Template template}) async {
|
||||||
final fiatFromTemplate =
|
|
||||||
FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency);
|
|
||||||
|
|
||||||
output.address = template.address;
|
output.address = template.address;
|
||||||
|
|
||||||
if (template.isCurrencySelected) {
|
if (template.isCurrencySelected) {
|
||||||
sendViewModel.setSelectedCryptoCurrency(template.cryptoCurrency);
|
sendViewModel.setSelectedCryptoCurrency(template.cryptoCurrency);
|
||||||
output.setCryptoAmount(template.amount);
|
output.setCryptoAmount(template.amount);
|
||||||
} else {
|
} else {
|
||||||
|
final fiatFromTemplate =
|
||||||
|
FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency);
|
||||||
|
|
||||||
sendViewModel.setFiatCurrency(fiatFromTemplate);
|
sendViewModel.setFiatCurrency(fiatFromTemplate);
|
||||||
output.setFiatAmount(template.amountFiat);
|
output.setFiatAmount(template.amountFiat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,8 @@
|
||||||
"powered_by": "Powered by ${title}",
|
"powered_by": "Powered by ${title}",
|
||||||
"error": "错误",
|
"error": "错误",
|
||||||
"estimated": "估计值",
|
"estimated": "估计值",
|
||||||
"min_value": "最低: ${value} ${currency}",
|
"min_value": "最小: ${value} ${currency}",
|
||||||
"max_value": "最高: ${value} ${currency}",
|
"max_value": "最大: ${value} ${currency}",
|
||||||
"change_currency": "更改币种",
|
"change_currency": "更改币种",
|
||||||
"overwrite_amount": "Overwrite amount",
|
"overwrite_amount": "Overwrite amount",
|
||||||
"qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?",
|
"qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?",
|
||||||
|
|
Loading…
Reference in a new issue