From 585a684ecc00d510fb4f5a2339c96fd765c19d28 Mon Sep 17 00:00:00 2001 From: julian <julian@cypherstack.com> Date: Sat, 4 Feb 2023 11:48:07 -0600 Subject: [PATCH] apply majestic bank api to an exchange class --- .../majestic_bank/majestic_bank_api.dart | 39 ++- .../majestic_bank/majestic_bank_exchange.dart | 247 +++++++++++++++--- 2 files changed, 251 insertions(+), 35 deletions(-) diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index e140e5308..6d7e2ffe7 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -86,6 +86,40 @@ class MajesticBankAPI { } } + Future<ExchangeResponse<MBLimit>> getLimit({ + required String fromCurrency, + }) async { + final uri = _buildUri( + endpoint: "limits", + params: { + "from_currency": fromCurrency, + }, + ); + + try { + final jsonObject = await _makeGetRequest(uri); + + final map = Map<String, dynamic>.from(jsonObject as Map); + + final limit = MBLimit( + currency: fromCurrency, + min: Decimal.parse(map["min"].toString()), + max: Decimal.parse(map["max"].toString()), + ); + + return ExchangeResponse(value: limit); + } catch (e, s) { + Logging.instance + .log("getLimits exception: $e\n$s", level: LogLevel.Error); + return ExchangeResponse( + exception: ExchangeException( + e.toString(), + ExchangeExceptionType.generic, + ), + ); + } + } + Future<ExchangeResponse<List<MBLimit>>> getLimits() async { final uri = _buildUri( endpoint: @@ -267,8 +301,9 @@ class MajesticBankAPI { } } - Future<ExchangeResponse<MBOrderStatus>> trackOrder( - {required String orderId}) async { + Future<ExchangeResponse<MBOrderStatus>> trackOrder({ + required String orderId, + }) async { final uri = _buildUri(endpoint: "track", params: { "trx": orderId, }); diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart index 978ffb914..4610f6c3d 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart @@ -1,4 +1,7 @@ import 'package:decimal/decimal.dart'; +import 'package:stackwallet/exceptions/exchange/exchange_exception.dart'; +import 'package:stackwallet/exceptions/exchange/majestic_bank/mb_exception.dart'; +import 'package:stackwallet/models/exchange/majestic_bank/mb_order.dart'; import 'package:stackwallet/models/exchange/response_objects/currency.dart'; import 'package:stackwallet/models/exchange/response_objects/estimate.dart'; import 'package:stackwallet/models/exchange/response_objects/pair.dart'; @@ -6,67 +9,212 @@ import 'package:stackwallet/models/exchange/response_objects/range.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/services/exchange/exchange.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; +import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_api.dart'; +import 'package:uuid/uuid.dart'; class MajesticBankExchange extends Exchange { static const exchangeName = "MajesticBank"; @override - Future<ExchangeResponse<Trade>> createTrade( - {required String from, - required String to, - required bool fixedRate, - required Decimal amount, - required String addressTo, - String? extraId, - required String addressRefund, - required String refundExtraId, - String? rateId, - required bool reversed}) { - // TODO: implement createTrade - throw UnimplementedError(); + Future<ExchangeResponse<Trade>> createTrade({ + required String from, + required String to, + required bool fixedRate, + required Decimal amount, + required String addressTo, + String? extraId, + required String addressRefund, + required String refundExtraId, + String? rateId, + required bool reversed, + }) async { + ExchangeResponse<MBOrder>? response; + + if (fixedRate) { + response = await MajesticBankAPI.instance.createFixedRateOrder( + amount: amount.toString(), + fromCurrency: from, + receiveCurrency: to, + receiveAddress: addressTo, + reversed: reversed, + ); + } else { + if (reversed) { + return ExchangeResponse( + exception: MBException( + "Reversed trade not available", + ExchangeExceptionType.generic, + ), + ); + } + response = await MajesticBankAPI.instance.createOrder( + fromAmount: amount.toString(), + fromCurrency: from, + receiveCurrency: to, + receiveAddress: addressTo, + ); + } + + if (response.value != null) { + final order = response.value!; + final trade = Trade( + uuid: const Uuid().v1(), + tradeId: order.orderId, + rateType: fixedRate ? "fixed" : "floating", + direction: reversed ? "reversed" : "direct", + timestamp: order.createdAt, + updatedAt: order.createdAt, + payInCurrency: order.fromCurrency, + payInAmount: order.fromAmount.toString(), + payInAddress: order.address, + payInNetwork: "", + payInExtraId: "", + payInTxid: "", + payOutCurrency: order.receiveCurrency, + payOutAmount: order.receiveAmount.toString(), + payOutAddress: addressTo, + payOutNetwork: "", + payOutExtraId: "", + payOutTxid: "", + refundAddress: addressRefund, + refundExtraId: refundExtraId, + status: "Waiting", + exchangeName: exchangeName, + ); + + return ExchangeResponse(value: trade); + } else { + return ExchangeResponse(exception: response.exception!); + } } @override - Future<ExchangeResponse<List<Currency>>> getAllCurrencies(bool fixedRate) { - // TODO: implement getAllCurrencies - throw UnimplementedError(); + Future<ExchangeResponse<List<Currency>>> getAllCurrencies( + bool fixedRate, + ) async { + final response = await MajesticBankAPI.instance.getLimits(); + if (response.value == null) { + return ExchangeResponse(exception: response.exception); + } + + final List<Currency> currencies = []; + final limits = response.value!; + + for (final limit in limits) { + final currency = Currency( + ticker: limit.currency, + name: limit.currency, + network: "", + image: "", + hasExternalId: false, + isFiat: false, + featured: false, + isStable: false, + supportsFixedRate: true, + ); + currencies.add(currency); + } + + return ExchangeResponse(value: currencies); } @override - Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate) { - // TODO: implement getAllPairs - throw UnimplementedError(); + Future<ExchangeResponse<List<Pair>>> getAllPairs(bool fixedRate) async { + final response = await MajesticBankAPI.instance.getRates(); + if (response.value == null) { + return ExchangeResponse(exception: response.exception); + } + + final List<Pair> pairs = []; + final rates = response.value!; + + for (final rate in rates) { + final pair = Pair( + from: rate.fromCurrency, + fromNetwork: "", + to: rate.toCurrency, + toNetwork: "", + fixedRate: true, + floatingRate: true, + ); + pairs.add(pair); + } + + return ExchangeResponse(value: pairs); } @override Future<ExchangeResponse<Estimate>> getEstimate( - String from, String to, Decimal amount, bool fixedRate, bool reversed) { - // TODO: implement getEstimate - throw UnimplementedError(); + String from, + String to, + Decimal amount, + bool fixedRate, + bool reversed, + ) async { + final response = await MajesticBankAPI.instance.calculateOrder( + amount: amount.toString(), + reversed: reversed, + fromCurrency: from, + receiveCurrency: to, + ); + if (response.value == null) { + return ExchangeResponse(exception: response.exception); + } + + final calc = response.value!; + final estimate = Estimate( + estimatedAmount: reversed ? calc.fromAmount : calc.receiveAmount, + fixedRate: fixedRate, + reversed: reversed, + ); + return ExchangeResponse(value: estimate); } @override Future<ExchangeResponse<List<Pair>>> getPairsFor( - String currency, bool fixedRate) { - // TODO: implement getPairsFor - throw UnimplementedError(); + String currency, + bool fixedRate, + ) async { + final response = await getAllPairs(fixedRate); + if (response.value == null) { + return ExchangeResponse(exception: response.exception); + } + + final pairs = response.value!.where( + (e) => + e.from.toUpperCase() == currency.toUpperCase() || + e.to.toUpperCase() == currency.toUpperCase(), + ); + + return ExchangeResponse(value: pairs.toList()); } @override Future<ExchangeResponse<Range>> getRange( - String from, String to, bool fixedRate) { - // TODO: implement getRange - throw UnimplementedError(); + String from, + String to, + bool fixedRate, + ) async { + final response = + await MajesticBankAPI.instance.getLimit(fromCurrency: from); + if (response.value == null) { + return ExchangeResponse(exception: response.exception); + } + + final limit = response.value!; + final range = Range(min: limit.min, max: limit.max); + + return ExchangeResponse(value: range); } @override - Future<ExchangeResponse<Trade>> getTrade(String tradeId) { + Future<ExchangeResponse<Trade>> getTrade(String tradeId) async { // TODO: implement getTrade throw UnimplementedError(); } @override - Future<ExchangeResponse<List<Trade>>> getTrades() { + Future<ExchangeResponse<List<Trade>>> getTrades() async { // TODO: implement getTrades throw UnimplementedError(); } @@ -75,8 +223,41 @@ class MajesticBankExchange extends Exchange { String get name => exchangeName; @override - Future<ExchangeResponse<Trade>> updateTrade(Trade trade) { - // TODO: implement updateTrade - throw UnimplementedError(); + Future<ExchangeResponse<Trade>> updateTrade(Trade trade) async { + final response = await MajesticBankAPI.instance.trackOrder( + orderId: trade.tradeId, + ); + + if (response.value != null) { + final status = response.value!; + final updatedTrade = Trade( + uuid: trade.uuid, + tradeId: status.orderId, + rateType: trade.rateType, + direction: trade.direction, + timestamp: trade.timestamp, + updatedAt: DateTime.now(), + payInCurrency: status.fromCurrency, + payInAmount: status.fromAmount.toString(), + payInAddress: status.address, + payInNetwork: trade.payInNetwork, + payInExtraId: trade.payInExtraId, + payInTxid: trade.payInTxid, + payOutCurrency: status.receiveCurrency, + payOutAmount: status.receiveAmount.toString(), + payOutAddress: trade.payOutAddress, + payOutNetwork: trade.payOutNetwork, + payOutExtraId: trade.payOutExtraId, + payOutTxid: trade.payOutTxid, + refundAddress: trade.refundAddress, + refundExtraId: trade.refundExtraId, + status: status.status, + exchangeName: exchangeName, + ); + + return ExchangeResponse(value: updatedTrade); + } else { + return ExchangeResponse(exception: response.exception); + } } }