2022-10-02 20:53:53 +00:00
|
|
|
import 'package:decimal/decimal.dart';
|
2022-10-03 00:54:35 +00:00
|
|
|
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
2022-10-03 16:30:50 +00:00
|
|
|
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
|
2022-10-02 20:53:53 +00:00
|
|
|
import 'package:stackwallet/models/exchange/response_objects/range.dart';
|
|
|
|
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
2023-02-05 20:32:39 +00:00
|
|
|
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
|
|
|
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
2022-10-02 21:48:43 +00:00
|
|
|
import 'package:stackwallet/services/exchange/change_now/change_now_api.dart';
|
2022-10-02 20:53:53 +00:00
|
|
|
import 'package:stackwallet/services/exchange/exchange.dart';
|
|
|
|
import 'package:stackwallet/services/exchange/exchange_response.dart';
|
2022-10-02 21:48:43 +00:00
|
|
|
import 'package:uuid/uuid.dart';
|
2022-10-02 20:53:53 +00:00
|
|
|
|
|
|
|
class ChangeNowExchange extends Exchange {
|
2023-02-05 20:32:39 +00:00
|
|
|
ChangeNowExchange._();
|
|
|
|
|
|
|
|
static ChangeNowExchange? _instance;
|
|
|
|
static ChangeNowExchange get instance => _instance ??= ChangeNowExchange._();
|
|
|
|
|
2022-10-03 00:54:35 +00:00
|
|
|
static const exchangeName = "ChangeNOW";
|
|
|
|
|
|
|
|
@override
|
|
|
|
String get name => exchangeName;
|
|
|
|
|
2022-10-02 20:53:53 +00:00
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<Trade>> createTrade({
|
|
|
|
required String from,
|
|
|
|
required String to,
|
|
|
|
required bool fixedRate,
|
|
|
|
required Decimal amount,
|
|
|
|
required String addressTo,
|
2022-10-03 00:54:35 +00:00
|
|
|
String? extraId,
|
2022-10-02 20:53:53 +00:00
|
|
|
required String addressRefund,
|
|
|
|
required String refundExtraId,
|
2022-10-03 00:54:35 +00:00
|
|
|
String? rateId,
|
2022-10-04 00:55:12 +00:00
|
|
|
required bool reversed,
|
2022-10-02 20:53:53 +00:00
|
|
|
}) async {
|
2022-10-03 00:54:35 +00:00
|
|
|
late final ExchangeResponse<ExchangeTransaction> response;
|
|
|
|
if (fixedRate) {
|
|
|
|
response = await ChangeNowAPI.instance.createFixedRateExchangeTransaction(
|
|
|
|
fromTicker: from,
|
|
|
|
toTicker: to,
|
|
|
|
receivingAddress: addressTo,
|
|
|
|
amount: amount,
|
|
|
|
rateId: rateId!,
|
|
|
|
extraId: extraId ?? "",
|
|
|
|
refundAddress: addressRefund,
|
|
|
|
refundExtraId: refundExtraId,
|
2022-10-04 00:55:12 +00:00
|
|
|
reversed: reversed,
|
2022-10-03 00:54:35 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
response = await ChangeNowAPI.instance.createStandardExchangeTransaction(
|
|
|
|
fromTicker: from,
|
|
|
|
toTicker: to,
|
|
|
|
receivingAddress: addressTo,
|
|
|
|
amount: amount,
|
|
|
|
extraId: extraId ?? "",
|
|
|
|
refundAddress: addressRefund,
|
|
|
|
refundExtraId: refundExtraId,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (response.exception != null) {
|
|
|
|
return ExchangeResponse(exception: response.exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
final statusResponse = await ChangeNowAPI.instance
|
|
|
|
.getTransactionStatus(id: response.value!.id);
|
|
|
|
if (statusResponse.exception != null) {
|
|
|
|
return ExchangeResponse(exception: statusResponse.exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ExchangeResponse(
|
|
|
|
value: Trade.fromExchangeTransaction(
|
|
|
|
response.value!.copyWith(
|
|
|
|
statusObject: statusResponse.value!,
|
|
|
|
),
|
2022-10-04 00:55:12 +00:00
|
|
|
reversed,
|
2022-10-03 00:54:35 +00:00
|
|
|
),
|
|
|
|
);
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<List<Currency>>> getAllCurrencies(
|
|
|
|
bool fixedRate,
|
|
|
|
) async {
|
2022-10-02 21:48:43 +00:00
|
|
|
return await ChangeNowAPI.instance.getAvailableCurrencies(
|
|
|
|
fixedRate: fixedRate ? true : null,
|
|
|
|
active: true,
|
|
|
|
);
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate) async {
|
2023-02-05 20:32:39 +00:00
|
|
|
if (fixedRate) {
|
|
|
|
final markets =
|
|
|
|
await ChangeNowAPI.instance.getAvailableFixedRateMarkets();
|
|
|
|
|
|
|
|
if (markets.value == null) {
|
|
|
|
return ExchangeResponse(exception: markets.exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
final List<Pair> pairs = [];
|
|
|
|
for (final market in markets.value!) {
|
|
|
|
pairs.add(
|
|
|
|
Pair(
|
|
|
|
exchangeName: ChangeNowExchange.exchangeName,
|
|
|
|
from: market.from,
|
|
|
|
fromNetwork: "",
|
|
|
|
to: market.to,
|
|
|
|
toNetwork: "",
|
|
|
|
fixedRate: true,
|
|
|
|
floatingRate: false,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return ExchangeResponse(value: pairs);
|
|
|
|
} else {
|
|
|
|
return await ChangeNowAPI.instance.getAvailableFloatingRatePairs();
|
|
|
|
}
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2022-10-03 16:30:50 +00:00
|
|
|
Future<ExchangeResponse<Estimate>> getEstimate(
|
2022-10-02 20:53:53 +00:00
|
|
|
String from,
|
|
|
|
String to,
|
|
|
|
Decimal amount,
|
|
|
|
bool fixedRate,
|
2022-10-02 21:48:43 +00:00
|
|
|
bool reversed,
|
2022-10-02 20:53:53 +00:00
|
|
|
) async {
|
2022-10-03 16:30:50 +00:00
|
|
|
late final ExchangeResponse<Estimate> response;
|
2022-10-02 21:48:43 +00:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
}
|
2022-10-03 16:30:50 +00:00
|
|
|
return response;
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2022-10-02 21:48:43 +00:00
|
|
|
Future<ExchangeResponse<Range>> getRange(
|
2022-10-02 20:53:53 +00:00
|
|
|
String from,
|
|
|
|
String to,
|
|
|
|
bool fixedRate,
|
|
|
|
) async {
|
2022-10-02 21:48:43 +00:00
|
|
|
return await ChangeNowAPI.instance.getRange(
|
|
|
|
fromTicker: from,
|
|
|
|
toTicker: to,
|
|
|
|
isFixedRate: fixedRate,
|
|
|
|
);
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<List<Pair>>> getPairsFor(
|
|
|
|
String currency,
|
|
|
|
bool fixedRate,
|
|
|
|
) async {
|
|
|
|
// TODO: implement getPairsFor
|
|
|
|
throw UnimplementedError();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<Trade>> getTrade(String tradeId) async {
|
2022-10-02 21:48:43 +00:00
|
|
|
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,
|
2022-10-03 13:59:59 +00:00
|
|
|
payInTxid: t.payinHash,
|
2022-10-02 21:48:43 +00:00
|
|
|
payOutCurrency: t.toCurrency,
|
|
|
|
payOutAmount: t.expectedReceiveAmountDecimal,
|
|
|
|
payOutAddress: t.payoutAddress,
|
|
|
|
payOutNetwork: "",
|
|
|
|
payOutExtraId: t.payoutExtraId,
|
2022-10-03 13:59:59 +00:00
|
|
|
payOutTxid: t.payoutHash,
|
2022-10-02 21:48:43 +00:00
|
|
|
refundAddress: t.refundAddress,
|
|
|
|
refundExtraId: t.refundExtraId,
|
|
|
|
status: t.status.name,
|
2022-10-03 00:54:35 +00:00
|
|
|
exchangeName: ChangeNowExchange.exchangeName,
|
2022-10-02 21:48:43 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
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,
|
2022-10-03 00:54:35 +00:00
|
|
|
rateType: trade.rateType,
|
|
|
|
direction: trade.direction,
|
2022-10-02 21:48:43 +00:00
|
|
|
timestamp: timestamp,
|
|
|
|
updatedAt: DateTime.tryParse(t.updatedAt) ?? timestamp,
|
|
|
|
payInCurrency: t.fromCurrency,
|
2022-10-03 00:54:35 +00:00
|
|
|
payInAmount: t.amountSendDecimal.isEmpty
|
|
|
|
? t.expectedSendAmountDecimal
|
|
|
|
: t.amountSendDecimal,
|
2022-10-02 21:48:43 +00:00
|
|
|
payInAddress: t.payinAddress,
|
2022-10-03 00:54:35 +00:00
|
|
|
payInNetwork: trade.payInNetwork,
|
2022-10-02 21:48:43 +00:00
|
|
|
payInExtraId: t.payinExtraId,
|
2022-10-03 00:54:35 +00:00
|
|
|
payInTxid: t.payinHash,
|
2022-10-02 21:48:43 +00:00
|
|
|
payOutCurrency: t.toCurrency,
|
2022-10-03 00:54:35 +00:00
|
|
|
payOutAmount: t.amountReceiveDecimal.isEmpty
|
|
|
|
? t.expectedReceiveAmountDecimal
|
|
|
|
: t.amountReceiveDecimal,
|
2022-10-02 21:48:43 +00:00
|
|
|
payOutAddress: t.payoutAddress,
|
2022-10-03 00:54:35 +00:00
|
|
|
payOutNetwork: trade.payOutNetwork,
|
2022-10-02 21:48:43 +00:00
|
|
|
payOutExtraId: t.payoutExtraId,
|
2022-10-03 00:54:35 +00:00
|
|
|
payOutTxid: t.payoutHash,
|
2022-10-02 21:48:43 +00:00
|
|
|
refundAddress: t.refundAddress,
|
|
|
|
refundExtraId: t.refundExtraId,
|
|
|
|
status: t.status.name,
|
2022-10-03 00:54:35 +00:00
|
|
|
exchangeName: ChangeNowExchange.exchangeName,
|
2022-10-02 21:48:43 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return ExchangeResponse(value: _trade);
|
2022-10-02 20:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<ExchangeResponse<List<Trade>>> getTrades() async {
|
|
|
|
// TODO: implement getTrades
|
|
|
|
throw UnimplementedError();
|
|
|
|
}
|
|
|
|
}
|