mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
CW-424-ChangeNOW-add-payload-details (#979)
* add payload details * remove unused import * fix payload
This commit is contained in:
parent
93eda7c206
commit
9afed201c6
5 changed files with 94 additions and 45 deletions
|
@ -1,6 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
import 'package:cake_wallet/exchange/trade_not_found_exeption.dart';
|
import 'package:cake_wallet/exchange/trade_not_found_exeption.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
|
import 'package:cake_wallet/utils/distribution_info.dart';
|
||||||
|
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
@ -14,7 +18,7 @@ import 'package:cake_wallet/exchange/changenow/changenow_request.dart';
|
||||||
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||||
|
|
||||||
class ChangeNowExchangeProvider extends ExchangeProvider {
|
class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
ChangeNowExchangeProvider()
|
ChangeNowExchangeProvider({required this.settingsStore})
|
||||||
: _lastUsedRateId = '',
|
: _lastUsedRateId = '',
|
||||||
super(
|
super(
|
||||||
pairList: CryptoCurrency.all
|
pairList: CryptoCurrency.all
|
||||||
|
@ -25,7 +29,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
.expand((i) => i)
|
.expand((i) => i)
|
||||||
.toList());
|
.toList());
|
||||||
|
|
||||||
static final apiKey = DeviceInfo.instance.isMobile ? secrets.changeNowApiKey : secrets.changeNowApiKeyDesktop;
|
static final apiKey =
|
||||||
|
DeviceInfo.instance.isMobile ? secrets.changeNowApiKey : secrets.changeNowApiKeyDesktop;
|
||||||
static const apiAuthority = 'api.changenow.io';
|
static const apiAuthority = 'api.changenow.io';
|
||||||
static const createTradePath = '/v2/exchange';
|
static const createTradePath = '/v2/exchange';
|
||||||
static const findTradeByIdPath = '/v2/exchange/by-id';
|
static const findTradeByIdPath = '/v2/exchange/by-id';
|
||||||
|
@ -46,21 +51,22 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
bool get supportsFixedRate => true;
|
bool get supportsFixedRate => true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExchangeProviderDescription get description =>
|
ExchangeProviderDescription get description => ExchangeProviderDescription.changeNow;
|
||||||
ExchangeProviderDescription.changeNow;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> checkIsAvailable() async => true;
|
Future<bool> checkIsAvailable() async => true;
|
||||||
|
|
||||||
|
final SettingsStore settingsStore;
|
||||||
|
|
||||||
String _lastUsedRateId;
|
String _lastUsedRateId;
|
||||||
|
|
||||||
static String getFlow(bool isFixedRate) => isFixedRate ? 'fixed-rate' : 'standard';
|
static String getFlow(bool isFixedRate) => isFixedRate ? 'fixed-rate' : 'standard';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Limits> fetchLimits({
|
Future<Limits> fetchLimits(
|
||||||
required CryptoCurrency from,
|
{required CryptoCurrency from,
|
||||||
required CryptoCurrency to,
|
required CryptoCurrency to,
|
||||||
required bool isFixedRateMode}) async {
|
required bool isFixedRateMode}) async {
|
||||||
final headers = {apiHeaderKey: apiKey};
|
final headers = {apiHeaderKey: apiKey};
|
||||||
final normalizedFrom = normalizeCryptoCurrency(from);
|
final normalizedFrom = normalizeCryptoCurrency(from);
|
||||||
final normalizedTo = normalizeCryptoCurrency(to);
|
final normalizedTo = normalizeCryptoCurrency(to);
|
||||||
|
@ -70,7 +76,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
'toCurrency': normalizedTo,
|
'toCurrency': normalizedTo,
|
||||||
'fromNetwork': networkFor(from),
|
'fromNetwork': networkFor(from),
|
||||||
'toNetwork': networkFor(to),
|
'toNetwork': networkFor(to),
|
||||||
'flow': flow};
|
'flow': flow
|
||||||
|
};
|
||||||
final uri = Uri.https(apiAuthority, rangePath, params);
|
final uri = Uri.https(apiAuthority, rangePath, params);
|
||||||
final response = await get(uri, headers: headers);
|
final response = await get(uri, headers: headers);
|
||||||
|
|
||||||
|
@ -87,19 +94,24 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
return Limits(
|
return Limits(
|
||||||
min: responseJSON['minAmount'] as double?,
|
min: responseJSON['minAmount'] as double?, max: responseJSON['maxAmount'] as double?);
|
||||||
max: responseJSON['maxAmount'] as double?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
|
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
|
||||||
final _request = request as ChangeNowRequest;
|
final _request = request as ChangeNowRequest;
|
||||||
final headers = {
|
final distributionPath = await DistributionInfo.instance.getDistributionPath();
|
||||||
apiHeaderKey: apiKey,
|
final formattedAppVersion = int.tryParse(settingsStore.appVersion.replaceAll('.', '')) ?? 0;
|
||||||
'Content-Type': 'application/json'};
|
final payload = {
|
||||||
|
'app': isMoneroOnly ? 'monerocom' : 'cakewallet',
|
||||||
|
'device': Platform.operatingSystem,
|
||||||
|
'distribution': distributionPath,
|
||||||
|
'version': formattedAppVersion
|
||||||
|
};
|
||||||
|
final headers = {apiHeaderKey: apiKey, 'Content-Type': 'application/json'};
|
||||||
final flow = getFlow(isFixedRateMode);
|
final flow = getFlow(isFixedRateMode);
|
||||||
final type = isFixedRateMode ? 'reverse' : 'direct';
|
final type = isFixedRateMode ? 'reverse' : 'direct';
|
||||||
final body = <String, String>{
|
final body = <String, dynamic>{
|
||||||
'fromCurrency': normalizeCryptoCurrency(_request.from),
|
'fromCurrency': normalizeCryptoCurrency(_request.from),
|
||||||
'toCurrency': normalizeCryptoCurrency(_request.to),
|
'toCurrency': normalizeCryptoCurrency(_request.to),
|
||||||
'fromNetwork': networkFor(_request.from),
|
'fromNetwork': networkFor(_request.from),
|
||||||
|
@ -109,7 +121,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
'address': _request.address,
|
'address': _request.address,
|
||||||
'flow': flow,
|
'flow': flow,
|
||||||
'type': type,
|
'type': type,
|
||||||
'refundAddress': _request.refundAddress
|
'refundAddress': _request.refundAddress,
|
||||||
|
'payload': payload,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isFixedRateMode) {
|
if (isFixedRateMode) {
|
||||||
|
@ -164,7 +177,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
Future<Trade> findTradeById({required String id}) async {
|
Future<Trade> findTradeById({required String id}) async {
|
||||||
final headers = {apiHeaderKey: apiKey};
|
final headers = {apiHeaderKey: apiKey};
|
||||||
final params = <String, String>{'id': id};
|
final params = <String, String>{'id': id};
|
||||||
final uri = Uri.https(apiAuthority,findTradeByIdPath, params);
|
final uri = Uri.https(apiAuthority, findTradeByIdPath, params);
|
||||||
final response = await get(uri, headers: headers);
|
final response = await get(uri, headers: headers);
|
||||||
|
|
||||||
if (response.statusCode == 404) {
|
if (response.statusCode == 404) {
|
||||||
|
@ -175,8 +188,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final error = responseJSON['message'] as String;
|
final error = responseJSON['message'] as String;
|
||||||
|
|
||||||
throw TradeNotFoundException(id,
|
throw TradeNotFoundException(id, provider: description, description: error);
|
||||||
provider: description, description: error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
|
@ -234,7 +246,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
'fromNetwork': networkFor(from),
|
'fromNetwork': networkFor(from),
|
||||||
'toNetwork': networkFor(to),
|
'toNetwork': networkFor(to),
|
||||||
'type': type,
|
'type': type,
|
||||||
'flow': flow};
|
'flow': flow
|
||||||
|
};
|
||||||
|
|
||||||
if (isReverse) {
|
if (isReverse) {
|
||||||
params['toAmount'] = amount.toString();
|
params['toAmount'] = amount.toString();
|
||||||
|
@ -246,7 +259,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
final response = await get(uri, headers: headers);
|
final response = await get(uri, headers: headers);
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final fromAmount = double.parse(responseJSON['fromAmount'].toString());
|
final fromAmount = double.parse(responseJSON['fromAmount'].toString());
|
||||||
final toAmount = double.parse(responseJSON['toAmount'].toString());
|
final toAmount = double.parse(responseJSON['toAmount'].toString());
|
||||||
final rateId = responseJSON['rateId'] as String? ?? '';
|
final rateId = responseJSON['rateId'] as String? ?? '';
|
||||||
|
|
||||||
if (rateId.isNotEmpty) {
|
if (rateId.isNotEmpty) {
|
||||||
|
@ -254,7 +267,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
return isReverse ? (amount / fromAmount) : (toAmount / amount);
|
return isReverse ? (amount / fromAmount) : (toAmount / amount);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -265,24 +278,20 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||||
case CryptoCurrency.usdt:
|
case CryptoCurrency.usdt:
|
||||||
return CryptoCurrency.btc.title.toLowerCase();
|
return CryptoCurrency.btc.title.toLowerCase();
|
||||||
default:
|
default:
|
||||||
return currency.tag != null
|
return currency.tag != null ? currency.tag!.toLowerCase() : currency.title.toLowerCase();
|
||||||
? currency.tag!.toLowerCase()
|
|
||||||
: currency.title.toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String normalizeCryptoCurrency(CryptoCurrency currency) {
|
String normalizeCryptoCurrency(CryptoCurrency currency) {
|
||||||
switch(currency) {
|
switch (currency) {
|
||||||
case CryptoCurrency.zec:
|
case CryptoCurrency.zec:
|
||||||
return 'zec';
|
return 'zec';
|
||||||
case CryptoCurrency.usdcpoly:
|
case CryptoCurrency.usdcpoly:
|
||||||
return 'usdcmatic';
|
return 'usdcmatic';
|
||||||
case CryptoCurrency.maticpoly:
|
case CryptoCurrency.maticpoly:
|
||||||
return 'maticmainnet';
|
return 'maticmainnet';
|
||||||
default:
|
default:
|
||||||
return currency.title.toLowerCase();
|
return currency.title.toLowerCase();
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
39
lib/utils/distribution_info.dart
Normal file
39
lib/utils/distribution_info.dart
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:package_info/package_info.dart';
|
||||||
|
|
||||||
|
enum DistributionType { googleplay, github, appstore, fdroid }
|
||||||
|
|
||||||
|
class DistributionInfo {
|
||||||
|
DistributionInfo._();
|
||||||
|
|
||||||
|
static DistributionInfo get instance => DistributionInfo._();
|
||||||
|
|
||||||
|
Future<String> getDistributionPath() async {
|
||||||
|
final isPlayStore = await isInstalledFromPlayStore();
|
||||||
|
final distributionPath = _getDistributionPath(isPlayStore);
|
||||||
|
|
||||||
|
return distributionPath.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
DistributionType _getDistributionPath(bool isPlayStore) {
|
||||||
|
if (isPlayStore) {
|
||||||
|
return DistributionType.googleplay;
|
||||||
|
} else if (Platform.isAndroid) {
|
||||||
|
return DistributionType.github;
|
||||||
|
} else if (Platform.isIOS) {
|
||||||
|
return DistributionType.appstore;
|
||||||
|
} else {
|
||||||
|
return DistributionType.github;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> isInstalledFromPlayStore() async {
|
||||||
|
try {
|
||||||
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
return packageInfo.packageName == 'com.android.vending';
|
||||||
|
} catch (e) {
|
||||||
|
print('Error: $e');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,8 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||||
_provider = XMRTOExchangeProvider();
|
_provider = XMRTOExchangeProvider();
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.changeNow:
|
case ExchangeProviderDescription.changeNow:
|
||||||
_provider = ChangeNowExchangeProvider();
|
_provider =
|
||||||
|
ChangeNowExchangeProvider(settingsStore: sendViewModel.balanceViewModel.settingsStore);
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.morphToken:
|
case ExchangeProviderDescription.morphToken:
|
||||||
_provider = MorphTokenExchangeProvider(trades: trades);
|
_provider = MorphTokenExchangeProvider(trades: trades);
|
||||||
|
|
|
@ -130,7 +130,7 @@ abstract class ExchangeViewModelBase with Store {
|
||||||
final SharedPreferences sharedPreferences;
|
final SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
List<ExchangeProvider> get _allProviders => [
|
List<ExchangeProvider> get _allProviders => [
|
||||||
ChangeNowExchangeProvider(),
|
ChangeNowExchangeProvider(settingsStore: _settingsStore),
|
||||||
SideShiftExchangeProvider(),
|
SideShiftExchangeProvider(),
|
||||||
SimpleSwapExchangeProvider(),
|
SimpleSwapExchangeProvider(),
|
||||||
TrocadorExchangeProvider(useTorOnly: _useTorOnly),
|
TrocadorExchangeProvider(useTorOnly: _useTorOnly),
|
||||||
|
|
|
@ -40,7 +40,7 @@ abstract class TradeDetailsViewModelBase with Store {
|
||||||
_provider = XMRTOExchangeProvider();
|
_provider = XMRTOExchangeProvider();
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.changeNow:
|
case ExchangeProviderDescription.changeNow:
|
||||||
_provider = ChangeNowExchangeProvider();
|
_provider = ChangeNowExchangeProvider(settingsStore: settingsStore);
|
||||||
break;
|
break;
|
||||||
case ExchangeProviderDescription.morphToken:
|
case ExchangeProviderDescription.morphToken:
|
||||||
_provider = MorphTokenExchangeProvider(trades: trades);
|
_provider = MorphTokenExchangeProvider(trades: trades);
|
||||||
|
|
Loading…
Reference in a new issue