mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-11 05:04:35 +00:00
generic changenow impl
This commit is contained in:
parent
9af457d1c6
commit
807379f112
5 changed files with 213 additions and 12 deletions
|
@ -11,6 +11,7 @@ import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart
|
|||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/fixed_rate_market.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/currency.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/range.dart';
|
||||
import 'package:stackwallet/services/exchange/exchange_response.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
||||
|
@ -266,6 +267,46 @@ class ChangeNowAPI {
|
|||
}
|
||||
}
|
||||
|
||||
/// The API endpoint returns minimal payment amount and maximum payment amount
|
||||
/// required to make an exchange. If you try to exchange less than minimum or
|
||||
/// more than maximum, the transaction will most likely fail. Any pair of
|
||||
/// assets has minimum amount and some of pairs have maximum amount.
|
||||
Future<ExchangeResponse<Range>> getRange({
|
||||
required String fromTicker,
|
||||
required String toTicker,
|
||||
required bool isFixedRate,
|
||||
String? apiKey,
|
||||
}) async {
|
||||
Map<String, dynamic>? params = {"api_key": apiKey ?? kChangeNowApiKey};
|
||||
|
||||
final uri = _buildUri(
|
||||
"/exchange-range${isFixedRate ? "/fixed-rate" : ""}/${fromTicker}_$toTicker",
|
||||
params);
|
||||
|
||||
try {
|
||||
final jsonObject = await _makeGetRequest(uri);
|
||||
|
||||
final json = Map<String, dynamic>.from(jsonObject as Map);
|
||||
return ExchangeResponse(
|
||||
value: Range(
|
||||
max: Decimal.tryParse(json["maxAmount"] as String? ?? ""),
|
||||
min: Decimal.tryParse(json["minAmount"] as String? ?? ""),
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"getRange exception: $e\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
return ExchangeResponse(
|
||||
exception: ExchangeException(
|
||||
e.toString(),
|
||||
ExchangeExceptionType.generic,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get estimated amount of [toTicker] cryptocurrency to receive
|
||||
/// for [fromAmount] of [fromTicker]
|
||||
Future<ExchangeResponse<EstimatedExchangeAmount>> getEstimatedExchangeAmount({
|
||||
|
@ -309,6 +350,59 @@ class ChangeNowAPI {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get estimated amount of [toTicker] cryptocurrency to receive
|
||||
/// for [fromAmount] of [fromTicker]
|
||||
Future<ExchangeResponse<EstimatedExchangeAmount>>
|
||||
getEstimatedExchangeAmountFixedRate({
|
||||
required String fromTicker,
|
||||
required String toTicker,
|
||||
required Decimal fromAmount,
|
||||
required bool reversed,
|
||||
String? apiKey,
|
||||
}) async {
|
||||
Map<String, dynamic> params = {"api_key": apiKey ?? kChangeNowApiKey};
|
||||
|
||||
late final Uri uri;
|
||||
if (reversed) {
|
||||
uri = _buildUri(
|
||||
"/exchange-deposit/fixed-rate/${fromAmount.toString()}/${fromTicker}_$toTicker",
|
||||
params,
|
||||
);
|
||||
} else {
|
||||
uri = _buildUri(
|
||||
"/exchange-amount/fixed-rate/${fromAmount.toString()}/${fromTicker}_$toTicker",
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// simple json object is expected here
|
||||
final json = await _makeGetRequest(uri);
|
||||
|
||||
try {
|
||||
final value = EstimatedExchangeAmount.fromJson(
|
||||
Map<String, dynamic>.from(json as Map));
|
||||
return ExchangeResponse(value: value);
|
||||
} catch (_) {
|
||||
return ExchangeResponse(
|
||||
exception: ExchangeException(
|
||||
"Failed to serialize $json",
|
||||
ExchangeExceptionType.serializeResponseError,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logging.instance.log("getEstimatedExchangeAmount exception: $e\n$s",
|
||||
level: LogLevel.Error);
|
||||
return ExchangeResponse(
|
||||
exception: ExchangeException(
|
||||
e.toString(),
|
||||
ExchangeExceptionType.generic,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// old v1 version
|
||||
/// This API endpoint returns fixed-rate estimated exchange amount of
|
||||
/// [toTicker] cryptocurrency to receive for [fromAmount] of [fromTicker]
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:decimal/decimal.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/estimated_exchange_amount.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/currency.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/services/exchange/change_now/change_now_api.dart';
|
||||
import 'package:stackwallet/services/exchange/exchange.dart';
|
||||
import 'package:stackwallet/services/exchange/exchange_response.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class ChangeNowExchange extends Exchange {
|
||||
@override
|
||||
|
@ -25,8 +28,10 @@ class ChangeNowExchange extends Exchange {
|
|||
Future<ExchangeResponse<List<Currency>>> getAllCurrencies(
|
||||
bool fixedRate,
|
||||
) async {
|
||||
// TODO: implement getAllCurrencies
|
||||
throw UnimplementedError();
|
||||
return await ChangeNowAPI.instance.getAvailableCurrencies(
|
||||
fixedRate: fixedRate ? true : null,
|
||||
active: true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -41,19 +46,41 @@ class ChangeNowExchange extends Exchange {
|
|||
String to,
|
||||
Decimal amount,
|
||||
bool fixedRate,
|
||||
bool reversed,
|
||||
) async {
|
||||
// TODO: implement getEstimate
|
||||
throw UnimplementedError();
|
||||
late final ExchangeResponse<EstimatedExchangeAmount> response;
|
||||
if (fixedRate) {
|
||||
response =
|
||||
await ChangeNowAPI.instance.getEstimatedExchangeAmountFixedRate(
|
||||
fromTicker: from,
|
||||
toTicker: to,
|
||||
fromAmount: amount,
|
||||
reversed: reversed,
|
||||
);
|
||||
} else {
|
||||
response = await ChangeNowAPI.instance.getEstimatedExchangeAmount(
|
||||
fromTicker: from,
|
||||
toTicker: to,
|
||||
fromAmount: amount,
|
||||
);
|
||||
}
|
||||
if (response.exception != null) {
|
||||
return ExchangeResponse(exception: response.exception);
|
||||
}
|
||||
return ExchangeResponse(value: response.value?.estimatedAmount);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExchangeResponse<Range>> getMinMaxExchangeAmounts(
|
||||
Future<ExchangeResponse<Range>> getRange(
|
||||
String from,
|
||||
String to,
|
||||
bool fixedRate,
|
||||
) async {
|
||||
// TODO: implement getMinMaxExchangeAmounts
|
||||
throw UnimplementedError();
|
||||
return await ChangeNowAPI.instance.getRange(
|
||||
fromTicker: from,
|
||||
toTicker: to,
|
||||
isFixedRate: fixedRate,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -67,8 +94,76 @@ class ChangeNowExchange extends Exchange {
|
|||
|
||||
@override
|
||||
Future<ExchangeResponse<Trade>> getTrade(String tradeId) async {
|
||||
// TODO: implement getTrade
|
||||
throw UnimplementedError();
|
||||
final response =
|
||||
await ChangeNowAPI.instance.getTransactionStatus(id: tradeId);
|
||||
if (response.exception != null) {
|
||||
return ExchangeResponse(exception: response.exception);
|
||||
}
|
||||
final t = response.value!;
|
||||
final timestamp = DateTime.tryParse(t.createdAt) ?? DateTime.now();
|
||||
|
||||
final trade = Trade(
|
||||
uuid: const Uuid().v1(),
|
||||
tradeId: tradeId,
|
||||
rateType: "",
|
||||
direction: "",
|
||||
timestamp: timestamp,
|
||||
updatedAt: DateTime.tryParse(t.updatedAt) ?? timestamp,
|
||||
payInCurrency: t.fromCurrency,
|
||||
payInAmount: t.expectedSendAmountDecimal,
|
||||
payInAddress: t.payinAddress,
|
||||
payInNetwork: "",
|
||||
payInExtraId: t.payinExtraId,
|
||||
payInTxid: "",
|
||||
payOutCurrency: t.toCurrency,
|
||||
payOutAmount: t.expectedReceiveAmountDecimal,
|
||||
payOutAddress: t.payoutAddress,
|
||||
payOutNetwork: "",
|
||||
payOutExtraId: t.payoutExtraId,
|
||||
payOutTxid: "",
|
||||
refundAddress: t.refundAddress,
|
||||
refundExtraId: t.refundExtraId,
|
||||
status: t.status.name,
|
||||
);
|
||||
|
||||
return ExchangeResponse(value: trade);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExchangeResponse<Trade>> updateTrade(Trade trade) async {
|
||||
final response =
|
||||
await ChangeNowAPI.instance.getTransactionStatus(id: trade.tradeId);
|
||||
if (response.exception != null) {
|
||||
return ExchangeResponse(exception: response.exception);
|
||||
}
|
||||
final t = response.value!;
|
||||
final timestamp = DateTime.tryParse(t.createdAt) ?? DateTime.now();
|
||||
|
||||
final _trade = Trade(
|
||||
uuid: trade.uuid,
|
||||
tradeId: trade.tradeId,
|
||||
rateType: "",
|
||||
direction: "",
|
||||
timestamp: timestamp,
|
||||
updatedAt: DateTime.tryParse(t.updatedAt) ?? timestamp,
|
||||
payInCurrency: t.fromCurrency,
|
||||
payInAmount: t.expectedSendAmountDecimal,
|
||||
payInAddress: t.payinAddress,
|
||||
payInNetwork: "",
|
||||
payInExtraId: t.payinExtraId,
|
||||
payInTxid: "",
|
||||
payOutCurrency: t.toCurrency,
|
||||
payOutAmount: t.expectedReceiveAmountDecimal,
|
||||
payOutAddress: t.payoutAddress,
|
||||
payOutNetwork: "",
|
||||
payOutExtraId: t.payoutExtraId,
|
||||
payOutTxid: "",
|
||||
refundAddress: t.refundAddress,
|
||||
refundExtraId: t.refundExtraId,
|
||||
status: t.status.name,
|
||||
);
|
||||
|
||||
return ExchangeResponse(value: _trade);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -18,10 +18,11 @@ abstract class Exchange {
|
|||
Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate);
|
||||
|
||||
Future<ExchangeResponse<Trade>> getTrade(String tradeId);
|
||||
Future<ExchangeResponse<Trade>> updateTrade(Trade trade);
|
||||
|
||||
Future<ExchangeResponse<List<Trade>>> getTrades();
|
||||
|
||||
Future<ExchangeResponse<Range>> getMinMaxExchangeAmounts(
|
||||
Future<ExchangeResponse<Range>> getRange(
|
||||
String from,
|
||||
String to,
|
||||
bool fixedRate,
|
||||
|
@ -32,6 +33,7 @@ abstract class Exchange {
|
|||
String to,
|
||||
Decimal amount,
|
||||
bool fixedRate,
|
||||
bool reversed,
|
||||
);
|
||||
|
||||
Future<ExchangeResponse<Trade>> createTrade({
|
||||
|
|
|
@ -334,6 +334,7 @@ class SimpleSwapAPI {
|
|||
Future<ExchangeResponse<Trade>> getExchange({
|
||||
required String exchangeId,
|
||||
String? apiKey,
|
||||
Trade? oldTrade,
|
||||
}) async {
|
||||
final uri = _buildUri(
|
||||
"/get_exchange",
|
||||
|
@ -349,7 +350,7 @@ class SimpleSwapAPI {
|
|||
final json = Map<String, dynamic>.from(jsonObject as Map);
|
||||
final ts = DateTime.parse(json["timestamp"] as String);
|
||||
final trade = Trade(
|
||||
uuid: const Uuid().v1(),
|
||||
uuid: oldTrade?.uuid ?? const Uuid().v1(),
|
||||
tradeId: json["id"] as String,
|
||||
rateType: json["type"] as String,
|
||||
direction: "direct",
|
||||
|
|
|
@ -73,6 +73,7 @@ class SimpleSwapExchange extends Exchange {
|
|||
String to,
|
||||
Decimal amount,
|
||||
bool fixedRate,
|
||||
bool reversed,
|
||||
) async {
|
||||
final response = await SimpleSwapAPI.instance.getEstimated(
|
||||
isFixedRate: fixedRate,
|
||||
|
@ -88,7 +89,7 @@ class SimpleSwapExchange extends Exchange {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ExchangeResponse<Range>> getMinMaxExchangeAmounts(
|
||||
Future<ExchangeResponse<Range>> getRange(
|
||||
String from,
|
||||
String to,
|
||||
bool fixedRate,
|
||||
|
@ -114,6 +115,14 @@ class SimpleSwapExchange extends Exchange {
|
|||
return await SimpleSwapAPI.instance.getExchange(exchangeId: tradeId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExchangeResponse<Trade>> updateTrade(Trade trade) async {
|
||||
return await SimpleSwapAPI.instance.getExchange(
|
||||
exchangeId: trade.tradeId,
|
||||
oldTrade: trade,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExchangeResponse<List<Trade>>> getTrades() async {
|
||||
// TODO: implement getTrades
|
||||
|
|
Loading…
Reference in a new issue