Fixes for backups for Android. Fixes for send almost all amount.
M committed
Jan 29, 2021 at 22:18 UTC
2ce34919bfb18443c30db1baae285e4f3c4b7278
10 files changed
+60
-21
android/app/build.gradle
+1
-1
@@ -31,7 +31,7 @@ if (keystorePropertiesFile.exists()) {
31
}
32
33
android {
34
- compileSdkVersion 28
34
+ compileSdkVersion 29
35
36
lintOptions {
37
disable 'InvalidPackage'
android/app/src/main/AndroidManifest.xml
+3
-1
@@ -4,12 +4,14 @@
4
<uses-permission android:name="android.permission.INTERNET"/>
5
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
6
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7
+ <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
8
9
<application
10
android:label="Cake Wallet"
11
android:allowBackup="false"
12
android:fullBackupContent="false"
12
- android:icon="@mipmap/ic_launcher">
13
+ android:icon="@mipmap/ic_launcher"
14
+ android:requestLegacyExternalStorage="true">
15
<activity
16
android:name=".MainActivity"
17
android:launchMode="singleTop"
ios/Podfile.lock
+6
@@ -72,6 +72,8 @@ PODS:
72
- Flutter
73
- path_provider (0.0.1):
74
- Flutter
75
+ - "permission_handler (5.0.1+1)":
76
+ - Flutter
77
- Reachability (3.2)
78
- SDWebImage (5.9.1):
79
- SDWebImage/Core (= 5.9.1)
@@ -98,6 +100,7 @@ DEPENDENCIES:
100
- local_auth (from `.symlinks/plugins/local_auth/ios`)
101
- package_info (from `.symlinks/plugins/package_info/ios`)
102
- path_provider (from `.symlinks/plugins/path_provider/ios`)
103
+ - permission_handler (from `.symlinks/plugins/permission_handler/ios`)
104
- share (from `.symlinks/plugins/share/ios`)
105
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
106
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
@@ -136,6 +139,8 @@ EXTERNAL SOURCES:
139
:path: ".symlinks/plugins/package_info/ios"
140
path_provider:
141
:path: ".symlinks/plugins/path_provider/ios"
142
+ permission_handler:
143
+ :path: ".symlinks/plugins/permission_handler/ios"
144
share:
145
:path: ".symlinks/plugins/share/ios"
146
shared_preferences:
@@ -159,6 +164,7 @@ SPEC CHECKSUMS:
164
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
165
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
166
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
167
+ permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6
168
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
169
SDWebImage: a990c053fff71e388a10f3357edb0be17929c9c5
170
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
lib/bitcoin/bitcoin_wallet.dart
+14
-7
@@ -261,14 +261,20 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
261
@override
262
Future<PendingBitcoinTransaction> createTransaction(
263
Object credentials) async {
264
+ const minAmount = 546;
265
final transactionCredentials = credentials as BitcoinTransactionCredentials;
266
final inputs = <BitcoinUnspent>[];
267
final allAmountFee =
268
calculateEstimatedFee(transactionCredentials.priority, null);
269
+ final allAmount = balance.confirmed - allAmountFee;
270
var fee = 0;
269
- final amount = transactionCredentials.amount != null
271
+ final credentialsAmount = transactionCredentials.amount != null
272
? stringDoubleToBitcoinAmount(transactionCredentials.amount)
271
- : balance.confirmed - allAmountFee;
273
+ : 0;
274
+ final amount = transactionCredentials.amount == null ||
275
+ allAmount - credentialsAmount < minAmount
276
+ ? allAmount
277
+ : credentialsAmount;
278
final txb = bitcoin.TransactionBuilder(network: bitcoin.bitcoin);
279
final changeAddress = address;
280
var leftAmount = amount;
@@ -294,8 +300,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
300
301
final totalAmount = amount + fee;
302
fee = transactionCredentials.amount != null
297
- ? feeAmountForPriority(
298
- transactionCredentials.priority, inputs.length, 2)
303
+ ? feeAmountForPriority(transactionCredentials.priority, inputs.length,
304
+ amount == allAmount ? 1 : 2)
305
: allAmountFee;
306
307
if (totalAmount > balance.confirmed) {
@@ -329,7 +335,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
335
final feeAmount = transactionCredentials.priority.rate * estimatedSize;
336
final changeValue = totalInputAmount - amount - feeAmount;
337
332
- if (changeValue > 0) {
338
+ if (changeValue > minAmount) {
339
txb.addOutput(changeAddress, changeValue);
340
}
341
@@ -375,8 +381,9 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
381
} else {
382
inputsCount = _unspent.length;
383
}
378
-
379
- return feeAmountForPriority(priority, inputsCount, 2);
384
+ // If send all, then we have no change value
385
+ return feeAmountForPriority(
386
+ priority, inputsCount, amount != null ? 2 : 1);
387
}
388
389
return 0;
lib/src/screens/backup/backup_page.dart
+9
-3
@@ -14,6 +14,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
14
import 'package:cake_wallet/view_model/backup_view_model.dart';
15
import 'package:cake_wallet/core/execution_state.dart';
16
import 'package:cake_wallet/src/screens/base_page.dart';
17
+import 'package:permission_handler/permission_handler.dart';
18
19
class BackupPage extends BasePage {
20
BackupPage(this.backupViewModelBase);
@@ -99,8 +100,6 @@ class BackupPage extends BasePage {
100
actionRightButton: () async {
101
Navigator.of(dialogContext).pop();
102
final backup = await backupViewModelBase.exportBackup();
102
- await backupViewModelBase.saveToDownload(
103
- backup.name, backup.content);
103
104
if (Platform.isAndroid) {
105
onExportAndroid(context, backup);
@@ -123,9 +122,16 @@ class BackupPage extends BasePage {
122
rightButtonText: 'Save to Downloads',
123
leftButtonText: 'Share',
124
actionRightButton: () async {
126
- Navigator.of(dialogContext).pop();
125
+ final permission = await Permission.storage.request();
126
+
127
+ if (permission.isDenied) {
128
+ Navigator.of(dialogContext).pop();
129
+ return;
130
+ }
131
+
132
await backupViewModelBase.saveToDownload(
133
backup.name, backup.content);
134
+ Navigator.of(dialogContext).pop();
135
},
136
actionLeftButton: () {
137
Navigator.of(dialogContext).pop();
lib/src/screens/exchange_trade/exchange_trade_page.dart
+6
-6
@@ -255,11 +255,11 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
255
.pendingTransaction.feeFormatted,
256
rightButtonText: S.of(context).ok,
257
leftButtonText: S.of(context).cancel,
258
- actionRightButton: () {
258
+ actionRightButton: () async {
259
Navigator.of(context).pop();
260
- widget.exchangeTradeViewModel.sendViewModel
260
+ await widget.exchangeTradeViewModel.sendViewModel
261
.commitTransaction();
262
- showPopUp<void>(
262
+ await showPopUp<void>(
263
context: context,
264
builder: (BuildContext context) {
265
return Observer(builder: (_) {
@@ -359,10 +359,10 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
359
});
360
},
361
actionLeftButton: () => Navigator.of(context).pop(),
362
- feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel
363
- .pendingTransaction.feeFormatted,
362
+ feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFeeFiatAmount
363
+ + ' ' + widget.exchangeTradeViewModel.sendViewModel.fiat.title,
364
fiatAmountValue: widget.exchangeTradeViewModel.sendViewModel
365
- .pendingTransactionFeeFiatAmount +
365
+ .pendingTransactionFiatAmount +
366
' ' +
367
widget.exchangeTradeViewModel.sendViewModel.fiat.title,
368
recipientTitle: S.of(context).recipient_address,
lib/view_model/backup_view_model.dart
+4
-2
@@ -1,5 +1,4 @@
1
import 'dart:io';
2
-
2
import 'package:cake_wallet/core/backup_service.dart';
3
import 'package:cake_wallet/core/execution_state.dart';
4
import 'package:cake_wallet/entities/secret_store_key.dart';
@@ -7,6 +6,7 @@ import 'package:cake_wallet/store/secret_store.dart';
6
import 'package:flutter/foundation.dart';
7
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
8
import 'package:mobx/mobx.dart';
9
+import 'package:intl/intl.dart';
10
11
part 'backup_view_model.g.dart';
12
@@ -56,9 +56,11 @@ abstract class BackupViewModelBase with Store {
56
state = IsExecutingState();
57
final backupContent = await backupService.exportBackup(backupPassword);
58
state = ExecutedSuccessfullyState();
59
+ final now = DateTime.now();
60
+ final formatter = DateFormat('yyyy-MM-dd_Hm');
61
62
return BackupExportFile(backupContent.toList(),
61
- name: 'backup_${DateTime.now().toString()}.zip');
63
+ name: 'cake_wallet_backup_${formatter.format(now)}');
64
} catch (e) {
65
print(e.toString());
66
state = FailureState(e.toString());
lib/view_model/send/send_view_model.dart
+1
@@ -167,6 +167,7 @@ abstract class SendViewModelBase with Store {
167
168
Validator get templateValidator => TemplateValidator();
169
170
+ @observable
171
PendingTransaction pendingTransaction;
172
173
@computed
pubspec.lock
+14
@@ -695,6 +695,20 @@ packages:
695
url: "https://pub.dartlang.org"
696
source: hosted
697
version: "1.9.2"
698
+ permission_handler:
699
+ dependency: "direct main"
700
+ description:
701
+ name: permission_handler
702
+ url: "https://pub.dartlang.org"
703
+ source: hosted
704
+ version: "5.0.1+1"
705
+ permission_handler_platform_interface:
706
+ dependency: transitive
707
+ description:
708
+ name: permission_handler_platform_interface
709
+ url: "https://pub.dartlang.org"
710
+ source: hosted
711
+ version: "2.0.1"
712
petitparser:
713
dependency: transitive
714
description:
pubspec.yaml
+2
-1
@@ -11,7 +11,7 @@ description: Cake Wallet.
11
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12
# Read more about iOS versioning at
13
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14
-version: 4.1.0+37
14
+version: 4.1.0+38
15
16
environment:
17
sdk: ">=2.7.0 <3.0.0"
@@ -72,6 +72,7 @@ dependencies:
72
cryptography: ^1.4.0
73
file_picker: ^2.1.4
74
unorm_dart: ^0.1.2
75
+ permission_handler: ^5.0.1+1
76
77
dev_dependencies:
78
flutter_test: