2022-10-20 17:47:36 +00:00
|
|
|
import 'dart:async';
|
2022-09-01 14:12:38 +00:00
|
|
|
import 'dart:collection';
|
|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
2022-04-13 13:28:21 +00:00
|
|
|
import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart';
|
2022-08-31 15:34:07 +00:00
|
|
|
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart';
|
2021-12-24 12:37:24 +00:00
|
|
|
import 'package:cw_core/wallet_base.dart';
|
|
|
|
import 'package:cw_core/crypto_currency.dart';
|
|
|
|
import 'package:cw_core/sync_status.dart';
|
|
|
|
import 'package:cw_core/wallet_type.dart';
|
|
|
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
2020-09-21 11:50:26 +00:00
|
|
|
import 'package:cake_wallet/exchange/exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/limits.dart';
|
|
|
|
import 'package:cake_wallet/exchange/trade.dart';
|
|
|
|
import 'package:cake_wallet/exchange/limits_state.dart';
|
2020-08-26 17:31:23 +00:00
|
|
|
import 'package:cake_wallet/store/dashboard/trades_store.dart';
|
2021-01-05 18:31:03 +00:00
|
|
|
import 'package:cake_wallet/store/settings_store.dart';
|
2020-07-31 15:29:21 +00:00
|
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:mobx/mobx.dart';
|
|
|
|
import 'package:cake_wallet/generated/i18n.dart';
|
|
|
|
import 'package:hive/hive.dart';
|
2020-09-21 11:50:26 +00:00
|
|
|
import 'package:cake_wallet/exchange/exchange_trade_state.dart';
|
|
|
|
import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/changenow/changenow_request.dart';
|
|
|
|
import 'package:cake_wallet/exchange/trade_request.dart';
|
|
|
|
import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/xmrto/xmrto_trade_request.dart';
|
|
|
|
import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart';
|
|
|
|
import 'package:cake_wallet/exchange/morphtoken/morphtoken_request.dart';
|
2020-07-31 15:29:21 +00:00
|
|
|
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
2020-09-21 11:50:26 +00:00
|
|
|
import 'package:cake_wallet/exchange/exchange_template.dart';
|
2022-09-01 14:12:38 +00:00
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
2020-07-31 15:29:21 +00:00
|
|
|
|
|
|
|
part 'exchange_view_model.g.dart';
|
|
|
|
|
|
|
|
class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel;
|
|
|
|
|
|
|
|
abstract class ExchangeViewModelBase with Store {
|
2021-01-05 18:31:03 +00:00
|
|
|
ExchangeViewModelBase(this.wallet, this.trades, this._exchangeTemplateStore,
|
2022-10-12 17:09:57 +00:00
|
|
|
this.tradesStore, this._settingsStore, this.sharedPreferences)
|
|
|
|
: _cryptoNumberFormat = NumberFormat(),
|
|
|
|
isReverse = false,
|
|
|
|
isFixedRateMode = false,
|
|
|
|
isReceiveAmountEntered = false,
|
|
|
|
depositAmount = '',
|
|
|
|
receiveAmount = '',
|
|
|
|
receiveAddress = '',
|
|
|
|
depositAddress = '',
|
|
|
|
isDepositAddressEnabled = false,
|
|
|
|
isReceiveAddressEnabled = false,
|
|
|
|
isReceiveAmountEditable = false,
|
|
|
|
receiveCurrencies = <CryptoCurrency>[],
|
|
|
|
depositCurrencies = <CryptoCurrency>[],
|
|
|
|
limits = Limits(min: 0, max: 0),
|
|
|
|
tradeState = ExchangeTradeStateInitial(),
|
|
|
|
limitsState = LimitsInitialState(),
|
|
|
|
receiveCurrency = wallet.currency,
|
|
|
|
depositCurrency = wallet.currency,
|
|
|
|
providerList = [ChangeNowExchangeProvider(), SideShiftExchangeProvider(), SimpleSwapExchangeProvider()],
|
2022-10-20 17:47:36 +00:00
|
|
|
selectedProviders = ObservableList<ExchangeProvider>() {
|
add new coins to exchange (#499)
* add new coins
APE, AVAXC, BTT, BTTBSC, DOGE, FIRO, USDTTRC20, HBAR, SC, SOL, USDC, USDCSOL, ZEN, XVG
* remove UST icon
* remove xhv from excludeDepositCurrencies
* remove xhv from excludeReceiveCurrencies
2022-09-07 12:10:21 +00:00
|
|
|
const excludeDepositCurrencies = [CryptoCurrency.btt, CryptoCurrency.nano];
|
|
|
|
const excludeReceiveCurrencies = [CryptoCurrency.xlm, CryptoCurrency.xrp,
|
|
|
|
CryptoCurrency.bnb, CryptoCurrency.btt, CryptoCurrency.nano];
|
2022-09-01 18:46:14 +00:00
|
|
|
_initialPairBasedOnWallet();
|
2022-10-20 17:47:36 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
final Map<String, dynamic> exchangeProvidersSelection = json
|
|
|
|
.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}") as Map<String, dynamic>;
|
|
|
|
|
|
|
|
/// if the provider is not in the user settings (user's first time or newly added provider)
|
|
|
|
/// then use its default value decided by us
|
2022-09-01 18:46:14 +00:00
|
|
|
selectedProviders = ObservableList.of(providersForCurrentPair().where(
|
2022-09-01 14:12:38 +00:00
|
|
|
(element) => exchangeProvidersSelection[element.title] == null
|
|
|
|
? element.isEnabled
|
|
|
|
: (exchangeProvidersSelection[element.title] as bool))
|
|
|
|
.toList());
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
_setAvailableProviders();
|
|
|
|
_calculateBestRate();
|
|
|
|
|
|
|
|
bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate());
|
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
|
|
|
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
|
|
|
receiveAddress = '';
|
2021-07-13 05:46:34 +00:00
|
|
|
depositAddress = depositCurrency == wallet.currency
|
|
|
|
? wallet.walletAddresses.address : '';
|
2022-09-01 14:12:38 +00:00
|
|
|
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = wallet.type == WalletType.bitcoin ? 8 : 12;
|
2020-09-02 08:47:41 +00:00
|
|
|
provider = providersForCurrentPair().first;
|
2020-11-10 14:58:40 +00:00
|
|
|
final initialProvider = provider;
|
2022-10-12 17:09:57 +00:00
|
|
|
provider!.checkIsAvailable().then((bool isAvailable) {
|
2020-11-10 14:58:40 +00:00
|
|
|
if (!isAvailable && provider == initialProvider) {
|
|
|
|
provider = providerList.firstWhere(
|
|
|
|
(provider) => provider is ChangeNowExchangeProvider,
|
|
|
|
orElse: () => providerList.last);
|
|
|
|
_onPairChange();
|
|
|
|
}
|
|
|
|
});
|
2021-05-07 07:36:38 +00:00
|
|
|
receiveCurrencies = CryptoCurrency.all
|
2022-04-01 13:31:05 +00:00
|
|
|
.where((cryptoCurrency) => !excludeReceiveCurrencies.contains(cryptoCurrency))
|
|
|
|
.toList();
|
|
|
|
depositCurrencies = CryptoCurrency.all
|
|
|
|
.where((cryptoCurrency) => !excludeDepositCurrencies.contains(cryptoCurrency))
|
2021-05-10 16:51:13 +00:00
|
|
|
.toList();
|
2022-01-26 15:44:15 +00:00
|
|
|
_defineIsReceiveAmountEditable();
|
2020-07-31 15:29:21 +00:00
|
|
|
loadLimits();
|
2022-01-26 15:44:15 +00:00
|
|
|
reaction(
|
|
|
|
(_) => isFixedRateMode,
|
2022-01-27 09:20:51 +00:00
|
|
|
(Object _) => loadLimits());
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
final WalletBase wallet;
|
|
|
|
final Box<Trade> trades;
|
2020-10-07 05:58:22 +00:00
|
|
|
final ExchangeTemplateStore _exchangeTemplateStore;
|
2020-08-26 17:31:23 +00:00
|
|
|
final TradesStore tradesStore;
|
2022-09-01 14:12:38 +00:00
|
|
|
final SharedPreferences sharedPreferences;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
|
|
|
@observable
|
2022-10-12 17:09:57 +00:00
|
|
|
ExchangeProvider? provider;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
/// Maps in dart are not sorted by default
|
|
|
|
/// SplayTreeMap is a map sorted by keys
|
|
|
|
/// will use it to sort available providers
|
2022-10-20 17:47:36 +00:00
|
|
|
/// based on the rate they yield for the current trade
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// initialize with descending comparator
|
|
|
|
/// since we want largest rate first
|
|
|
|
final SplayTreeMap<double, ExchangeProvider> _sortedAvailableProviders =
|
|
|
|
SplayTreeMap<double, ExchangeProvider>((double a, double b) => b.compareTo(a));
|
|
|
|
|
|
|
|
final List<ExchangeProvider> _tradeAvailableProviders = [];
|
2022-09-01 14:12:38 +00:00
|
|
|
|
|
|
|
@observable
|
|
|
|
ObservableList<ExchangeProvider> selectedProviders;
|
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
@observable
|
|
|
|
List<ExchangeProvider> providerList;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
CryptoCurrency depositCurrency;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
CryptoCurrency receiveCurrency;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
LimitsState limitsState;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
ExchangeTradeState tradeState;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
String depositAmount;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
String receiveAmount;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
String depositAddress;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
String receiveAddress;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
bool isDepositAddressEnabled;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
bool isReceiveAddressEnabled;
|
|
|
|
|
2020-10-12 16:47:01 +00:00
|
|
|
@observable
|
2020-09-25 19:55:41 +00:00
|
|
|
bool isReceiveAmountEntered;
|
|
|
|
|
2021-02-16 19:06:23 +00:00
|
|
|
@observable
|
|
|
|
bool isReceiveAmountEditable;
|
|
|
|
|
|
|
|
@observable
|
|
|
|
bool isFixedRateMode;
|
|
|
|
|
2020-11-02 11:33:45 +00:00
|
|
|
@computed
|
|
|
|
SyncStatus get status => wallet.syncStatus;
|
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
@computed
|
|
|
|
ObservableList<ExchangeTemplate> get templates =>
|
2020-10-07 05:58:22 +00:00
|
|
|
_exchangeTemplateStore.templates;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2021-01-05 18:31:03 +00:00
|
|
|
bool get hasAllAmount =>
|
|
|
|
wallet.type == WalletType.bitcoin && depositCurrency == wallet.currency;
|
|
|
|
|
2021-12-24 12:37:24 +00:00
|
|
|
bool get isMoneroWallet => wallet.type == WalletType.monero;
|
2021-07-23 11:05:33 +00:00
|
|
|
|
2021-04-06 17:11:26 +00:00
|
|
|
List<CryptoCurrency> receiveCurrencies;
|
|
|
|
|
2022-04-01 13:31:05 +00:00
|
|
|
List<CryptoCurrency> depositCurrencies;
|
|
|
|
|
2021-01-05 18:31:03 +00:00
|
|
|
Limits limits;
|
|
|
|
|
2022-01-26 15:44:15 +00:00
|
|
|
bool isReverse;
|
|
|
|
|
2021-01-05 18:31:03 +00:00
|
|
|
NumberFormat _cryptoNumberFormat;
|
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
final SettingsStore _settingsStore;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
double _bestRate = 0.0;
|
|
|
|
|
|
|
|
late Timer bestRateSync;
|
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
@action
|
2022-10-12 17:09:57 +00:00
|
|
|
void changeDepositCurrency({required CryptoCurrency currency}) {
|
2020-07-31 15:29:21 +00:00
|
|
|
depositCurrency = currency;
|
2021-02-18 19:08:52 +00:00
|
|
|
isFixedRateMode = false;
|
2020-07-31 15:29:21 +00:00
|
|
|
_onPairChange();
|
|
|
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
|
|
|
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
2022-10-12 17:09:57 +00:00
|
|
|
void changeReceiveCurrency({required CryptoCurrency currency}) {
|
2020-07-31 15:29:21 +00:00
|
|
|
receiveCurrency = currency;
|
2021-02-18 19:08:52 +00:00
|
|
|
isFixedRateMode = false;
|
2020-07-31 15:29:21 +00:00
|
|
|
_onPairChange();
|
|
|
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
|
|
|
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
2022-10-20 17:47:36 +00:00
|
|
|
Future<void> changeReceiveAmount({required String amount}) async {
|
2020-07-31 15:29:21 +00:00
|
|
|
receiveAmount = amount;
|
2022-01-26 15:44:15 +00:00
|
|
|
isReverse = true;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
if (amount.isEmpty) {
|
2020-07-31 15:29:21 +00:00
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
final _enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0;
|
2022-09-01 14:12:38 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
if (_bestRate == 0) {
|
|
|
|
depositAmount = S.current.fetching;
|
|
|
|
|
|
|
|
await _calculateBestRate();
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
2022-10-20 17:47:36 +00:00
|
|
|
|
|
|
|
depositAmount = _cryptoNumberFormat
|
|
|
|
.format(_enteredAmount / _bestRate)
|
|
|
|
.toString()
|
|
|
|
.replaceAll(RegExp('\\,'), '');
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
2022-10-20 17:47:36 +00:00
|
|
|
Future<void> changeDepositAmount({required String amount}) async {
|
2020-07-31 15:29:21 +00:00
|
|
|
depositAmount = amount;
|
2022-01-26 15:44:15 +00:00
|
|
|
isReverse = false;
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
if (amount.isEmpty) {
|
2020-07-31 15:29:21 +00:00
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
final _enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0;
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
/// in case the best rate was not calculated yet
|
|
|
|
if (_bestRate == 0) {
|
|
|
|
receiveAmount = S.current.fetching;
|
|
|
|
|
|
|
|
await _calculateBestRate();
|
|
|
|
}
|
|
|
|
|
|
|
|
receiveAmount = _cryptoNumberFormat
|
|
|
|
.format(_bestRate * _enteredAmount)
|
|
|
|
.toString()
|
|
|
|
.replaceAll(RegExp('\\,'), '');
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _calculateBestRate() async {
|
|
|
|
final result = await Future.wait<double>(
|
|
|
|
_tradeAvailableProviders
|
|
|
|
.map((element) => element.calculateAmount(
|
|
|
|
from: depositCurrency,
|
|
|
|
to: receiveCurrency,
|
|
|
|
amount: 1,
|
|
|
|
isFixedRateMode: isFixedRateMode,
|
|
|
|
isReceiveAmount: false))
|
|
|
|
);
|
|
|
|
|
|
|
|
_sortedAvailableProviders.clear();
|
|
|
|
|
|
|
|
for (int i=0;i<result.length;i++) {
|
|
|
|
if (result[i] != 0) {
|
|
|
|
/// add this provider as its valid for this trade
|
|
|
|
_sortedAvailableProviders[result[i]] = _tradeAvailableProviders[i];
|
2022-09-07 11:43:03 +00:00
|
|
|
}
|
2022-10-20 17:47:36 +00:00
|
|
|
}
|
|
|
|
if (_sortedAvailableProviders.isNotEmpty) {
|
|
|
|
_bestRate = _sortedAvailableProviders.keys.first;
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
2022-10-20 17:47:36 +00:00
|
|
|
Future<void> loadLimits() async {
|
2022-09-01 14:12:38 +00:00
|
|
|
if (selectedProviders.isEmpty) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
limitsState = LimitsIsLoading();
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
final from = isFixedRateMode
|
2022-01-26 15:44:15 +00:00
|
|
|
? receiveCurrency
|
|
|
|
: depositCurrency;
|
2022-10-20 17:47:36 +00:00
|
|
|
final to = isFixedRateMode
|
2022-01-26 15:44:15 +00:00
|
|
|
? depositCurrency
|
|
|
|
: receiveCurrency;
|
2022-09-01 14:12:38 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
double lowestMin = double.maxFinite;
|
|
|
|
double? highestMax = 0.0;
|
|
|
|
|
|
|
|
for (var provider in selectedProviders) {
|
|
|
|
/// if this provider is not valid for the current pair, skip it
|
|
|
|
if (!providersForCurrentPair().contains(provider)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
final tempLimits = await provider.fetchLimits(
|
|
|
|
from: from,
|
|
|
|
to: to,
|
|
|
|
isFixedRateMode: isFixedRateMode);
|
|
|
|
|
|
|
|
if (tempLimits.min != null && tempLimits.min! < lowestMin) {
|
|
|
|
lowestMin = tempLimits.min!;
|
|
|
|
}
|
|
|
|
if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) {
|
|
|
|
highestMax = tempLimits.max;
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
2022-10-20 17:47:36 +00:00
|
|
|
} catch (e) {
|
|
|
|
continue;
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
2022-10-20 17:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lowestMin < double.maxFinite) {
|
|
|
|
limits = Limits(min: lowestMin, max: highestMax);
|
2022-09-01 14:12:38 +00:00
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
limitsState = LimitsLoadedSuccessfully(limits: limits);
|
2022-10-20 17:47:36 +00:00
|
|
|
} else {
|
|
|
|
limitsState = LimitsLoadedFailure(error: 'Limits loading failed');
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
2022-10-12 17:09:57 +00:00
|
|
|
Future<void> createTrade() async {
|
|
|
|
TradeRequest? request;
|
|
|
|
String amount = '';
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
for (var provider in _sortedAvailableProviders.values) {
|
2022-09-01 14:12:38 +00:00
|
|
|
if (!(await provider.checkIsAvailable())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (provider is SideShiftExchangeProvider) {
|
|
|
|
request = SideShiftRequest(
|
2022-04-13 13:28:21 +00:00
|
|
|
depositMethod: depositCurrency,
|
|
|
|
settleMethod: receiveCurrency,
|
2022-10-20 17:47:36 +00:00
|
|
|
depositAmount: depositAmount.replaceAll(',', '.'),
|
2022-04-13 13:28:21 +00:00
|
|
|
settleAddress: receiveAddress,
|
|
|
|
refundAddress: depositAddress,
|
2022-09-01 14:12:38 +00:00
|
|
|
);
|
|
|
|
amount = depositAmount;
|
|
|
|
}
|
2022-04-13 13:28:21 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
if (provider is SimpleSwapExchangeProvider) {
|
|
|
|
request = SimpleSwapRequest(
|
2022-08-31 15:34:07 +00:00
|
|
|
from: depositCurrency,
|
|
|
|
to: receiveCurrency,
|
2022-10-20 17:47:36 +00:00
|
|
|
amount: depositAmount.replaceAll(',', '.'),
|
2022-08-31 15:34:07 +00:00
|
|
|
address: receiveAddress,
|
|
|
|
refundAddress: depositAddress,
|
2022-09-01 14:12:38 +00:00
|
|
|
);
|
|
|
|
amount = depositAmount;
|
|
|
|
}
|
2022-08-31 15:34:07 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
if (provider is XMRTOExchangeProvider) {
|
|
|
|
request = XMRTOTradeRequest(
|
|
|
|
from: depositCurrency,
|
|
|
|
to: receiveCurrency,
|
2022-10-20 17:47:36 +00:00
|
|
|
amount: depositAmount.replaceAll(',', '.'),
|
|
|
|
receiveAmount: receiveAmount.replaceAll(',', '.'),
|
2022-09-01 14:12:38 +00:00
|
|
|
address: receiveAddress,
|
|
|
|
refundAddress: depositAddress,
|
|
|
|
isBTCRequest: isReceiveAmountEntered);
|
|
|
|
amount = depositAmount;
|
|
|
|
}
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
if (provider is ChangeNowExchangeProvider) {
|
|
|
|
request = ChangeNowRequest(
|
|
|
|
from: depositCurrency,
|
|
|
|
to: receiveCurrency,
|
2022-10-20 17:47:36 +00:00
|
|
|
fromAmount: depositAmount.replaceAll(',', '.'),
|
|
|
|
toAmount: receiveAmount.replaceAll(',', '.'),
|
2022-09-01 14:12:38 +00:00
|
|
|
refundAddress: depositAddress,
|
|
|
|
address: receiveAddress,
|
|
|
|
isReverse: isReverse);
|
|
|
|
amount = isReverse ? receiveAmount : depositAmount;
|
|
|
|
}
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
if (provider is MorphTokenExchangeProvider) {
|
|
|
|
request = MorphTokenRequest(
|
|
|
|
from: depositCurrency,
|
|
|
|
to: receiveCurrency,
|
2022-10-20 17:47:36 +00:00
|
|
|
amount: depositAmount.replaceAll(',', '.'),
|
2022-09-01 14:12:38 +00:00
|
|
|
refundAddress: depositAddress,
|
|
|
|
address: receiveAddress);
|
|
|
|
amount = depositAmount;
|
|
|
|
}
|
2020-07-31 15:29:21 +00:00
|
|
|
|
2022-09-01 14:12:38 +00:00
|
|
|
amount = amount.replaceAll(',', '.');
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
if (limitsState is LimitsLoadedSuccessfully) {
|
2022-10-12 17:09:57 +00:00
|
|
|
if (double.parse(amount) < limits.min!) {
|
2022-09-01 14:12:38 +00:00
|
|
|
continue;
|
2022-10-12 17:09:57 +00:00
|
|
|
} else if (limits.max != null && double.parse(amount) > limits.max!) {
|
2022-09-01 14:12:38 +00:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
tradeState = TradeIsCreating();
|
|
|
|
final trade = await provider.createTrade(
|
2022-10-12 17:09:57 +00:00
|
|
|
request: request!, isFixedRateMode: isFixedRateMode);
|
2022-09-01 14:12:38 +00:00
|
|
|
trade.walletId = wallet.id;
|
|
|
|
tradesStore.setTrade(trade);
|
|
|
|
await trades.add(trade);
|
|
|
|
tradeState = TradeIsCreatedSuccessfully(trade: trade);
|
|
|
|
/// return after the first successful trade
|
|
|
|
return;
|
|
|
|
} catch (e) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-01 14:12:38 +00:00
|
|
|
|
|
|
|
/// if the code reached here then none of the providers succeeded
|
|
|
|
tradeState = TradeIsCreatedFailure(
|
|
|
|
title: S.current.trade_not_created,
|
|
|
|
error: S.current.none_of_selected_providers_can_exchange);
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
void reset() {
|
2021-02-19 08:37:30 +00:00
|
|
|
_initialPairBasedOnWallet();
|
2020-10-12 16:47:01 +00:00
|
|
|
isReceiveAmountEntered = false;
|
2020-07-31 15:29:21 +00:00
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
2021-07-13 05:46:34 +00:00
|
|
|
depositAddress = depositCurrency == wallet.currency
|
|
|
|
? wallet.walletAddresses.address : '';
|
|
|
|
receiveAddress = receiveCurrency == wallet.currency
|
|
|
|
? wallet.walletAddresses.address : '';
|
2020-07-31 15:29:21 +00:00
|
|
|
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
|
|
|
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
2021-02-18 19:08:52 +00:00
|
|
|
isFixedRateMode = false;
|
2020-07-31 15:29:21 +00:00
|
|
|
_onPairChange();
|
|
|
|
}
|
|
|
|
|
2021-01-05 18:31:03 +00:00
|
|
|
@action
|
|
|
|
void calculateDepositAllAmount() {
|
2021-12-24 12:37:24 +00:00
|
|
|
if (wallet.type == WalletType.bitcoin) {
|
2022-10-12 17:09:57 +00:00
|
|
|
final availableBalance = wallet.balance[wallet.currency]!.available;
|
|
|
|
final priority = _settingsStore.priority[wallet.type]!;
|
2021-01-27 13:51:51 +00:00
|
|
|
final fee = wallet.calculateEstimatedFee(priority, null);
|
2021-01-05 18:31:03 +00:00
|
|
|
|
|
|
|
if (availableBalance < fee || availableBalance == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final amount = availableBalance - fee;
|
2022-10-12 17:09:57 +00:00
|
|
|
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
|
2021-01-05 18:31:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-07 05:58:22 +00:00
|
|
|
void updateTemplate() => _exchangeTemplateStore.update();
|
|
|
|
|
2020-11-10 14:58:40 +00:00
|
|
|
void addTemplate(
|
2022-10-12 17:09:57 +00:00
|
|
|
{required String amount,
|
|
|
|
required String depositCurrency,
|
|
|
|
required String receiveCurrency,
|
|
|
|
required String provider,
|
|
|
|
required String depositAddress,
|
|
|
|
required String receiveAddress}) =>
|
2020-11-10 14:58:40 +00:00
|
|
|
_exchangeTemplateStore.addTemplate(
|
|
|
|
amount: amount,
|
|
|
|
depositCurrency: depositCurrency,
|
|
|
|
receiveCurrency: receiveCurrency,
|
|
|
|
provider: provider,
|
|
|
|
depositAddress: depositAddress,
|
|
|
|
receiveAddress: receiveAddress);
|
2020-10-07 05:58:22 +00:00
|
|
|
|
2022-10-12 17:09:57 +00:00
|
|
|
void removeTemplate({required ExchangeTemplate template}) =>
|
2020-11-10 14:58:40 +00:00
|
|
|
_exchangeTemplateStore.remove(template: template);
|
2020-10-07 05:58:22 +00:00
|
|
|
|
2020-07-31 15:29:21 +00:00
|
|
|
List<ExchangeProvider> providersForCurrentPair() {
|
|
|
|
return _providersForPair(from: depositCurrency, to: receiveCurrency);
|
|
|
|
}
|
|
|
|
|
|
|
|
List<ExchangeProvider> _providersForPair(
|
2022-10-12 17:09:57 +00:00
|
|
|
{required CryptoCurrency from, required CryptoCurrency to}) {
|
2020-07-31 15:29:21 +00:00
|
|
|
final providers = providerList
|
|
|
|
.where((provider) => provider.pairList
|
2020-09-02 08:47:41 +00:00
|
|
|
.where((pair) =>
|
2022-10-20 17:47:36 +00:00
|
|
|
pair.from == from && pair.to == to)
|
2020-09-02 08:47:41 +00:00
|
|
|
.isNotEmpty)
|
2020-07-31 15:29:21 +00:00
|
|
|
.toList();
|
|
|
|
|
|
|
|
return providers;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onPairChange() {
|
2022-09-01 14:12:38 +00:00
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
2022-10-20 17:47:36 +00:00
|
|
|
loadLimits();
|
|
|
|
_setAvailableProviders();
|
|
|
|
_bestRate = 0;
|
|
|
|
_calculateBestRate();
|
2020-07-31 15:29:21 +00:00
|
|
|
}
|
|
|
|
|
2020-09-02 08:47:41 +00:00
|
|
|
void _initialPairBasedOnWallet() {
|
|
|
|
switch (wallet.type) {
|
|
|
|
case WalletType.monero:
|
|
|
|
depositCurrency = CryptoCurrency.xmr;
|
|
|
|
receiveCurrency = CryptoCurrency.btc;
|
|
|
|
break;
|
|
|
|
case WalletType.bitcoin:
|
|
|
|
depositCurrency = CryptoCurrency.btc;
|
|
|
|
receiveCurrency = CryptoCurrency.xmr;
|
|
|
|
break;
|
2021-05-07 07:36:38 +00:00
|
|
|
case WalletType.litecoin:
|
|
|
|
depositCurrency = CryptoCurrency.ltc;
|
|
|
|
receiveCurrency = CryptoCurrency.xmr;
|
|
|
|
break;
|
2022-09-01 18:46:14 +00:00
|
|
|
case WalletType.haven:
|
|
|
|
depositCurrency = CryptoCurrency.xhv;
|
|
|
|
receiveCurrency = CryptoCurrency.btc;
|
|
|
|
break;
|
2020-09-02 08:47:41 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 17:36:03 +00:00
|
|
|
|
|
|
|
void _defineIsReceiveAmountEditable() {
|
2021-03-15 17:54:04 +00:00
|
|
|
/*if ((provider is ChangeNowExchangeProvider)
|
2021-02-23 17:36:03 +00:00
|
|
|
&&(depositCurrency == CryptoCurrency.xmr)
|
|
|
|
&&(receiveCurrency == CryptoCurrency.btc)) {
|
|
|
|
isReceiveAmountEditable = true;
|
|
|
|
} else {
|
|
|
|
isReceiveAmountEditable = false;
|
2021-03-15 17:54:04 +00:00
|
|
|
}*/
|
2022-01-26 15:44:15 +00:00
|
|
|
//isReceiveAmountEditable = false;
|
2022-09-01 14:12:38 +00:00
|
|
|
// isReceiveAmountEditable = selectedProviders.any((provider) => provider is ChangeNowExchangeProvider);
|
|
|
|
// isReceiveAmountEditable = provider is ChangeNowExchangeProvider || provider is SimpleSwapExchangeProvider;
|
|
|
|
isReceiveAmountEditable = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
void addExchangeProvider(ExchangeProvider provider) {
|
|
|
|
selectedProviders.add(provider);
|
2022-10-20 17:47:36 +00:00
|
|
|
if (providersForCurrentPair().contains(provider)) {
|
|
|
|
_tradeAvailableProviders.add(provider);
|
|
|
|
}
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
void removeExchangeProvider(ExchangeProvider provider) {
|
|
|
|
selectedProviders.remove(provider);
|
2022-10-20 17:47:36 +00:00
|
|
|
_tradeAvailableProviders.remove(provider);
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
void saveSelectedProviders() {
|
|
|
|
depositAmount = '';
|
|
|
|
receiveAmount = '';
|
|
|
|
isFixedRateMode = false;
|
|
|
|
_defineIsReceiveAmountEditable();
|
|
|
|
loadLimits();
|
2022-10-20 17:47:36 +00:00
|
|
|
_bestRate = 0;
|
|
|
|
_calculateBestRate();
|
2022-09-01 14:12:38 +00:00
|
|
|
|
|
|
|
final Map<String, dynamic> exchangeProvidersSelection = json
|
|
|
|
.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}") as Map<String, dynamic>;
|
|
|
|
|
2022-10-20 17:47:36 +00:00
|
|
|
for (var provider in providerList) {
|
|
|
|
exchangeProvidersSelection[provider.title] = selectedProviders.contains(provider);
|
2022-09-01 14:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sharedPreferences.setString(
|
|
|
|
PreferencesKey.exchangeProvidersSelection,
|
|
|
|
json.encode(exchangeProvidersSelection),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool get isAvailableInSelected {
|
|
|
|
final providersForPair = providersForCurrentPair();
|
|
|
|
return selectedProviders.any((element) => element.isAvailable && providersForPair.contains(element));
|
2021-02-23 17:36:03 +00:00
|
|
|
}
|
2022-10-20 17:47:36 +00:00
|
|
|
|
|
|
|
void _setAvailableProviders() {
|
|
|
|
_tradeAvailableProviders.clear();
|
|
|
|
|
|
|
|
_tradeAvailableProviders.addAll(
|
|
|
|
selectedProviders
|
|
|
|
.where((provider) => providersForCurrentPair().contains(provider)));
|
|
|
|
}
|
2020-09-02 08:47:41 +00:00
|
|
|
}
|