CW-526-Add-Trocador-providers-option-in-privacy-settings (#1177)
* Trocador settings page UI * add trocador providers states * add settings icon * minor fix * Revert "minor fix" This reverts commit e59d9dfdaf9bd1c13a17ae5012db80a8f973a4d4. * fixes * PR fixes * remove trocador menu icon
Serhii committed
Nov 17, 2023 at 01:23 UTC
36361ef329fb7ae988d3e4e48b4109b7b98cc836
9 files changed
+134
-5
lib/di.dart
+6
@@ -45,6 +45,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar
45
import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart';
46
import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart';
47
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
48
+import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
49
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
50
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
51
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
@@ -92,6 +93,7 @@ import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
93
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
94
import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
95
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
96
+import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
97
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
98
import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
99
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
@@ -699,6 +701,8 @@ Future<void> setup({
701
return PrivacySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
702
});
703
704
+ getIt.registerFactory(() => TrocadorProvidersViewModel(getIt.get<SettingsStore>()));
705
+
706
getIt.registerFactory(() {
707
return OtherSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
708
});
@@ -752,6 +756,8 @@ Future<void> setup({
756
757
getIt.registerFactory(() => PrivacyPage(getIt.get<PrivacySettingsViewModel>()));
758
759
+ getIt.registerFactory(() => TrocadorProvidersPage(getIt.get<TrocadorProvidersViewModel>()));
760
+
761
getIt.registerFactory(() => DomainLookupsPage(getIt.get<PrivacySettingsViewModel>()));
762
763
getIt.registerFactory(() => DisplaySettingsPage(getIt.get<DisplaySettingsViewModel>()));
lib/exchange/provider/trocador_exchange_provider.dart
+39
-4
@@ -12,11 +12,27 @@ import 'package:cw_core/crypto_currency.dart';
12
import 'package:http/http.dart';
13
14
class TrocadorExchangeProvider extends ExchangeProvider {
15
- TrocadorExchangeProvider({this.useTorOnly = false})
16
- : _lastUsedRateId = '',
15
+ TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
16
+ : _lastUsedRateId = '', _provider = [],
17
super(pairList: supportedPairs(_notSupported));
18
19
bool useTorOnly;
20
+ final Map<String, bool> providerStates;
21
+
22
+ static const List<String> availableProviders = [
23
+ 'Swapter',
24
+ 'StealthEx',
25
+ 'Simpleswap',
26
+ 'Swapuz'
27
+ 'ChangeNow',
28
+ 'Changehero',
29
+ 'FixedFloat',
30
+ 'LetsExchange',
31
+ 'Exolix',
32
+ 'Godex',
33
+ 'Exch',
34
+ 'CoinCraddle'
35
+ ];
36
37
static const List<CryptoCurrency> _notSupported = [
38
CryptoCurrency.stx,
@@ -33,6 +49,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
49
static const coinPath = 'api/coin';
50
51
String _lastUsedRateId;
52
+ List<dynamic> _provider;
53
54
@override
55
String get title => 'Trocador';
@@ -105,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
122
'payment': isFixedRateMode ? 'True' : 'False',
123
'min_kycrating': 'C',
124
'markup': markup,
108
- 'best_only': 'True',
125
};
126
127
final uri = await _getUri(newRatePath, params);
@@ -115,6 +131,9 @@ class TrocadorExchangeProvider extends ExchangeProvider {
131
final toAmount = double.parse(responseJSON['amount_to'].toString());
132
final rateId = responseJSON['trade_id'] as String? ?? '';
133
134
+ var quotes = responseJSON['quotes']['quotes'] as List;
135
+ _provider = quotes.map((quote) => quote['provider']).toList();
136
+
137
if (rateId.isNotEmpty) _lastUsedRateId = rateId;
138
139
return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount);
@@ -126,6 +145,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
145
146
@override
147
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
148
+
149
final params = {
150
'api_key': apiKey,
151
'ticker_from': _normalizeCurrency(request.fromCurrency),
@@ -135,7 +155,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
155
'payment': isFixedRateMode ? 'True' : 'False',
156
'min_kycrating': 'C',
157
'markup': markup,
138
- 'best_only': 'True',
158
if (!isFixedRateMode) 'amount_from': request.fromAmount,
159
if (isFixedRateMode) 'amount_to': request.toAmount,
160
'address': request.toAddress,
@@ -153,6 +172,22 @@ class TrocadorExchangeProvider extends ExchangeProvider {
172
params['id'] = _lastUsedRateId;
173
}
174
175
+
176
+ String firstAvailableProvider = '';
177
+
178
+ for (var provider in _provider) {
179
+ if (providerStates.containsKey(provider) && providerStates[provider] == true) {
180
+ firstAvailableProvider = provider as String;
181
+ break;
182
+ }
183
+ }
184
+
185
+ if (firstAvailableProvider.isEmpty) {
186
+ throw Exception('No available provider is enabled');
187
+ }
188
+
189
+ params['provider'] = firstAvailableProvider;
190
+
191
final uri = await _getUri(createTradePath, params);
192
final response = await get(uri);
193
lib/router.dart
+5
@@ -42,6 +42,7 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart';
42
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
43
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
44
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
45
+import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
46
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
47
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
48
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
@@ -323,6 +324,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
324
return CupertinoPageRoute<void>(
325
fullscreenDialog: true, builder: (_) => getIt.get<PrivacyPage>());
326
327
+ case Routes.trocadorProvidersPage:
328
+ return CupertinoPageRoute<void>(
329
+ fullscreenDialog: true, builder: (_) => getIt.get<TrocadorProvidersPage>());
330
+
331
case Routes.domainLookupsPage:
332
return CupertinoPageRoute<void>(
333
fullscreenDialog: true, builder: (_) => getIt.get<DomainLookupsPage>());
lib/routes.dart
+1
@@ -81,6 +81,7 @@ class Routes {
81
static const connectionSync = '/connection_sync_page';
82
static const securityBackupPage = '/security_and_backup_page';
83
static const privacyPage = '/privacy_page';
84
+ static const trocadorProvidersPage = '/trocador_providers_page';
85
static const domainLookupsPage = '/domain_lookups_page';
86
static const displaySettingsPage = '/display_settings_page';
87
static const otherSettingsPage = '/other_settings_page';
lib/src/screens/settings/privacy_page.dart
+4
@@ -90,6 +90,10 @@ class PrivacyPage extends BasePage {
90
title: S.current.domain_looks_up,
91
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
92
),
93
+ SettingsCellWithArrow(
94
+ title: 'Trocador providers',
95
+ handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
96
+ ),
97
],
98
);
99
}),
lib/src/screens/settings/trocador_providers_page.dart
new
+37
@@ -0,0 +1,37 @@
1
+import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
2
+import 'package:cake_wallet/src/screens/base_page.dart';
3
+import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
4
+import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
5
+import 'package:flutter/material.dart';
6
+import 'package:flutter_mobx/flutter_mobx.dart';
7
+
8
+class TrocadorProvidersPage extends BasePage {
9
+ TrocadorProvidersPage(this.trocadorProvidersViewModel);
10
+
11
+ @override
12
+ String get title => 'Trocador Providers';
13
+
14
+ final TrocadorProvidersViewModel trocadorProvidersViewModel;
15
+
16
+ @override
17
+ Widget body(BuildContext context) {
18
+ final availableProviders = TrocadorExchangeProvider.availableProviders;
19
+ final providerStates = trocadorProvidersViewModel.providerStates;
20
+ return Container(
21
+ padding: EdgeInsets.only(top: 10),
22
+ child: ListView.builder(
23
+ itemCount: availableProviders.length,
24
+ itemBuilder: (_, index) {
25
+ String provider = availableProviders[index];
26
+ return Observer(
27
+ builder: (_) => SettingsSwitcherCell(
28
+ title: provider,
29
+ value: providerStates[provider] ?? false,
30
+ onValueChange: (BuildContext _, bool value) {
31
+ trocadorProvidersViewModel.toggleProviderState(provider);
32
+ }));
33
+ },
34
+ ),
35
+ );
36
+ }
37
+}
lib/store/settings_store.dart
+19
@@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
10
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
11
import 'package:cake_wallet/entities/preferences_key.dart';
12
import 'package:cake_wallet/entities/sort_balance_types.dart';
13
+import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
14
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
15
import 'package:cake_wallet/utils/device_info.dart';
16
import 'package:cake_wallet/ethereum/ethereum.dart';
@@ -161,6 +162,8 @@ abstract class SettingsStoreBase with Store {
162
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
163
}
164
165
+ initializeTrocadorProviderStates();
166
+
167
reaction(
168
(_) => fiatCurrency,
169
(FiatCurrency fiatCurrency) => sharedPreferences.setString(
@@ -515,6 +518,9 @@ abstract class SettingsStoreBase with Store {
518
@observable
519
ObservableMap<WalletType, TransactionPriority> priority;
520
521
+ @observable
522
+ ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
523
+
524
@observable
525
SortBalanceBy sortBalanceBy;
526
@@ -1059,6 +1065,19 @@ abstract class SettingsStoreBase with Store {
1065
powNodes[walletType] = node;
1066
}
1067
1068
+ void initializeTrocadorProviderStates() {
1069
+ for (var provider in TrocadorExchangeProvider.availableProviders) {
1070
+ final savedState = _sharedPreferences.getBool(provider) ?? true;
1071
+ trocadorProviderStates[provider] = savedState;
1072
+ }
1073
+ }
1074
+
1075
+ void saveTrocadorProviderState(String providerName, bool state) {
1076
+ _sharedPreferences.setBool(providerName, state);
1077
+ trocadorProviderStates[providerName] = state;
1078
+ }
1079
+
1080
+
1081
static Future<String?> _getDeviceName() async {
1082
String? deviceName = '';
1083
final deviceInfoPlugin = DeviceInfoPlugin();
lib/view_model/exchange/exchange_view_model.dart
+2
-1
@@ -146,7 +146,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
146
ChangeNowExchangeProvider(settingsStore: _settingsStore),
147
SideShiftExchangeProvider(),
148
SimpleSwapExchangeProvider(),
149
- TrocadorExchangeProvider(useTorOnly: _useTorOnly),
149
+ TrocadorExchangeProvider(useTorOnly: _useTorOnly,
150
+ providerStates: _settingsStore.trocadorProviderStates),
151
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
152
];
153
lib/view_model/settings/trocador_providers_view_model.dart
new
+21
@@ -0,0 +1,21 @@
1
+import 'package:cake_wallet/store/settings_store.dart';
2
+import 'package:mobx/mobx.dart';
3
+
4
+part 'trocador_providers_view_model.g.dart';
5
+
6
+class TrocadorProvidersViewModel = TrocadorProvidersViewModelBase with _$TrocadorProvidersViewModel;
7
+
8
+abstract class TrocadorProvidersViewModelBase with Store {
9
+ TrocadorProvidersViewModelBase(this._settingsStore);
10
+
11
+ final SettingsStore _settingsStore;
12
+
13
+ @computed
14
+ Map<String, bool> get providerStates => _settingsStore.trocadorProviderStates;
15
+
16
+ @action
17
+ void toggleProviderState(String providerName) {
18
+ final currentState = providerStates[providerName] ?? false;
19
+ _settingsStore.saveTrocadorProviderState(providerName, !currentState);
20
+ }
21
+}
\ No newline at end of file