2023-01-11 23:04:03 +00:00
|
|
|
import 'dart:convert';
|
|
|
|
|
2023-01-16 23:38:42 +00:00
|
|
|
import 'package:decimal/decimal.dart';
|
2023-01-12 21:15:42 +00:00
|
|
|
import 'package:flutter/foundation.dart';
|
2023-01-11 23:04:03 +00:00
|
|
|
import 'package:http/http.dart' as http;
|
2023-01-14 00:07:27 +00:00
|
|
|
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
2023-01-11 23:04:03 +00:00
|
|
|
// import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart';
|
|
|
|
// import 'package:stackwallet/models/exchange/response_objects/pair.dart';
|
|
|
|
// import 'package:stackwallet/models/exchange/response_objects/range.dart';
|
|
|
|
// import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
|
|
|
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
2023-01-16 23:38:42 +00:00
|
|
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
2023-01-11 23:04:03 +00:00
|
|
|
// import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
|
|
|
import 'package:stackwallet/services/buy/buy_response.dart';
|
|
|
|
import 'package:stackwallet/utilities/logger.dart';
|
2023-01-14 14:21:32 +00:00
|
|
|
import 'package:tuple/tuple.dart';
|
2023-01-11 23:04:03 +00:00
|
|
|
|
|
|
|
class SimplexAPI {
|
|
|
|
static const String scheme = "https";
|
|
|
|
static const String authority = "sandbox-api.stackwallet.com";
|
|
|
|
|
|
|
|
SimplexAPI._();
|
|
|
|
static final SimplexAPI _instance = SimplexAPI._();
|
|
|
|
static SimplexAPI get instance => _instance;
|
|
|
|
|
|
|
|
/// set this to override using standard http client. Useful for testing
|
|
|
|
http.Client? client;
|
|
|
|
|
|
|
|
Uri _buildUri(String path, Map<String, String>? params) {
|
|
|
|
return Uri.https(authority, path, params);
|
|
|
|
}
|
|
|
|
|
2023-01-14 14:21:32 +00:00
|
|
|
Future<BuyResponse<Tuple2<List<Crypto>, List<Fiat>>>> getSupported() async {
|
2023-01-12 20:14:53 +00:00
|
|
|
// example for quote courtesy of @danrmiller
|
2023-01-12 20:38:03 +00:00
|
|
|
// curl -H "Content-Type: application/json" -d '{"digital_currency": "BTC", "fiat_currency": "USD", "requested_currency": "USD", "requested_amount": 100}' http://sandbox-api.stackwallet.com/quote
|
|
|
|
// official docs reference eg
|
2023-01-12 20:14:53 +00:00
|
|
|
// curl --request GET \
|
|
|
|
// --url https://sandbox.test-simplexcc.com/v2/supported_crypto_currencies \
|
|
|
|
// --header 'accept: application/json'
|
|
|
|
|
2023-01-11 23:04:03 +00:00
|
|
|
try {
|
2023-01-12 20:38:03 +00:00
|
|
|
Map<String, String> headers = {
|
|
|
|
'Content-Type': 'application/json',
|
2023-01-12 20:14:53 +00:00
|
|
|
};
|
2023-01-12 20:38:03 +00:00
|
|
|
String data =
|
|
|
|
'{"digital_currency": "BTC", "fiat_currency": "USD", "requested_currency": "USD", "requested_amount": 100}';
|
|
|
|
Uri url = Uri.parse('http://sandbox-api.stackwallet.com/quote');
|
|
|
|
|
|
|
|
var res = await http.post(url, headers: headers, body: data);
|
|
|
|
|
|
|
|
if (res.statusCode != 200) {
|
|
|
|
throw Exception(
|
|
|
|
'getAvailableCurrencies exception: statusCode= ${res.statusCode}');
|
|
|
|
}
|
2023-01-11 23:04:03 +00:00
|
|
|
|
2023-01-14 14:21:32 +00:00
|
|
|
final jsonArray = jsonDecode(res.body);
|
2023-01-12 00:13:34 +00:00
|
|
|
|
2023-01-12 21:15:42 +00:00
|
|
|
return await compute(_parseSupported, jsonArray);
|
2023-01-11 23:04:03 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
Logging.instance.log("getAvailableCurrencies exception: $e\n$s",
|
|
|
|
level: LogLevel.Error);
|
|
|
|
return BuyResponse(
|
|
|
|
exception: BuyException(
|
|
|
|
e.toString(),
|
|
|
|
BuyExceptionType.generic,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-14 14:21:32 +00:00
|
|
|
BuyResponse<Tuple2<List<Crypto>, List<Fiat>>> _parseSupported(
|
|
|
|
dynamic jsonArray) {
|
2023-01-11 23:04:03 +00:00
|
|
|
try {
|
2023-01-14 00:07:27 +00:00
|
|
|
List<Crypto> cryptos = [];
|
2023-01-12 21:15:42 +00:00
|
|
|
List<Fiat> fiats = [];
|
2023-01-11 23:04:03 +00:00
|
|
|
|
2023-01-13 02:21:19 +00:00
|
|
|
var supportedCryptos =
|
2023-01-12 21:15:42 +00:00
|
|
|
jsonArray['result']['supported_digital_currencies'];
|
2023-01-14 00:07:27 +00:00
|
|
|
// TODO map List<String> supportedCryptos to List<Crypto>
|
|
|
|
for (final ticker in supportedCryptos as List) {
|
|
|
|
cryptos.add(Crypto.fromJson({
|
|
|
|
'ticker': ticker as String,
|
2023-01-14 00:30:45 +00:00
|
|
|
'name': ticker,
|
|
|
|
'image': "",
|
2023-01-14 00:07:27 +00:00
|
|
|
}));
|
|
|
|
}
|
2023-01-13 02:21:19 +00:00
|
|
|
var supportedFiats = jsonArray['result']['supported_fiat_currencies'];
|
2023-01-14 00:07:27 +00:00
|
|
|
// TODO map List<String> supportedFiats to List<Fiat>
|
|
|
|
for (final ticker in supportedFiats as List) {
|
|
|
|
fiats.add(Fiat.fromJson({
|
|
|
|
'ticker': ticker as String,
|
2023-01-14 00:30:45 +00:00
|
|
|
'name': ticker,
|
|
|
|
'image': "",
|
2023-01-14 00:07:27 +00:00
|
|
|
}));
|
|
|
|
}
|
2023-01-13 02:21:19 +00:00
|
|
|
|
2023-01-14 14:21:32 +00:00
|
|
|
return BuyResponse(value: Tuple2(cryptos, fiats));
|
2023-01-11 23:04:03 +00:00
|
|
|
} catch (e, s) {
|
2023-01-13 02:21:19 +00:00
|
|
|
Logging.instance
|
|
|
|
.log("_parseSupported exception: $e\n$s", level: LogLevel.Error);
|
2023-01-11 23:04:03 +00:00
|
|
|
return BuyResponse(
|
|
|
|
exception: BuyException(
|
|
|
|
e.toString(),
|
|
|
|
BuyExceptionType.generic,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 23:38:42 +00:00
|
|
|
Future<BuyResponse<SimplexQuote>> getQuote(SimplexQuote quote) async {
|
|
|
|
// example for quote courtesy of @danrmiller
|
|
|
|
// curl -H "Content-Type: application/json" -d '{"digital_currency": "BTC", "fiat_currency": "USD", "requested_currency": "USD", "requested_amount": 100}' http://sandbox-api.stackwallet.com/quote
|
|
|
|
// official docs reference eg
|
|
|
|
// curl --request GET \
|
|
|
|
// --url https://sandbox.test-simplexcc.com/v2/supported_crypto_currencies \
|
|
|
|
// --header 'accept: application/json'
|
|
|
|
|
|
|
|
try {
|
|
|
|
Map<String, String> headers = {
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
};
|
|
|
|
String data =
|
|
|
|
'{"digital_currency": "${quote.crypto.ticker.toUpperCase()}", "fiat_currency": "${quote.fiat.ticker.toUpperCase()}", "requested_currency": "USD", "requested_amount": ${quote.youPayFiatPrice}}';
|
|
|
|
Uri url = Uri.parse('http://sandbox-api.stackwallet.com/quote');
|
|
|
|
|
|
|
|
var res = await http.post(url, headers: headers, body: data);
|
|
|
|
|
|
|
|
if (res.statusCode != 200) {
|
2023-01-17 00:49:15 +00:00
|
|
|
throw Exception('getQuote exception: statusCode= ${res.statusCode}');
|
2023-01-16 23:38:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
final jsonArray = jsonDecode(res.body);
|
|
|
|
|
2023-01-17 00:08:37 +00:00
|
|
|
jsonArray['quote'] = quote; // Add and pass this on
|
|
|
|
|
2023-01-16 23:38:42 +00:00
|
|
|
return await compute(_parseQuote, jsonArray);
|
|
|
|
} catch (e, s) {
|
2023-01-17 00:49:15 +00:00
|
|
|
Logging.instance.log("getQuote exception: $e\n$s", level: LogLevel.Error);
|
2023-01-16 23:38:42 +00:00
|
|
|
return BuyResponse(
|
|
|
|
exception: BuyException(
|
|
|
|
e.toString(),
|
|
|
|
BuyExceptionType.generic,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BuyResponse<SimplexQuote> _parseQuote(dynamic jsonArray) {
|
|
|
|
try {
|
|
|
|
String fiatPrice = "${jsonArray['result']['fiat_money']['total_amount']}";
|
|
|
|
String cryptoAmount = "${jsonArray['result']['digital_money']['amount']}";
|
|
|
|
|
2023-01-17 00:08:37 +00:00
|
|
|
SimplexQuote quote = jsonArray['quote'] as SimplexQuote;
|
|
|
|
final SimplexQuote _quote = SimplexQuote(
|
|
|
|
crypto: quote.crypto,
|
|
|
|
fiat: quote.fiat,
|
|
|
|
youPayFiatPrice: Decimal.parse(fiatPrice),
|
|
|
|
youReceiveCryptoAmount: Decimal.parse(cryptoAmount),
|
|
|
|
purchaseId: jsonArray['result']['quote_id'] as String,
|
|
|
|
receivingAddress: quote.receivingAddress);
|
2023-01-16 23:38:42 +00:00
|
|
|
|
2023-01-17 00:08:37 +00:00
|
|
|
return BuyResponse(value: _quote);
|
2023-01-16 23:38:42 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
Logging.instance
|
2023-01-17 00:49:15 +00:00
|
|
|
.log("_parseQuote exception: $e\n$s", level: LogLevel.Error);
|
2023-01-16 23:38:42 +00:00
|
|
|
return BuyResponse(
|
|
|
|
exception: BuyException(
|
|
|
|
e.toString(),
|
|
|
|
BuyExceptionType.generic,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-01-17 00:49:03 +00:00
|
|
|
|
|
|
|
void newOrder(SimplexQuote quote) async {
|
|
|
|
try {
|
|
|
|
// TODO launch URL which POSTs headers like https://integrations.simplex.com/docs/new-window-payment-form-submission-1
|
|
|
|
|
|
|
|
// Not working example so not helpful
|
|
|
|
// curl -H "Content-Type: application/json" -d '{"account_details": {"app_end_user_id": "asd"}, "transaction_details": {"digital_currency": "BTC", "fiat_currency": "USD", "requested_currency": "USD", "requested_amount": 101}}' http://sandbox-api.stackwallet.com/order
|
|
|
|
Map<String, String> headers = {
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
};
|
|
|
|
String data =
|
|
|
|
'{"account_details": {"app_end_user_id": "${quote.receivingAddress}"}, "transaction_details": {"digital_currency": "${quote.crypto.ticker.toUpperCase()}", "fiat_currency": "${quote.fiat.ticker.toUpperCase()}", "requested_currency": "USD", "requested_amount": ${quote.youPayFiatPrice}}}';
|
|
|
|
Uri url = Uri.parse('http://sandbox-api.stackwallet.com/order');
|
|
|
|
|
|
|
|
var res = await http.post(url, headers: headers, body: data);
|
|
|
|
|
|
|
|
if (res.statusCode != 200) {
|
|
|
|
throw Exception('newOrder exception: statusCode= ${res.statusCode}');
|
|
|
|
}
|
|
|
|
|
|
|
|
final jsonArray = jsonDecode(res.body);
|
|
|
|
|
|
|
|
return;
|
|
|
|
} catch (e, s) {
|
|
|
|
Logging.instance.log("newOrder exception: $e\n$s", level: LogLevel.Error);
|
|
|
|
return; /*BuyResponse(
|
|
|
|
exception: BuyException(
|
|
|
|
e.toString(),
|
|
|
|
BuyExceptionType.generic,
|
|
|
|
),
|
|
|
|
);*/
|
|
|
|
}
|
|
|
|
}
|
2023-01-11 23:04:03 +00:00
|
|
|
}
|