CAKE-43 | added the ability to enter an amount for xmr.to exchange in both currencies xmr and btc; added isReceiveAmountEntered to ExchangeViewModel; added receiveAmount and isBTCRequest to XMRTOTradeRequest; added isReceiveAmount to calculateAmount method of ExchangeProvider; fixed XMRTOExchangeProvider
OleksandrSobol committed
Sep 25, 2020 at 22:55 UTC
bc85058ad8468dd6c009cbe7e82ca9ec989fb3fd
8 files changed
+50
-20
lib/exchange/changenow/changenow_exchange_provider.dart
+2
-1
@@ -146,7 +146,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
146
147
@override
148
Future<double> calculateAmount(
149
- {CryptoCurrency from, CryptoCurrency to, double amount}) async {
149
+ {CryptoCurrency from, CryptoCurrency to, double amount,
150
+ bool isReceiveAmount}) async {
151
final url = apiUri +
152
_exchangeAmountUriSufix +
153
amount.toString() +
lib/exchange/exchange_provider.dart
+1
-1
@@ -20,5 +20,5 @@ abstract class ExchangeProvider {
20
Future<Trade> createTrade({TradeRequest request});
21
Future<Trade> findTradeById({@required String id});
22
Future<double> calculateAmount(
23
- {CryptoCurrency from, CryptoCurrency to, double amount});
23
+ {CryptoCurrency from, CryptoCurrency to, double amount, bool isReceiveAmount});
24
}
lib/exchange/morphtoken/morphtoken_exchange_provider.dart
+2
-1
@@ -186,7 +186,8 @@ class MorphTokenExchangeProvider extends ExchangeProvider {
186
187
@override
188
Future<double> calculateAmount(
189
- {CryptoCurrency from, CryptoCurrency to, double amount}) async {
189
+ {CryptoCurrency from, CryptoCurrency to, double amount,
190
+ bool isReceiveAmount}) async {
191
final url = apiUri + _ratesURISuffix;
192
final response = await get(url);
193
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
lib/exchange/xmrto/xmrto_exchange_provider.dart
+17
-9
@@ -21,8 +21,8 @@ class XMRTOExchangeProvider extends ExchangeProvider {
21
]);
22
23
static const userAgent = 'CakeWallet/XMR iOS';
24
- static const originalApiUri = 'https://xmr.to/api/v2/xmr2btc';
25
- static const proxyApiUri = 'https://xmrproxy.net/api/v2/xmr2btc';
24
+ static const originalApiUri = 'https://xmr.to/api/v3/xmr2btc';
25
+ static const proxyApiUri = 'https://xmrproxy.net/api/v3/xmr2btc';
26
static const _orderParameterUriSufix = '/order_parameter_query';
27
static const _orderStatusUriSufix = '/order_status_query/';
28
static const _orderCreateUriSufix = '/order_create/';
@@ -61,9 +61,9 @@ class XMRTOExchangeProvider extends ExchangeProvider {
61
}
62
63
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
64
- double min = responseJSON['lower_limit'] as double;
65
- double max = responseJSON['upper_limit'] as double;
66
- final price = responseJSON['price'] as double;
64
+ double min = double.parse(responseJSON['lower_limit'] as String);
65
+ double max = double.parse(responseJSON['upper_limit'] as String);
66
+ final price = double.parse(responseJSON['price'] as String);
67
68
if (price > 0) {
69
try {
@@ -88,7 +88,12 @@ class XMRTOExchangeProvider extends ExchangeProvider {
88
final _request = request as XMRTOTradeRequest;
89
final url = await getApiUri() + _orderCreateUriSufix;
90
final body = {
91
- 'xmr_amount': _request.amount,
91
+ 'amount': _request.isBTCRequest
92
+ ? _request.receiveAmount
93
+ : _request.amount,
94
+ 'amount_currency': _request.isBTCRequest
95
+ ? _request.to.toString()
96
+ : _request.from.toString(),
97
'btc_dest_address': _request.address
98
};
99
final response = await post(url,
@@ -165,7 +170,8 @@ class XMRTOExchangeProvider extends ExchangeProvider {
170
171
@override
172
Future<double> calculateAmount(
168
- {CryptoCurrency from, CryptoCurrency to, double amount}) async {
173
+ {CryptoCurrency from, CryptoCurrency to, double amount,
174
+ bool isReceiveAmount}) async {
175
if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) {
176
return 0;
177
}
@@ -174,7 +180,9 @@ class XMRTOExchangeProvider extends ExchangeProvider {
180
_rate = await _fetchRates();
181
}
182
177
- final double result = _rate * amount;
183
+ final double result = isReceiveAmount
184
+ ? _rate == 0 ? 0 : amount / _rate
185
+ : _rate * amount;
186
187
return double.parse(result.toStringAsFixed(12));
188
}
@@ -185,7 +193,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
193
final response =
194
await get(url, headers: {'Content-Type': 'application/json'});
195
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
188
- final price = responseJSON['price'] as double;
196
+ final price = double.parse(responseJSON['price'] as String);
197
198
return price;
199
} catch (e) {
lib/exchange/xmrto/xmrto_trade_request.dart
+5
-1
@@ -7,12 +7,16 @@ class XMRTOTradeRequest extends TradeRequest {
7
{@required this.from,
8
@required this.to,
9
@required this.amount,
10
+ @required this.receiveAmount,
11
@required this.address,
11
- @required this.refundAddress});
12
+ @required this.refundAddress,
13
+ @required this.isBTCRequest});
14
15
final CryptoCurrency from;
16
final CryptoCurrency to;
17
final String amount;
18
+ final String receiveAmount;
19
final String address;
20
final String refundAddress;
21
+ final bool isBTCRequest;
22
}
lib/src/screens/dashboard/dashboard_page.dart
+3
-3
@@ -114,9 +114,9 @@ class DashboardPage extends BasePage {
114
alignment: Alignment.centerLeft,
115
),
116
ActionButton(
117
- image: sendImage,
118
- title: S.of(context).send,
119
- route: Routes.send,
117
+ image: exchangeImage,
118
+ title: S.of(context).exchange,
119
+ route: Routes.exchange,
120
alignment: Alignment.centerLeft,
121
),
122
],
lib/src/screens/exchange/exchange_page.dart
+10
-1
@@ -1,4 +1,5 @@
1
import 'dart:ui';
2
+import 'package:cake_wallet/exchange/exchange_provider.dart';
3
import 'package:cake_wallet/exchange/exchange_template.dart';
4
import 'package:cake_wallet/src/screens/base_page.dart';
5
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
@@ -181,7 +182,7 @@ class ExchangePage extends BasePage {
182
exchangeViewModel.wallet.currency
183
? exchangeViewModel.wallet.address
184
: exchangeViewModel.receiveAddress,
184
- initialIsAmountEditable: false,
185
+ initialIsAmountEditable: exchangeViewModel.provider is XMRTOExchangeProvider ? true : false,
186
initialIsAddressEditable:
187
exchangeViewModel.isReceiveAddressEnabled,
188
isAmountEstimated: true,
@@ -487,6 +488,12 @@ class ExchangePage extends BasePage {
488
receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
489
});
490
491
+ reaction((_) => exchangeViewModel.provider, (ExchangeProvider provider) {
492
+ provider is XMRTOExchangeProvider
493
+ ? receiveKey.currentState.isAmountEditable(isEditable: true)
494
+ : receiveKey.currentState.isAmountEditable(isEditable: false);
495
+ });
496
+
497
// FIXME: FIXME
498
499
// reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) {
@@ -540,6 +547,7 @@ class ExchangePage extends BasePage {
547
if (depositAmountController.text != exchangeViewModel.depositAmount) {
548
exchangeViewModel.changeDepositAmount(
549
amount: depositAmountController.text);
550
+ exchangeViewModel.isReceiveAmountEntered = false;
551
}
552
});
553
@@ -550,6 +558,7 @@ class ExchangePage extends BasePage {
558
if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
559
exchangeViewModel.changeReceiveAmount(
560
amount: receiveAmountController.text);
561
+ exchangeViewModel.isReceiveAmountEntered = true;
562
}
563
});
564
lib/view_model/exchange/exchange_view_model.dart
+10
-3
@@ -48,6 +48,7 @@ abstract class ExchangeViewModelBase with Store {
48
tradeState = ExchangeTradeStateInitial();
49
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
50
provider = providersForCurrentPair().first;
51
+ isReceiveAmountEntered = false;
52
loadLimits();
53
}
54
@@ -92,6 +93,8 @@ abstract class ExchangeViewModelBase with Store {
93
@observable
94
bool isReceiveAddressEnabled;
95
96
+ bool isReceiveAmountEntered;
97
+
98
Limits limits;
99
100
NumberFormat _cryptoNumberFormat;
@@ -138,7 +141,8 @@ abstract class ExchangeViewModelBase with Store {
141
142
provider
143
.calculateAmount(
141
- from: depositCurrency, to: receiveCurrency, amount: _amount)
144
+ from: depositCurrency, to: receiveCurrency, amount: _amount,
145
+ isReceiveAmount: true)
146
.then((amount) => _cryptoNumberFormat
147
.format(amount)
148
.toString()
@@ -159,7 +163,8 @@ abstract class ExchangeViewModelBase with Store {
163
final _amount = double.parse(amount);
164
provider
165
.calculateAmount(
162
- from: depositCurrency, to: receiveCurrency, amount: _amount)
166
+ from: depositCurrency, to: receiveCurrency, amount: _amount,
167
+ isReceiveAmount: false)
168
.then((amount) => _cryptoNumberFormat
169
.format(amount)
170
.toString()
@@ -191,8 +196,10 @@ abstract class ExchangeViewModelBase with Store {
196
from: depositCurrency,
197
to: receiveCurrency,
198
amount: depositAmount,
199
+ receiveAmount: receiveAmount,
200
address: receiveAddress,
195
- refundAddress: depositAddress);
201
+ refundAddress: depositAddress,
202
+ isBTCRequest: isReceiveAmountEntered);
203
amount = depositAmount;
204
currency = depositCurrency;
205
}