diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index b40aeb7c8..9b3f47314 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -46,6 +46,7 @@
+
diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart
index 7eba43aa7..e10e79f1e 100644
--- a/cw_ethereum/lib/ethereum_client.dart
+++ b/cw_ethereum/lib/ethereum_client.dart
@@ -93,6 +93,7 @@ class EthereumClient {
EthereumAddress.fromHex(toAddress),
BigInt.parse(amount),
credentials: privateKey,
+ transaction: transaction,
);
};
}
@@ -107,7 +108,7 @@ class EthereumClient {
}
Future sendTransaction(Uint8List signedTransaction) async =>
- await _client!.sendRawTransaction(signedTransaction);
+ await _client!.sendRawTransaction(prependTransactionType(0x02, signedTransaction));
Future getTransactionDetails(String transactionHash) async {
// Wait for the transaction receipt to become available
diff --git a/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart
index 5d808be8f..453482e0a 100644
--- a/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart
+++ b/cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart
@@ -1,4 +1,8 @@
class MoneroTransactionNoInputsException implements Exception {
+ MoneroTransactionNoInputsException(this.inputsSize);
+
+ int inputsSize;
+
@override
- String toString() => 'Not enough inputs available. Please select more under Coin Control';
+ String toString() => 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control';
}
diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart
index 69cd5458e..f9b3c1997 100644
--- a/cw_monero/lib/monero_wallet.dart
+++ b/cw_monero/lib/monero_wallet.dart
@@ -210,7 +210,7 @@ abstract class MoneroWalletBase extends WalletBase
acc + (value.formattedCryptoAmount ?? 0));
+ final estimatedFee = calculateEstimatedFee(_credentials.priority, totalAmount);
if (unlockedBalance < totalAmount) {
throw MoneroTransactionCreationException('You do not have enough XMR to send this amount.');
}
+ if (allInputsAmount < totalAmount + estimatedFee) {
+ throw MoneroTransactionNoInputsException(inputs.length);
+ }
+
final moneroOutputs = outputs.map((output) {
final outputAddress = output.isParsedAddress
? output.extractedAddress
@@ -262,6 +267,12 @@ abstract class MoneroWalletBase extends WalletBasecakewallet
+
+ CFBundleTypeRole
+ Editor
+
CFBundleTypeRole
Editor
diff --git a/lib/main.dart b/lib/main.dart
index 62d18708e..40d7468f2 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -114,7 +114,7 @@ Future initializeAppConfigs() async {
CakeHive.registerAdapter(OrderAdapter());
}
- if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
+ if (!CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
CakeHive.registerAdapter(UnspentCoinsInfoAdapter());
}
diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart
index 9303cb053..a08b8a8a7 100644
--- a/lib/src/screens/dashboard/home_settings_page.dart
+++ b/lib/src/screens/dashboard/home_settings_page.dart
@@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.da
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/themes/extensions/address_theme.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
+import 'package:cake_wallet/themes/extensions/picker_theme.dart';
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@@ -55,7 +56,8 @@ class HomeSettingsPage extends BasePage {
padding: const EdgeInsetsDirectional.only(start: 16),
child: TextFormField(
controller: _searchController,
- style: TextStyle(color: Theme.of(context).dialogTheme.backgroundColor),
+ style: TextStyle(
+ color: Theme.of(context).extension()!.searchHintColor),
decoration: InputDecoration(
hintText: S.of(context).search_add_token,
prefixIcon: Image.asset("assets/images/search_icon.png"),
diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart
index 3298a50c0..af775705b 100644
--- a/lib/src/screens/root/root.dart
+++ b/lib/src/screens/root/root.dart
@@ -140,7 +140,7 @@ class RootState extends State with WidgetsBindingObserver {
}
_reset();
totpAuth.close(
- route: launchUri != null ? Routes.send : null,
+ route: _isValidPaymentUri() ? Routes.send : null,
arguments: PaymentRequest.fromUri(launchUri),
);
launchUri = null;
@@ -152,7 +152,7 @@ class RootState extends State with WidgetsBindingObserver {
} else {
_reset();
auth.close(
- route: launchUri != null ? Routes.send : null,
+ route: _isValidPaymentUri() ? Routes.send : null,
arguments: PaymentRequest.fromUri(launchUri),
);
launchUri = null;
@@ -161,7 +161,7 @@ class RootState extends State with WidgetsBindingObserver {
},
);
});
- } else if (launchUri != null) {
+ } else if (_isValidPaymentUri()) {
widget.navigatorKey.currentState?.pushNamed(
Routes.send,
arguments: PaymentRequest.fromUri(launchUri),
@@ -183,4 +183,6 @@ class RootState extends State with WidgetsBindingObserver {
_isInactive = value;
_isInactiveController.add(value);
}
+
+ bool _isValidPaymentUri() => launchUri?.path.isNotEmpty ?? false;
}
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index b24e9b01f..961cf4ba5 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -100,7 +100,7 @@ class SendPage extends BasePage {
AppBarStyle get appBarStyle => AppBarStyle.transparent;
double _sendCardHeight(BuildContext context) {
- final double initialHeight = sendViewModel.hasCoinControl ? 490 : 465;
+ final double initialHeight = sendViewModel.hasCoinControl ? 500 : 465;
if (!ResponsiveLayoutUtil.instance.isMobile) {
return initialHeight - 66;
diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart
index 4b1034f2b..2b96a3053 100644
--- a/lib/src/screens/settings/manage_nodes_page.dart
+++ b/lib/src/screens/settings/manage_nodes_page.dart
@@ -34,13 +34,12 @@ class ManageNodesPage extends BasePage {
SizedBox(height: 20),
Observer(
builder: (BuildContext context) {
+ int itemsCount = nodeListViewModel.nodes.length;
return Flexible(
child: SectionStandardList(
sectionCount: 1,
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
- itemCounter: (int sectionIndex) {
- return nodeListViewModel.nodes.length;
- },
+ itemCounter: (int sectionIndex) => itemsCount,
itemBuilder: (_, index) {
return Observer(
builder: (context) {
diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart
index e8e7702fa..5c51a8757 100644
--- a/lib/utils/exception_handler.dart
+++ b/lib/utils/exception_handler.dart
@@ -32,6 +32,14 @@ class ExceptionHandler {
const String separator = '''\n\n==========================================================
==========================================================\n\n''';
+ /// don't save existing errors
+ if (file.existsSync()) {
+ final String fileContent = await file.readAsString();
+ if (fileContent.contains("${exception.values.first}")) {
+ return;
+ }
+ }
+
file.writeAsStringSync(
"$exception $separator",
mode: FileMode.append,
@@ -83,6 +91,10 @@ class ExceptionHandler {
library: errorDetails.library,
);
+ if (errorDetails.silent) {
+ return;
+ }
+
final sharedPrefs = await SharedPreferences.getInstance();
final lastPopupDate =
diff --git a/lib/view_model/anon_invoice_page_view_model.dart b/lib/view_model/anon_invoice_page_view_model.dart
index b9617e6dd..53e8473a0 100644
--- a/lib/view_model/anon_invoice_page_view_model.dart
+++ b/lib/view_model/anon_invoice_page_view_model.dart
@@ -93,7 +93,11 @@ abstract class AnonInvoicePageViewModelBase with Store {
Future createInvoice() async {
state = IsExecutingState();
if (amount.isNotEmpty) {
- final amountInCrypto = double.parse(amount);
+ final amountInCrypto = double.tryParse(amount);
+ if (amountInCrypto == null) {
+ state = FailureState('Amount is invalid');
+ return;
+ }
if (minimum != null && amountInCrypto < minimum!) {
state = FailureState('Amount is too small');
return;
diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart
index 4ff3cb390..2e90a3a33 100644
--- a/lib/view_model/exchange/exchange_view_model.dart
+++ b/lib/view_model/exchange/exchange_view_model.dart
@@ -225,7 +225,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
@computed
List get walletContactsToShow => contactListViewModel.walletContacts
- .where((element) => receiveCurrency == null || element.type == receiveCurrency)
+ .where((element) => element.type == receiveCurrency)
.toList();
@action
@@ -550,6 +550,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
amount = amount.replaceAll(',', '.');
if (limitsState is LimitsLoadedSuccessfully) {
+ if (double.tryParse(amount) == null) {
+ continue;
+ }
if (limits.max != null && double.parse(amount) < limits.min!) {
continue;
} else if (limits.max != null && double.parse(amount) > limits.max!) {
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index 4655a70b5..da79a5076 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -49,7 +49,7 @@ dependencies:
lottie: ^1.3.0
animate_do: ^2.1.0
cupertino_icons: ^1.0.5
- encrypt: ^5.0.1
+ encrypt: 5.0.1
crypto: ^3.0.2
# password: ^1.0.0
basic_utils: ^5.6.1
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index 627b8d318..ed86b1933 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -5,6 +5,7 @@ APP_ANDROID_VERSION=""
APP_ANDROID_BUILD_VERSION=""
APP_ANDROID_ID=""
APP_ANDROID_PACKAGE=""
+APP_ANDROID_SCHEME=""
MONERO_COM="monero.com"
CAKEWALLET="cakewallet"
@@ -18,12 +19,14 @@ MONERO_COM_VERSION="1.6.0"
MONERO_COM_BUILD_NUMBER=56
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
+MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.9.0"
CAKEWALLET_BUILD_NUMBER=169
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
+CAKEWALLET_SCHEME="cakewallet"
HAVEN_NAME="Haven"
HAVEN_VERSION="1.0.0"
@@ -44,6 +47,7 @@ case $APP_ANDROID_TYPE in
APP_ANDROID_BUILD_NUMBER=$MONERO_COM_BUILD_NUMBER
APP_ANDROID_BUNDLE_ID=$MONERO_COM_BUNDLE_ID
APP_ANDROID_PACKAGE=$MONERO_COM_PACKAGE
+ APP_ANDROID_SCHEME=$MONERO_COM_SCHEME
;;
$CAKEWALLET)
APP_ANDROID_NAME=$CAKEWALLET_NAME
@@ -51,6 +55,7 @@ case $APP_ANDROID_TYPE in
APP_ANDROID_BUILD_NUMBER=$CAKEWALLET_BUILD_NUMBER
APP_ANDROID_BUNDLE_ID=$CAKEWALLET_BUNDLE_ID
APP_ANDROID_PACKAGE=$CAKEWALLET_PACKAGE
+ APP_ANDROID_SCHEME=$CAKEWALLET_SCHEME
;;
$HAVEN)
APP_ANDROID_NAME=$HAVEN_NAME
@@ -66,4 +71,5 @@ export APP_ANDROID_NAME
export APP_ANDROID_VERSION
export APP_ANDROID_BUILD_NUMBER
export APP_ANDROID_BUNDLE_ID
-export APP_ANDROID_PACKAGE
\ No newline at end of file
+export APP_ANDROID_PACKAGE
+export APP_ANDROID_SCHEME
\ No newline at end of file
diff --git a/scripts/android/inject_app_details.sh b/scripts/android/inject_app_details.sh
index 340966044..27b7efa39 100755
--- a/scripts/android/inject_app_details.sh
+++ b/scripts/android/inject_app_details.sh
@@ -8,6 +8,7 @@ fi
cd ../..
sed -i "0,/version:/{s/version:.*/version: ${APP_ANDROID_VERSION}+${APP_ANDROID_BUILD_NUMBER}/}" ./pubspec.yaml
sed -i "0,/version:/{s/__APP_PACKAGE__/${APP_ANDROID_PACKAGE}/}" ./android/app/src/main/AndroidManifest.xml
+sed -i "0,/__APP_SCHEME__/s/__APP_SCHEME__/${APP_ANDROID_SCHEME}/" ./android/app/src/main/AndroidManifest.xml
sed -i "0,/version:/{s/__versionCode__/${APP_ANDROID_BUILD_NUMBER}/}" ./android/app/src/main/AndroidManifest.xml
sed -i "0,/version:/{s/__versionName__/${APP_ANDROID_VERSION}/}" ./android/app/src/main/AndroidManifest.xml
cd scripts/android
diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh
index 470f47efc..82b333d36 100755
--- a/scripts/ios/app_config.sh
+++ b/scripts/ios/app_config.sh
@@ -16,6 +16,11 @@ cp -rf ./ios/Runner/InfoBase.plist ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${APP_IOS_BUNDLE_ID}" ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${APP_IOS_VERSION}" ./ios/Runner/Info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${APP_IOS_BUILD_NUMBER}" ./ios/Runner/Info.plist
+
+/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLName string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
+/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes array" ./ios/Runner/Info.plist
+/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:1:CFBundleURLSchemes: string ${APP_IOS_TYPE}" ./ios/Runner/Info.plist
+
CONFIG_ARGS=""
case $APP_IOS_TYPE in