From d9905a7cf36802f706c80f8d69592960e65d1028 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo <41484542+godilite@users.noreply.github.com> Date: Wed, 31 Aug 2022 18:34:07 +0300 Subject: [PATCH] Cw 110 integrate simple swap exchange (#459) * add support for SimpleSwap exchange * fix edit receive amount field * fixed merge conflicts * Fix issues from code review --- .../org.eclipse.buildship.core.prefs | 2 +- assets/images/simpleSwap.png | Bin 0 -> 3016 bytes .../exchange_provider_description.dart | 5 + .../sideshift_exchange_provider.dart | 14 +- .../simpleswap_exchange_provider.dart | 217 ++++++++++++++++++ .../simpleswap/simpleswap_request.dart | 20 ++ .../screens/dashboard/widgets/trade_row.dart | 3 + lib/src/screens/exchange/exchange_page.dart | 2 + .../exchange/exchange_template_page.dart | 4 - .../widgets/present_provider_picker.dart | 3 + lib/store/dashboard/trade_filter_store.dart | 17 +- .../exchange/exchange_trade_view_model.dart | 8 + .../exchange/exchange_view_model.dart | 18 +- lib/view_model/trade_details_view_model.dart | 10 + tool/utils/secret_key.dart | 1 + 15 files changed, 307 insertions(+), 17 deletions(-) create mode 100644 assets/images/simpleSwap.png create mode 100644 lib/exchange/simpleswap/simpleswap_exchange_provider.dart create mode 100644 lib/exchange/simpleswap/simpleswap_request.dart diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index e8895216f..9d2efc8e7 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,2 +1,2 @@ connection.project.dir= -eclipse.preferences.version=1 +eclipse.preferences.version=1 \ No newline at end of file diff --git a/assets/images/simpleSwap.png b/assets/images/simpleSwap.png new file mode 100644 index 0000000000000000000000000000000000000000..3c89687a5f867c04a65c8180a0afa381c9fbfabb GIT binary patch literal 3016 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 ki8+u&JovGheeJJ static const sideShift = ExchangeProviderDescription(title: 'SideShift', raw: 3); + + static const simpleSwap = + ExchangeProviderDescription(title: 'SimpleSwap', raw: 4); static ExchangeProviderDescription deserialize({int raw}) { switch (raw) { @@ -24,6 +27,8 @@ class ExchangeProviderDescription extends EnumerableItem return morphToken; case 3: return sideShift; + case 4: + return simpleSwap; default: return null; } diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/sideshift/sideshift_exchange_provider.dart index c512b6322..1f06de94e 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/sideshift/sideshift_exchange_provider.dart @@ -47,8 +47,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { if (amount == 0) { return 0.0; } - final fromCurrency = normalizeCryptoCurrency(from); - final toCurrency = normalizeCryptoCurrency(to); + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); final url = apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency; final response = await get(url); @@ -136,8 +136,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { Future _createQuote(SideShiftRequest request) async { final url = apiBaseUrl + quotePath; final headers = {'Content-Type': 'application/json'}; - final depositMethod = normalizeCryptoCurrency(request.depositMethod); - final settleMethod = normalizeCryptoCurrency(request.settleMethod); + final depositMethod = _normalizeCryptoCurrency(request.depositMethod); + final settleMethod = _normalizeCryptoCurrency(request.settleMethod); final body = { 'depositMethod': depositMethod, 'settleMethod': settleMethod, @@ -166,8 +166,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { @override Future fetchLimits( {CryptoCurrency from, CryptoCurrency to, bool isFixedRateMode}) async { - final fromCurrency = normalizeCryptoCurrency(from); - final toCurrency = normalizeCryptoCurrency(to); + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); final url = apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency; final response = await get(url); @@ -247,7 +247,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { @override String get title => 'SideShift'; - static String normalizeCryptoCurrency(CryptoCurrency currency) { + static String _normalizeCryptoCurrency(CryptoCurrency currency) { switch (currency) { case CryptoCurrency.zaddr: return 'zaddr'; diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart new file mode 100644 index 000000000..78e83dd4d --- /dev/null +++ b/lib/exchange/simpleswap/simpleswap_exchange_provider.dart @@ -0,0 +1,217 @@ +import 'dart:convert'; + +import 'package:cake_wallet/exchange/exchange_pair.dart'; +import 'package:cake_wallet/exchange/exchange_provider.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; +import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; +import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:http/http.dart'; + +class SimpleSwapExchangeProvider extends ExchangeProvider { + SimpleSwapExchangeProvider() + : super( + pairList: CryptoCurrency.all + .map((i) => + CryptoCurrency.all.map((k) => ExchangePair(from: i, to: k, reverse: true)).where((c) => c != null)) + .expand((i) => i) + .toList()); + + static const apiAuthority = 'api.simpleswap.io'; + static const getEstimatePath = '/v1/get_estimated'; + static const rangePath = '/v1/get_ranges'; + static const getExchangePath = '/v1/get_exchange'; + static const createExchangePath = '/v1/create_exchange'; + static const apiKey = secrets.simpleSwapApiKey; + + @override + ExchangeProviderDescription get description => + ExchangeProviderDescription.simpleSwap; + + @override + Future calculateAmount( + {CryptoCurrency from, CryptoCurrency to, double amount, bool isFixedRateMode, bool isReceiveAmount}) async { + try { + if (amount == 0) { + return 0.0; + } + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); + final params = { + 'api_key': apiKey, + 'currency_from': fromCurrency, + 'currency_to': toCurrency, + 'amount': amount.toString(), + 'fixed': isFixedRateMode.toString() + }; + final uri = Uri.https(apiAuthority, getEstimatePath, params); + + final response = await get(uri); + + if (response.body == null) return 0.00; + final data = json.decode(response.body) as String; + + return double.parse(data); + } catch (_) { + return 0.00; + } + } + + @override + Future checkIsAvailable() async { + final uri = Uri.https(apiAuthority, getEstimatePath, {'api_key': apiKey}); + final response = await get(uri); + + return !(response.statusCode == 403); + } + + @override + Future createTrade({TradeRequest request, bool isFixedRateMode}) async { + final _request = request as SimpleSwapRequest; + final headers = { + 'Content-Type': 'application/json'}; + final params = { + 'api_key': apiKey, + }; + final body = { + "currency_from": _normalizeCryptoCurrency(_request.from), + "currency_to": _normalizeCryptoCurrency(_request.to), + "amount": _request.amount, + "fixed": isFixedRateMode, + "user_refund_address": _request.refundAddress, + "address_to": _request.address + }; + final uri = Uri.https(apiAuthority, createExchangePath, params); + + final response = await post(uri, headers: headers, body: json.encode(body)); + + if (response.statusCode != 200) { + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + + throw TradeNotCreatedException(description, description: error); + } + + throw TradeNotCreatedException(description); + } + + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['id'] as String; + final inputAddress = responseJSON['address_from'] as String; + final settleAddress = responseJSON['user_refund_address'] as String; + + return Trade( + id: id, + provider: description, + from: _request.from, + to: _request.to, + inputAddress: inputAddress, + refundAddress: settleAddress, + state: TradeState.created, + amount: _request.amount, + createdAt: DateTime.now(), + ); + } + + @override + Future fetchLimits({CryptoCurrency from, CryptoCurrency to, bool isFixedRateMode}) async { + final fromCurrency = _normalizeCryptoCurrency(from); + final toCurrency = _normalizeCryptoCurrency(to); + final params = { + 'api_key': apiKey, + 'fixed': isFixedRateMode.toString(), + 'currency_from': fromCurrency, + 'currency_to': toCurrency, + }; + final uri = Uri.https(apiAuthority, rangePath, params); + + final response = await get(uri); + + if (response.statusCode == 500) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + + throw Exception('$error'); + } + + if (response.statusCode != 200) { + return null; + } + + final responseJSON = json.decode(response.body) as Map; + final min = responseJSON['min'] != null ? double.tryParse(responseJSON['min'] as String) : null; + final max = responseJSON['max'] != null ? double.parse(responseJSON['max'] as String) : null; + + return Limits(min: min, max: max); + } + + @override + Future findTradeById({String id}) async { + final params = {'api_key': apiKey, 'id': id}; + final uri = Uri.https(apiAuthority, getExchangePath, params); + final response = await get(uri); + + if (response.statusCode == 404) { + throw TradeNotFoundException(id, provider: description); + } + + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + + throw TradeNotFoundException(id, provider: description, description: error); + } + + if (response.statusCode != 200) { + return null; + } + + final responseJSON = json.decode(response.body) as Map; + final fromCurrency = responseJSON['currency_from'] as String; + final from = CryptoCurrency.fromString(fromCurrency); + final toCurrency = responseJSON['currency_to'] as String; + final to = CryptoCurrency.fromString(toCurrency); + final inputAddress = responseJSON['address_from'] as String; + final expectedSendAmount = responseJSON['expected_amount'].toString(); + final status = responseJSON['status'] as String; + final state = TradeState.deserialize(raw: status); + + return Trade( + id: id, + from: from, + to: to, + provider: description, + inputAddress: inputAddress, + amount: expectedSendAmount, + state: state, + ); + } + + @override + bool get isAvailable => true; + + @override + String get title => 'SimpleSwap'; + + static String _normalizeCryptoCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.zaddr: + return 'zec'; + case CryptoCurrency.zec: + return 'zec'; + case CryptoCurrency.bnb: + return currency.tag.toLowerCase(); + case CryptoCurrency.usdterc20: + return 'usdterc'; + default: + return currency.title.toLowerCase(); + } + } +} diff --git a/lib/exchange/simpleswap/simpleswap_request.dart b/lib/exchange/simpleswap/simpleswap_request.dart new file mode 100644 index 000000000..03a53c38e --- /dev/null +++ b/lib/exchange/simpleswap/simpleswap_request.dart @@ -0,0 +1,20 @@ +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; + +class SimpleSwapRequest extends TradeRequest { + SimpleSwapRequest({ + @required this.from, + @required this.to, + @required this.address, + @required this.amount, + @required this.refundAddress, + }); + + CryptoCurrency from; + CryptoCurrency to; + String address; + String amount; + String toAmount; + String refundAddress; +} diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index faaac9edb..55b7cadc2 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -90,6 +90,9 @@ class TradeRow extends StatelessWidget { case ExchangeProviderDescription.sideShift: image = Image.asset('assets/images/sideshift.png', width: 36, height: 36); break; + case ExchangeProviderDescription.simpleSwap: + image = Image.asset('assets/images/simpleSwap.png', width: 36, height: 36); + break; default: image = null; } diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 0c1ae01b3..3fce3029a 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -744,7 +744,9 @@ class ExchangePage extends BasePage { }); _receiveAmountFocus.addListener(() { + if(receiveAmountController.text.isNotEmpty){ exchangeViewModel.isFixedRateMode = true; + } exchangeViewModel.changeReceiveAmount( amount: receiveAmountController.text); }); diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 7d98594d5..5b6f50844 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -1,8 +1,6 @@ import 'dart:ui'; import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -19,9 +17,7 @@ import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; -import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart'; diff --git a/lib/src/screens/exchange/widgets/present_provider_picker.dart b/lib/src/screens/exchange/widgets/present_provider_picker.dart index 16b35d7bb..51738986a 100644 --- a/lib/src/screens/exchange/widgets/present_provider_picker.dart +++ b/lib/src/screens/exchange/widgets/present_provider_picker.dart @@ -74,6 +74,9 @@ class PresentProviderPicker extends StatelessWidget { case ExchangeProviderDescription.sideShift: images.add(Image.asset('assets/images/sideshift.png', width: 20)); break; + case ExchangeProviderDescription.simpleSwap: + images.add(Image.asset('assets/images/simpleSwap.png', width: 20)); + break; } } diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 11ac2a8a4..5cb7fd9e2 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -11,7 +11,9 @@ abstract class TradeFilterStoreBase with Store { TradeFilterStoreBase( {this.displayXMRTO = true, this.displayChangeNow = true, - this.displayMorphToken = true}); + this.displayMorphToken = true, + this.displaySimpleSwap = true, + }); @observable bool displayXMRTO; @@ -22,6 +24,9 @@ abstract class TradeFilterStoreBase with Store { @observable bool displayMorphToken; + @observable + bool displaySimpleSwap; + @action void toggleDisplayExchange(ExchangeProviderDescription provider) { switch (provider) { @@ -34,13 +39,16 @@ abstract class TradeFilterStoreBase with Store { case ExchangeProviderDescription.morphToken: displayMorphToken = !displayMorphToken; break; + case ExchangeProviderDescription.simpleSwap: + displaySimpleSwap = !displaySimpleSwap; + break; } } List filtered({List trades, WalletBase wallet}) { final _trades = trades.where((item) => item.trade.walletId == wallet.id).toList(); - final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken; + final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken || !displaySimpleSwap; return needToFilter ? _trades @@ -52,7 +60,10 @@ abstract class TradeFilterStoreBase with Store { ExchangeProviderDescription.changeNow) || (displayMorphToken && item.trade.provider == - ExchangeProviderDescription.morphToken)) + ExchangeProviderDescription.morphToken) + ||(displaySimpleSwap && + item.trade.provider == + ExchangeProviderDescription.simpleSwap)) .toList() : _trades; } diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index de2ac6daa..16523a8ce 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; +import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; @@ -37,6 +39,12 @@ abstract class ExchangeTradeViewModelBase with Store { case ExchangeProviderDescription.morphToken: _provider = MorphTokenExchangeProvider(trades: trades); break; + case ExchangeProviderDescription.sideShift: + _provider = SideShiftExchangeProvider(); + break; + case ExchangeProviderDescription.simpleSwap: + _provider = SimpleSwapExchangeProvider(); + break; } items = ObservableList(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 3eed44011..f0ff5ee9e 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -1,5 +1,7 @@ import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; +import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/sync_status.dart'; @@ -35,7 +37,7 @@ abstract class ExchangeViewModelBase with Store { this.tradesStore, this._settingsStore) { const excludeDepositCurrencies = [CryptoCurrency.xhv]; const excludeReceiveCurrencies = [CryptoCurrency.xlm, CryptoCurrency.xrp, CryptoCurrency.bnb, CryptoCurrency.xhv]; - providerList = [ChangeNowExchangeProvider(), SideShiftExchangeProvider()]; + providerList = [ChangeNowExchangeProvider(), SideShiftExchangeProvider(), SimpleSwapExchangeProvider()]; _initialPairBasedOnWallet(); isDepositAddressEnabled = !(depositCurrency == wallet.currency); isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); @@ -267,6 +269,18 @@ abstract class ExchangeViewModelBase with Store { currency = depositCurrency; } + if (provider is SimpleSwapExchangeProvider) { + request = SimpleSwapRequest( + from: depositCurrency, + to: receiveCurrency, + amount: depositAmount?.replaceAll(',', '.'), + address: receiveAddress, + refundAddress: depositAddress, + ); + amount = depositAmount; + currency = depositCurrency; + } + if (provider is XMRTOExchangeProvider) { request = XMRTOTradeRequest( from: depositCurrency, @@ -459,6 +473,6 @@ abstract class ExchangeViewModelBase with Store { isReceiveAmountEditable = false; }*/ //isReceiveAmountEditable = false; - isReceiveAmountEditable = provider is ChangeNowExchangeProvider; + isReceiveAmountEditable = provider is ChangeNowExchangeProvider || provider is SimpleSwapExchangeProvider; } } diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index 043028c90..00aabdebd 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; +import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/utils/date_formatter.dart'; @@ -35,6 +36,9 @@ abstract class TradeDetailsViewModelBase with Store { case ExchangeProviderDescription.sideShift: _provider = SideShiftExchangeProvider(); break; + case ExchangeProviderDescription.simpleSwap: + _provider = SimpleSwapExchangeProvider(); + break; } items = ObservableList(); @@ -112,6 +116,12 @@ abstract class TradeDetailsViewModelBase with Store { title: 'Track', value: buildURL, onTap: () => launch(buildURL))); } + if (trade.provider == ExchangeProviderDescription.simpleSwap) { + final buildURL = 'https://simpleswap.io/exchange?id=${trade.id.toString()}'; + items.add(TrackTradeListItem( + title: 'Track', value: buildURL, onTap: () => launch(buildURL))); + } + if (trade.createdAt != null) { items.add(StandartListItem( title: S.current.trade_details_created_at, diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index aa9928c8c..9bf360017 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -25,6 +25,7 @@ class SecretKey { SecretKey('moonPaySecretKey', () => ''), SecretKey('sideShiftAffiliateId', () => ''), SecretKey('sideShiftApiKey', () => ''), + SecretKey('simpleSwapApiKey', () => '') ]; final String name;