mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Cw 682 integrate stealth ex exchange provider (#1575)
* add stealthEx provider * minor fix * Update pr_test_build.yml * Update dashboard_view_model.dart * update api key * add api key * add secret to linux [skip ci] * fix network param issue * additional fee percent [skip ci] * fix for poly network * add StealthEx tracking link. * minor fix * update name [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
580bd01345
commit
f279a222df
12 changed files with 362 additions and 21 deletions
2
.github/workflows/pr_test_build_android.yml
vendored
2
.github/workflows/pr_test_build_android.yml
vendored
|
@ -168,6 +168,8 @@ jobs:
|
||||||
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
||||||
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
|
echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
|
||||||
|
|
||||||
- name: Rename app
|
- name: Rename app
|
||||||
run: |
|
run: |
|
||||||
|
|
2
.github/workflows/pr_test_build_linux.yml
vendored
2
.github/workflows/pr_test_build_linux.yml
vendored
|
@ -154,6 +154,8 @@ jobs:
|
||||||
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
||||||
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||||
|
echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart
|
||||||
|
|
||||||
- name: Rename app
|
- name: Rename app
|
||||||
run: |
|
run: |
|
||||||
|
|
BIN
assets/images/stealthex.png
Normal file
BIN
assets/images/stealthex.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
|
@ -27,6 +27,8 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
|
||||||
ExchangeProviderDescription(title: 'ThorChain', raw: 8, image: 'assets/images/thorchain.png');
|
ExchangeProviderDescription(title: 'ThorChain', raw: 8, image: 'assets/images/thorchain.png');
|
||||||
static const quantex =
|
static const quantex =
|
||||||
ExchangeProviderDescription(title: 'Quantex', raw: 9, image: 'assets/images/quantex.png');
|
ExchangeProviderDescription(title: 'Quantex', raw: 9, image: 'assets/images/quantex.png');
|
||||||
|
static const stealthEx =
|
||||||
|
ExchangeProviderDescription(title: 'StealthEx', raw: 10, image: 'assets/images/stealthex.png');
|
||||||
|
|
||||||
static ExchangeProviderDescription deserialize({required int raw}) {
|
static ExchangeProviderDescription deserialize({required int raw}) {
|
||||||
switch (raw) {
|
switch (raw) {
|
||||||
|
@ -50,6 +52,8 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
|
||||||
return thorChain;
|
return thorChain;
|
||||||
case 9:
|
case 9:
|
||||||
return quantex;
|
return quantex;
|
||||||
|
case 10:
|
||||||
|
return stealthEx;
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize');
|
throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize');
|
||||||
}
|
}
|
||||||
|
|
299
lib/exchange/provider/stealth_ex_exchange_provider.dart
Normal file
299
lib/exchange/provider/stealth_ex_exchange_provider.dart
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
|
||||||
|
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||||
|
import 'package:cake_wallet/exchange/limits.dart';
|
||||||
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
|
import 'package:cake_wallet/exchange/trade_not_created_exception.dart';
|
||||||
|
import 'package:cake_wallet/exchange/trade_request.dart';
|
||||||
|
import 'package:cake_wallet/exchange/trade_state.dart';
|
||||||
|
import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
class StealthExExchangeProvider extends ExchangeProvider {
|
||||||
|
StealthExExchangeProvider() : super(pairList: supportedPairs(_notSupported));
|
||||||
|
|
||||||
|
static const List<CryptoCurrency> _notSupported = [];
|
||||||
|
|
||||||
|
static final apiKey = secrets.stealthExBearerToken;
|
||||||
|
static final _additionalFeePercent = double.tryParse(secrets.stealthExAdditionalFeePercent);
|
||||||
|
static const _baseUrl = 'https://api.stealthex.io';
|
||||||
|
static const _rangePath = '/v4/rates/range';
|
||||||
|
static const _amountPath = '/v4/rates/estimated-amount';
|
||||||
|
static const _exchangesPath = '/v4/exchanges';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => 'StealthEX';
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isAvailable => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isEnabled => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get supportsFixedRate => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ExchangeProviderDescription get description => ExchangeProviderDescription.stealthEx;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> checkIsAvailable() async => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Limits> fetchLimits(
|
||||||
|
{required CryptoCurrency from,
|
||||||
|
required CryptoCurrency to,
|
||||||
|
required bool isFixedRateMode}) async {
|
||||||
|
final curFrom = isFixedRateMode ? to : from;
|
||||||
|
final curTo = isFixedRateMode ? from : to;
|
||||||
|
|
||||||
|
final headers = {'Authorization': apiKey, 'Content-Type': 'application/json'};
|
||||||
|
final body = {
|
||||||
|
'route': {
|
||||||
|
'from': {'symbol': _getName(curFrom), 'network': _getNetwork(curFrom)},
|
||||||
|
'to': {'symbol': _getName(curTo), 'network': _getNetwork(curTo)}
|
||||||
|
},
|
||||||
|
'estimation': isFixedRateMode ? 'reversed' : 'direct',
|
||||||
|
'rate': isFixedRateMode ? 'fixed' : 'floating',
|
||||||
|
'additional_fee_percent': _additionalFeePercent,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(Uri.parse(_baseUrl + _rangePath),
|
||||||
|
headers: headers, body: json.encode(body));
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw Exception('StealthEx fetch limits failed: ${response.body}');
|
||||||
|
}
|
||||||
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final min = responseJSON['min_amount'] as double?;
|
||||||
|
final max = responseJSON['max_amount'] as double?;
|
||||||
|
return Limits(min: min, max: max);
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
throw Exception('StealthEx failed to fetch limits');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<double> fetchRate(
|
||||||
|
{required CryptoCurrency from,
|
||||||
|
required CryptoCurrency to,
|
||||||
|
required double amount,
|
||||||
|
required bool isFixedRateMode,
|
||||||
|
required bool isReceiveAmount}) async {
|
||||||
|
final response = await getEstimatedExchangeAmount(
|
||||||
|
from: from, to: to, amount: amount, isFixedRateMode: isFixedRateMode);
|
||||||
|
final estimatedAmount = response['estimated_amount'] as double? ?? 0.0;
|
||||||
|
return estimatedAmount > 0.0
|
||||||
|
? isFixedRateMode
|
||||||
|
? amount / estimatedAmount
|
||||||
|
: estimatedAmount / amount
|
||||||
|
: 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Trade> createTrade(
|
||||||
|
{required TradeRequest request,
|
||||||
|
required bool isFixedRateMode,
|
||||||
|
required bool isSendAll}) async {
|
||||||
|
String? rateId;
|
||||||
|
String? validUntil;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isFixedRateMode) {
|
||||||
|
final response = await getEstimatedExchangeAmount(
|
||||||
|
from: request.fromCurrency,
|
||||||
|
to: request.toCurrency,
|
||||||
|
amount: double.parse(request.toAmount),
|
||||||
|
isFixedRateMode: isFixedRateMode);
|
||||||
|
rateId = response['rate_id'] as String?;
|
||||||
|
validUntil = response['valid_until'] as String?;
|
||||||
|
if (rateId == null) throw TradeNotCreatedException(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
final headers = {'Authorization': apiKey, 'Content-Type': 'application/json'};
|
||||||
|
final body = {
|
||||||
|
'route': {
|
||||||
|
'from': {
|
||||||
|
'symbol': _getName(request.fromCurrency),
|
||||||
|
'network': _getNetwork(request.fromCurrency)
|
||||||
|
},
|
||||||
|
'to': {'symbol': _getName(request.toCurrency), 'network': _getNetwork(request.toCurrency)}
|
||||||
|
},
|
||||||
|
'estimation': isFixedRateMode ? 'reversed' : 'direct',
|
||||||
|
'rate': isFixedRateMode ? 'fixed' : 'floating',
|
||||||
|
if (isFixedRateMode) 'rate_id': rateId,
|
||||||
|
'amount':
|
||||||
|
isFixedRateMode ? double.parse(request.toAmount) : double.parse(request.fromAmount),
|
||||||
|
'address': request.toAddress,
|
||||||
|
'refund_address': request.refundAddress,
|
||||||
|
'additional_fee_percent': _additionalFeePercent,
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await http.post(Uri.parse(_baseUrl + _exchangesPath),
|
||||||
|
headers: headers, body: json.encode(body));
|
||||||
|
|
||||||
|
if (response.statusCode != 201) {
|
||||||
|
throw Exception('StealthEx create trade failed: ${response.body}');
|
||||||
|
}
|
||||||
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final deposit = responseJSON['deposit'] as Map<String, dynamic>;
|
||||||
|
final withdrawal = responseJSON['withdrawal'] as Map<String, dynamic>;
|
||||||
|
|
||||||
|
final id = responseJSON['id'] as String;
|
||||||
|
final from = deposit['symbol'] as String;
|
||||||
|
final to = withdrawal['symbol'] as String;
|
||||||
|
final payoutAddress = withdrawal['address'] as String;
|
||||||
|
final depositAddress = deposit['address'] as String;
|
||||||
|
final refundAddress = responseJSON['refund_address'] as String;
|
||||||
|
final depositAmount = toDouble(deposit['amount']);
|
||||||
|
final receiveAmount = toDouble(withdrawal['amount']);
|
||||||
|
final status = responseJSON['status'] as String;
|
||||||
|
final createdAtString = responseJSON['created_at'] as String;
|
||||||
|
|
||||||
|
final createdAt = DateTime.parse(createdAtString);
|
||||||
|
final expiredAt = validUntil != null
|
||||||
|
? DateTime.parse(validUntil)
|
||||||
|
: DateTime.now().add(Duration(minutes: 5));
|
||||||
|
|
||||||
|
|
||||||
|
CryptoCurrency fromCurrency;
|
||||||
|
if (request.fromCurrency.tag != null && request.fromCurrency.title.toLowerCase() == from) {
|
||||||
|
fromCurrency = request.fromCurrency;
|
||||||
|
} else {
|
||||||
|
fromCurrency = CryptoCurrency.fromString(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
CryptoCurrency toCurrency;
|
||||||
|
if (request.toCurrency.tag != null && request.toCurrency.title.toLowerCase() == to) {
|
||||||
|
toCurrency = request.toCurrency;
|
||||||
|
} else {
|
||||||
|
toCurrency = CryptoCurrency.fromString(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Trade(
|
||||||
|
id: id,
|
||||||
|
from: fromCurrency,
|
||||||
|
to: toCurrency,
|
||||||
|
provider: description,
|
||||||
|
inputAddress: depositAddress,
|
||||||
|
payoutAddress: payoutAddress,
|
||||||
|
refundAddress: refundAddress,
|
||||||
|
amount: depositAmount.toString(),
|
||||||
|
receiveAmount: receiveAmount.toString(),
|
||||||
|
state: TradeState.deserialize(raw: status),
|
||||||
|
createdAt: createdAt,
|
||||||
|
expiredAt: expiredAt,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
throw TradeNotCreatedException(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Trade> findTradeById({required String id}) async {
|
||||||
|
final headers = {'Authorization': apiKey, 'Content-Type': 'application/json'};
|
||||||
|
|
||||||
|
final uri = Uri.parse('$_baseUrl$_exchangesPath/$id');
|
||||||
|
final response = await http.get(uri, headers: headers);
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw Exception('StealthEx fetch trade failed: ${response.body}');
|
||||||
|
}
|
||||||
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final deposit = responseJSON['deposit'] as Map<String, dynamic>;
|
||||||
|
final withdrawal = responseJSON['withdrawal'] as Map<String, dynamic>;
|
||||||
|
|
||||||
|
final respId = responseJSON['id'] as String;
|
||||||
|
final from = deposit['symbol'] as String;
|
||||||
|
final to = withdrawal['symbol'] as String;
|
||||||
|
final payoutAddress = withdrawal['address'] as String;
|
||||||
|
final depositAddress = deposit['address'] as String;
|
||||||
|
final refundAddress = responseJSON['refund_address'] as String;
|
||||||
|
final depositAmount = toDouble(deposit['amount']);
|
||||||
|
final receiveAmount = toDouble(withdrawal['amount']);
|
||||||
|
final status = responseJSON['status'] as String;
|
||||||
|
final createdAtString = responseJSON['created_at'] as String;
|
||||||
|
final createdAt = DateTime.parse(createdAtString);
|
||||||
|
|
||||||
|
return Trade(
|
||||||
|
id: respId,
|
||||||
|
from: CryptoCurrency.fromString(from),
|
||||||
|
to: CryptoCurrency.fromString(to),
|
||||||
|
provider: description,
|
||||||
|
inputAddress: depositAddress,
|
||||||
|
payoutAddress: payoutAddress,
|
||||||
|
refundAddress: refundAddress,
|
||||||
|
amount: depositAmount.toString(),
|
||||||
|
receiveAmount: receiveAmount.toString(),
|
||||||
|
state: TradeState.deserialize(raw: status),
|
||||||
|
createdAt: createdAt,
|
||||||
|
isRefund: status == 'refunded',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> getEstimatedExchangeAmount(
|
||||||
|
{required CryptoCurrency from,
|
||||||
|
required CryptoCurrency to,
|
||||||
|
required double amount,
|
||||||
|
required bool isFixedRateMode}) async {
|
||||||
|
final headers = {'Authorization': apiKey, 'Content-Type': 'application/json'};
|
||||||
|
|
||||||
|
final body = {
|
||||||
|
'route': {
|
||||||
|
'from': {'symbol': _getName(from), 'network': _getNetwork(from)},
|
||||||
|
'to': {'symbol': _getName(to), 'network': _getNetwork(to)}
|
||||||
|
},
|
||||||
|
'estimation': isFixedRateMode ? 'reversed' : 'direct',
|
||||||
|
'rate': isFixedRateMode ? 'fixed' : 'floating',
|
||||||
|
'amount': amount,
|
||||||
|
'additional_fee_percent': _additionalFeePercent,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(Uri.parse(_baseUrl + _amountPath),
|
||||||
|
headers: headers, body: json.encode(body));
|
||||||
|
if (response.statusCode != 200) return {};
|
||||||
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final rate = responseJSON['rate'] as Map<String, dynamic>?;
|
||||||
|
return {
|
||||||
|
'estimated_amount': responseJSON['estimated_amount'] as double?,
|
||||||
|
if (rate != null) 'valid_until': rate['valid_until'] as String?,
|
||||||
|
if (rate != null) 'rate_id': rate['id'] as String?
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double toDouble(dynamic value) {
|
||||||
|
if (value is int) {
|
||||||
|
return value.toDouble();
|
||||||
|
} else if (value is double) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getName(CryptoCurrency currency) {
|
||||||
|
if (currency == CryptoCurrency.usdcEPoly) return 'usdce';
|
||||||
|
return currency.title.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getNetwork(CryptoCurrency currency) {
|
||||||
|
if (currency.tag == null) return 'mainnet';
|
||||||
|
|
||||||
|
if (currency == CryptoCurrency.maticpoly) return 'mainnet';
|
||||||
|
|
||||||
|
if (currency.tag == 'POLY') return 'matic';
|
||||||
|
|
||||||
|
return currency.tag!.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,6 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
|
||||||
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
|
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
|
||||||
static const sending = TradeState(raw: 'sending', title: 'Sending');
|
static const sending = TradeState(raw: 'sending', title: 'Sending');
|
||||||
static const success = TradeState(raw: 'success', title: 'Success');
|
static const success = TradeState(raw: 'success', title: 'Success');
|
||||||
|
|
||||||
static TradeState deserialize({required String raw}) {
|
static TradeState deserialize({required String raw}) {
|
||||||
|
|
||||||
switch (raw) {
|
switch (raw) {
|
||||||
|
@ -119,6 +118,7 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
|
||||||
case 'refunded':
|
case 'refunded':
|
||||||
return refunded;
|
return refunded;
|
||||||
case 'confirmation':
|
case 'confirmation':
|
||||||
|
case 'verifying':
|
||||||
return confirmation;
|
return confirmation;
|
||||||
case 'confirmed':
|
case 'confirmed':
|
||||||
return confirmed;
|
return confirmed;
|
||||||
|
|
|
@ -16,7 +16,8 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
displaySimpleSwap = true,
|
displaySimpleSwap = true,
|
||||||
displayTrocador = true,
|
displayTrocador = true,
|
||||||
displayExolix = true,
|
displayExolix = true,
|
||||||
displayThorChain = true;
|
displayThorChain = true,
|
||||||
|
displayStealthEx = true;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool displayXMRTO;
|
bool displayXMRTO;
|
||||||
|
@ -42,6 +43,9 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
@observable
|
@observable
|
||||||
bool displayThorChain;
|
bool displayThorChain;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool displayStealthEx;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get displayAllTrades =>
|
bool get displayAllTrades =>
|
||||||
displayChangeNow &&
|
displayChangeNow &&
|
||||||
|
@ -49,7 +53,8 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
displaySimpleSwap &&
|
displaySimpleSwap &&
|
||||||
displayTrocador &&
|
displayTrocador &&
|
||||||
displayExolix &&
|
displayExolix &&
|
||||||
displayThorChain;
|
displayThorChain &&
|
||||||
|
displayStealthEx;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void toggleDisplayExchange(ExchangeProviderDescription provider) {
|
void toggleDisplayExchange(ExchangeProviderDescription provider) {
|
||||||
|
@ -78,6 +83,9 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
case ExchangeProviderDescription.thorChain:
|
case ExchangeProviderDescription.thorChain:
|
||||||
displayThorChain = !displayThorChain;
|
displayThorChain = !displayThorChain;
|
||||||
break;
|
break;
|
||||||
|
case ExchangeProviderDescription.stealthEx:
|
||||||
|
displayStealthEx = !displayStealthEx;
|
||||||
|
break;
|
||||||
case ExchangeProviderDescription.all:
|
case ExchangeProviderDescription.all:
|
||||||
if (displayAllTrades) {
|
if (displayAllTrades) {
|
||||||
displayChangeNow = false;
|
displayChangeNow = false;
|
||||||
|
@ -88,6 +96,7 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
displayTrocador = false;
|
displayTrocador = false;
|
||||||
displayExolix = false;
|
displayExolix = false;
|
||||||
displayThorChain = false;
|
displayThorChain = false;
|
||||||
|
displayStealthEx = false;
|
||||||
} else {
|
} else {
|
||||||
displayChangeNow = true;
|
displayChangeNow = true;
|
||||||
displaySideShift = true;
|
displaySideShift = true;
|
||||||
|
@ -97,6 +106,7 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
displayTrocador = true;
|
displayTrocador = true;
|
||||||
displayExolix = true;
|
displayExolix = true;
|
||||||
displayThorChain = true;
|
displayThorChain = true;
|
||||||
|
displayStealthEx = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -112,13 +122,19 @@ abstract class TradeFilterStoreBase with Store {
|
||||||
? _trades
|
? _trades
|
||||||
.where((item) =>
|
.where((item) =>
|
||||||
(displayXMRTO && item.trade.provider == ExchangeProviderDescription.xmrto) ||
|
(displayXMRTO && item.trade.provider == ExchangeProviderDescription.xmrto) ||
|
||||||
(displaySideShift && item.trade.provider == ExchangeProviderDescription.sideShift) ||
|
(displaySideShift &&
|
||||||
(displayChangeNow && item.trade.provider == ExchangeProviderDescription.changeNow) ||
|
item.trade.provider == ExchangeProviderDescription.sideShift) ||
|
||||||
(displayMorphToken && item.trade.provider == ExchangeProviderDescription.morphToken) ||
|
(displayChangeNow &&
|
||||||
(displaySimpleSwap && item.trade.provider == ExchangeProviderDescription.simpleSwap) ||
|
item.trade.provider == ExchangeProviderDescription.changeNow) ||
|
||||||
|
(displayMorphToken &&
|
||||||
|
item.trade.provider == ExchangeProviderDescription.morphToken) ||
|
||||||
|
(displaySimpleSwap &&
|
||||||
|
item.trade.provider == ExchangeProviderDescription.simpleSwap) ||
|
||||||
(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) ||
|
(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) ||
|
||||||
(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix) ||
|
(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix) ||
|
||||||
(displayThorChain && item.trade.provider == ExchangeProviderDescription.thorChain))
|
(displayThorChain &&
|
||||||
|
item.trade.provider == ExchangeProviderDescription.thorChain) ||
|
||||||
|
(displayStealthEx && item.trade.provider == ExchangeProviderDescription.stealthEx))
|
||||||
.toList()
|
.toList()
|
||||||
: _trades;
|
: _trades;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||||
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
import 'package:cake_wallet/entities/balance_display_mode.dart';
|
||||||
|
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
import 'package:cake_wallet/entities/provider_types.dart';
|
import 'package:cake_wallet/entities/provider_types.dart';
|
||||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
|
||||||
import 'package:cake_wallet/entities/service_status.dart';
|
import 'package:cake_wallet/entities/service_status.dart';
|
||||||
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
@ -45,11 +47,9 @@ import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:eth_sig_util/util/utils.dart';
|
import 'package:eth_sig_util/util/utils.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
|
||||||
|
|
||||||
part 'dashboard_view_model.g.dart';
|
part 'dashboard_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -129,6 +129,11 @@ abstract class DashboardViewModelBase with Store {
|
||||||
caption: ExchangeProviderDescription.thorChain.title,
|
caption: ExchangeProviderDescription.thorChain.title,
|
||||||
onChanged: () =>
|
onChanged: () =>
|
||||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.thorChain)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.thorChain)),
|
||||||
|
FilterItem(
|
||||||
|
value: () => tradeFilterStore.displayStealthEx,
|
||||||
|
caption: ExchangeProviderDescription.stealthEx.title,
|
||||||
|
onChanged: () =>
|
||||||
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.stealthEx)),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
subname = '',
|
subname = '',
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/quantex_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/quantex_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart';
|
||||||
|
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/trade.dart';
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
|
@ -52,6 +53,8 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||||
case ExchangeProviderDescription.quantex:
|
case ExchangeProviderDescription.quantex:
|
||||||
_provider = QuantexExchangeProvider();
|
_provider = QuantexExchangeProvider();
|
||||||
break;
|
break;
|
||||||
|
case ExchangeProviderDescription.stealthEx:
|
||||||
|
_provider = StealthExExchangeProvider();
|
||||||
case ExchangeProviderDescription.thorChain:
|
case ExchangeProviderDescription.thorChain:
|
||||||
_provider = ThorChainExchangeProvider(tradesStore: trades);
|
_provider = ThorChainExchangeProvider(tradesStore: trades);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:convert';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cake_wallet/core/create_trade_result.dart';
|
import 'package:cake_wallet/core/create_trade_result.dart';
|
||||||
|
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/sync_status.dart';
|
import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
|
@ -160,15 +161,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||||
final SharedPreferences sharedPreferences;
|
final SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
List<ExchangeProvider> get _allProviders => [
|
List<ExchangeProvider> get _allProviders => [
|
||||||
ChangeNowExchangeProvider(settingsStore: _settingsStore),
|
ChangeNowExchangeProvider(settingsStore: _settingsStore),
|
||||||
SideShiftExchangeProvider(),
|
SideShiftExchangeProvider(),
|
||||||
SimpleSwapExchangeProvider(),
|
SimpleSwapExchangeProvider(),
|
||||||
ThorChainExchangeProvider(tradesStore: trades),
|
ThorChainExchangeProvider(tradesStore: trades),
|
||||||
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
|
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
|
||||||
QuantexExchangeProvider(),
|
QuantexExchangeProvider(),
|
||||||
TrocadorExchangeProvider(
|
StealthExExchangeProvider(),
|
||||||
useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates),
|
TrocadorExchangeProvider(
|
||||||
];
|
useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates),
|
||||||
|
];
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
ExchangeProvider? provider;
|
ExchangeProvider? provider;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/quantex_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/quantex_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart';
|
||||||
|
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
||||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||||
import 'package:cake_wallet/exchange/trade.dart';
|
import 'package:cake_wallet/exchange/trade.dart';
|
||||||
|
@ -60,6 +61,9 @@ abstract class TradeDetailsViewModelBase with Store {
|
||||||
case ExchangeProviderDescription.quantex:
|
case ExchangeProviderDescription.quantex:
|
||||||
_provider = QuantexExchangeProvider();
|
_provider = QuantexExchangeProvider();
|
||||||
break;
|
break;
|
||||||
|
case ExchangeProviderDescription.stealthEx:
|
||||||
|
_provider = StealthExExchangeProvider();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateItems();
|
_updateItems();
|
||||||
|
@ -86,6 +90,8 @@ abstract class TradeDetailsViewModelBase with Store {
|
||||||
return 'https://track.ninerealms.com/${trade.id}';
|
return 'https://track.ninerealms.com/${trade.id}';
|
||||||
case ExchangeProviderDescription.quantex:
|
case ExchangeProviderDescription.quantex:
|
||||||
return 'https://myquantex.com/send/${trade.id}';
|
return 'https://myquantex.com/send/${trade.id}';
|
||||||
|
case ExchangeProviderDescription.stealthEx:
|
||||||
|
return 'https://stealthex.io/exchange/?id=${trade.id}';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ class SecretKey {
|
||||||
SecretKey('cakePayApiKey', () => ''),
|
SecretKey('cakePayApiKey', () => ''),
|
||||||
SecretKey('CSRFToken', () => ''),
|
SecretKey('CSRFToken', () => ''),
|
||||||
SecretKey('authorization', () => ''),
|
SecretKey('authorization', () => ''),
|
||||||
|
SecretKey('stealthExBearerToken', () => ''),
|
||||||
|
SecretKey('stealthExAdditionalFeePercent', () => ''),
|
||||||
];
|
];
|
||||||
|
|
||||||
static final evmChainsSecrets = [
|
static final evmChainsSecrets = [
|
||||||
|
|
Loading…
Reference in a new issue