mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Fixes for exchanges. CAKE-159.
This commit is contained in:
parent
d7c33b0ab5
commit
93049b4aa1
7 changed files with 113 additions and 76 deletions
|
@ -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";
|
||||
|
|
|
@ -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() +
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue