Generic fixes (#1823)

* add timeout for mempool fee api and make it only in bitcoin

* disable Monero Ledger for desktop

* handle onramper tag issue

* better handle main actions UI

* make service status scrollable with a better UI

* fix stupid race condition

* minor handling

* update btc fee api
update our xmr node to use ssl

* manually add supported unstoppable domains for now

* change bitcoin default node
code enhancement

* revert debugging code [skip ci]

* minor enhancements [skip ci]

* increase sync indicator size [skip ci]

* fix selecting USA country not triggering the reaction

* fix scrolling on cake features page [skip ci]
This commit is contained in:
Omar Hatem 2024-11-25 18:26:41 +02:00 committed by GitHub
parent 367c36b4d5
commit 59e8550e4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 271 additions and 152 deletions

View file

@ -1,6 +1,3 @@
-
uri: electrum.cakewallet.com:50002
useSSL: true
- -
uri: btc-electrum.cakewallet.com:50002 uri: btc-electrum.cakewallet.com:50002
useSSL: true useSSL: true

View file

@ -2,6 +2,7 @@
uri: xmr-node.cakewallet.com:18081 uri: xmr-node.cakewallet.com:18081
is_default: true is_default: true
trusted: true trusted: true
useSSL: true
- -
uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081 uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081
is_default: false is_default: false

View file

@ -486,10 +486,11 @@ abstract class ElectrumWalletBase
@action @action
Future<void> updateFeeRates() async { Future<void> updateFeeRates() async {
if (await checkIfMempoolAPIIsEnabled()) { if (await checkIfMempoolAPIIsEnabled() && type == WalletType.bitcoin) {
try { try {
final response = final response = await http
await http.get(Uri.parse("http://mempool.cakewallet.com:8999/api/v1/fees/recommended")); .get(Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended"))
.timeout(Duration(seconds: 5));
final result = json.decode(response.body) as Map<String, dynamic>; final result = json.decode(response.body) as Map<String, dynamic>;
final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0; final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0;

View file

@ -286,8 +286,18 @@ Future<void> loadWallet(
/// 0: Software Wallet /// 0: Software Wallet
/// 1: Ledger /// 1: Ledger
/// 2: Trezor /// 2: Trezor
final deviceType = monero.WalletManager_queryWalletDevice(wmPtr, late final deviceType;
keysFileName: "$path.keys", password: password, kdfRounds: 1);
if (Platform.isAndroid || Platform.isIOS) {
deviceType = monero.WalletManager_queryWalletDevice(
wmPtr,
keysFileName: "$path.keys",
password: password,
kdfRounds: 1,
);
} else {
deviceType = 0;
}
if (deviceType == 1) { if (deviceType == 1) {
final dummyWPtr = wptr ?? final dummyWPtr = wptr ??

View file

@ -252,7 +252,11 @@ class OnRamperBuyProvider extends BuyProvider {
case 'POL': case 'POL':
return 'POLYGON'; return 'POLYGON';
default: default:
return CryptoCurrency.fromString(tag).fullName ?? tag; try {
return CryptoCurrency.fromString(tag).fullName!;
} catch (_) {
return tag;
}
} }
} }

View file

@ -260,10 +260,22 @@ Future<void> defaultSettingsMigration(
updateBtcElectrumNodeToUseSSL(nodes, sharedPreferences); updateBtcElectrumNodeToUseSSL(nodes, sharedPreferences);
break; break;
case 43: case 43:
_updateCakeXmrNode(nodes); await _updateCakeXmrNode(nodes);
_deselectExchangeProvider(sharedPreferences, "THORChain"); _deselectExchangeProvider(sharedPreferences, "THORChain");
_deselectExchangeProvider(sharedPreferences, "SimpleSwap"); _deselectExchangeProvider(sharedPreferences, "SimpleSwap");
break; break;
case 44:
await _updateCakeXmrNode(nodes);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.bitcoin,
newDefaultUri: newCakeWalletBitcoinUri,
currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
useSSL: true,
oldUri: 'cakewallet.com',
);
break;
default: default:
break; break;
@ -279,17 +291,54 @@ Future<void> defaultSettingsMigration(
await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
} }
void _updateCakeXmrNode(Box<Node> nodes) { /// generic function for changing any wallet default node
/// instead of making a new function for each change
Future<void> _changeDefaultNode({
required Box<Node> nodes,
required SharedPreferences sharedPreferences,
required WalletType type,
required String newDefaultUri,
required String currentNodePreferenceKey,
required bool useSSL,
required String oldUri, // leave empty if you want to force replace the node regardless of the user's current node
}) async {
final currentNodeId = sharedPreferences.getInt(currentNodePreferenceKey);
final currentNode = nodes.values.firstWhere((node) => node.key == currentNodeId);
final shouldReplace = currentNode.uriRaw.contains(oldUri);
if (shouldReplace) {
var newNodeId =
nodes.values.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.key;
// new node doesn't exist, then add it
if (newNodeId == null) {
final newNode = Node(
uri: newDefaultUri,
type: type,
useSSL: useSSL,
);
await nodes.add(newNode);
newNodeId = newNode.key;
}
await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId as int);
}
}
Future<void> _updateCakeXmrNode(Box<Node> nodes) async {
final node = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletMoneroUri); final node = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletMoneroUri);
if (node != null && !node.trusted) { if (node != null) {
node.trusted = true; node.trusted = true;
node.save(); node.useSSL = true;
await node.save();
} }
} }
void updateBtcElectrumNodeToUseSSL(Box<Node> nodes, SharedPreferences sharedPreferences) { void updateBtcElectrumNodeToUseSSL(Box<Node> nodes, SharedPreferences sharedPreferences) {
final btcElectrumNode = nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletBitcoinUri); final btcElectrumNode =
nodes.values.firstWhereOrNull((element) => element.uriRaw == newCakeWalletBitcoinUri);
if (btcElectrumNode != null) { if (btcElectrumNode != null) {
btcElectrumNode.useSSL = true; btcElectrumNode.useSSL = true;
@ -538,7 +587,6 @@ Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) {
} }
Node getMoneroDefaultNode({required Box<Node> nodes}) { Node getMoneroDefaultNode({required Box<Node> nodes}) {
final timeZone = DateTime.now().timeZoneOffset.inHours;
var nodeUri = newCakeWalletMoneroUri; var nodeUri = newCakeWalletMoneroUri;
try { try {
@ -858,7 +906,8 @@ Future<void> changeDefaultMoneroNode(
} }
}); });
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero, trusted: true); final newCakeWalletNode =
Node(uri: newCakeWalletMoneroUri, type: WalletType.monero, trusted: true);
await nodeSource.add(newCakeWalletNode); await nodeSource.add(newCakeWalletNode);
@ -897,7 +946,7 @@ Future<void> updateBtcNanoWalletInfos(Box<WalletInfo> walletsInfoSource) async {
Future<void> changeDefaultNanoNode( Future<void> changeDefaultNanoNode(
Box<Node> nodeSource, SharedPreferences sharedPreferences) async { Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
const oldNanoNodeUriPattern = 'rpc.nano.to'; const oldNanoNodeUriPattern = 'rpc.nano.to';
final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final currentNanoNode = nodeSource.values.firstWhere((node) => node.key == currentNanoNodeId); final currentNanoNode = nodeSource.values.firstWhere((node) => node.key == currentNanoNodeId);
final newCakeWalletNode = Node( final newCakeWalletNode = Node(
@ -909,7 +958,8 @@ Future<void> changeDefaultNanoNode(
await nodeSource.add(newCakeWalletNode); await nodeSource.add(newCakeWalletNode);
if (currentNanoNode.uri.toString().contains(oldNanoNodeUriPattern)) { if (currentNanoNode.uri.toString().contains(oldNanoNodeUriPattern)) {
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int); await sharedPreferences.setInt(
PreferencesKey.currentNanoNodeIdKey, newCakeWalletNode.key as int);
} }
} }
@ -924,7 +974,7 @@ Future<void> changeDefaultBitcoinNode(
currentBitcoinNode.uri.toString().contains(cakeWalletBitcoinNodeUriPattern); currentBitcoinNode.uri.toString().contains(cakeWalletBitcoinNodeUriPattern);
final newCakeWalletBitcoinNode = final newCakeWalletBitcoinNode =
Node(uri: newCakeWalletBitcoinUri, type: WalletType.bitcoin, useSSL: false); Node(uri: newCakeWalletBitcoinUri, type: WalletType.bitcoin, useSSL: true);
if (!nodeSource.values.any((element) => element.uriRaw == newCakeWalletBitcoinUri)) { if (!nodeSource.values.any((element) => element.uriRaw == newCakeWalletBitcoinUri)) {
await nodeSource.add(newCakeWalletBitcoinNode); await nodeSource.add(newCakeWalletBitcoinNode);

View file

@ -1,7 +1,5 @@
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View file

@ -26,23 +26,80 @@ class AddressResolver {
final SettingsStore settingsStore; final SettingsStore settingsStore;
static const unstoppableDomains = [ static const unstoppableDomains = [
'crypto', "888",
'zil', "altimist",
'x', "anime",
'wallet', "austin",
'bitcoin', "bald",
'888', "benji",
'nft', "bet",
'dao', "binanceus",
'blockchain', "bitcoin",
'polygon', "bitget",
'klever', "blockchain",
'hi', "ca",
'kresus', "chomp",
'anime', "clay",
'manga', "co",
'binanceus', "com",
'xmr', "crypto",
"dao",
"dfz",
"digital",
"dream",
"eth",
"ethermail",
"farms",
"fun",
"go",
"group",
"hi",
"host",
"info",
"io",
"klever",
"kresus",
"kryptic",
"lfg",
"life",
"live",
"ltd",
"manga",
"metropolis",
"moon",
"mumu",
"net",
"nft",
"online",
"org",
"pog",
"polygon",
"press",
"pro",
"propykeys",
"pudgy",
"pw",
"raiin",
"secret",
"site",
"smobler",
"space",
"stepn",
"store",
"tball",
"tech",
"ubu",
"uno",
"unstoppable",
"wallet",
"website",
"wifi",
"witg",
"wrkx",
"x",
"xmr",
"xyz",
"zil",
]; ];
static String? extractAddressByType({required String raw, required CryptoCurrency type}) { static String? extractAddressByType({required String raw, required CryptoCurrency type}) {

View file

@ -16,7 +16,6 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/locales/locale.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/reactions/bootstrap.dart'; import 'package:cake_wallet/reactions/bootstrap.dart';
import 'package:cake_wallet/router.dart' as Router; import 'package:cake_wallet/router.dart' as Router;
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
@ -204,7 +203,7 @@ Future<void> initializeAppConfigs() async {
transactionDescriptions: transactionDescriptions, transactionDescriptions: transactionDescriptions,
secureStorage: secureStorage, secureStorage: secureStorage,
anonpayInvoiceInfo: anonpayInvoiceInfo, anonpayInvoiceInfo: anonpayInvoiceInfo,
initialMigrationVersion: 43, initialMigrationVersion: 44,
); );
} }

View file

@ -63,6 +63,8 @@ void startCurrentWalletChangeReaction(
startWalletSyncStatusChangeReaction(wallet, fiatConversionStore); startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
startCheckConnectionReaction(wallet, settingsStore); startCheckConnectionReaction(wallet, settingsStore);
await Future.delayed(Duration.zero);
if (wallet.type == WalletType.monero || if (wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero || wallet.type == WalletType.wownero ||
wallet.type == WalletType.bitcoin || wallet.type == WalletType.bitcoin ||

View file

@ -291,7 +291,8 @@ class _DashboardPageView extends BasePage {
children: MainActions.all children: MainActions.all
.where((element) => element.canShow?.call(dashboardViewModel) ?? true) .where((element) => element.canShow?.call(dashboardViewModel) ?? true)
.map( .map(
(action) => Semantics( (action) => Expanded(
child: Semantics(
button: true, button: true,
enabled: (action.isEnabled?.call(dashboardViewModel) ?? true), enabled: (action.isEnabled?.call(dashboardViewModel) ?? true),
child: ActionButton( child: ActionButton(
@ -319,6 +320,7 @@ class _DashboardPageView extends BasePage {
.labelTextColor, .labelTextColor,
), ),
), ),
),
) )
.toList(), .toList(),
), ),

View file

@ -10,25 +10,17 @@ import 'package:cake_wallet/view_model/dashboard/cake_features_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_svg/flutter_svg.dart';
class CakeFeaturesPage extends StatelessWidget { class CakeFeaturesPage extends StatelessWidget {
CakeFeaturesPage({required this.dashboardViewModel, required this.cakeFeaturesViewModel}); CakeFeaturesPage({required this.dashboardViewModel, required this.cakeFeaturesViewModel});
final DashboardViewModel dashboardViewModel; final DashboardViewModel dashboardViewModel;
final CakeFeaturesViewModel cakeFeaturesViewModel; final CakeFeaturesViewModel cakeFeaturesViewModel;
final _scrollController = ScrollController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0), padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: RawScrollbar(
thumbColor: Colors.white.withOpacity(0.15),
radius: Radius.circular(20),
thumbVisibility: true,
thickness: 2,
controller: _scrollController,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0), padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column( child: Column(
@ -45,7 +37,6 @@ class CakeFeaturesPage extends StatelessWidget {
), ),
Expanded( Expanded(
child: ListView( child: ListView(
controller: _scrollController,
children: <Widget>[ children: <Widget>[
SizedBox(height: 20), SizedBox(height: 20),
DashBoardRoundedCardWidget( DashBoardRoundedCardWidget(
@ -96,7 +87,6 @@ class CakeFeaturesPage extends StatelessWidget {
], ],
), ),
), ),
),
); );
} }

View file

@ -8,7 +8,7 @@ class SyncIndicatorIcon extends StatelessWidget {
{this.boolMode = true, {this.boolMode = true,
this.isSynced = false, this.isSynced = false,
this.value = waiting, this.value = waiting,
this.size = 4.0}); this.size = 6.0});
final bool boolMode; final bool boolMode;
final bool isSynced; final bool isSynced;

View file

@ -191,6 +191,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
height = wownero!.getHeightByDate(date: date); height = wownero!.getHeightByDate(date: date);
} }
} }
if (mounted) {
setState(() { setState(() {
dateController.text = DateFormat('yyyy-MM-dd').format(date); dateController.text = DateFormat('yyyy-MM-dd').format(date);
restoreHeightController.text = '$height'; restoreHeightController.text = '$height';
@ -198,6 +199,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
}); });
} }
} }
}
void _changeHeight(int height) { void _changeHeight(int height) {
_height = height; _height = height;

View file

@ -92,15 +92,17 @@ class _ServicesUpdatesWidgetState extends State<ServicesUpdatesWidget> {
); );
} }
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 20), padding: const EdgeInsets.symmetric(horizontal: 12),
child: Stack( child: Column(
children: [ children: [
body, Expanded(child: body),
Align( Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 8), horizontal: MediaQuery.of(context).size.width / 8,
vertical: 20,
),
child: PrimaryImageButton( child: PrimaryImageButton(
onPressed: () { onPressed: () {
try { try {

View file

@ -50,8 +50,8 @@ abstract class AppStoreBase with Store {
getIt.get<Web3WalletService>().create(); getIt.get<Web3WalletService>().create();
await getIt.get<Web3WalletService>().init(); await getIt.get<Web3WalletService>().init();
} }
await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name); getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
await getIt getIt
.get<SharedPreferences>() .get<SharedPreferences>()
.setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type)); .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
} }

View file

@ -204,7 +204,11 @@ abstract class CakePayCardsListViewModelBase with Store {
} }
@action @action
void setSelectedCountry(Country country) => settingsStore.selectedCakePayCountry = country; void setSelectedCountry(Country country) {
// just so it triggers the reaction even when selecting the default country
settingsStore.selectedCakePayCountry = null;
settingsStore.selectedCakePayCountry = country;
}
@action @action
void togglePrepaidCards() => displayPrepaidCards = !displayPrepaidCards; void togglePrepaidCards() => displayPrepaidCards = !displayPrepaidCards;

View file

@ -919,7 +919,7 @@
"wallet_seed_legacy": "Graine de portefeuille hérité", "wallet_seed_legacy": "Graine de portefeuille hérité",
"wallet_store_monero_wallet": "Portefeuille (Wallet) Monero", "wallet_store_monero_wallet": "Portefeuille (Wallet) Monero",
"walletConnect": "WalletConnect", "walletConnect": "WalletConnect",
"wallets": "Portefeuilles (Wallets)", "wallets": "Portefeuilles",
"warning": "Avertissement", "warning": "Avertissement",
"welcome": "Bienvenue sur", "welcome": "Bienvenue sur",
"welcome_to_cakepay": "Bienvenue sur Cake Pay !", "welcome_to_cakepay": "Bienvenue sur Cake Pay !",

View file

@ -16,13 +16,13 @@ if [ -n "$1" ]; then
fi fi
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.8.0" MONERO_COM_VERSION="1.8.1"
MONERO_COM_BUILD_NUMBER=36 MONERO_COM_BUILD_NUMBER=37
MONERO_COM_BUNDLE_ID="com.cakewallet.monero" MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.14.0" CAKEWALLET_VERSION="1.14.1"
CAKEWALLET_BUILD_NUMBER=95 CAKEWALLET_BUILD_NUMBER=96
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then