Fixes for exchanges. CAKE-159.

This commit is contained in:
M 2020-11-10 16:58:40 +02:00
parent d7c33b0ab5
commit 93049b4aa1
7 changed files with 113 additions and 76 deletions

View file

@ -354,7 +354,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -371,7 +371,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.0.2;
MARKETING_VERSION = 4.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -494,7 +494,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -511,7 +511,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.0.2;
MARKETING_VERSION = 4.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -528,7 +528,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -545,7 +545,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.0.2;
MARKETING_VERSION = 4.0.3;
PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View file

@ -18,19 +18,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
ChangeNowExchangeProvider()
: super(
pairList: CryptoCurrency.all
.map((i) {
return CryptoCurrency.all.map((k) {
if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) {
return ExchangePair(from: i, to: k, reverse: false);
}
if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) {
return null;
}
return ExchangePair(from: i, to: k, reverse: true);
}).where((c) => c != null);
})
.map((i) => CryptoCurrency.all
.map((k) => ExchangePair(from: i, to: k, reverse: true))
.where((c) => c != null))
.expand((i) => i)
.toList());
@ -43,10 +33,16 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
@override
String get title => 'ChangeNOW';
@override
bool get isAvailable => true;
@override
ExchangeProviderDescription get description =>
ExchangeProviderDescription.changeNow;
@override
Future<bool> checkIsAvailable() async => true;
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
final symbol = from.toString() + '_' + to.toString();
@ -146,8 +142,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
@override
Future<double> calculateAmount(
{CryptoCurrency from, CryptoCurrency to, double amount,
bool isReceiveAmount}) async {
{CryptoCurrency from,
CryptoCurrency to,
double amount,
bool isReceiveAmount}) async {
final url = apiUri +
_exchangeAmountUriSufix +
amount.toString() +

View file

@ -12,6 +12,7 @@ abstract class ExchangeProvider {
String get title;
List<ExchangePair> pairList;
ExchangeProviderDescription description;
bool get isAvailable;
@override
String toString() => title;
@ -21,4 +22,5 @@ abstract class ExchangeProvider {
Future<Trade> findTradeById({@required String id});
Future<double> calculateAmount(
{CryptoCurrency from, CryptoCurrency to, double amount, bool isReceiveAmount});
Future<bool> checkIsAvailable();
}

View file

@ -60,10 +60,16 @@ class MorphTokenExchangeProvider extends ExchangeProvider {
@override
String get title => 'MorphToken';
@override
bool get isAvailable => true;
@override
ExchangeProviderDescription get description =>
ExchangeProviderDescription.morphToken;
@override
Future<bool> checkIsAvailable() async => true;
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
final url = apiUri + _limitsURISuffix;

View file

@ -15,44 +15,47 @@ import 'package:cake_wallet/exchange/trade_not_found_exeption.dart';
class XMRTOExchangeProvider extends ExchangeProvider {
XMRTOExchangeProvider()
: super(pairList: [
: _isAvailable = false,
super(pairList: [
ExchangePair(
from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false)
]);
static const userAgent = 'CakeWallet/XMR iOS';
static const originalApiUri = 'https://xmr.to/api/v3/xmr2btc';
static const proxyApiUri = 'https://xmrproxy.net/api/v3/xmr2btc';
static const _orderParameterUriSufix = '/order_parameter_query';
static const _orderStatusUriSufix = '/order_status_query/';
static const _orderCreateUriSufix = '/order_create/';
static String _apiUri = '';
static const _orderParameterUriSuffix = '/order_parameter_query';
static const _orderStatusUriSuffix = '/order_status_query/';
static const _orderCreateUriSuffix = '/order_create/';
static Future<String> getApiUri() async {
if (_apiUri != null && _apiUri.isNotEmpty) {
return _apiUri;
}
const url = originalApiUri + _orderParameterUriSufix;
static Future<bool> _checkIsAvailable() async {
const url = originalApiUri + _orderParameterUriSuffix;
final response =
await get(url, headers: {'Content-Type': 'application/json'});
_apiUri = response.statusCode == 403 ? proxyApiUri : originalApiUri;
return _apiUri;
return !(response.statusCode == 403);
}
@override
String get title => 'XMR.TO';
@override
bool get isAvailable => _isAvailable;
@override
ExchangeProviderDescription get description =>
ExchangeProviderDescription.xmrto;
double _rate = 0;
bool _isAvailable;
@override
Future<bool> checkIsAvailable() async {
_isAvailable = await _checkIsAvailable();
return isAvailable;
}
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
final url = await getApiUri() + _orderParameterUriSufix;
final url = originalApiUri + _orderParameterUriSuffix;
final response = await get(url);
final correction = 0.001;
@ -67,9 +70,9 @@ class XMRTOExchangeProvider extends ExchangeProvider {
if (price > 0) {
try {
min = min/price + correction;
min = min / price + correction;
min = _limitsFormat(min);
max = max/price - correction;
max = max / price - correction;
max = _limitsFormat(max);
} catch (e) {
min = 0;
@ -86,11 +89,10 @@ class XMRTOExchangeProvider extends ExchangeProvider {
@override
Future<Trade> createTrade({TradeRequest request}) async {
final _request = request as XMRTOTradeRequest;
final url = await getApiUri() + _orderCreateUriSufix;
final url = originalApiUri + _orderCreateUriSuffix;
final body = {
'amount': _request.isBTCRequest
? _request.receiveAmount
: _request.amount,
'amount':
_request.isBTCRequest ? _request.receiveAmount : _request.amount,
'amount_currency': _request.isBTCRequest
? _request.to.toString()
: _request.from.toString(),
@ -129,7 +131,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
'Content-Type': 'application/json',
'User-Agent': userAgent
};
final url = await getApiUri() + _orderStatusUriSufix;
final url = originalApiUri + _orderStatusUriSuffix;
final body = {'uuid': id};
final response = await post(url, headers: headers, body: json.encode(body));
@ -170,8 +172,10 @@ class XMRTOExchangeProvider extends ExchangeProvider {
@override
Future<double> calculateAmount(
{CryptoCurrency from, CryptoCurrency to, double amount,
bool isReceiveAmount}) async {
{CryptoCurrency from,
CryptoCurrency to,
double amount,
bool isReceiveAmount}) async {
if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) {
return 0;
}
@ -181,7 +185,9 @@ class XMRTOExchangeProvider extends ExchangeProvider {
}
final double result = isReceiveAmount
? _rate == 0 ? 0 : amount / _rate
? _rate == 0
? 0
: amount / _rate
: _rate * amount;
return double.parse(result.toStringAsFixed(12));
@ -189,7 +195,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
Future<double> _fetchRates() async {
try {
final url = await getApiUri() + _orderParameterUriSufix;
final url = originalApiUri + _orderParameterUriSuffix;
final response =
await get(url, headers: {'Content-Type': 'application/json'});
final responseJSON = json.decode(response.body) as Map<String, dynamic>;

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
@ -14,8 +15,8 @@ class PresentProviderPicker extends StatelessWidget {
@override
Widget build(BuildContext context) {
final arrowBottom =
Image.asset('assets/images/arrow_bottom_purple_icon.png',
final arrowBottom = Image.asset(
'assets/images/arrow_bottom_purple_icon.png',
color: Colors.white,
height: 6);
@ -50,8 +51,7 @@ class PresentProviderPicker extends StatelessWidget {
child: arrowBottom,
)
],
)
);
));
}
void _presentProviderPicker(BuildContext context) {
@ -64,7 +64,6 @@ class PresentProviderPicker extends StatelessWidget {
switch (provider.description) {
case ExchangeProviderDescription.xmrto:
images.add(Image.asset('assets/images/xmr_btc.png'));
description = S.of(context).picker_description;
break;
case ExchangeProviderDescription.changeNow:
images.add(Image.asset('assets/images/change_now.png'));
@ -76,14 +75,25 @@ class PresentProviderPicker extends StatelessWidget {
}
showPopUp<void>(
builder: (_) => Picker(
builder: (BuildContext popUpContext) => Picker(
items: items,
images: images,
selectedAtIndex: selectedItem,
title: S.of(context).change_exchange_provider,
description: description,
onItemSelected: (ExchangeProvider provider) =>
exchangeViewModel.changeProvider(provider: provider)),
onItemSelected: (ExchangeProvider provider) {
if (!provider.isAvailable) {
showPopUp<void>(
builder: (BuildContext popUpContext) => AlertWithOneAction(
alertTitle: 'Error',
alertContent: 'The exchange is blocked in your region.',
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop()),
context: context);
return;
}
exchangeViewModel.changeProvider(provider: provider);
}),
context: context);
}
}
}

View file

@ -28,10 +28,7 @@ class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel;
abstract class ExchangeViewModelBase with Store {
ExchangeViewModelBase(
this.wallet,
this.trades,
this._exchangeTemplateStore,
this.tradesStore) {
this.wallet, this.trades, this._exchangeTemplateStore, this.tradesStore) {
providerList = [
XMRTOExchangeProvider(),
ChangeNowExchangeProvider(),
@ -43,12 +40,22 @@ abstract class ExchangeViewModelBase with Store {
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
depositAmount = '';
receiveAmount = '';
depositAddress = '';
receiveAddress = '';
depositAddress = depositCurrency == wallet.currency ? wallet.address : '';
limitsState = LimitsInitialState();
tradeState = ExchangeTradeStateInitial();
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
provider = providersForCurrentPair().first;
final initialProvider = provider;
provider.checkIsAvailable().then((bool isAvailable) {
if (!isAvailable && provider == initialProvider) {
provider = providerList.firstWhere(
(provider) => provider is ChangeNowExchangeProvider,
orElse: () => providerList.last);
_onPairChange();
}
});
isReceiveAmountEntered = false;
loadLimits();
}
@ -146,7 +153,9 @@ abstract class ExchangeViewModelBase with Store {
provider
.calculateAmount(
from: depositCurrency, to: receiveCurrency, amount: _amount,
from: depositCurrency,
to: receiveCurrency,
amount: _amount,
isReceiveAmount: true)
.then((amount) => _cryptoNumberFormat
.format(amount)
@ -168,7 +177,9 @@ abstract class ExchangeViewModelBase with Store {
final _amount = double.parse(amount.replaceAll(',', '.'));
provider
.calculateAmount(
from: depositCurrency, to: receiveCurrency, amount: _amount,
from: depositCurrency,
to: receiveCurrency,
amount: _amount,
isReceiveAmount: false)
.then((amount) => _cryptoNumberFormat
.format(amount)
@ -277,19 +288,23 @@ abstract class ExchangeViewModelBase with Store {
void updateTemplate() => _exchangeTemplateStore.update();
void addTemplate({String amount, String depositCurrency, String receiveCurrency,
String provider, String depositAddress, String receiveAddress}) =>
_exchangeTemplateStore.addTemplate(
amount: amount,
depositCurrency: depositCurrency,
receiveCurrency: receiveCurrency,
provider: provider,
depositAddress: depositAddress,
receiveAddress: receiveAddress
);
void addTemplate(
{String amount,
String depositCurrency,
String receiveCurrency,
String provider,
String depositAddress,
String receiveAddress}) =>
_exchangeTemplateStore.addTemplate(
amount: amount,
depositCurrency: depositCurrency,
receiveCurrency: receiveCurrency,
provider: provider,
depositAddress: depositAddress,
receiveAddress: receiveAddress);
void removeTemplate({ExchangeTemplate template}) =>
_exchangeTemplateStore.remove(template: template);
_exchangeTemplateStore.remove(template: template);
List<ExchangeProvider> providersForCurrentPair() {
return _providersForPair(from: depositCurrency, to: receiveCurrency);
@ -322,9 +337,9 @@ abstract class ExchangeViewModelBase with Store {
}
}
depositAddress = depositCurrency == wallet.currency ? wallet.address : '';
depositAmount = '';
receiveAmount = '';
loadLimits();
}