Fix issues from code review

Godwin Asuquo committed Mar 1, 2023 at 23:44 UTC b0175719b93a4297d842b569887b5f214f779f96
11 files changed +165 -83
.github/workflows/pr_test_build.yml
-8
@@ -77,14 +77,6 @@ jobs:
77 run: |
78 cd /opt/android/cake_wallet
79 flutter packages pub run tool/generate_localization.dart
80 -
81 - - name: Upgrade flutter packages
82 - run: |
83 - cd /opt/android/cake_wallet
84 - cd cw_core && flutter pub upgrade && cd ..
85 - cd cw_monero && flutter pub upgrade && cd ..
86 - cd cw_bitcoin && flutter pub upgrade && cd ..
87 - cd cw_haven && flutter pub upgrade && cd ..
80
81 - name: Build generated code
82 run: |
lib/entities/default_settings_migration.dart
+15 -1
@@ -1,10 +1,12 @@
1 import 'dart:io' show File, Platform;
2 import 'package:cake_wallet/bitcoin/bitcoin.dart';
3 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
4 import 'package:cw_core/pathForWallet.dart';
5 import 'package:cake_wallet/entities/secret_store_key.dart';
6 import 'package:flutter/foundation.dart';
7 import 'package:flutter_secure_storage/flutter_secure_storage.dart';
8 import 'package:hive/hive.dart';
9 +import 'package:share_plus/share_plus.dart';
10 import 'package:shared_preferences/shared_preferences.dart';
11 import 'package:cake_wallet/entities/preferences_key.dart';
12 import 'package:cw_core/wallet_type.dart';
@@ -142,7 +144,9 @@ Future defaultSettingsMigration(
144 case 19:
145 await validateBitcoinSavedTransactionPriority(sharedPreferences);
146 break;
145 -
147 + case 20:
148 + await migrateExchangeStatus(sharedPreferences);
149 + break;
150 default:
151 break;
152 }
@@ -501,3 +505,13 @@ Future<void> changeDefaultHavenNode(
505 await node.save();
506 });
507 }
508 +
509 +Future<void> migrateExchangeStatus(SharedPreferences sharedPreferences) async {
510 + final isExchangeDisabled = sharedPreferences.getBool(PreferencesKey.disableExchangeKey);
511 + if (isExchangeDisabled == null) {
512 + return;
513 + }
514 +
515 + await sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, isExchangeDisabled
516 + ? ExchangeApiMode.disabled.raw : ExchangeApiMode.enabled.raw);
517 +}
lib/entities/exchange_api_mode.dart new
+39
@@ -0,0 +1,39 @@
1 +import 'package:cake_wallet/generated/i18n.dart';
2 +import 'package:cw_core/enumerable_item.dart';
3 +
4 +class ExchangeApiMode extends EnumerableItem<int> with Serializable<int> {
5 + const ExchangeApiMode({required String title, required int raw}) : super(title: title, raw: raw);
6 +
7 + static const all = [ExchangeApiMode.enabled, ExchangeApiMode.torOnly, ExchangeApiMode.disabled];
8 +
9 + static const enabled = ExchangeApiMode(raw: 0, title: 'Enabled');
10 + static const torOnly = ExchangeApiMode(raw: 1, title: 'Tor only');
11 + static const disabled = ExchangeApiMode(raw: 2, title: 'Disabled');
12 +
13 + static ExchangeApiMode deserialize({required int raw}) {
14 + switch (raw) {
15 + case 0:
16 + return enabled;
17 + case 1:
18 + return torOnly;
19 + case 2:
20 + return disabled;
21 + default:
22 + throw Exception('Unexpected token: $raw for ExchangeApiMode deserialize');
23 + }
24 + }
25 +
26 + @override
27 + String toString() {
28 + switch (this) {
29 + case ExchangeApiMode.enabled:
30 + return S.current.enabled;
31 + case ExchangeApiMode.torOnly:
32 + return S.current.tor_only;
33 + case ExchangeApiMode.disabled:
34 + return S.current.disabled;
35 + default:
36 + return '';
37 + }
38 + }
39 +}
\ No newline at end of file
lib/exchange/exchange_provider.dart
+1 -1
@@ -14,7 +14,7 @@ abstract class ExchangeProvider {
14 bool get isAvailable;
15 bool get isEnabled;
16 bool get supportsFixedRate;
17 - bool get shouldUseOnionAddress => false;
17 + bool get supportsOnionAddress => false;
18
19 @override
20 String toString() => title;
lib/exchange/trocador/trocador_exchange_provider.dart
+18 -6
@@ -13,9 +13,11 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets;
13 import 'package:http/http.dart';
14
15 class TrocadorExchangeProvider extends ExchangeProvider {
16 - TrocadorExchangeProvider()
16 + TrocadorExchangeProvider({this.useTorOnly = false})
17 : _lastUsedRateId = '',
18 super(pairList: _supportedPairs());
19 +
20 + bool useTorOnly;
21
22 static const List<CryptoCurrency> _notSupported = [
23 CryptoCurrency.scrt,
@@ -83,7 +85,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
85 params['id'] = _lastUsedRateId;
86 }
87
86 - final String apiAuthority = shouldUseOnionAddress ? await _getAuthority() : clearNetAuthority;
88 + final String apiAuthority = await _getAuthority();
89
90 final uri = Uri.https(apiAuthority, createTradePath, params);
91 final response = await get(uri);
@@ -142,7 +144,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
144 'name': from.name,
145 };
146
145 - final String apiAuthority = shouldUseOnionAddress ? await _getAuthority() : clearNetAuthority;
147 + final String apiAuthority = await _getAuthority();
148 final uri = Uri.https(apiAuthority, coinPath, params);
149
150 final response = await get(uri);
@@ -178,7 +180,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
180 return 0.0;
181 }
182
181 - final String apiAuthority = shouldUseOnionAddress ? await _getAuthority() : clearNetAuthority;
183 + final String apiAuthority = await _getAuthority();
184
185 final params = <String, String>{
186 'api_key': apiKey,
@@ -214,7 +216,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
216
217 @override
218 Future<Trade> findTradeById({required String id}) async {
217 - final String apiAuthority = shouldUseOnionAddress ? await _getAuthority() : clearNetAuthority;
219 + final String apiAuthority = await _getAuthority();
220 final uri = Uri.https(apiAuthority, tradePath, {'api_key': apiKey, 'id': id});
221 return get(uri).then((response) {
222 if (response.statusCode != 200) {
@@ -265,7 +267,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
267 bool get supportsFixedRate => true;
268
269 @override
268 - bool get shouldUseOnionAddress => true;
270 + bool get supportsOnionAddress => true;
271
272 @override
273 String get title => 'Trocador';
@@ -297,11 +299,21 @@ class TrocadorExchangeProvider extends ExchangeProvider {
299 }
300
301 Future<String> _getAuthority() async {
302 + if(!supportsOnionAddress){
303 + return clearNetAuthority;
304 + }
305 +
306 try {
307 + if (useTorOnly) {
308 + return onionApiAuthority;
309 + }
310 +
311 final uri = Uri.https(onionApiAuthority, '/api/trade');
312 await get(uri);
313 +
314 return onionApiAuthority;
315 } catch (e) {
316 +
317 return clearNetAuthority;
318 }
319 }
lib/src/screens/new_wallet/advanced_privacy_settings_page.dart
+49 -36
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
2 import 'package:cake_wallet/entities/fiat_api_mode.dart';
3 import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
4 import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
@@ -48,43 +49,55 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
49 padding: EdgeInsets.only(top: 24),
50 child: ScrollableWithBottomSection(
51 contentPadding: EdgeInsets.only(bottom: 24),
51 - content: Observer(
52 - builder: (_) => Column(
53 - crossAxisAlignment: CrossAxisAlignment.center,
54 - children: [
55 - SettingsChoicesCell(
56 - ChoicesListItem<FiatApiMode>(
57 - title: S.current.fiat_api,
58 - items: FiatApiMode.all,
59 - selectedItem: widget.privacySettingsViewModel.fiatApi,
60 - onItemSelected: (FiatApiMode mode) =>
61 - widget.privacySettingsViewModel.setFiatMode(mode),
62 - ),
63 - ),
64 - SettingsChoicesCell(
65 - ChoicesListItem<FiatApiMode>(
66 - title: S.current.exchange,
67 - items: FiatApiMode.all,
68 - selectedItem: widget.privacySettingsViewModel.exchangeStatus,
69 - onItemSelected: (FiatApiMode mode) =>
70 - widget.privacySettingsViewModel.setEnableExchange(mode),
71 - ),
72 - ),
73 - SettingsSwitcherCell(
74 - title: S.current.add_custom_node,
75 - value: widget.privacySettingsViewModel.addCustomNode,
76 - onValueChange: (_, __) => widget.privacySettingsViewModel.toggleAddCustomNode(),
77 - ),
78 - if (widget.privacySettingsViewModel.addCustomNode)
79 - Padding(
80 - padding: EdgeInsets.only(left: 24, right: 24, top: 24),
81 - child: NodeForm(
82 - formKey: _formKey,
83 - nodeViewModel: widget.nodeViewModel,
52 + content: Column(
53 + crossAxisAlignment: CrossAxisAlignment.center,
54 + children: [
55 + Observer(
56 + builder: (_) {
57 + return SettingsSwitcherCell(
58 + title: S.current.disable_fiat,
59 + value: widget.privacySettingsViewModel.fiatApi == FiatApiMode.disabled,
60 + onValueChange: (BuildContext context, bool value) {
61 + widget.privacySettingsViewModel.setFiatMode(value);
62 + });
63 + }
64 + ),
65 + Observer(
66 + builder: (_) {
67 + return SettingsChoicesCell(
68 + ChoicesListItem<ExchangeApiMode>(
69 + title: S.current.exchange,
70 + items: ExchangeApiMode.all,
71 + selectedItem: widget.privacySettingsViewModel.exchangeStatus,
72 + onItemSelected: (ExchangeApiMode mode) =>
73 + widget.privacySettingsViewModel.setEnableExchange(mode),
74 ),
85 - )
86 - ],
87 - ),
75 + );
76 + }
77 + ),
78 + Observer(
79 + builder: (_) {
80 + return Column(
81 + children: [
82 + SettingsSwitcherCell(
83 + title: S.current.add_custom_node,
84 + value: widget.privacySettingsViewModel.addCustomNode,
85 + onValueChange: (_, __) => widget.privacySettingsViewModel.toggleAddCustomNode(),
86 + ),
87 + if (widget.privacySettingsViewModel.addCustomNode)
88 + Padding(
89 + padding: EdgeInsets.only(left: 24, right: 24, top: 24),
90 + child: NodeForm(
91 + formKey: _formKey,
92 + nodeViewModel: widget.nodeViewModel,
93 + ),
94 + )
95 + ],
96 + );
97 + }
98 + ),
99 +
100 + ],
101 ),
102 bottomSectionPadding: EdgeInsets.all(24),
103 bottomSection: Column(
lib/src/screens/settings/privacy_page.dart
+10 -11
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
2 import 'package:cake_wallet/entities/fiat_api_mode.dart';
3 import 'package:cake_wallet/generated/i18n.dart';
4 import 'package:cake_wallet/src/screens/base_page.dart';
@@ -24,20 +25,18 @@ class PrivacyPage extends BasePage {
25 return Column(
26 mainAxisSize: MainAxisSize.min,
27 children: [
28 + SettingsSwitcherCell(
29 + title: S.current.disable_fiat,
30 + value: _privacySettingsViewModel.isFiatDisabled,
31 + onValueChange: (BuildContext context, bool value) {
32 + _privacySettingsViewModel.setFiatMode(value);
33 + }),
34 SettingsChoicesCell(
28 - ChoicesListItem<FiatApiMode>(
29 - title: S.current.fiat_api,
30 - items: FiatApiMode.all,
31 - selectedItem: _privacySettingsViewModel.fiatApi,
32 - onItemSelected: (FiatApiMode mode) => _privacySettingsViewModel.setFiatMode(mode),
33 - ),
34 - ),
35 - SettingsChoicesCell(
36 - ChoicesListItem<FiatApiMode>(
35 + ChoicesListItem<ExchangeApiMode>(
36 title: S.current.exchange,
38 - items: FiatApiMode.all,
37 + items: ExchangeApiMode.all,
38 selectedItem: _privacySettingsViewModel.exchangeStatus,
40 - onItemSelected: (FiatApiMode mode) => _privacySettingsViewModel.setEnableExchange(mode),
39 + onItemSelected: (ExchangeApiMode mode) => _privacySettingsViewModel.setEnableExchange(mode),
40 ),
41 ),
42 SettingsSwitcherCell(
lib/store/settings_store.dart
+8 -7
@@ -1,4 +1,5 @@
1 import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
3 import 'package:cake_wallet/entities/pin_code_required_duration.dart';
4 import 'package:cake_wallet/entities/preferences_key.dart';
5 import 'package:cw_core/transaction_priority.dart';
@@ -31,7 +32,7 @@ abstract class SettingsStoreBase with Store {
32 required bool initialSaveRecipientAddress,
33 required FiatApiMode initialFiatMode,
34 required bool initialAllowBiometricalAuthentication,
34 - required FiatApiMode initialExchangeStatus,
35 + required ExchangeApiMode initialExchangeStatus,
36 required ThemeBase initialTheme,
37 required int initialPinLength,
38 required String initialLanguageCode,
@@ -154,7 +155,7 @@ abstract class SettingsStoreBase with Store {
155
156 reaction(
157 (_) => exchangeStatus,
157 - (FiatApiMode mode) => sharedPreferences.setInt(
158 + (ExchangeApiMode mode) => sharedPreferences.setInt(
159 PreferencesKey.exchangeStatusKey, mode.serialize()));
160
161 this
@@ -192,7 +193,7 @@ abstract class SettingsStoreBase with Store {
193 bool allowBiometricalAuthentication;
194
195 @observable
195 - FiatApiMode exchangeStatus;
196 + ExchangeApiMode exchangeStatus;
197
198 @observable
199 ThemeBase currentTheme;
@@ -284,9 +285,9 @@ abstract class SettingsStoreBase with Store {
285 final allowBiometricalAuthentication = sharedPreferences
286 .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
287 false;
287 - final exchangeStatus = FiatApiMode.deserialize(
288 + final exchangeStatus = ExchangeApiMode.deserialize(
289 raw: sharedPreferences
289 - .getInt(PreferencesKey.exchangeStatusKey) ?? FiatApiMode.enabled.raw);
290 + .getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw);
291 final legacyTheme =
292 (sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy) ?? false)
293 ? ThemeType.dark.index
@@ -401,9 +402,9 @@ abstract class SettingsStoreBase with Store {
402 allowBiometricalAuthentication = sharedPreferences
403 .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
404 allowBiometricalAuthentication;
404 - exchangeStatus = FiatApiMode.deserialize(
405 + exchangeStatus = ExchangeApiMode.deserialize(
406 raw: sharedPreferences
406 - .getInt(PreferencesKey.exchangeStatusKey) ?? FiatApiMode.enabled.raw);
407 + .getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw);
408 final legacyTheme =
409 (sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy) ?? false)
410 ? ThemeType.dark.index
lib/view_model/advanced_privacy_settings_view_model.dart
+9 -4
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
2 import 'package:cake_wallet/entities/fiat_api_mode.dart';
3 import 'package:cake_wallet/store/settings_store.dart';
4 import 'package:cw_core/wallet_type.dart';
@@ -12,7 +13,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
13 AdvancedPrivacySettingsViewModelBase(this.type, this._settingsStore) : _addCustomNode = false;
14
15 @computed
15 - FiatApiMode get exchangeStatus => _settingsStore.exchangeStatus;
16 + ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus;
17
18 @computed
19 FiatApiMode get fiatApi => _settingsStore.fiatApiMode;
@@ -28,12 +29,16 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
29 bool get addCustomNode => _addCustomNode;
30
31 @action
31 - void setFiatMode(FiatApiMode value) {
32 - _settingsStore.fiatApiMode = value;
32 + void setFiatMode(bool value) {
33 + if (value) {
34 + _settingsStore.fiatApiMode = FiatApiMode.disabled;
35 + return;
36 + }
37 + _settingsStore.fiatApiMode = FiatApiMode.enabled;
38 }
39
40 @action
36 - void setEnableExchange(FiatApiMode value) {
41 + void setEnableExchange(ExchangeApiMode value) {
42 _settingsStore.exchangeStatus = value;
43 }
44
lib/view_model/exchange/exchange_view_model.dart
+6 -4
@@ -56,6 +56,7 @@ abstract class ExchangeViewModelBase with Store {
56 isDepositAddressEnabled = false,
57 isReceiveAddressEnabled = false,
58 isReceiveAmountEditable = false,
59 + _providerUseTorOnly = false,
60 receiveCurrencies = <CryptoCurrency>[],
61 depositCurrencies = <CryptoCurrency>[],
62 limits = Limits(min: 0, max: 0),
@@ -65,6 +66,7 @@ abstract class ExchangeViewModelBase with Store {
66 depositCurrency = wallet.currency,
67 providerList = [],
68 selectedProviders = ObservableList<ExchangeProvider>() {
69 + _providerUseTorOnly = _settingsStore.exchangeStatus == FiatApiMode.torOnly;
70 _setProviders();
71 const excludeDepositCurrencies = [CryptoCurrency.btt, CryptoCurrency.nano];
72 const excludeReceiveCurrencies = [CryptoCurrency.xlm, CryptoCurrency.xrp,
@@ -121,18 +123,18 @@ abstract class ExchangeViewModelBase with Store {
123 _calculateBestRate();
124 });
125 }
124 -
126 + bool _providerUseTorOnly;
127 final WalletBase wallet;
128 final Box<Trade> trades;
129 final ExchangeTemplateStore _exchangeTemplateStore;
130 final TradesStore tradesStore;
131 final SharedPreferences sharedPreferences;
132
131 - final _allProviders = [
133 + List<ExchangeProvider> get _allProviders => [
134 ChangeNowExchangeProvider(),
135 SideShiftExchangeProvider(),
136 SimpleSwapExchangeProvider(),
135 - TrocadorExchangeProvider(),
137 + TrocadorExchangeProvider(useTorOnly: _providerUseTorOnly),
138 ];
139
140 @observable
@@ -695,7 +697,7 @@ abstract class ExchangeViewModelBase with Store {
697
698 void _setProviders(){
699 if (_settingsStore.exchangeStatus == FiatApiMode.torOnly) {
698 - providerList = _allProviders.where((provider) => provider.shouldUseOnionAddress).toList();
700 + providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList();
701 } else {
702 providerList = _allProviders;
703 }
lib/view_model/settings/privacy_settings_view_model.dart
+10 -5
@@ -1,3 +1,4 @@
1 +import 'package:cake_wallet/entities/exchange_api_mode.dart';
2 import 'package:cake_wallet/store/settings_store.dart';
3 import 'package:mobx/mobx.dart';
4 import 'package:cake_wallet/entities/fiat_api_mode.dart';
@@ -12,23 +13,27 @@ abstract class PrivacySettingsViewModelBase with Store {
13 final SettingsStore _settingsStore;
14
15 @computed
15 - FiatApiMode get exchangeStatus => _settingsStore.exchangeStatus;
16 + ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus;
17
18 @computed
19 bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress;
20
21 @computed
21 - FiatApiMode get fiatApi => _settingsStore.fiatApiMode;
22 + bool get isFiatDisabled => _settingsStore.fiatApiMode == FiatApiMode.disabled;
23
24 @action
25 void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value;
26
27 @action
27 - void setEnableExchange(FiatApiMode value) => _settingsStore.exchangeStatus = value;
28 + void setEnableExchange(ExchangeApiMode value) => _settingsStore.exchangeStatus = value;
29
30 @action
30 - void setFiatMode(FiatApiMode value) {
31 - _settingsStore.fiatApiMode = value;
31 + void setFiatMode(bool value) {
32 + if (value) {
33 + _settingsStore.fiatApiMode = FiatApiMode.disabled;
34 + return;
35 + }
36 + _settingsStore.fiatApiMode = FiatApiMode.enabled;
37 }
38
39 }