Another beautiful day changes

M committed Jan 11, 2021 at 19:15 UTC 9db6e233c713cecf570dafff648ccf8f3dd02a31
24 files changed +400 -259
lib/bitcoin/bitcoin_address_record.dart
+8
@@ -1,4 +1,5 @@
1 import 'dart:convert';
2 +import 'package:quiver/core.dart';
3
4 class BitcoinAddressRecord {
5 BitcoinAddressRecord(this.address, {this.index});
@@ -10,8 +11,15 @@ class BitcoinAddressRecord {
11 index: decoded['index'] as int);
12 }
13
14 + @override
15 + bool operator ==(Object o) =>
16 + o is BitcoinAddressRecord && address == o.address;
17 +
18 final String address;
19 int index;
20
21 + @override
22 + int get hashCode => address.hashCode;
23 +
24 String toJSON() => json.encode({'address': address, 'index': index});
25 }
lib/bitcoin/bitcoin_balance.dart
+5 -28
@@ -1,16 +1,12 @@
1 import 'dart:convert';
2
3 -import 'package:cake_wallet/entities/balance_display_mode.dart';
3 import 'package:flutter/foundation.dart';
4 import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart';
5 import 'package:cake_wallet/entities/balance.dart';
6
7 class BitcoinBalance extends Balance {
8 const BitcoinBalance({@required this.confirmed, @required this.unconfirmed})
10 - : super(const [
11 - BalanceDisplayMode.availableBalance,
12 - BalanceDisplayMode.fullBalance
13 - ]);
9 + : super(confirmed, unconfirmed);
10
11 factory BitcoinBalance.fromJSON(String jsonSource) {
12 if (jsonSource == null) {
@@ -27,31 +23,12 @@ class BitcoinBalance extends Balance {
23 final int confirmed;
24 final int unconfirmed;
25
30 - int get total => confirmed + unconfirmed;
31 -
32 - int get availableBalance =>
33 - (confirmed ?? 0) + (unconfirmed < 0 ? unconfirmed : 0);
34 -
35 - String get confirmedFormatted => bitcoinAmountToString(amount: confirmed);
36 -
37 - String get unconfirmedFormatted => bitcoinAmountToString(amount: unconfirmed);
38 -
39 - String get totalFormatted => bitcoinAmountToString(amount: total);
40 -
41 - String get availableBalanceFormatted =>
42 - bitcoinAmountToString(amount: availableBalance);
26 + @override
27 + String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed);
28
29 @override
45 - String formattedBalance(BalanceDisplayMode mode) {
46 - switch (mode) {
47 - case BalanceDisplayMode.fullBalance:
48 - return totalFormatted;
49 - case BalanceDisplayMode.availableBalance:
50 - return availableBalanceFormatted;
51 - default:
52 - return null;
53 - }
54 - }
30 + String get formattedAdditionalBalance =>
31 + bitcoinAmountToString(amount: unconfirmed);
32
33 String toJSON() =>
34 json.encode({'confirmed': confirmed, 'unconfirmed': unconfirmed});
lib/bitcoin/bitcoin_wallet.dart
+3 -3
@@ -47,7 +47,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
47 network: bitcoin.bitcoin)
48 .derivePath("m/0'/0"),
49 addresses = initialAddresses != null
50 - ? ObservableList<BitcoinAddressRecord>.of(initialAddresses)
50 + ? ObservableList<BitcoinAddressRecord>.of(initialAddresses.toSet())
51 : ObservableList<BitcoinAddressRecord>(),
52 syncStatus = NotConnectedSyncStatus(),
53 _password = password,
@@ -267,14 +267,14 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
267 final fee = feeAmountForPriority(transactionCredentials.priority);
268 final amount = transactionCredentials.amount != null
269 ? stringDoubleToBitcoinAmount(transactionCredentials.amount)
270 - : balance.availableBalance - fee;
270 + : balance.confirmed - fee;
271 final totalAmount = amount + fee;
272 final txb = bitcoin.TransactionBuilder(network: bitcoin.bitcoin);
273 final changeAddress = address;
274 var leftAmount = totalAmount;
275 var totalInputAmount = 0;
276
277 - if (totalAmount > balance.availableBalance) {
277 + if (totalAmount > balance.confirmed) {
278 throw BitcoinTransactionWrongBalanceException();
279 }
280
lib/core/wallet_base.dart
+2 -1
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:flutter/foundation.dart';
3 import 'package:cake_wallet/entities/wallet_info.dart';
4 import 'package:cake_wallet/core/pending_transaction.dart';
@@ -9,7 +10,7 @@ import 'package:cake_wallet/entities/sync_status.dart';
10 import 'package:cake_wallet/entities/node.dart';
11 import 'package:cake_wallet/entities/wallet_type.dart';
12
12 -abstract class WalletBase<BalaceType> {
13 +abstract class WalletBase<BalaceType extends Balance> {
14 WalletBase(this.walletInfo);
15
16 static String idFor(String name, WalletType type) =>
lib/entities/balance.dart
+7 -5
@@ -1,9 +1,11 @@
1 -import 'package:cake_wallet/entities/balance_display_mode.dart';
2 -
1 abstract class Balance {
4 - const Balance(this.availableModes);
2 + const Balance(this.available, this.additional);
3 +
4 + final int available;
5 +
6 + final int additional;
7
6 - final List<BalanceDisplayMode> availableModes;
8 + String get formattedAvailableBalance;
9
8 - String formattedBalance(BalanceDisplayMode mode);
10 + String get formattedAdditionalBalance;
11 }
lib/entities/balance_display_mode.dart
+8 -3
@@ -7,15 +7,16 @@ class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
7 : super(title: title, raw: raw);
8
9 static const all = [
10 - BalanceDisplayMode.fullBalance,
11 - BalanceDisplayMode.availableBalance,
12 - BalanceDisplayMode.hiddenBalance
10 + BalanceDisplayMode.hiddenBalance,
11 + BalanceDisplayMode.displayableBalance,
12 ];
13 static const fullBalance = BalanceDisplayMode(raw: 0, title: 'Full Balance');
14 static const availableBalance =
15 BalanceDisplayMode(raw: 1, title: 'Available Balance');
16 static const hiddenBalance =
17 BalanceDisplayMode(raw: 2, title: 'Hidden Balance');
18 + static const displayableBalance =
19 + BalanceDisplayMode(raw: 3, title: 'Displayable Balance');
20
21 static BalanceDisplayMode deserialize({int raw}) {
22 switch (raw) {
@@ -25,6 +26,8 @@ class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
26 return availableBalance;
27 case 2:
28 return hiddenBalance;
29 + case 3:
30 + return displayableBalance;
31 default:
32 return null;
33 }
@@ -39,6 +42,8 @@ class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
42 return S.current.xmr_available_balance;
43 case BalanceDisplayMode.hiddenBalance:
44 return S.current.xmr_hidden;
45 + case BalanceDisplayMode.displayableBalance:
46 + return S.current.displayable;
47 default:
48 return '';
49 }
lib/entities/default_settings_migration.dart
+12
@@ -80,6 +80,11 @@ Future defaultSettingsMigration(
80 case 5:
81 await addAddressesForMoneroWallets(walletInfoSource);
82 break;
83 +
84 + case 6:
85 + await updateDisplayModes(sharedPreferences);
86 + break;
87 +
88 default:
89 break;
90 }
@@ -220,3 +225,10 @@ Future<void> addAddressesForMoneroWallets(
225 }
226 });
227 }
228 +
229 +Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
230 + final currentBalanceDisplayMode =
231 + sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey);
232 + final balanceDisplayMode = currentBalanceDisplayMode < 2 ? 3 : 2;
233 + await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
234 +}
lib/generated/i18n.dart
+92
@@ -374,6 +374,10 @@ class S implements WidgetsLocalizations {
374 String wallet_list_failed_to_remove(String wallet_name, String error) => "Failed to remove ${wallet_name} wallet. ${error}";
375 String wallet_list_loading_wallet(String wallet_name) => "Loading ${wallet_name} wallet";
376 String wallet_list_removing_wallet(String wallet_name) => "Removing ${wallet_name} wallet";
377 + String get exchange_incorrect_current_wallet_for_xmr => "If you want to exchange XMR from your Cake Wallet Monero balance, please switch to your Monero wallet first.";
378 + String get confirmed => 'Confirmed';
379 + String get unconfirmed => 'Unconfirmed';
380 + String get displayable => 'Displayable';
381 }
382
383 class $de extends S {
@@ -1088,6 +1092,14 @@ class $de extends S {
1092 String wallet_list_failed_to_load(String wallet_name, String error) => "Laden fehlgeschlagen ${wallet_name} Wallet. ${error}";
1093 @override
1094 String wallet_list_removing_wallet(String wallet_name) => "Entfernen ${wallet_name} Wallet";
1095 + @override
1096 + String get exchange_incorrect_current_wallet_for_xmr => "Wenn Sie XMR von Ihrem Cake Wallet Monero-Guthaben austauschen möchten, wechseln Sie bitte zuerst zu Ihrem Monero Wallet.";
1097 + @override
1098 + String get confirmed => 'Bestätigt';
1099 + @override
1100 + String get unconfirmed => 'Unbestätigt';
1101 + @override
1102 + String get displayable => 'Anzeigebar';
1103 }
1104
1105 class $hi extends S {
@@ -1802,6 +1814,14 @@ class $hi extends S {
1814 String wallet_list_failed_to_load(String wallet_name, String error) => "लोड करने में विफल ${wallet_name} बटुआ. ${error}";
1815 @override
1816 String wallet_list_removing_wallet(String wallet_name) => "निकाला जा रहा है ${wallet_name} बटुआ";
1817 + @override
1818 + String get exchange_incorrect_current_wallet_for_xmr => "यदि आप अपने केक वॉलेट मोनेरो बैलेंस से एक्सएमआर का आदान-प्रदान करना चाहते हैं, तो कृपया अपने मोनेरो वॉलेट में जाएं।";
1819 + @override
1820 + String get confirmed => 'की पुष्टि की';
1821 + @override
1822 + String get unconfirmed => 'अपुष्ट';
1823 + @override
1824 + String get displayable => 'प्रदर्शन योग्य';
1825 }
1826
1827 class $ru extends S {
@@ -2516,6 +2536,14 @@ class $ru extends S {
2536 String wallet_list_failed_to_load(String wallet_name, String error) => "Ошибка при загрузке ${wallet_name} кошелька. ${error}";
2537 @override
2538 String wallet_list_removing_wallet(String wallet_name) => "Удаление ${wallet_name} кошелька";
2539 + @override
2540 + String get exchange_incorrect_current_wallet_for_xmr => "Если вы хотите обменять XMR со своего баланса Monero в Cake Wallet, сначала переключитесь на свой кошелек Monero.";
2541 + @override
2542 + String get confirmed => 'Подтверждено';
2543 + @override
2544 + String get unconfirmed => 'Неподтвержденный';
2545 + @override
2546 + String get displayable => 'Отображаемый';
2547 }
2548
2549 class $ko extends S {
@@ -3230,6 +3258,14 @@ class $ko extends S {
3258 String wallet_list_failed_to_load(String wallet_name, String error) => "불러 오지 못했습니다 ${wallet_name} 지갑. ${error}";
3259 @override
3260 String wallet_list_removing_wallet(String wallet_name) => "풀이 ${wallet_name} 지갑";
3261 + @override
3262 + String get exchange_incorrect_current_wallet_for_xmr => "Cake Wallet Monero 잔액에서 XMR을 교환하려면 먼저 Monero 지갑으로 전환하십시오.";
3263 + @override
3264 + String get confirmed => '확인';
3265 + @override
3266 + String get unconfirmed => '미확인';
3267 + @override
3268 + String get displayable => '표시 가능';
3269 }
3270
3271 class $pt extends S {
@@ -3944,6 +3980,14 @@ class $pt extends S {
3980 String wallet_list_failed_to_load(String wallet_name, String error) => "Falha ao abrir a carteira ${wallet_name}. ${error}";
3981 @override
3982 String wallet_list_removing_wallet(String wallet_name) => "Removendo a carteira ${wallet_name}";
3983 + @override
3984 + String get exchange_incorrect_current_wallet_for_xmr => "Se você deseja trocar o XMR de seu saldo da Carteira Monero Cake, troque primeiro para sua carteira Monero.";
3985 + @override
3986 + String get confirmed => 'Confirmada';
3987 + @override
3988 + String get unconfirmed => 'Não confirmado';
3989 + @override
3990 + String get displayable => 'Exibível';
3991 }
3992
3993 class $uk extends S {
@@ -4658,6 +4702,14 @@ class $uk extends S {
4702 String wallet_list_failed_to_load(String wallet_name, String error) => "Помилка при завантаженні ${wallet_name} гаманця. ${error}";
4703 @override
4704 String wallet_list_removing_wallet(String wallet_name) => "Видалення ${wallet_name} гаманця";
4705 + @override
4706 + String get exchange_incorrect_current_wallet_for_xmr => "Якщо ви хочете обміняти XMR із вашого балансу Cake Wallet Monero, спочатку перейдіть на свій гаманець Monero.";
4707 + @override
4708 + String get confirmed => 'Підтверджено';
4709 + @override
4710 + String get unconfirmed => 'Непідтверджений';
4711 + @override
4712 + String get displayable => 'Відображуваний';
4713 }
4714
4715 class $ja extends S {
@@ -5372,6 +5424,14 @@ class $ja extends S {
5424 String wallet_list_failed_to_load(String wallet_name, String error) => "読み込みに失敗しました ${wallet_name} 財布. ${error}";
5425 @override
5426 String wallet_list_removing_wallet(String wallet_name) => "取りはずし ${wallet_name} 財布";
5427 + @override
5428 + String get exchange_incorrect_current_wallet_for_xmr => "Cake Wallet Moneroの残高からXMRを交換する場合は、最初にMoneroウォレットに切り替えてください。";
5429 + @override
5430 + String get confirmed => '確認済み';
5431 + @override
5432 + String get unconfirmed => '未確認';
5433 + @override
5434 + String get displayable => '表示可能';
5435 }
5436
5437 class $en extends S {
@@ -6090,6 +6150,14 @@ class $pl extends S {
6150 String wallet_list_failed_to_load(String wallet_name, String error) => "Nie udało się załadować ${wallet_name} portfel. ${error}";
6151 @override
6152 String wallet_list_removing_wallet(String wallet_name) => "Usuwanie ${wallet_name} portfel";
6153 + @override
6154 + String get exchange_incorrect_current_wallet_for_xmr => "Jeśli chcesz wymienić XMR z salda Cake Wallet Monero, najpierw przełącz się na portfel Monero.";
6155 + @override
6156 + String get confirmed => 'Potwierdzony';
6157 + @override
6158 + String get unconfirmed => 'niepotwierdzony';
6159 + @override
6160 + String get displayable => 'Wyświetlane';
6161 }
6162
6163 class $es extends S {
@@ -6804,6 +6872,14 @@ class $es extends S {
6872 String wallet_list_failed_to_load(String wallet_name, String error) => "No se pudo cargar ${wallet_name} la billetera. ${error}";
6873 @override
6874 String wallet_list_removing_wallet(String wallet_name) => "Retirar ${wallet_name} billetera";
6875 + @override
6876 + String get exchange_incorrect_current_wallet_for_xmr => "Si desea intercambiar XMR de su saldo de Cake Wallet Monero, primero cambie a su billetera Monero.";
6877 + @override
6878 + String get confirmed => 'Confirmada';
6879 + @override
6880 + String get unconfirmed => 'inconfirmado';
6881 + @override
6882 + String get displayable => 'Visualizable';
6883 }
6884
6885 class $nl extends S {
@@ -7518,6 +7594,14 @@ class $nl extends S {
7594 String wallet_list_failed_to_load(String wallet_name, String error) => "Laden mislukt ${wallet_name} portemonnee. ${error}";
7595 @override
7596 String wallet_list_removing_wallet(String wallet_name) => "Verwijderen ${wallet_name} portemonnee";
7597 + @override
7598 + String get exchange_incorrect_current_wallet_for_xmr => "Als u XMR wilt omwisselen van uw Cake Wallet Monero-saldo, moet u eerst overschakelen naar uw Monero-portemonnee.";
7599 + @override
7600 + String get confirmed => 'bevestigd';
7601 + @override
7602 + String get unconfirmed => 'niet bevestigd';
7603 + @override
7604 + String get displayable => 'Weer te geven';
7605 }
7606
7607 class $zh extends S {
@@ -8232,6 +8316,14 @@ class $zh extends S {
8316 String wallet_list_failed_to_load(String wallet_name, String error) => "加载失败 ${wallet_name} 钱包. ${error}";
8317 @override
8318 String wallet_list_removing_wallet(String wallet_name) => "拆下 ${wallet_name} 钱包";
8319 + @override
8320 + String get exchange_incorrect_current_wallet_for_xmr => "如果要从Cake Wallet Monero余额中兑换XMR,请先切换到Monero钱包。";
8321 + @override
8322 + String get confirmed => '已确认';
8323 + @override
8324 + String get unconfirmed => '未经证实';
8325 + @override
8326 + String get displayable => '可显示';
8327 }
8328
8329 class GeneratedLocalizationsDelegate extends LocalizationsDelegate<S> {
lib/main.dart
+22 -19
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
2 import 'package:cake_wallet/themes/theme_base.dart';
3 import 'package:flutter/material.dart';
4 import 'package:flutter/services.dart';
@@ -54,11 +55,11 @@ void main() async {
55 TransactionDescription.boxName,
56 encryptionKey: transactionDescriptionsBoxKey);
57 final trades =
57 - await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
58 + await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
59 final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
60 final templates = await Hive.openBox<Template>(Template.boxName);
61 final exchangeTemplates =
61 - await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
62 + await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
63 await initialSetup(
64 sharedPreferences: await SharedPreferences.getInstance(),
65 nodes: nodes,
@@ -77,24 +78,24 @@ void main() async {
78 home: Scaffold(
79 body: Container(
80 margin:
80 - EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
81 + EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
82 child: Text(
83 'Error:\n${e.toString()}',
84 style: TextStyle(fontSize: 22),
85 )))));
86 }
87 }
87 -Future<void> initialSetup(
88 - {@required SharedPreferences sharedPreferences,
89 - @required Box<Node> nodes,
90 - @required Box<WalletInfo> walletInfoSource,
91 - @required Box<Contact> contactSource,
92 - @required Box<Trade> tradesSource,
93 - // @required FiatConvertationService fiatConvertationService,
94 - @required Box<Template> templates,
95 - @required Box<ExchangeTemplate> exchangeTemplates,
96 - @required Box<TransactionDescription> transactionDescriptions,
97 - int initialMigrationVersion = 5}) async {
88 +
89 +Future<void> initialSetup({@required SharedPreferences sharedPreferences,
90 + @required Box<Node> nodes,
91 + @required Box<WalletInfo> walletInfoSource,
92 + @required Box<Contact> contactSource,
93 + @required Box<Trade> tradesSource,
94 + // @required FiatConvertationService fiatConvertationService,
95 + @required Box<Template> templates,
96 + @required Box<ExchangeTemplate> exchangeTemplates,
97 + @required Box<TransactionDescription> transactionDescriptions,
98 + int initialMigrationVersion = 6}) async {
99 await defaultSettingsMigration(
100 version: initialMigrationVersion,
101 sharedPreferences: sharedPreferences,
@@ -122,7 +123,9 @@ class App extends StatelessWidget {
123
124 @override
125 Widget build(BuildContext context) {
125 - final settingsStore = getIt.get<AppStore>().settingsStore;
126 + final settingsStore = getIt
127 + .get<AppStore>()
128 + .settingsStore;
129 final statusBarColor = Colors.transparent;
130 final authenticationStore = getIt.get<AuthenticationStore>();
131 final initialRoute = authenticationStore.state == AuthenticationState.denied
@@ -132,11 +135,11 @@ class App extends StatelessWidget {
135 return Observer(builder: (BuildContext context) {
136 final currentTheme = settingsStore.currentTheme;
137 final statusBarBrightness = currentTheme.type == ThemeType.dark
135 - ? Brightness.light
136 - : Brightness.dark;
138 + ? Brightness.light
139 + : Brightness.dark;
140 final statusBarIconBrightness = currentTheme.type == ThemeType.dark
138 - ? Brightness.light
139 - : Brightness.dark;
141 + ? Brightness.light
142 + : Brightness.dark;
143 SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
144 statusBarColor: statusBarColor,
145 statusBarBrightness: statusBarBrightness,
lib/monero/monero_balance.dart
+7 -18
@@ -8,20 +8,15 @@ class MoneroBalance extends Balance {
8 : formattedFullBalance = moneroAmountToString(amount: fullBalance),
9 formattedUnlockedBalance =
10 moneroAmountToString(amount: unlockedBalance),
11 - super(const [
12 - BalanceDisplayMode.availableBalance,
13 - BalanceDisplayMode.fullBalance
14 - ]);
11 + super(unlockedBalance, fullBalance);
12
13 MoneroBalance.fromString(
14 {@required this.formattedFullBalance,
15 @required this.formattedUnlockedBalance})
16 : fullBalance = moneroParseAmount(amount: formattedFullBalance),
17 unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance),
21 - super(const [
22 - BalanceDisplayMode.availableBalance,
23 - BalanceDisplayMode.fullBalance
24 - ]);
18 + super(moneroParseAmount(amount: formattedUnlockedBalance),
19 + moneroParseAmount(amount: formattedFullBalance));
20
21 final int fullBalance;
22 final int unlockedBalance;
@@ -29,14 +24,8 @@ class MoneroBalance extends Balance {
24 final String formattedUnlockedBalance;
25
26 @override
32 - String formattedBalance(BalanceDisplayMode mode) {
33 - switch (mode) {
34 - case BalanceDisplayMode.fullBalance:
35 - return formattedFullBalance;
36 - case BalanceDisplayMode.availableBalance:
37 - return formattedUnlockedBalance;
38 - default:
39 - return null;
40 - }
41 - }
27 + String get formattedAvailableBalance => formattedUnlockedBalance;
28 +
29 + @override
30 + String get formattedAdditionalBalance => formattedFullBalance;
31 }
lib/reactions/on_current_wallet_change.dart
+3 -2
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:mobx/mobx.dart';
3 import 'package:shared_preferences/shared_preferences.dart';
4 import 'package:cake_wallet/di.dart';
@@ -19,7 +20,7 @@ void startCurrentWalletChangeReaction(AppStore appStore,
20 _onCurrentWalletChangeReaction?.reaction?.dispose();
21
22 _onCurrentWalletChangeReaction =
22 - reaction((_) => appStore.wallet, (WalletBase wallet) async {
23 + reaction((_) => appStore.wallet, (WalletBase<Balance> wallet) async {
24 try {
25 final node = settingsStore.getCurrentNode(wallet.type);
26 startWalletSyncStatusChangeReaction(wallet);
@@ -44,7 +45,7 @@ void startCurrentWalletChangeReaction(AppStore appStore,
45 });
46
47 _onCurrentWalletChangeFiatRateUpdateReaction =
47 - reaction((_) => appStore.wallet, (WalletBase wallet) async {
48 + reaction((_) => appStore.wallet, (WalletBase<Balance> wallet) async {
49 try {
50 fiatConversionStore.prices[wallet.currency] = 0;
51 fiatConversionStore.prices[wallet.currency] =
lib/reactions/on_wallet_sync_status_change.dart
+2 -1
@@ -1,10 +1,11 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:mobx/mobx.dart';
3 import 'package:cake_wallet/core/wallet_base.dart';
4 import 'package:cake_wallet/entities/sync_status.dart';
5
6 ReactionDisposer _onWalletSyncStatusChangeReaction;
7
7 -void startWalletSyncStatusChangeReaction(WalletBase wallet) {
8 +void startWalletSyncStatusChangeReaction(WalletBase<Balance> wallet) {
9 _onWalletSyncStatusChangeReaction?.reaction?.dispose();
10 _onWalletSyncStatusChangeReaction =
11 reaction((_) => wallet.syncStatus, (SyncStatus status) async {
lib/src/screens/dashboard/widgets/address_page.dart
+3
@@ -19,6 +19,9 @@ class AddressPage extends StatelessWidget {
19 @override
20 Widget build(BuildContext context) {
21 return KeyboardActions(
22 + autoScroll: false,
23 + disableScroll: true,
24 + tapOutsideToDismiss: true,
25 config: KeyboardActionsConfig(
26 keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
27 keyboardBarColor:
lib/src/screens/dashboard/widgets/balance_page.dart
+83 -72
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/crypto_currency.dart';
2 import 'package:flutter/material.dart';
3 import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
4 import 'package:flutter_mobx/flutter_mobx.dart';
@@ -10,77 +11,87 @@ class BalancePage extends StatelessWidget {
11
12 @override
13 Widget build(BuildContext context) {
13 - return GestureDetector(
14 - onTapUp: (_) {
15 - if (dashboardViewModel.balanceViewModel.canReverse) {
16 - dashboardViewModel.balanceViewModel.isReversing = false;
17 - }
18 - },
19 - onTapDown: (_) {
20 - if (dashboardViewModel.balanceViewModel.canReverse) {
21 - dashboardViewModel.balanceViewModel.isReversing = true;
22 - }
23 - },
24 - child: Container(
25 - color: Colors.transparent,
26 - padding: EdgeInsets.all(24),
27 - child: Column(
28 - mainAxisAlignment: MainAxisAlignment.center,
29 - crossAxisAlignment: CrossAxisAlignment.center,
30 - children: <Widget>[
31 - Observer(builder: (_) {
32 - return Text(
33 - dashboardViewModel.balanceViewModel.currency.toString(),
34 - style: TextStyle(
35 - fontSize: 40,
36 - fontWeight: FontWeight.bold,
37 - color: Theme.of(context)
38 - .accentTextTheme
39 - .display2
40 - .backgroundColor,
41 - height: 1),
42 - );
43 - }),
44 - Observer(builder: (_) {
45 - return Text(
46 - dashboardViewModel.balanceViewModel.displayMode.toString(),
47 - style: TextStyle(
48 - fontSize: 12,
49 - fontWeight: FontWeight.w600,
50 - color: Theme.of(context)
51 - .accentTextTheme
52 - .display2
53 - .backgroundColor,
54 - height: 1),
55 - );
56 - }),
57 - SizedBox(height: 10),
58 - Observer(builder: (_) {
59 - return AutoSizeText(
60 - dashboardViewModel.balanceViewModel.cryptoBalance,
61 - style: TextStyle(
62 - fontSize: 54,
63 - fontWeight: FontWeight.bold,
64 - color: Theme.of(context)
65 - .accentTextTheme
66 - .display3
67 - .backgroundColor,
68 - height: 1),
69 - maxLines: 1,
70 - textAlign: TextAlign.center);
71 - }),
72 - SizedBox(height: 10),
73 - Observer(builder: (_) {
74 - return Text(dashboardViewModel.balanceViewModel.fiatBalance,
75 - style: TextStyle(
76 - fontSize: 18,
77 - fontWeight: FontWeight.w500,
78 - color: Theme.of(context).indicatorColor,
79 - height: 1),
80 - textAlign: TextAlign.center);
81 - }),
82 - ],
83 - ),
84 - ));
14 + return Container(
15 + color: Colors.transparent,
16 + padding: EdgeInsets.all(24),
17 + child: Column(
18 + mainAxisAlignment: MainAxisAlignment.center,
19 + crossAxisAlignment: CrossAxisAlignment.center,
20 + children: <Widget>[
21 + Observer(builder: (_) {
22 + return Text(
23 + dashboardViewModel.balanceViewModel.currency.toString(),
24 + style: TextStyle(
25 + fontSize: 40,
26 + fontWeight: FontWeight.bold,
27 + color: Theme.of(context)
28 + .accentTextTheme
29 + .display2
30 + .backgroundColor,
31 + height: 1),
32 + );
33 + }),
34 + SizedBox(height: 10),
35 + Observer(builder: (_) {
36 + return Text(
37 + '${dashboardViewModel.balanceViewModel.availableBalanceLabel} (${dashboardViewModel.balanceViewModel.availableFiatBalance.toString()})',
38 + style: TextStyle(
39 + fontSize: 12,
40 + fontWeight: FontWeight.w600,
41 + color: Theme.of(context)
42 + .accentTextTheme
43 + .display2
44 + .backgroundColor,
45 + height: 1),
46 + );
47 + }),
48 + SizedBox(height: 10),
49 + Observer(builder: (_) {
50 + return AutoSizeText(
51 + dashboardViewModel.balanceViewModel.availableBalance,
52 + style: TextStyle(
53 + fontSize: 54,
54 + fontWeight: FontWeight.bold,
55 + color: Theme.of(context)
56 + .accentTextTheme
57 + .display3
58 + .backgroundColor,
59 + height: 1),
60 + maxLines: 1,
61 + textAlign: TextAlign.center);
62 + }),
63 + SizedBox(height: 10),
64 + Observer(builder: (_) {
65 + return Text(
66 + '${dashboardViewModel.balanceViewModel.additionalBalanceLabel} (${dashboardViewModel.balanceViewModel.additionalFiatBalance.toString()})',
67 + style: TextStyle(
68 + fontSize: 12,
69 + fontWeight: FontWeight.w600,
70 + color: Theme.of(context)
71 + .accentTextTheme
72 + .display2
73 + .backgroundColor,
74 + height: 1),
75 + );
76 + }),
77 + SizedBox(height: 10),
78 + Observer(builder: (_) {
79 + return AutoSizeText(
80 + dashboardViewModel.balanceViewModel.additionalBalance
81 + .toString(),
82 + style: TextStyle(
83 + fontSize: 18,
84 + fontWeight: FontWeight.bold,
85 + color: Theme.of(context)
86 + .accentTextTheme
87 + .display3
88 + .backgroundColor,
89 + height: 1),
90 + maxLines: 1,
91 + textAlign: TextAlign.center);
92 + }),
93 + ],
94 + ),
95 + );
96 }
97 }
lib/src/screens/exchange/exchange_page.dart
+25 -3
@@ -1,5 +1,6 @@
1 import 'dart:ui';
2 import 'package:cake_wallet/entities/sync_status.dart';
3 +import 'package:cake_wallet/entities/wallet_type.dart';
4 import 'package:dotted_border/dotted_border.dart';
5 import 'package:flutter/cupertino.dart';
6 import 'package:flutter/material.dart';
@@ -183,9 +184,30 @@ class ExchangePage extends BasePage {
184 isAmountEstimated: false,
185 hasRefundAddress: true,
186 currencies: CryptoCurrency.all,
186 - onCurrencySelected: (currency) =>
187 - exchangeViewModel.changeDepositCurrency(
188 - currency: currency),
187 + onCurrencySelected: (currency) {
188 + // FIXME: need to move it into view model
189 + if (currency == CryptoCurrency.xmr &&
190 + exchangeViewModel.wallet.type ==
191 + WalletType.bitcoin) {
192 + showPopUp<void>(
193 + context: context,
194 + builder: (dialogContext) {
195 + return AlertWithOneAction(
196 + alertTitle: S.of(context).error,
197 + alertContent: S
198 + .of(context)
199 + .exchange_incorrect_current_wallet_for_xmr,
200 + buttonText: S.of(context).ok,
201 + buttonAction: () =>
202 + Navigator.of(dialogContext)
203 + .pop());
204 + });
205 + return;
206 + }
207 +
208 + exchangeViewModel.changeDepositCurrency(
209 + currency: currency);
210 + },
211 imageArrow: arrowBottomPurple,
212 currencyButtonColor: Colors.transparent,
213 addressButtonsColor:
lib/src/screens/exchange/widgets/exchange_card.dart
+34 -27
@@ -235,33 +235,40 @@ class ExchangeCardState extends State<ExchangeCard> {
235 )),
236 Padding(
237 padding: EdgeInsets.only(top: 5),
238 - child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <
239 - Widget>[
240 - _min != null
241 - ? Text(
242 - S.of(context).min_value(_min, _selectedCurrency.toString()),
243 - style: TextStyle(
244 - fontSize: 10,
245 - height: 1.2,
246 - color: Theme.of(context)
247 - .accentTextTheme
248 - .display4
249 - .decorationColor),
250 - )
251 - : Offstage(),
252 - _min != null ? SizedBox(width: 10) : Offstage(),
253 - _max != null
254 - ? Text(
255 - S.of(context).max_value(_max, _selectedCurrency.toString()),
256 - style: TextStyle(
257 - fontSize: 10,
258 - height: 1.2,
259 - color: Theme.of(context)
260 - .accentTextTheme
261 - .display4
262 - .decorationColor))
263 - : Offstage(),
264 - ]),
238 + child: Container(
239 + height: 15,
240 + child: Row(
241 + mainAxisAlignment: MainAxisAlignment.start,
242 + children: <Widget>[
243 + _min != null
244 + ? Text(
245 + S
246 + .of(context)
247 + .min_value(_min, _selectedCurrency.toString()),
248 + style: TextStyle(
249 + fontSize: 10,
250 + height: 1.2,
251 + color: Theme.of(context)
252 + .accentTextTheme
253 + .display4
254 + .decorationColor),
255 + )
256 + : Offstage(),
257 + _min != null ? SizedBox(width: 10) : Offstage(),
258 + _max != null
259 + ? Text(
260 + S
261 + .of(context)
262 + .max_value(_max, _selectedCurrency.toString()),
263 + style: TextStyle(
264 + fontSize: 10,
265 + height: 1.2,
266 + color: Theme.of(context)
267 + .accentTextTheme
268 + .display4
269 + .decorationColor))
270 + : Offstage(),
271 + ])),
272 ),
273 !_isAddressEditable && widget.hasRefundAddress
274 ? Padding(
lib/src/screens/receive/widgets/qr_widget.dart
+1 -1
@@ -54,7 +54,7 @@ class QRWidget extends StatelessWidget {
54 ]),
55 isAmountFieldShow
56 ? Padding(
57 - padding: EdgeInsets.only(top: 60),
57 + padding: EdgeInsets.only(top: 40),
58 child: Row(
59 children: <Widget>[
60 Expanded(
lib/store/app_store.dart
+2 -1
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:mobx/mobx.dart';
3 import 'package:cake_wallet/core/wallet_base.dart';
4 import 'package:cake_wallet/store/wallet_list_store.dart';
@@ -19,7 +20,7 @@ abstract class AppStoreBase with Store {
20 AuthenticationStore authenticationStore;
21
22 @observable
22 - WalletBase wallet;
23 + WalletBase<Balance> wallet;
24
25 WalletListStore walletList;
26
lib/view_model/dashboard/balance_view_model.dart
+58 -53
@@ -1,14 +1,13 @@
1 -import 'package:cake_wallet/bitcoin/bitcoin_balance.dart';
1 import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
2 import 'package:cake_wallet/core/wallet_base.dart';
3 import 'package:cake_wallet/entities/balance.dart';
4 import 'package:cake_wallet/entities/crypto_currency.dart';
6 -import 'package:cake_wallet/monero/monero_balance.dart';
5 +import 'package:cake_wallet/entities/wallet_type.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 import 'package:cake_wallet/monero/monero_wallet.dart';
8 import 'package:cake_wallet/entities/balance_display_mode.dart';
9 import 'package:cake_wallet/entities/calculate_fiat_amount.dart';
10 import 'package:cake_wallet/store/app_store.dart';
11 -import 'package:cake_wallet/view_model/dashboard/wallet_balance.dart';
11 import 'package:cake_wallet/store/settings_store.dart';
12 import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
13 import 'package:flutter/cupertino.dart';
@@ -51,8 +50,7 @@ abstract class BalanceViewModelBase with Store {
50 final SettingsStore settingsStore;
51 final FiatConversionStore fiatConvertationStore;
52
54 - bool get canReverse =>
55 - (appStore.wallet.balance.availableModes as List).length > 1;
53 + bool get canReverse => false;
54
55 @observable
56 bool isReversing;
@@ -61,7 +59,7 @@ abstract class BalanceViewModelBase with Store {
59 Balance balance;
60
61 @observable
64 - WalletBase wallet;
62 + WalletBase<Balance> wallet;
63
64 @computed
65 double get price => fiatConvertationStore.prices[appStore.wallet.currency];
@@ -77,63 +75,80 @@ abstract class BalanceViewModelBase with Store {
75 : savedDisplayMode;
76
77 @computed
80 - String get cryptoBalance {
81 - final walletBalance = _walletBalance;
82 - var _balance = '---';
83 -
84 - if (displayMode == BalanceDisplayMode.availableBalance) {
85 - _balance = walletBalance.unlockedBalance ?? '0.0';
78 + String get availableBalanceLabel {
79 + if (wallet.type == WalletType.monero) {
80 + return S.current.xmr_available_balance;
81 }
82
88 - if (displayMode == BalanceDisplayMode.fullBalance) {
89 - _balance = walletBalance.totalBalance ?? '0.0';
83 + return S.current.confirmed;
84 + }
85 +
86 + @computed
87 + String get additionalBalanceLabel {
88 + if (wallet.type == WalletType.monero) {
89 + return S.current.xmr_full_balance;
90 }
91
92 - return _balance;
92 + return S.current.unconfirmed;
93 }
94
95 @computed
96 - String get fiatBalance {
96 + String get availableBalance {
97 final walletBalance = _walletBalance;
98 - final fiatCurrency = settingsStore.fiatCurrency;
99 - var _balance = '---';
98
101 - final totalBalance =
102 - _getFiatBalance(price: price, cryptoAmount: walletBalance.totalBalance);
99 + if (settingsStore.balanceDisplayMode == BalanceDisplayMode.hiddenBalance) {
100 + return '---';
101 + }
102
104 - final unlockedBalance = _getFiatBalance(
105 - price: price, cryptoAmount: walletBalance.unlockedBalance);
103 + return walletBalance.formattedAvailableBalance;
104 + }
105
107 - if (displayMode == BalanceDisplayMode.availableBalance) {
108 - _balance = fiatCurrency.toString() + ' ' + unlockedBalance ?? '0.00';
109 - }
106 + @computed
107 + String get additionalBalance {
108 + final walletBalance = _walletBalance;
109
111 - if (displayMode == BalanceDisplayMode.fullBalance) {
112 - _balance = fiatCurrency.toString() + ' ' + totalBalance ?? '0.00';
110 + if (settingsStore.balanceDisplayMode == BalanceDisplayMode.hiddenBalance) {
111 + return '---';
112 }
113
115 - return _balance;
114 + return walletBalance.formattedAdditionalBalance;
115 }
116
117 @computed
119 - WalletBalance get _walletBalance {
120 - final _balance = balance;
118 + String get availableFiatBalance {
119 + final walletBalance = _walletBalance;
120 + final fiatCurrency = settingsStore.fiatCurrency;
121
122 - if (_balance is MoneroBalance) {
123 - return WalletBalance(
124 - unlockedBalance: _balance.formattedUnlockedBalance,
125 - totalBalance: _balance.formattedFullBalance);
122 + if (settingsStore.balanceDisplayMode == BalanceDisplayMode.hiddenBalance) {
123 + return '---';
124 }
125
128 - if (_balance is BitcoinBalance) {
129 - return WalletBalance(
130 - unlockedBalance: _balance.availableBalanceFormatted,
131 - totalBalance: _balance.totalFormatted);
126 + return fiatCurrency.toString() +
127 + ' ' +
128 + _getFiatBalance(
129 + price: price,
130 + cryptoAmount: walletBalance.formattedAvailableBalance);
131 + }
132 +
133 + @computed
134 + String get additionalFiatBalance {
135 + final walletBalance = _walletBalance;
136 + final fiatCurrency = settingsStore.fiatCurrency;
137 +
138 + if (settingsStore.balanceDisplayMode == BalanceDisplayMode.hiddenBalance) {
139 + return '---';
140 }
141
134 - return null;
142 + return fiatCurrency.toString() +
143 + ' ' +
144 + _getFiatBalance(
145 + price: price,
146 + cryptoAmount: walletBalance.formattedAdditionalBalance);
147 }
148
149 + @computed
150 + Balance get _walletBalance => wallet.balance;
151 +
152 @computed
153 CryptoCurrency get currency => appStore.wallet.currency;
154
@@ -141,24 +156,14 @@ abstract class BalanceViewModelBase with Store {
156 ReactionDisposer _reaction;
157
158 @action
144 - void _onWalletChange(WalletBase wallet) {
159 + void _onWalletChange(WalletBase<Balance> wallet) {
160 this.wallet = wallet;
161
147 - if (wallet is MoneroWallet) {
148 - balance = wallet.balance;
149 - }
150 -
151 - if (wallet is BitcoinWallet) {
152 - balance = wallet.balance;
153 - }
162 + balance = wallet.balance;
163
164 _onCurrentWalletChangeReaction?.reaction?.dispose();
156 - _onCurrentWalletChangeReaction =
157 - reaction<void>((_) => wallet.balance, (dynamic balance) {
158 - if (balance is Balance) {
159 - this.balance = balance;
160 - }
161 - });
165 + _onCurrentWalletChangeReaction = reaction<Balance>(
166 + (_) => wallet.balance, (Balance balance) => this.balance = balance);
167 }
168
169 String _getFiatBalance({double price, String cryptoAmount}) {
lib/view_model/dashboard/dashboard_view_model.dart
+3 -2
@@ -1,5 +1,6 @@
1 import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
2 import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
3 +import 'package:cake_wallet/entities/balance.dart';
4 import 'package:cake_wallet/entities/transaction_history.dart';
5 import 'package:cake_wallet/monero/account.dart';
6 import 'package:cake_wallet/monero/monero_balance.dart';
@@ -184,7 +185,7 @@ abstract class DashboardViewModelBase with Store {
185 }
186
187 @observable
187 - WalletBase wallet;
188 + WalletBase<Balance> wallet;
189
190 bool get hasRescan => wallet.type == WalletType.monero;
191
@@ -212,7 +213,7 @@ abstract class DashboardViewModelBase with Store {
213 }
214
215 @action
215 - void _onWalletChange(WalletBase wallet) {
216 + void _onWalletChange(WalletBase<Balance> wallet) {
217 this.wallet = wallet;
218 type = wallet.type;
219 name = wallet.name;
lib/view_model/exchange/exchange_view_model.dart
+1 -1
@@ -301,7 +301,7 @@ abstract class ExchangeViewModelBase with Store {
301 @action
302 void calculateDepositAllAmount() {
303 if (wallet is BitcoinWallet) {
304 - final availableBalance = wallet.balance.availableBalance as int;
304 + final availableBalance = wallet.balance.available;
305 final fee = BitcoinWalletBase.feeAmountForPriority(
306 _settingsStore.transactionPriority);
307
lib/view_model/send/send_view_model.dart
+7 -8
@@ -134,9 +134,7 @@ abstract class SendViewModelBase with Store {
134 PendingTransaction pendingTransaction;
135
136 @computed
137 - String get balance =>
138 - _wallet.balance.formattedBalance(BalanceDisplayMode.availableBalance)
139 - as String ?? '0.0';
137 + String get balance => _wallet.balance.formattedAvailableBalance ?? '0.0';
138
139 @computed
140 bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus;
@@ -183,11 +181,12 @@ abstract class SendViewModelBase with Store {
181
182 if (pendingTransaction.id?.isNotEmpty ?? false) {
183 _settingsStore.shouldSaveRecipientAddress
186 - ? await transactionDescriptionBox.add(TransactionDescription(
187 - id: pendingTransaction.id, recipientAddress: address,
188 - transactionNote: note))
189 - : await transactionDescriptionBox.add(TransactionDescription(
190 - id: pendingTransaction.id, transactionNote: note));
184 + ? await transactionDescriptionBox.add(TransactionDescription(
185 + id: pendingTransaction.id,
186 + recipientAddress: address,
187 + transactionNote: note))
188 + : await transactionDescriptionBox.add(TransactionDescription(
189 + id: pendingTransaction.id, transactionNote: note));
190 }
191
192 state = TransactionCommitted();
lib/view_model/settings/settings_view_model.dart
+9 -9
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:cake_wallet/themes/theme_base.dart';
3 import 'package:cake_wallet/themes/theme_list.dart';
4 import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
@@ -28,7 +29,7 @@ part 'settings_view_model.g.dart';
29 class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel;
30
31 abstract class SettingsViewModelBase with Store {
31 - SettingsViewModelBase(this._settingsStore, WalletBase wallet)
32 + SettingsViewModelBase(this._settingsStore, WalletBase<Balance> wallet)
33 : itemHeaders = {},
34 _walletType = wallet.type,
35 _biometricAuth = BiometricAuth() {
@@ -45,13 +46,12 @@ abstract class SettingsViewModelBase with Store {
46
47 sections = [
48 [
48 - if ((wallet.balance.availableModes as List).length > 1)
49 - PickerListItem(
50 - title: S.current.settings_display_balance_as,
51 - items: BalanceDisplayMode.all,
52 - selectedItem: () => balanceDisplayMode,
53 - onItemSelected: (BalanceDisplayMode mode) =>
54 - _settingsStore.balanceDisplayMode = mode),
49 + PickerListItem(
50 + title: S.current.settings_display_balance_as,
51 + items: BalanceDisplayMode.all,
52 + selectedItem: () => balanceDisplayMode,
53 + onItemSelected: (BalanceDisplayMode mode) =>
54 + _settingsStore.balanceDisplayMode = mode),
55 PickerListItem(
56 title: S.current.settings_currency,
57 items: FiatCurrency.all,
@@ -120,7 +120,7 @@ abstract class SettingsViewModelBase with Store {
120 items: ThemeList.all,
121 selectedItem: () => theme,
122 onItemSelected: (ThemeBase theme) =>
123 - _settingsStore.currentTheme = theme)
123 + _settingsStore.currentTheme = theme)
124 ],
125 [
126 LinkListItem(
lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+3 -2
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/balance.dart';
2 import 'package:cake_wallet/store/app_store.dart';
3 import 'package:flutter/foundation.dart';
4 import 'package:mobx/mobx.dart';
@@ -60,7 +61,7 @@ abstract class WalletAddressListViewModelBase with Store {
61 _appStore = appStore;
62 _wallet = _appStore.wallet;
63 hasAccounts = _wallet?.type == WalletType.monero;
63 - _onWalletChangeReaction = reaction((_) => _appStore.wallet, (WalletBase wallet) {
64 + _onWalletChangeReaction = reaction((_) => _appStore.wallet, (WalletBase<Balance> wallet) {
65 _wallet = wallet;
66 hasAccounts = _wallet.type == WalletType.monero;
67 });
@@ -145,7 +146,7 @@ abstract class WalletAddressListViewModelBase with Store {
146 bool get hasAddressList => _wallet.type == WalletType.monero;
147
148 @observable
148 - WalletBase _wallet;
149 + WalletBase<Balance> _wallet;
150
151 List<ListItem> _baseItems;
152