Fiat api fix (#1070)
* Cw 474 linux swapping wallets btc then xmr still shows btc receive qr code (#1068) * feat: improve address page txt field * fix: switching wallets from the desktop dropdown updates dashboard pages * Revert "feat: improve address page txt field" This reverts commit 0a30e6d9e1d13795219b66a6fdf2c1d218479089. * refactor: rename to WalletChangeListener * fix: _init also behaves on wallet change * Fix Fiat conversion API parsing Cherry pick fix for Desktop switching wallets not updating dashboard screens * Minor indentations fix [skip ci] --------- Co-authored-by: Rafael Saes <76502841+saltrafael@users.noreply.github.com>
Omar Hatem committed
Sep 1, 2023 at 18:06 UTC
68a821cc0e293e38dccdc6cc0e015ed86f087489
7 files changed
+208
-200
cw_monero/ios/Classes/monero_api.cpp
+7
-7
@@ -139,7 +139,7 @@ extern "C"
139
int8_t direction;
140
int8_t isPending;
141
uint32_t subaddrIndex;
142
-
142
+
143
char *hash;
144
char *paymentId;
145
@@ -154,7 +154,7 @@ extern "C"
154
std::set<uint32_t>::iterator it = transaction->subaddrIndex().begin();
155
subaddrIndex = *it;
156
confirmations = transaction->confirmations();
157
- datetime = static_cast<int64_t>(transaction->timestamp());
157
+ datetime = static_cast<int64_t>(transaction->timestamp());
158
direction = transaction->direction();
159
isPending = static_cast<int8_t>(transaction->isPending());
160
std::string *hash_str = new std::string(transaction->hash());
@@ -234,7 +234,7 @@ extern "C"
234
}
235
236
void setUnlocked(bool unlocked);
237
-
237
+
238
};
239
240
Monero::Coins *m_coins;
@@ -254,7 +254,7 @@ extern "C"
254
{
255
m_wallet = wallet;
256
m_listener = nullptr;
257
-
257
+
258
259
if (wallet != nullptr)
260
{
@@ -479,7 +479,7 @@ extern "C"
479
{
480
nice(19);
481
Monero::Wallet *wallet = get_current_wallet();
482
-
482
+
483
std::string _login = "";
484
std::string _password = "";
485
std::string _socksProxyAddress = "";
@@ -568,7 +568,7 @@ extern "C"
568
_preferred_inputs.insert(std::string(*preferred_inputs));
569
preferred_inputs++;
570
}
571
-
571
+
572
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
573
std::string _payment_id;
574
Monero::PendingTransaction *transaction;
@@ -587,7 +587,7 @@ extern "C"
587
{
588
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
589
}
590
-
590
+
591
int status = transaction->status();
592
593
if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical)
lib/core/fiat_conversion_service.dart
+4
-4
@@ -21,7 +21,7 @@ Future<double> _fetchPrice(Map<String, dynamic> args) async {
21
'key': secrets.fiatApiKey,
22
};
23
24
- double price = 0.0;
24
+ num price = 0.0;
25
26
try {
27
late final Uri uri;
@@ -41,12 +41,12 @@ Future<double> _fetchPrice(Map<String, dynamic> args) async {
41
final results = responseJSON['results'] as Map<String, dynamic>;
42
43
if (results.isNotEmpty) {
44
- price = results.values.first as double;
44
+ price = results.values.first as num;
45
}
46
47
- return price;
47
+ return price.toDouble();
48
} catch (e) {
49
- return price;
49
+ return price.toDouble();
50
}
51
}
52
lib/core/wallet_change_listener_view_model.dart
new
+30
@@ -0,0 +1,30 @@
1
+import 'package:cw_core/balance.dart';
2
+import 'package:cw_core/transaction_history.dart';
3
+import 'package:cw_core/transaction_info.dart';
4
+import 'package:mobx/mobx.dart';
5
+import 'package:cw_core/wallet_base.dart';
6
+import 'package:cake_wallet/store/app_store.dart';
7
+
8
+part 'wallet_change_listener_view_model.g.dart';
9
+
10
+class WalletChangeListenerViewModel = WalletChangeListenerViewModelBase
11
+ with _$WalletChangeListenerViewModel;
12
+
13
+abstract class WalletChangeListenerViewModelBase with Store {
14
+ WalletChangeListenerViewModelBase({
15
+ required AppStore appStore,
16
+ }) : _wallet = appStore.wallet! {
17
+ reaction((_) => appStore.wallet, (WalletBase? wallet) {
18
+ _wallet = wallet!;
19
+ onWalletChange(wallet);
20
+ });
21
+ }
22
+
23
+ void onWalletChange(WalletBase wallet) {}
24
+
25
+ @observable
26
+ WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
27
+ @computed
28
+ WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> get wallet =>
29
+ _wallet;
30
+}
lib/di.dart
+2
-3
@@ -523,8 +523,7 @@ Future<void> setup({
523
524
getIt.registerFactory<SendViewModel>(
525
() => SendViewModel(
526
- getIt.get<AppStore>().wallet!,
527
- getIt.get<AppStore>().settingsStore,
526
+ getIt.get<AppStore>(),
527
getIt.get<SendTemplateViewModel>(),
528
getIt.get<FiatConversionStore>(),
529
getIt.get<BalanceViewModel>(),
@@ -702,7 +701,7 @@ Future<void> setup({
701
));
702
703
getIt.registerFactory(() => ExchangeViewModel(
705
- getIt.get<AppStore>().wallet!,
704
+ getIt.get<AppStore>(),
705
_tradesSource,
706
getIt.get<ExchangeTemplateStore>(),
707
getIt.get<TradesStore>(),
lib/view_model/exchange/exchange_view_model.dart
+70
-94
@@ -2,6 +2,7 @@ import 'dart:async';
2
import 'dart:collection';
3
import 'dart:convert';
4
5
+import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
6
import 'package:cake_wallet/entities/exchange_api_mode.dart';
7
import 'package:cake_wallet/entities/preferences_key.dart';
8
import 'package:cake_wallet/entities/wallet_contact.dart';
@@ -13,7 +14,7 @@ import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart';
14
import 'package:cake_wallet/exchange/trocador/trocador_request.dart';
15
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
16
import 'package:cw_core/transaction_priority.dart';
16
-import 'package:cw_core/wallet_base.dart';
17
+import 'package:cake_wallet/store/app_store.dart';
18
import 'package:cw_core/crypto_currency.dart';
19
import 'package:cw_core/sync_status.dart';
20
import 'package:cw_core/wallet_type.dart';
@@ -45,16 +46,22 @@ part 'exchange_view_model.g.dart';
46
47
class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel;
48
48
-abstract class ExchangeViewModelBase with Store {
49
+abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with Store {
50
+ @override
51
+ void onWalletChange(wallet) {
52
+ receiveCurrency = wallet.currency;
53
+ depositCurrency = wallet.currency;
54
+ }
55
+
56
ExchangeViewModelBase(
50
- this.wallet,
51
- this.trades,
52
- this._exchangeTemplateStore,
53
- this.tradesStore,
54
- this._settingsStore,
55
- this.sharedPreferences,
56
- this.contactListViewModel)
57
- : _cryptoNumberFormat = NumberFormat(),
57
+ AppStore appStore,
58
+ this.trades,
59
+ this._exchangeTemplateStore,
60
+ this.tradesStore,
61
+ this._settingsStore,
62
+ this.sharedPreferences,
63
+ this.contactListViewModel,
64
+ ) : _cryptoNumberFormat = NumberFormat(),
65
isFixedRateMode = false,
66
isReceiveAmountEntered = false,
67
depositAmount = '',
@@ -70,10 +77,11 @@ abstract class ExchangeViewModelBase with Store {
77
limits = Limits(min: 0, max: 0),
78
tradeState = ExchangeTradeStateInitial(),
79
limitsState = LimitsInitialState(),
73
- receiveCurrency = wallet.currency,
74
- depositCurrency = wallet.currency,
80
+ receiveCurrency = appStore.wallet!.currency,
81
+ depositCurrency = appStore.wallet!.currency,
82
providerList = [],
76
- selectedProviders = ObservableList<ExchangeProvider>() {
83
+ selectedProviders = ObservableList<ExchangeProvider>(),
84
+ super(appStore: appStore) {
85
_useTorOnly = _settingsStore.exchangeStatus == ExchangeApiMode.torOnly;
86
_setProviders();
87
const excludeDepositCurrencies = [CryptoCurrency.btt, CryptoCurrency.nano];
@@ -86,10 +94,9 @@ abstract class ExchangeViewModelBase with Store {
94
];
95
_initialPairBasedOnWallet();
96
89
- final Map<String, dynamic> exchangeProvidersSelection = json.decode(
90
- sharedPreferences
91
- .getString(PreferencesKey.exchangeProvidersSelection) ??
92
- "{}") as Map<String, dynamic>;
97
+ final Map<String, dynamic> exchangeProvidersSelection =
98
+ json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
99
+ as Map<String, dynamic>;
100
101
/// if the provider is not in the user settings (user's first time or newly added provider)
102
/// then use its default value decided by us
@@ -102,34 +109,28 @@ abstract class ExchangeViewModelBase with Store {
109
_setAvailableProviders();
110
_calculateBestRate();
111
105
- bestRateSync =
106
- Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
112
+ bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
113
114
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
115
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
116
depositAmount = '';
117
receiveAmount = '';
118
receiveAddress = '';
113
- depositAddress = depositCurrency == wallet.currency
114
- ? wallet.walletAddresses.address
115
- : '';
119
+ depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : '';
120
provider = providersForCurrentPair().first;
121
final initialProvider = provider;
122
provider!.checkIsAvailable().then((bool isAvailable) {
123
if (!isAvailable && provider == initialProvider) {
120
- provider = providerList.firstWhere(
121
- (provider) => provider is ChangeNowExchangeProvider,
124
+ provider = providerList.firstWhere((provider) => provider is ChangeNowExchangeProvider,
125
orElse: () => providerList.last);
126
_onPairChange();
127
}
128
});
129
receiveCurrencies = CryptoCurrency.all
127
- .where((cryptoCurrency) =>
128
- !excludeReceiveCurrencies.contains(cryptoCurrency))
130
+ .where((cryptoCurrency) => !excludeReceiveCurrencies.contains(cryptoCurrency))
131
.toList();
132
depositCurrencies = CryptoCurrency.all
131
- .where((cryptoCurrency) =>
132
- !excludeDepositCurrencies.contains(cryptoCurrency))
133
+ .where((cryptoCurrency) => !excludeDepositCurrencies.contains(cryptoCurrency))
134
.toList();
135
_defineIsReceiveAmountEditable();
136
loadLimits();
@@ -140,7 +141,6 @@ abstract class ExchangeViewModelBase with Store {
141
});
142
}
143
bool _useTorOnly;
143
- final WalletBase wallet;
144
final Box<Trade> trades;
145
final ExchangeTemplateStore _exchangeTemplateStore;
146
final TradesStore tradesStore;
@@ -165,8 +165,7 @@ abstract class ExchangeViewModelBase with Store {
165
/// initialize with descending comparator
166
/// since we want largest rate first
167
final SplayTreeMap<double, ExchangeProvider> _sortedAvailableProviders =
168
- SplayTreeMap<double, ExchangeProvider>(
169
- (double a, double b) => b.compareTo(a));
168
+ SplayTreeMap<double, ExchangeProvider>((double a, double b) => b.compareTo(a));
169
170
final List<ExchangeProvider> _tradeAvailableProviders = [];
171
@@ -222,21 +221,17 @@ abstract class ExchangeViewModelBase with Store {
221
SyncStatus get status => wallet.syncStatus;
222
223
@computed
225
- ObservableList<ExchangeTemplate> get templates =>
226
- _exchangeTemplateStore.templates;
224
+ ObservableList<ExchangeTemplate> get templates => _exchangeTemplateStore.templates;
225
226
@computed
229
- List<WalletContact> get walletContactsToShow =>
230
- contactListViewModel.walletContacts
231
- .where((element) =>
232
- receiveCurrency == null || element.type == receiveCurrency)
233
- .toList();
227
+ List<WalletContact> get walletContactsToShow => contactListViewModel.walletContacts
228
+ .where((element) => receiveCurrency == null || element.type == receiveCurrency)
229
+ .toList();
230
231
@action
232
bool checkIfWalletIsAnInternalWallet(String address) {
237
- final walletContactList = walletContactsToShow
238
- .where((element) => element.address == address)
239
- .toList();
233
+ final walletContactList =
234
+ walletContactsToShow.where((element) => element.address == address).toList();
235
236
return walletContactList.isNotEmpty;
237
}
@@ -256,7 +251,6 @@ abstract class ExchangeViewModelBase with Store {
251
return false;
252
}
253
259
-
254
@computed
255
TransactionPriority get transactionPriority {
256
final priority = _settingsStore.priority[wallet.type];
@@ -269,7 +263,8 @@ abstract class ExchangeViewModelBase with Store {
263
}
264
265
bool get hasAllAmount =>
272
- (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) && depositCurrency == wallet.currency;
266
+ (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) &&
267
+ depositCurrency == wallet.currency;
268
269
bool get isMoneroWallet => wallet.type == WalletType.monero;
270
@@ -277,14 +272,11 @@ abstract class ExchangeViewModelBase with Store {
272
switch (wallet.type) {
273
case WalletType.monero:
274
case WalletType.haven:
280
- return transactionPriority ==
281
- monero!.getMoneroTransactionPrioritySlow();
275
+ return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
276
case WalletType.bitcoin:
283
- return transactionPriority ==
284
- bitcoin!.getBitcoinTransactionPrioritySlow();
277
+ return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
278
case WalletType.litecoin:
286
- return transactionPriority ==
287
- bitcoin!.getLitecoinTransactionPrioritySlow();
279
+ return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow();
280
default:
281
return false;
282
}
@@ -390,20 +382,18 @@ abstract class ExchangeViewModelBase with Store {
382
}
383
384
Future<void> _calculateBestRate() async {
393
- final amount =
394
- double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1;
385
+ final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? 1;
386
387
final _providers = _tradeAvailableProviders
388
.where((element) => !isFixedRateMode || element.supportsFixedRate)
389
.toList();
390
400
- final result = await Future.wait<double>(_providers.map((element) =>
401
- element.fetchRate(
402
- from: depositCurrency,
403
- to: receiveCurrency,
404
- amount: amount,
405
- isFixedRateMode: isFixedRateMode,
406
- isReceiveAmount: isFixedRateMode)));
391
+ final result = await Future.wait<double>(_providers.map((element) => element.fetchRate(
392
+ from: depositCurrency,
393
+ to: receiveCurrency,
394
+ amount: amount,
395
+ isFixedRateMode: isFixedRateMode,
396
+ isReceiveAmount: isFixedRateMode)));
397
398
_sortedAvailableProviders.clear();
399
@@ -445,14 +435,13 @@ abstract class ExchangeViewModelBase with Store {
435
}
436
437
try {
448
- final tempLimits = await provider.fetchLimits(
449
- from: from, to: to, isFixedRateMode: isFixedRateMode);
438
+ final tempLimits =
439
+ await provider.fetchLimits(from: from, to: to, isFixedRateMode: isFixedRateMode);
440
441
if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) {
442
lowestMin = tempLimits.min;
443
}
454
- if (highestMax != null &&
455
- (tempLimits.max ?? double.maxFinite) > highestMax) {
444
+ if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) {
445
highestMax = tempLimits.max;
446
}
447
} catch (e) {
@@ -568,8 +557,8 @@ abstract class ExchangeViewModelBase with Store {
557
} else {
558
try {
559
tradeState = TradeIsCreating();
571
- final trade = await provider.createTrade(
572
- request: request!, isFixedRateMode: isFixedRateMode);
560
+ final trade =
561
+ await provider.createTrade(request: request!, isFixedRateMode: isFixedRateMode);
562
trade.walletId = wallet.id;
563
tradesStore.setTrade(trade);
564
await trades.add(trade);
@@ -604,12 +593,8 @@ abstract class ExchangeViewModelBase with Store {
593
isReceiveAmountEntered = false;
594
depositAmount = '';
595
receiveAmount = '';
607
- depositAddress = depositCurrency == wallet.currency
608
- ? wallet.walletAddresses.address
609
- : '';
610
- receiveAddress = receiveCurrency == wallet.currency
611
- ? wallet.walletAddresses.address
612
- : '';
596
+ depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : '';
597
+ receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : '';
598
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
599
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
600
isFixedRateMode = false;
@@ -628,8 +613,7 @@ abstract class ExchangeViewModelBase with Store {
613
}
614
615
final amount = availableBalance - fee;
631
- changeDepositAmount(
632
- amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
616
+ changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
617
}
618
}
619
@@ -664,9 +648,8 @@ abstract class ExchangeViewModelBase with Store {
648
List<ExchangeProvider> _providersForPair(
649
{required CryptoCurrency from, required CryptoCurrency to}) {
650
final providers = providerList
667
- .where((provider) => provider.pairList
668
- .where((pair) => pair.from == from && pair.to == to)
669
- .isNotEmpty)
651
+ .where((provider) =>
652
+ provider.pairList.where((pair) => pair.from == from && pair.to == to).isNotEmpty)
653
.toList();
654
655
return providers;
@@ -746,14 +729,12 @@ abstract class ExchangeViewModelBase with Store {
729
_bestRate = 0;
730
_calculateBestRate();
731
749
- final Map<String, dynamic> exchangeProvidersSelection = json.decode(
750
- sharedPreferences
751
- .getString(PreferencesKey.exchangeProvidersSelection) ??
752
- "{}") as Map<String, dynamic>;
732
+ final Map<String, dynamic> exchangeProvidersSelection =
733
+ json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
734
+ as Map<String, dynamic>;
735
736
for (var provider in providerList) {
755
- exchangeProvidersSelection[provider.title] =
756
- selectedProviders.contains(provider);
737
+ exchangeProvidersSelection[provider.title] = selectedProviders.contains(provider);
738
}
739
740
sharedPreferences.setString(
@@ -764,15 +745,15 @@ abstract class ExchangeViewModelBase with Store {
745
746
bool get isAvailableInSelected {
747
final providersForPair = providersForCurrentPair();
767
- return selectedProviders.any(
768
- (element) => element.isAvailable && providersForPair.contains(element));
748
+ return selectedProviders
749
+ .any((element) => element.isAvailable && providersForPair.contains(element));
750
}
751
752
void _setAvailableProviders() {
753
_tradeAvailableProviders.clear();
754
774
- _tradeAvailableProviders.addAll(selectedProviders
775
- .where((provider) => providersForCurrentPair().contains(provider)));
755
+ _tradeAvailableProviders.addAll(
756
+ selectedProviders.where((provider) => providersForCurrentPair().contains(provider)));
757
}
758
759
@action
@@ -780,16 +761,13 @@ abstract class ExchangeViewModelBase with Store {
761
switch (wallet.type) {
762
case WalletType.monero:
763
case WalletType.haven:
783
- _settingsStore.priority[wallet.type] =
784
- monero!.getMoneroTransactionPriorityAutomatic();
764
+ _settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
765
break;
766
case WalletType.bitcoin:
787
- _settingsStore.priority[wallet.type] =
788
- bitcoin!.getBitcoinTransactionPriorityMedium();
767
+ _settingsStore.priority[wallet.type] = bitcoin!.getBitcoinTransactionPriorityMedium();
768
break;
769
case WalletType.litecoin:
791
- _settingsStore.priority[wallet.type] =
792
- bitcoin!.getLitecoinTransactionPriorityMedium();
770
+ _settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium();
771
break;
772
default:
773
break;
@@ -798,9 +776,7 @@ abstract class ExchangeViewModelBase with Store {
776
777
void _setProviders() {
778
if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly) {
801
- providerList = _allProviders
802
- .where((provider) => provider.supportsOnionAddress)
803
- .toList();
779
+ providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList();
780
} else {
781
providerList = _allProviders;
782
}
lib/view_model/send/send_view_model.dart
+69
-62
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
2
import 'package:cake_wallet/entities/contact_record.dart';
3
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
4
import 'package:cake_wallet/entities/transaction_description.dart';
@@ -15,7 +16,7 @@ import 'package:cake_wallet/core/address_validator.dart';
16
import 'package:cake_wallet/core/amount_validator.dart';
17
import 'package:cw_core/pending_transaction.dart';
18
import 'package:cake_wallet/core/validator.dart';
18
-import 'package:cw_core/wallet_base.dart';
19
+import 'package:cake_wallet/store/app_store.dart';
20
import 'package:cake_wallet/core/execution_state.dart';
21
import 'package:cake_wallet/monero/monero.dart';
22
import 'package:cw_core/sync_status.dart';
@@ -34,30 +35,38 @@ part 'send_view_model.g.dart';
35
36
class SendViewModel = SendViewModelBase with _$SendViewModel;
37
37
-abstract class SendViewModelBase with Store {
38
+abstract class SendViewModelBase extends WalletChangeListenerViewModel with Store {
39
+ @override
40
+ void onWalletChange(wallet) {
41
+ currencies = wallet.balance.keys.toList();
42
+ selectedCryptoCurrency = wallet.currency;
43
+ hasMultipleTokens = wallet.type == WalletType.ethereum;
44
+ }
45
+
46
SendViewModelBase(
39
- this._wallet,
40
- this._settingsStore,
41
- this.sendTemplateViewModel,
42
- this._fiatConversationStore,
43
- this.balanceViewModel,
44
- this.contactListViewModel,
45
- this.transactionDescriptionBox)
46
- : state = InitialExecutionState(),
47
- currencies = _wallet.balance.keys.toList(),
48
- selectedCryptoCurrency = _wallet.currency,
49
- hasMultipleTokens = _wallet.type == WalletType.ethereum,
47
+ AppStore appStore,
48
+ this.sendTemplateViewModel,
49
+ this._fiatConversationStore,
50
+ this.balanceViewModel,
51
+ this.contactListViewModel,
52
+ this.transactionDescriptionBox,
53
+ ) : state = InitialExecutionState(),
54
+ currencies = appStore.wallet!.balance.keys.toList(),
55
+ selectedCryptoCurrency = appStore.wallet!.currency,
56
+ hasMultipleTokens = appStore.wallet!.type == WalletType.ethereum,
57
outputs = ObservableList<Output>(),
51
- fiatFromSettings = _settingsStore.fiatCurrency {
52
- final priority = _settingsStore.priority[_wallet.type];
53
- final priorities = priorityForWalletType(_wallet.type);
54
-
55
- if (!priorityForWalletType(_wallet.type).contains(priority)) {
56
- _settingsStore.priority[_wallet.type] = priorities.first;
58
+ _settingsStore = appStore.settingsStore,
59
+ fiatFromSettings = appStore.settingsStore.fiatCurrency,
60
+ super(appStore: appStore) {
61
+ final priority = _settingsStore.priority[wallet.type];
62
+ final priorities = priorityForWalletType(wallet.type);
63
+
64
+ if (!priorityForWalletType(wallet.type).contains(priority)) {
65
+ _settingsStore.priority[wallet.type] = priorities.first;
66
}
67
68
outputs
60
- .add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
69
+ .add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
70
}
71
72
@observable
@@ -68,7 +77,7 @@ abstract class SendViewModelBase with Store {
77
@action
78
void addOutput() {
79
outputs
71
- .add(Output(_wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
80
+ .add(Output(wallet, _settingsStore, _fiatConversationStore, () => selectedCryptoCurrency));
81
}
82
83
@action
@@ -107,9 +116,8 @@ abstract class SendViewModelBase with Store {
116
String get pendingTransactionFeeFiatAmount {
117
try {
118
if (pendingTransaction != null) {
110
- final currency = walletType == WalletType.ethereum
111
- ? _wallet.currency
112
- : selectedCryptoCurrency;
119
+ final currency =
120
+ walletType == WalletType.ethereum ? wallet.currency : selectedCryptoCurrency;
121
final fiat = calculateFiatAmount(
122
price: _fiatConversationStore.prices[currency]!,
123
cryptoAmount: pendingTransaction!.feeFormatted);
@@ -125,19 +133,19 @@ abstract class SendViewModelBase with Store {
133
FiatCurrency get fiat => _settingsStore.fiatCurrency;
134
135
TransactionPriority get transactionPriority {
128
- final priority = _settingsStore.priority[_wallet.type];
136
+ final priority = _settingsStore.priority[wallet.type];
137
138
if (priority == null) {
131
- throw Exception('Unexpected type ${_wallet.type}');
139
+ throw Exception('Unexpected type ${wallet.type}');
140
}
141
142
return priority;
143
}
144
137
- CryptoCurrency get currency => _wallet.currency;
145
+ CryptoCurrency get currency => wallet.currency;
146
147
Validator<String> get amountValidator =>
140
- AmountValidator(currency: walletTypeToCryptoCurrency(_wallet.type));
148
+ AmountValidator(currency: walletTypeToCryptoCurrency(wallet.type));
149
150
Validator<String> get allAmountValidator => AllAmountValidator();
151
@@ -151,7 +159,7 @@ abstract class SendViewModelBase with Store {
159
PendingTransaction? pendingTransaction;
160
161
@computed
154
- String get balance => _wallet.balance[selectedCryptoCurrency]!.formattedAvailableBalance;
162
+ String get balance => wallet.balance[selectedCryptoCurrency]!.formattedAvailableBalance;
163
164
@computed
165
bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
@@ -165,7 +173,7 @@ abstract class SendViewModelBase with Store {
173
isFiatDisabled ? '' : pendingTransactionFeeFiatAmount + ' ' + fiat.title;
174
175
@computed
168
- bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus;
176
+ bool get isReadyForSend => wallet.syncStatus is SyncedSyncStatus;
177
178
@computed
179
List<Template> get templates => sendTemplateViewModel.templates
@@ -174,39 +182,40 @@ abstract class SendViewModelBase with Store {
182
183
@computed
184
bool get hasCoinControl =>
177
- _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin || _wallet.type == WalletType.monero;
185
+ wallet.type == WalletType.bitcoin ||
186
+ wallet.type == WalletType.litecoin ||
187
+ wallet.type == WalletType.monero;
188
189
@computed
190
bool get isElectrumWallet =>
181
- _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin;
191
+ wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin;
192
193
@observable
194
CryptoCurrency selectedCryptoCurrency;
195
196
List<CryptoCurrency> currencies;
197
188
- bool get hasYat => outputs.any((out) =>
189
- out.isParsedAddress &&
190
- out.parsedAddress.parseFrom == ParseFrom.yatRecord);
198
+ bool get hasYat => outputs
199
+ .any((out) => out.isParsedAddress && out.parsedAddress.parseFrom == ParseFrom.yatRecord);
200
192
- WalletType get walletType => _wallet.type;
201
+ WalletType get walletType => wallet.type;
202
194
- String? get walletCurrencyName =>
195
- _wallet.currency.fullName?.toLowerCase() ?? _wallet.currency.name;
203
+ String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name;
204
205
bool get hasCurrecyChanger => walletType == WalletType.haven;
206
207
@computed
208
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
209
202
- final WalletBase _wallet;
210
final SettingsStore _settingsStore;
211
final SendTemplateViewModel sendTemplateViewModel;
212
final BalanceViewModel balanceViewModel;
213
final ContactListViewModel contactListViewModel;
214
final FiatConversionStore _fiatConversationStore;
215
final Box<TransactionDescription> transactionDescriptionBox;
209
- final bool hasMultipleTokens;
216
+
217
+ @observable
218
+ bool hasMultipleTokens;
219
220
@computed
221
List<ContactRecord> get contactsToShow => contactListViewModel.contacts
@@ -275,7 +284,7 @@ abstract class SendViewModelBase with Store {
284
Future<void> createTransaction() async {
285
try {
286
state = IsExecutingState();
278
- pendingTransaction = await _wallet.createTransaction(_credentials());
287
+ pendingTransaction = await wallet.createTransaction(_credentials());
288
state = ExecutedSuccessfullyState();
289
} catch (e) {
290
state = FailureState(e.toString());
@@ -322,61 +331,60 @@ abstract class SendViewModelBase with Store {
331
332
@action
333
void setTransactionPriority(TransactionPriority priority) =>
325
- _settingsStore.priority[_wallet.type] = priority;
334
+ _settingsStore.priority[wallet.type] = priority;
335
336
Object _credentials() {
328
- switch (_wallet.type) {
337
+ switch (wallet.type) {
338
case WalletType.bitcoin:
330
- final priority = _settingsStore.priority[_wallet.type];
339
+ final priority = _settingsStore.priority[wallet.type];
340
341
if (priority == null) {
333
- throw Exception('Priority is null for wallet type: ${_wallet.type}');
342
+ throw Exception('Priority is null for wallet type: ${wallet.type}');
343
}
344
345
return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority);
346
case WalletType.litecoin:
338
- final priority = _settingsStore.priority[_wallet.type];
347
+ final priority = _settingsStore.priority[wallet.type];
348
349
if (priority == null) {
341
- throw Exception('Priority is null for wallet type: ${_wallet.type}');
350
+ throw Exception('Priority is null for wallet type: ${wallet.type}');
351
}
352
353
return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority);
354
case WalletType.monero:
346
- final priority = _settingsStore.priority[_wallet.type];
355
+ final priority = _settingsStore.priority[wallet.type];
356
357
if (priority == null) {
349
- throw Exception('Priority is null for wallet type: ${_wallet.type}');
358
+ throw Exception('Priority is null for wallet type: ${wallet.type}');
359
}
360
361
return monero!
362
.createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority);
363
case WalletType.haven:
355
- final priority = _settingsStore.priority[_wallet.type];
364
+ final priority = _settingsStore.priority[wallet.type];
365
366
if (priority == null) {
358
- throw Exception('Priority is null for wallet type: ${_wallet.type}');
367
+ throw Exception('Priority is null for wallet type: ${wallet.type}');
368
}
369
370
return haven!.createHavenTransactionCreationCredentials(
371
outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title);
372
case WalletType.ethereum:
364
- final priority = _settingsStore.priority[_wallet.type];
373
+ final priority = _settingsStore.priority[wallet.type];
374
375
if (priority == null) {
367
- throw Exception('Priority is null for wallet type: ${_wallet.type}');
376
+ throw Exception('Priority is null for wallet type: ${wallet.type}');
377
}
378
370
- return ethereum!.createEthereumTransactionCredentials(
371
- outputs, priority: priority, currency: selectedCryptoCurrency);
379
+ return ethereum!.createEthereumTransactionCredentials(outputs,
380
+ priority: priority, currency: selectedCryptoCurrency);
381
default:
373
- throw Exception('Unexpected wallet type: ${_wallet.type}');
382
+ throw Exception('Unexpected wallet type: ${wallet.type}');
383
}
384
}
385
386
String displayFeeRate(dynamic priority) {
387
final _priority = priority as TransactionPriority;
379
- final wallet = _wallet;
388
389
if (isElectrumWallet) {
390
final rate = bitcoin!.getFeeRate(wallet, _priority);
@@ -387,22 +395,21 @@ abstract class SendViewModelBase with Store {
395
}
396
397
bool _isEqualCurrency(String currency) =>
390
- _wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase());
398
+ wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase());
399
400
@action
401
void onClose() => _settingsStore.fiatCurrency = fiatFromSettings;
402
403
@action
396
- void setFiatCurrency(FiatCurrency fiat) =>
397
- _settingsStore.fiatCurrency = fiat;
404
+ void setFiatCurrency(FiatCurrency fiat) => _settingsStore.fiatCurrency = fiat;
405
406
@action
407
void setSelectedCryptoCurrency(String cryptoCurrency) {
408
try {
402
- selectedCryptoCurrency = _wallet.balance.keys
409
+ selectedCryptoCurrency = wallet.balance.keys
410
.firstWhere((e) => cryptoCurrency.toLowerCase() == e.title.toLowerCase());
411
} catch (e) {
405
- selectedCryptoCurrency = _wallet.currency;
412
+ selectedCryptoCurrency = wallet.currency;
413
}
414
}
415
}
lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+26
-30
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
2
import 'package:cake_wallet/ethereum/ethereum.dart';
3
import 'package:cake_wallet/entities/fiat_currency.dart';
4
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
@@ -5,16 +6,12 @@ import 'package:cake_wallet/store/yat/yat_store.dart';
6
import 'package:cw_core/currency.dart';
7
import 'package:intl/intl.dart';
8
import 'package:mobx/mobx.dart';
8
-import 'package:cw_core/wallet_base.dart';
9
import 'package:cake_wallet/utils/list_item.dart';
10
import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart';
11
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart';
12
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
13
import 'package:cw_core/wallet_type.dart';
14
import 'package:cake_wallet/bitcoin/bitcoin.dart';
15
-import 'package:cw_core/transaction_history.dart';
16
-import 'package:cw_core/balance.dart';
17
-import 'package:cw_core/transaction_info.dart';
15
import 'package:cake_wallet/store/app_store.dart';
16
import 'package:cake_wallet/monero/monero.dart';
17
import 'package:cake_wallet/haven/haven.dart';
@@ -110,29 +107,36 @@ class EthereumURI extends PaymentURI {
107
}
108
}
109
113
-abstract class WalletAddressListViewModelBase with Store {
110
+abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store {
111
WalletAddressListViewModelBase({
112
required AppStore appStore,
113
required this.yatStore,
114
required this.fiatConversionStore,
118
- }) : _appStore = appStore,
119
- _baseItems = <ListItem>[],
120
- _wallet = appStore.wallet!,
115
+ }) : _baseItems = <ListItem>[],
116
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
117
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
118
hasAccounts =
119
appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven,
125
- amount = '' {
120
+ amount = '',
121
+ super(appStore: appStore) {
122
_init();
123
}
124
125
+ @override
126
+ void onWalletChange(wallet) {
127
+ _init();
128
+
129
+ selectedCurrency = walletTypeToCryptoCurrency(wallet.type);
130
+ hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven;
131
+ }
132
+
133
static const String _cryptoNumberPattern = '0.00000000';
134
135
final NumberFormat _cryptoNumberFormat;
136
137
final FiatConversionStore fiatConversionStore;
138
135
- List<Currency> get currencies => [walletTypeToCryptoCurrency(_wallet.type), ...FiatCurrency.all];
139
+ List<Currency> get currencies => [walletTypeToCryptoCurrency(wallet.type), ...FiatCurrency.all];
140
141
@observable
142
Currency selectedCurrency;
@@ -144,31 +148,31 @@ abstract class WalletAddressListViewModelBase with Store {
148
String amount;
149
150
@computed
147
- WalletType get type => _wallet.type;
151
+ WalletType get type => wallet.type;
152
153
@computed
154
WalletAddressListItem get address =>
151
- WalletAddressListItem(address: _wallet.walletAddresses.address, isPrimary: false);
155
+ WalletAddressListItem(address: wallet.walletAddresses.address, isPrimary: false);
156
157
@computed
158
PaymentURI get uri {
155
- if (_wallet.type == WalletType.monero) {
159
+ if (wallet.type == WalletType.monero) {
160
return MoneroURI(amount: amount, address: address.address);
161
}
162
159
- if (_wallet.type == WalletType.haven) {
163
+ if (wallet.type == WalletType.haven) {
164
return HavenURI(amount: amount, address: address.address);
165
}
166
163
- if (_wallet.type == WalletType.bitcoin) {
167
+ if (wallet.type == WalletType.bitcoin) {
168
return BitcoinURI(amount: amount, address: address.address);
169
}
170
167
- if (_wallet.type == WalletType.litecoin) {
171
+ if (wallet.type == WalletType.litecoin) {
172
return LitecoinURI(amount: amount, address: address.address);
173
}
174
171
- if (_wallet.type == WalletType.ethereum) {
175
+ if (wallet.type == WalletType.ethereum) {
176
return EthereumURI(amount: amount, address: address.address);
177
}
178
@@ -182,7 +186,6 @@ abstract class WalletAddressListViewModelBase with Store {
186
187
@computed
188
ObservableList<ListItem> get addressList {
185
- final wallet = _wallet;
189
final addressList = ObservableList<ListItem>();
190
191
if (wallet.type == WalletType.monero) {
@@ -237,8 +240,6 @@ abstract class WalletAddressListViewModelBase with Store {
240
241
@computed
242
String get accountLabel {
240
- final wallet = _wallet;
241
-
243
if (wallet.type == WalletType.monero) {
244
return monero!.getCurrentAccount(wallet).label;
245
}
@@ -251,29 +252,24 @@ abstract class WalletAddressListViewModelBase with Store {
252
}
253
254
@computed
254
- bool get hasAddressList => _wallet.type == WalletType.monero || _wallet.type == WalletType.haven;
255
+ bool get hasAddressList => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
256
257
@computed
258
bool get showElectrumAddressDisclaimer =>
258
- _wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin;
259
-
260
- @observable
261
- WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
259
+ wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin;
260
261
List<ListItem> _baseItems;
262
265
- AppStore _appStore;
266
-
263
final YatStore yatStore;
264
265
@action
266
void setAddress(WalletAddressListItem address) =>
271
- _wallet.walletAddresses.address = address.address;
267
+ wallet.walletAddresses.address = address.address;
268
269
void _init() {
270
_baseItems = [];
271
276
- if (_wallet.type == WalletType.monero || _wallet.type == WalletType.haven) {
272
+ if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) {
273
_baseItems.add(WalletAccountListHeader());
274
}
275
@@ -294,7 +290,7 @@ abstract class WalletAddressListViewModelBase with Store {
290
}
291
292
void _convertAmountToCrypto() {
297
- final cryptoCurrency = walletTypeToCryptoCurrency(_wallet.type);
293
+ final cryptoCurrency = walletTypeToCryptoCurrency(wallet.type);
294
try {
295
final crypto =
296
double.parse(amount.replaceAll(',', '.')) / fiatConversionStore.prices[cryptoCurrency]!;