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 e59d9dfdaf.

* fixes

* PR fixes

* remove trocador menu icon
This commit is contained in:
Serhii 2023-11-17 01:23:34 +02:00 committed by GitHub
parent bb5336ff60
commit 36361ef329
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 134 additions and 5 deletions

View file

@ -45,6 +45,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar
import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart';
import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart';
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
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';
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
@ -699,6 +701,8 @@ Future<void> setup({
return PrivacySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
});
getIt.registerFactory(() => TrocadorProvidersViewModel(getIt.get<SettingsStore>()));
getIt.registerFactory(() {
return OtherSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
});
@ -752,6 +756,8 @@ Future<void> setup({
getIt.registerFactory(() => PrivacyPage(getIt.get<PrivacySettingsViewModel>()));
getIt.registerFactory(() => TrocadorProvidersPage(getIt.get<TrocadorProvidersViewModel>()));
getIt.registerFactory(() => DomainLookupsPage(getIt.get<PrivacySettingsViewModel>()));
getIt.registerFactory(() => DisplaySettingsPage(getIt.get<DisplaySettingsViewModel>()));

View file

@ -12,11 +12,27 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:http/http.dart';
class TrocadorExchangeProvider extends ExchangeProvider {
TrocadorExchangeProvider({this.useTorOnly = false})
: _lastUsedRateId = '',
TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
: _lastUsedRateId = '', _provider = [],
super(pairList: supportedPairs(_notSupported));
bool useTorOnly;
final Map<String, bool> providerStates;
static const List<String> availableProviders = [
'Swapter',
'StealthEx',
'Simpleswap',
'Swapuz'
'ChangeNow',
'Changehero',
'FixedFloat',
'LetsExchange',
'Exolix',
'Godex',
'Exch',
'CoinCraddle'
];
static const List<CryptoCurrency> _notSupported = [
CryptoCurrency.stx,
@ -33,6 +49,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
static const coinPath = 'api/coin';
String _lastUsedRateId;
List<dynamic> _provider;
@override
String get title => 'Trocador';
@ -105,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
'payment': isFixedRateMode ? 'True' : 'False',
'min_kycrating': 'C',
'markup': markup,
'best_only': 'True',
};
final uri = await _getUri(newRatePath, params);
@ -115,6 +131,9 @@ class TrocadorExchangeProvider extends ExchangeProvider {
final toAmount = double.parse(responseJSON['amount_to'].toString());
final rateId = responseJSON['trade_id'] as String? ?? '';
var quotes = responseJSON['quotes']['quotes'] as List;
_provider = quotes.map((quote) => quote['provider']).toList();
if (rateId.isNotEmpty) _lastUsedRateId = rateId;
return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount);
@ -126,6 +145,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final params = {
'api_key': apiKey,
'ticker_from': _normalizeCurrency(request.fromCurrency),
@ -135,7 +155,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
'payment': isFixedRateMode ? 'True' : 'False',
'min_kycrating': 'C',
'markup': markup,
'best_only': 'True',
if (!isFixedRateMode) 'amount_from': request.fromAmount,
if (isFixedRateMode) 'amount_to': request.toAmount,
'address': request.toAddress,
@ -153,6 +172,22 @@ class TrocadorExchangeProvider extends ExchangeProvider {
params['id'] = _lastUsedRateId;
}
String firstAvailableProvider = '';
for (var provider in _provider) {
if (providerStates.containsKey(provider) && providerStates[provider] == true) {
firstAvailableProvider = provider as String;
break;
}
}
if (firstAvailableProvider.isEmpty) {
throw Exception('No available provider is enabled');
}
params['provider'] = firstAvailableProvider;
final uri = await _getUri(createTradePath, params);
final response = await get(uri);

View file

@ -42,6 +42,7 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart';
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
@ -323,6 +324,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
return CupertinoPageRoute<void>(
fullscreenDialog: true, builder: (_) => getIt.get<PrivacyPage>());
case Routes.trocadorProvidersPage:
return CupertinoPageRoute<void>(
fullscreenDialog: true, builder: (_) => getIt.get<TrocadorProvidersPage>());
case Routes.domainLookupsPage:
return CupertinoPageRoute<void>(
fullscreenDialog: true, builder: (_) => getIt.get<DomainLookupsPage>());

View file

@ -81,6 +81,7 @@ class Routes {
static const connectionSync = '/connection_sync_page';
static const securityBackupPage = '/security_and_backup_page';
static const privacyPage = '/privacy_page';
static const trocadorProvidersPage = '/trocador_providers_page';
static const domainLookupsPage = '/domain_lookups_page';
static const displaySettingsPage = '/display_settings_page';
static const otherSettingsPage = '/other_settings_page';

View file

@ -90,6 +90,10 @@ class PrivacyPage extends BasePage {
title: S.current.domain_looks_up,
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
),
SettingsCellWithArrow(
title: 'Trocador providers',
handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
),
],
);
}),

View file

@ -0,0 +1,37 @@
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
class TrocadorProvidersPage extends BasePage {
TrocadorProvidersPage(this.trocadorProvidersViewModel);
@override
String get title => 'Trocador Providers';
final TrocadorProvidersViewModel trocadorProvidersViewModel;
@override
Widget body(BuildContext context) {
final availableProviders = TrocadorExchangeProvider.availableProviders;
final providerStates = trocadorProvidersViewModel.providerStates;
return Container(
padding: EdgeInsets.only(top: 10),
child: ListView.builder(
itemCount: availableProviders.length,
itemBuilder: (_, index) {
String provider = availableProviders[index];
return Observer(
builder: (_) => SettingsSwitcherCell(
title: provider,
value: providerStates[provider] ?? false,
onValueChange: (BuildContext _, bool value) {
trocadorProvidersViewModel.toggleProviderState(provider);
}));
},
),
);
}
}

View file

@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
@ -161,6 +162,8 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
}
initializeTrocadorProviderStates();
reaction(
(_) => fiatCurrency,
(FiatCurrency fiatCurrency) => sharedPreferences.setString(
@ -515,6 +518,9 @@ abstract class SettingsStoreBase with Store {
@observable
ObservableMap<WalletType, TransactionPriority> priority;
@observable
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
@observable
SortBalanceBy sortBalanceBy;
@ -1059,6 +1065,19 @@ abstract class SettingsStoreBase with Store {
powNodes[walletType] = node;
}
void initializeTrocadorProviderStates() {
for (var provider in TrocadorExchangeProvider.availableProviders) {
final savedState = _sharedPreferences.getBool(provider) ?? true;
trocadorProviderStates[provider] = savedState;
}
}
void saveTrocadorProviderState(String providerName, bool state) {
_sharedPreferences.setBool(providerName, state);
trocadorProviderStates[providerName] = state;
}
static Future<String?> _getDeviceName() async {
String? deviceName = '';
final deviceInfoPlugin = DeviceInfoPlugin();

View file

@ -146,7 +146,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
ChangeNowExchangeProvider(settingsStore: _settingsStore),
SideShiftExchangeProvider(),
SimpleSwapExchangeProvider(),
TrocadorExchangeProvider(useTorOnly: _useTorOnly),
TrocadorExchangeProvider(useTorOnly: _useTorOnly,
providerStates: _settingsStore.trocadorProviderStates),
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
];

View file

@ -0,0 +1,21 @@
import 'package:cake_wallet/store/settings_store.dart';
import 'package:mobx/mobx.dart';
part 'trocador_providers_view_model.g.dart';
class TrocadorProvidersViewModel = TrocadorProvidersViewModelBase with _$TrocadorProvidersViewModel;
abstract class TrocadorProvidersViewModelBase with Store {
TrocadorProvidersViewModelBase(this._settingsStore);
final SettingsStore _settingsStore;
@computed
Map<String, bool> get providerStates => _settingsStore.trocadorProviderStates;
@action
void toggleProviderState(String providerName) {
final currentState = providerStates[providerName] ?? false;
_settingsStore.saveTrocadorProviderState(providerName, !currentState);
}
}