From ba893652efceb7a3c4af6094136eb9251ad6ea10 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Jul 2025 10:12:05 -0600 Subject: [PATCH 1/7] temp eth sync "fix" --- lib/wallets/wallet/impl/ethereum_wallet.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/impl/ethereum_wallet.dart b/lib/wallets/wallet/impl/ethereum_wallet.dart index 35e0bc174..efb19bcbc 100644 --- a/lib/wallets/wallet/impl/ethereum_wallet.dart +++ b/lib/wallets/wallet/impl/ethereum_wallet.dart @@ -338,7 +338,14 @@ class EthereumWallet extends Bip39Wallet with PrivateKeyInterface { final Amount txFee = element.gasCost; final transactionAmount = element.value; final addressFrom = checksumEthereumAddress(element.from); - final addressTo = checksumEthereumAddress(element.to); + final String addressTo; + try { + addressTo = checksumEthereumAddress(element.to); + } catch (e, s) { + Logging.instance.w("Ignoring eth transaction:\n$e\n$s"); + // temp "fix" + continue; + } bool isIncoming; bool txFailed = false; From 394f469069a2a69889c0ceddc11c35b427957b42 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 22 Jul 2025 10:55:12 -0600 Subject: [PATCH 2/7] fix (bandaid?) xelis open-close-open wallet quickly bug --- .../wallet/intermediate/lib_xelis_wallet.dart | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart index 901223469..2415af7bd 100644 --- a/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart +++ b/lib/wallets/wallet/intermediate/lib_xelis_wallet.dart @@ -327,6 +327,10 @@ abstract class LibXelisWallet @override Future open() async { + while (exitInProgress) { + await Future.delayed(const Duration(milliseconds: 500)); + } + try { await connect(); } catch (e) { @@ -339,18 +343,25 @@ abstract class LibXelisWallet unawaited(refresh()); } + bool exitInProgress = false; + @override Future exit() async { - await refreshMutex.protect(() async { - timer?.cancel(); - timer = null; - - await _eventSubscription?.cancel(); - _eventSubscription = null; - - await libXelisWallet?.offlineMode(); - await super.exit(); - }); + exitInProgress = true; + try { + await refreshMutex.protect(() async { + timer?.cancel(); + timer = null; + + await _eventSubscription?.cancel(); + _eventSubscription = null; + + await libXelisWallet?.offlineMode(); + await super.exit(); + }); + } finally { + exitInProgress = false; + } } void invalidSeedLengthCheck(int length) { From 801b504c9891068dafeb64484f618c09bbcd00e1 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 09:33:57 -0600 Subject: [PATCH 3/7] disable/remove majestic bank --- lib/models/isar/exchange_cache/currency.dart | 4 +- lib/pages/exchange_view/exchange_form.dart | 2 - .../exchange_provider_options.dart | 24 +- .../exchange_view/trade_details_view.dart | 151 ++-- lib/services/exchange/exchange.dart | 6 +- .../exchange_data_loading_service.dart | 47 +- .../majestic_bank/majestic_bank_api.dart | 770 +++++++++--------- .../majestic_bank/majestic_bank_exchange.dart | 692 ++++++++-------- lib/services/notifications_service.dart | 68 +- lib/utilities/assets.dart | 9 +- 10 files changed, 863 insertions(+), 910 deletions(-) diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index 04c510186..f719f5a3c 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -13,7 +13,6 @@ import 'package:isar/isar.dart'; import '../../../app_config.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../../services/exchange/trocador/trocador_exchange.dart'; import 'pair.dart'; @@ -82,8 +81,7 @@ class Currency { // case const (SimpleSwapExchange): // currently a hardcoded of coins so we can just - const (MajesticBankExchange) => ticker.toLowerCase(), - + // const (MajesticBankExchange) => ticker.toLowerCase(), const (TrocadorExchange) => (network == "Mainnet" ? ticker.toLowerCase() : network), diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 93e15c4bb..675cd30cd 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -30,7 +30,6 @@ import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; import '../../services/exchange/exchange_response.dart'; -import '../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../services/exchange/trocador/trocador_exchange.dart'; import '../../themes/stack_colors.dart'; @@ -80,7 +79,6 @@ class _ExchangeFormState extends ConsumerState { return Exchange.exchangesWithTorSupport; } else { return [ - MajesticBankExchange.instance, ChangeNowExchange.instance, TrocadorExchange.instance, NanswapExchange.instance, diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart index 6bc4b5c04..a2ef39305 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart @@ -15,7 +15,6 @@ import '../../../models/exchange/aggregate_currency.dart'; import '../../../providers/providers.dart'; import '../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../services/exchange/exchange.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; @@ -82,11 +81,6 @@ class _ExchangeProviderOptionsState sendCurrency: sendCurrency, receiveCurrency: receivingCurrency, ); - final showMajesticBank = exchangeSupported( - exchangeName: MajesticBankExchange.exchangeName, - sendCurrency: sendCurrency, - receiveCurrency: receivingCurrency, - ); final showTrocador = exchangeSupported( exchangeName: TrocadorExchange.exchangeName, sendCurrency: sendCurrency, @@ -112,20 +106,7 @@ class _ExchangeProviderOptionsState fixedRate: widget.fixedRate, reversed: widget.reversed, ), - if (showChangeNow && showMajesticBank) - isDesktop - ? Container( - height: 1, - color: Theme.of(context).extension()!.background, - ) - : const SizedBox(height: 16), - if (showMajesticBank) - ExchangeOption( - exchange: MajesticBankExchange.instance, - fixedRate: widget.fixedRate, - reversed: widget.reversed, - ), - if ((showChangeNow || showMajesticBank) && showTrocador) + if (showChangeNow && showTrocador) isDesktop ? Container( height: 1, @@ -138,8 +119,7 @@ class _ExchangeProviderOptionsState reversed: widget.reversed, exchange: TrocadorExchange.instance, ), - if ((showChangeNow || showMajesticBank || showTrocador) && - showNanswap) + if ((showChangeNow || showTrocador) && showNanswap) isDesktop ? Container( height: 1, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index a0ccd79a5..329f1d572 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -29,7 +29,6 @@ import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange.dart'; -import '../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../../services/exchange/nanswap/nanswap_exchange.dart'; import '../../services/exchange/simpleswap/simpleswap_exchange.dart'; import '../../services/exchange/trocador/trocador_exchange.dart'; @@ -101,7 +100,7 @@ class _TradeDetailsViewState extends ConsumerState { .trades .firstWhere((e) => e.tradeId == tradeId); - if (mounted) { + if (mounted && trade.exchangeName != "Majestic Bank") { final exchange = Exchange.fromName(trade.exchangeName); final response = await exchange.updateTrade(trade); @@ -435,36 +434,6 @@ class _TradeDetailsViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Status", style: STextStyles.itemSubtitle(context)), - if (trade.exchangeName == - MajesticBankExchange.exchangeName && - trade.status == "Completed") - Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: () { - showDialog( - context: context, - builder: - (context) => const StackOkDialog( - title: "Trade Info", - message: - "Majestic Bank does not store order data indefinitely", - ), - ); - }, - child: SvgPicture.asset( - Assets.svg.circleInfo, - height: 20, - width: 20, - color: - Theme.of( - context, - ).extension()!.infoItemIcons, - ), - ), - ], - ), ], ), const SizedBox(height: 4), @@ -1202,68 +1171,66 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - isDesktop ? const _Divider() : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Tracking", style: STextStyles.itemSubtitle(context)), - const SizedBox(height: 4), - Builder( - builder: (context) { - late final String url; - switch (trade.exchangeName) { - case ChangeNowExchange.exchangeName: - url = - "https://changenow.io/exchange/txs/${trade.tradeId}"; - break; - case SimpleSwapExchange.exchangeName: - url = - "https://simpleswap.io/exchange?id=${trade.tradeId}"; - break; - case MajesticBankExchange.exchangeName: - url = - "https://majesticbank.sc/track?trx=${trade.tradeId}"; - break; - case NanswapExchange.exchangeName: - url = - "https://nanswap.com/transaction/${trade.tradeId}"; - break; - - default: - if (trade.exchangeName.startsWith( - TrocadorExchange.exchangeName, - )) { + if (trade.exchangeName != "Majestic Bank") + isDesktop ? const _Divider() : const SizedBox(height: 12), + if (trade.exchangeName != "Majestic Bank") + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Tracking", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 4), + Builder( + builder: (context) { + late final String url; + switch (trade.exchangeName) { + case ChangeNowExchange.exchangeName: url = - "https://trocador.app/en/checkout/${trade.tradeId}"; - } - } - return ConditionalParent( - condition: isDesktop, - builder: - (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), - child: GestureDetector( - onTap: () { - launchUrl( - Uri.parse(url), - mode: LaunchMode.externalApplication, - ); - }, - child: Text(url, style: STextStyles.link2(context)), - ), - ); - }, - ), - ], + "https://changenow.io/exchange/txs/${trade.tradeId}"; + break; + case SimpleSwapExchange.exchangeName: + url = + "https://simpleswap.io/exchange?id=${trade.tradeId}"; + break; + case NanswapExchange.exchangeName: + url = + "https://nanswap.com/transaction/${trade.tradeId}"; + break; + + default: + if (trade.exchangeName.startsWith( + TrocadorExchange.exchangeName, + )) { + url = + "https://trocador.app/en/checkout/${trade.tradeId}"; + } + } + return ConditionalParent( + condition: isDesktop, + builder: + (child) => MouseRegion( + cursor: SystemMouseCursors.click, + child: child, + ), + child: GestureDetector( + onTap: () { + launchUrl( + Uri.parse(url), + mode: LaunchMode.externalApplication, + ); + }, + child: Text(url, style: STextStyles.link2(context)), + ), + ); + }, + ), + ], + ), ), - ), if (!isDesktop) const SizedBox(height: 12), if (!isDesktop && showSendFromStackButton) SecondaryButton( diff --git a/lib/services/exchange/exchange.dart b/lib/services/exchange/exchange.dart index f25bddc77..05ca33e87 100644 --- a/lib/services/exchange/exchange.dart +++ b/lib/services/exchange/exchange.dart @@ -30,8 +30,8 @@ abstract class Exchange { return ChangeNowExchange.instance; case SimpleSwapExchange.exchangeName: return SimpleSwapExchange.instance; - case MajesticBankExchange.exchangeName: - return MajesticBankExchange.instance; + // case MajesticBankExchange.exchangeName: + // return MajesticBankExchange.instance; case TrocadorExchange.exchangeName: return TrocadorExchange.instance; case NanswapExchange.exchangeName: @@ -106,7 +106,7 @@ abstract class Exchange { /// /// Add to this list when adding a new exchange which supports Tor. static List get exchangesWithTorSupport => [ - MajesticBankExchange.instance, + // MajesticBankExchange.instance, TrocadorExchange.instance, NanswapExchange.instance, // Maybe?? ]; diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index f1a181104..78fb0117f 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -23,7 +23,6 @@ import '../../utilities/logger.dart'; import '../../utilities/prefs.dart'; import '../../utilities/stack_file_system.dart'; import 'change_now/change_now_exchange.dart'; -import 'majestic_bank/majestic_bank_exchange.dart'; import 'nanswap/nanswap_exchange.dart'; import 'trocador/trocador_exchange.dart'; @@ -194,7 +193,7 @@ class ExchangeDataLoadingService { // Exchanges which support Tor just get treated normally. final futures = [ - loadMajesticBankCurrencies(), + // loadMajesticBankCurrencies(), loadTrocadorCurrencies(), loadNanswapCurrencies(), ]; @@ -359,28 +358,28 @@ class ExchangeDataLoadingService { // } // } - Future loadMajesticBankCurrencies() async { - if (_isar == null) { - await initDB(); - } - final exchange = MajesticBankExchange.instance; - final responseCurrencies = await exchange.getAllCurrencies(false); - - if (responseCurrencies.value != null) { - await isar.writeTxn(() async { - final idsToDelete = - await isar.currencies - .where() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .idProperty() - .findAll(); - await isar.currencies.deleteAll(idsToDelete); - await isar.currencies.putAll(responseCurrencies.value!); - }); - } else { - Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); - } - } + // Future loadMajesticBankCurrencies() async { + // if (_isar == null) { + // await initDB(); + // } + // final exchange = MajesticBankExchange.instance; + // final responseCurrencies = await exchange.getAllCurrencies(false); + // + // if (responseCurrencies.value != null) { + // await isar.writeTxn(() async { + // final idsToDelete = + // await isar.currencies + // .where() + // .exchangeNameEqualTo(MajesticBankExchange.exchangeName) + // .idProperty() + // .findAll(); + // await isar.currencies.deleteAll(idsToDelete); + // await isar.currencies.putAll(responseCurrencies.value!); + // }); + // } else { + // Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); + // } + // } Future loadTrocadorCurrencies() async { if (_isar == null) { diff --git a/lib/services/exchange/majestic_bank/majestic_bank_api.dart b/lib/services/exchange/majestic_bank/majestic_bank_api.dart index ee87bf159..7d713d6d6 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_api.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_api.dart @@ -1,385 +1,385 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'dart:convert'; - -import 'package:decimal/decimal.dart'; - -import '../../../exceptions/exchange/exchange_exception.dart'; -import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; -import '../../../exceptions/exchange/pair_unavailable_exception.dart'; -import '../../../models/exchange/majestic_bank/mb_limit.dart'; -import '../../../models/exchange/majestic_bank/mb_order.dart'; -import '../../../models/exchange/majestic_bank/mb_order_calculation.dart'; -import '../../../models/exchange/majestic_bank/mb_order_status.dart'; -import '../../../models/exchange/majestic_bank/mb_rate.dart'; -import '../../../networking/http.dart'; -import '../../../utilities/logger.dart'; -import '../../../utilities/prefs.dart'; -import '../../tor_service.dart'; -import '../exchange_response.dart'; - -class MajesticBankAPI { - static const String scheme = "https"; - static const String authority = "majesticbank.sc"; - static const String version = "v1"; - static const kMajesticBankRefCode = "rjWugM"; - - MajesticBankAPI._(); - - static final MajesticBankAPI _instance = MajesticBankAPI._(); - - static MajesticBankAPI get instance => _instance; - - HTTP client = HTTP(); - - Uri _buildUri({required String endpoint, Map? params}) { - return Uri.https(authority, "/api/$version/$endpoint", params); - } - - Future _makeGetRequest(Uri uri) async { - // final client = this.client ?? http.Client(); - int code = -1; - try { - final response = await client.get( - url: uri, - proxyInfo: - Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, - ); - - code = response.code; - - final parsed = jsonDecode(response.body); - - return parsed; - } catch (e, s) { - Logging.instance.e( - "_makeRequest($uri) HTTP:$code threw: ", - error: e, - stackTrace: s, - ); - rethrow; - } - } - - Future>> getRates() async { - final uri = _buildUri(endpoint: "rates"); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.from(jsonObject as Map); - final List rates = []; - for (final key in map.keys) { - final currencies = key.split("-"); - if (currencies.length == 2) { - final rate = MBRate( - fromCurrency: currencies.first, - toCurrency: currencies.last, - rate: Decimal.parse(map[key].toString()), - ); - rates.add(rate); - } - } - return ExchangeResponse(value: rates); - } catch (e, s) { - Logging.instance.e("getRates exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> getLimit({ - required String fromCurrency, - }) async { - final uri = _buildUri( - endpoint: "limits", - params: {"from_currency": fromCurrency}, - ); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.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.e("getLimits exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future>> getLimits() async { - final uri = _buildUri( - endpoint: - "rates", // limits are included in the rates call for some reason??? - ); - - try { - final jsonObject = await _makeGetRequest(uri); - - final map = Map.from(jsonObject as Map)["limits"] as Map; - final List limits = []; - for (final key in map.keys) { - final limit = MBLimit( - currency: key as String, - min: Decimal.parse(map[key]["min"].toString()), - max: Decimal.parse(map[key]["max"].toString()), - ); - limits.add(limit); - } - - return ExchangeResponse(value: limits); - } catch (e, s) { - Logging.instance.e("getLimits exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// If [reversed] then the amount is the expected receive_amount, otherwise - /// the amount is assumed to be the from_amount. - Future> calculateOrder({ - required String amount, - required bool reversed, - required String fromCurrency, - required String receiveCurrency, - }) async { - final params = { - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - }; - - if (reversed) { - params["receive_amount"] = amount; - } else { - params["from_amount"] = amount; - } - - final uri = _buildUri(endpoint: "calculate", params: params); - - try { - final jsonObject = await _makeGetRequest(uri); - final map = Map.from(jsonObject as Map); - - if (map["error"] != null) { - final errorMessage = map["extra"] as String?; - if (errorMessage != null && - errorMessage.startsWith("Bad") && - errorMessage.endsWith("currency symbol")) { - return ExchangeResponse( - exception: PairUnavailableException( - errorMessage, - ExchangeExceptionType.generic, - ), - ); - } else { - return ExchangeResponse( - exception: ExchangeException( - errorMessage ?? "Error: ${map["error"]}", - ExchangeExceptionType.generic, - ), - ); - } - } - - final result = MBOrderCalculation( - fromCurrency: map["from_currency"] as String, - fromAmount: Decimal.parse(map["from_amount"].toString()), - receiveCurrency: map["receive_currency"] as String, - receiveAmount: Decimal.parse(map["receive_amount"].toString()), - ); - - return ExchangeResponse(value: result); - } catch (e, s) { - Logging.instance.e( - "calculateOrder $fromCurrency-$receiveCurrency exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> createOrder({ - required String fromAmount, - required String fromCurrency, - required String receiveCurrency, - required String receiveAddress, - }) async { - final params = { - "from_amount": fromAmount, - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - "receive_address": receiveAddress, - "referral_code": kMajesticBankRefCode, - }; - - final uri = _buildUri(endpoint: "exchange", params: params); - - try { - final now = DateTime.now(); - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - final order = MBOrder( - orderId: json["trx"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - orderType: MBOrderType.floating, - expiration: json["expiration"] as int, - createdAt: now, - ); - - return ExchangeResponse(value: order); - } catch (e, s) { - Logging.instance.e("createOrder exception", error: e, stackTrace: s); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - /// Fixed rate for 10 minutes, useful for payments. - /// If [reversed] then the amount is the expected receive_amount, otherwise - /// the amount is assumed to be the from_amount. - Future> createFixedRateOrder({ - required String amount, - required String fromCurrency, - required String receiveCurrency, - required String receiveAddress, - required bool reversed, - }) async { - final params = { - "from_currency": fromCurrency, - "receive_currency": receiveCurrency, - "receive_address": receiveAddress, - "referral_code": kMajesticBankRefCode, - }; - - if (reversed) { - params["receive_amount"] = amount; - } else { - params["from_amount"] = amount; - } - - final uri = _buildUri(endpoint: "pay", params: params); - - try { - final now = DateTime.now(); - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - final order = MBOrder( - orderId: json["trx"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - orderType: MBOrderType.fixed, - expiration: json["expiration"] as int, - createdAt: now, - ); - - return ExchangeResponse(value: order); - } catch (e, s) { - Logging.instance.e( - "createFixedRateOrder exception: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } - - Future> trackOrder({ - required String orderId, - }) async { - final uri = _buildUri(endpoint: "track", params: {"trx": orderId}); - - try { - final jsonObject = await _makeGetRequest(uri); - final json = Map.from(jsonObject as Map); - - if (json.length == 2) { - return ExchangeResponse( - exception: MBException( - json["status"] as String, - ExchangeExceptionType.orderNotFound, - ), - ); - } - - final status = MBOrderStatus( - orderId: json["trx"] as String, - status: json["status"] as String, - fromCurrency: json["from_currency"] as String, - fromAmount: Decimal.parse(json["from_amount"].toString()), - receiveCurrency: json["receive_currency"] as String, - receiveAmount: Decimal.parse(json["receive_amount"].toString()), - address: json["address"] as String, - received: Decimal.parse(json["received"].toString()), - confirmed: Decimal.parse(json["confirmed"].toString()), - ); - - return ExchangeResponse(value: status); - } catch (e, s) { - Logging.instance.e( - "trackOrder exception when trying to parse $json: ", - error: e, - stackTrace: s, - ); - return ExchangeResponse( - exception: ExchangeException( - e.toString(), - ExchangeExceptionType.generic, - ), - ); - } - } -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'dart:convert'; +// +// import 'package:decimal/decimal.dart'; +// +// import '../../../exceptions/exchange/exchange_exception.dart'; +// import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; +// import '../../../exceptions/exchange/pair_unavailable_exception.dart'; +// import '../../../models/exchange/majestic_bank/mb_limit.dart'; +// import '../../../models/exchange/majestic_bank/mb_order.dart'; +// import '../../../models/exchange/majestic_bank/mb_order_calculation.dart'; +// import '../../../models/exchange/majestic_bank/mb_order_status.dart'; +// import '../../../models/exchange/majestic_bank/mb_rate.dart'; +// import '../../../networking/http.dart'; +// import '../../../utilities/logger.dart'; +// import '../../../utilities/prefs.dart'; +// import '../../tor_service.dart'; +// import '../exchange_response.dart'; +// +// class MajesticBankAPI { +// static const String scheme = "https"; +// static const String authority = "majesticbank.sc"; +// static const String version = "v1"; +// static const kMajesticBankRefCode = "rjWugM"; +// +// MajesticBankAPI._(); +// +// static final MajesticBankAPI _instance = MajesticBankAPI._(); +// +// static MajesticBankAPI get instance => _instance; +// +// HTTP client = HTTP(); +// +// Uri _buildUri({required String endpoint, Map? params}) { +// return Uri.https(authority, "/api/$version/$endpoint", params); +// } +// +// Future _makeGetRequest(Uri uri) async { +// // final client = this.client ?? http.Client(); +// int code = -1; +// try { +// final response = await client.get( +// url: uri, +// proxyInfo: +// Prefs.instance.useTor +// ? TorService.sharedInstance.getProxyInfo() +// : null, +// ); +// +// code = response.code; +// +// final parsed = jsonDecode(response.body); +// +// return parsed; +// } catch (e, s) { +// Logging.instance.e( +// "_makeRequest($uri) HTTP:$code threw: ", +// error: e, +// stackTrace: s, +// ); +// rethrow; +// } +// } +// +// Future>> getRates() async { +// final uri = _buildUri(endpoint: "rates"); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.from(jsonObject as Map); +// final List rates = []; +// for (final key in map.keys) { +// final currencies = key.split("-"); +// if (currencies.length == 2) { +// final rate = MBRate( +// fromCurrency: currencies.first, +// toCurrency: currencies.last, +// rate: Decimal.parse(map[key].toString()), +// ); +// rates.add(rate); +// } +// } +// return ExchangeResponse(value: rates); +// } catch (e, s) { +// Logging.instance.e("getRates exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> getLimit({ +// required String fromCurrency, +// }) async { +// final uri = _buildUri( +// endpoint: "limits", +// params: {"from_currency": fromCurrency}, +// ); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.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.e("getLimits exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future>> getLimits() async { +// final uri = _buildUri( +// endpoint: +// "rates", // limits are included in the rates call for some reason??? +// ); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// +// final map = Map.from(jsonObject as Map)["limits"] as Map; +// final List limits = []; +// for (final key in map.keys) { +// final limit = MBLimit( +// currency: key as String, +// min: Decimal.parse(map[key]["min"].toString()), +// max: Decimal.parse(map[key]["max"].toString()), +// ); +// limits.add(limit); +// } +// +// return ExchangeResponse(value: limits); +// } catch (e, s) { +// Logging.instance.e("getLimits exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// /// If [reversed] then the amount is the expected receive_amount, otherwise +// /// the amount is assumed to be the from_amount. +// Future> calculateOrder({ +// required String amount, +// required bool reversed, +// required String fromCurrency, +// required String receiveCurrency, +// }) async { +// final params = { +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// }; +// +// if (reversed) { +// params["receive_amount"] = amount; +// } else { +// params["from_amount"] = amount; +// } +// +// final uri = _buildUri(endpoint: "calculate", params: params); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// final map = Map.from(jsonObject as Map); +// +// if (map["error"] != null) { +// final errorMessage = map["extra"] as String?; +// if (errorMessage != null && +// errorMessage.startsWith("Bad") && +// errorMessage.endsWith("currency symbol")) { +// return ExchangeResponse( +// exception: PairUnavailableException( +// errorMessage, +// ExchangeExceptionType.generic, +// ), +// ); +// } else { +// return ExchangeResponse( +// exception: ExchangeException( +// errorMessage ?? "Error: ${map["error"]}", +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// final result = MBOrderCalculation( +// fromCurrency: map["from_currency"] as String, +// fromAmount: Decimal.parse(map["from_amount"].toString()), +// receiveCurrency: map["receive_currency"] as String, +// receiveAmount: Decimal.parse(map["receive_amount"].toString()), +// ); +// +// return ExchangeResponse(value: result); +// } catch (e, s) { +// Logging.instance.e( +// "calculateOrder $fromCurrency-$receiveCurrency exception: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> createOrder({ +// required String fromAmount, +// required String fromCurrency, +// required String receiveCurrency, +// required String receiveAddress, +// }) async { +// final params = { +// "from_amount": fromAmount, +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// "receive_address": receiveAddress, +// "referral_code": kMajesticBankRefCode, +// }; +// +// final uri = _buildUri(endpoint: "exchange", params: params); +// +// try { +// final now = DateTime.now(); +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// final order = MBOrder( +// orderId: json["trx"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// orderType: MBOrderType.floating, +// expiration: json["expiration"] as int, +// createdAt: now, +// ); +// +// return ExchangeResponse(value: order); +// } catch (e, s) { +// Logging.instance.e("createOrder exception", error: e, stackTrace: s); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// /// Fixed rate for 10 minutes, useful for payments. +// /// If [reversed] then the amount is the expected receive_amount, otherwise +// /// the amount is assumed to be the from_amount. +// Future> createFixedRateOrder({ +// required String amount, +// required String fromCurrency, +// required String receiveCurrency, +// required String receiveAddress, +// required bool reversed, +// }) async { +// final params = { +// "from_currency": fromCurrency, +// "receive_currency": receiveCurrency, +// "receive_address": receiveAddress, +// "referral_code": kMajesticBankRefCode, +// }; +// +// if (reversed) { +// params["receive_amount"] = amount; +// } else { +// params["from_amount"] = amount; +// } +// +// final uri = _buildUri(endpoint: "pay", params: params); +// +// try { +// final now = DateTime.now(); +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// final order = MBOrder( +// orderId: json["trx"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// orderType: MBOrderType.fixed, +// expiration: json["expiration"] as int, +// createdAt: now, +// ); +// +// return ExchangeResponse(value: order); +// } catch (e, s) { +// Logging.instance.e( +// "createFixedRateOrder exception: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// +// Future> trackOrder({ +// required String orderId, +// }) async { +// final uri = _buildUri(endpoint: "track", params: {"trx": orderId}); +// +// try { +// final jsonObject = await _makeGetRequest(uri); +// final json = Map.from(jsonObject as Map); +// +// if (json.length == 2) { +// return ExchangeResponse( +// exception: MBException( +// json["status"] as String, +// ExchangeExceptionType.orderNotFound, +// ), +// ); +// } +// +// final status = MBOrderStatus( +// orderId: json["trx"] as String, +// status: json["status"] as String, +// fromCurrency: json["from_currency"] as String, +// fromAmount: Decimal.parse(json["from_amount"].toString()), +// receiveCurrency: json["receive_currency"] as String, +// receiveAmount: Decimal.parse(json["receive_amount"].toString()), +// address: json["address"] as String, +// received: Decimal.parse(json["received"].toString()), +// confirmed: Decimal.parse(json["confirmed"].toString()), +// ); +// +// return ExchangeResponse(value: status); +// } catch (e, s) { +// Logging.instance.e( +// "trackOrder exception when trying to parse $json: ", +// error: e, +// stackTrace: s, +// ); +// return ExchangeResponse( +// exception: ExchangeException( +// e.toString(), +// ExchangeExceptionType.generic, +// ), +// ); +// } +// } +// } diff --git a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart index b1f8be150..aacceb587 100644 --- a/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart +++ b/lib/services/exchange/majestic_bank/majestic_bank_exchange.dart @@ -1,346 +1,346 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:decimal/decimal.dart'; -import 'package:uuid/uuid.dart'; - -import '../../../app_config.dart'; -import '../../../exceptions/exchange/exchange_exception.dart'; -import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; -import '../../../models/exchange/majestic_bank/mb_order.dart'; -import '../../../models/exchange/response_objects/estimate.dart'; -import '../../../models/exchange/response_objects/range.dart'; -import '../../../models/exchange/response_objects/trade.dart'; -import '../../../models/isar/exchange_cache/currency.dart'; -import '../../../models/isar/exchange_cache/pair.dart'; -import '../exchange.dart'; -import '../exchange_response.dart'; -import 'majestic_bank_api.dart'; - -class MajesticBankExchange extends Exchange { - MajesticBankExchange._(); - - static MajesticBankExchange? _instance; - static MajesticBankExchange get instance => - _instance ??= MajesticBankExchange._(); - - static const exchangeName = "Majestic Bank"; - - static const kMajesticBankCurrencyNames = { - "BCH": "Bitcoin Cash", - "BTC": "Bitcoin", - "DOGE": "Dogecoin", - "EPIC": "Epic Cash", - "FIRO": "Firo", - "LTC": "Litecoin", - "NMC": "Namecoin", - "PART": "Particl", - "WOW": "Wownero", - "XMR": "Monero", - }; - - @override - bool get supportsRefundAddress => false; - - @override - Future> createTrade({ - required String from, - required String to, - required String? fromNetwork, - required String? toNetwork, - required bool fixedRate, - required Decimal amount, - required String addressTo, - String? extraId, - required String addressRefund, - required String refundExtraId, - Estimate? estimate, - required bool reversed, - }) async { - ExchangeResponse? 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>> getAllCurrencies( - bool fixedRate, - ) async { - final response = await MajesticBankAPI.instance.getLimits(); - if (response.value == null) { - return ExchangeResponse(exception: response.exception); - } - - final List currencies = []; - final limits = response.value!; - - for (final limit in limits) { - final currency = Currency( - exchangeName: MajesticBankExchange.exchangeName, - ticker: limit.currency, - name: - kMajesticBankCurrencyNames[limit.currency] ?? - limit.currency, // todo: add more names if MB adds more - network: "", - image: "", - isFiat: false, - rateType: SupportedRateType.both, - isAvailable: true, - isStackCoin: AppConfig.isStackCoin(limit.currency), - tokenContract: null, - ); - currencies.add(currency); - } - - return ExchangeResponse(value: currencies); - } - - // @override - // Future>> getPairedCurrencies( - // String forCurrency, - // bool fixedRate, - // ) { - // // TODO: change this if the api changes to allow getting by paired currency - // return getAllCurrencies(fixedRate); - // } - // - // @override - // Future>> getAllPairs(bool fixedRate) async { - // final response = await MajesticBankAPI.instance.getRates(); - // if (response.value == null) { - // return ExchangeResponse(exception: response.exception); - // } - // - // final List pairs = []; - // final rates = response.value!; - // - // for (final rate in rates) { - // final pair = Pair( - // exchangeName: MajesticBankExchange.exchangeName, - // from: rate.fromCurrency, - // to: rate.toCurrency, - // rateType: SupportedRateType.both, - // ); - // pairs.add(pair); - // } - // - // return ExchangeResponse(value: pairs); - // } - - @override - Future>> getEstimates( - String from, - String? fromNetwork, - String to, - String? toNetwork, - 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, - exchangeProvider: MajesticBankExchange.exchangeName, - ); - return ExchangeResponse(value: [estimate]); - } - - // @override - // Future>> getPairsFor( - // 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> getRange( - String from, - String? fromNetwork, - String to, - String? toNetwork, - 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> getTrade(String tradeId) async { - // TODO: implement getTrade - throw UnimplementedError(); - } - - @override - Future>> getTrades() async { - // TODO: implement getTrades - throw UnimplementedError(); - } - - @override - String get name => exchangeName; - - @override - Future> 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 { - if (response.exception?.type == ExchangeExceptionType.orderNotFound) { - final updatedTrade = Trade( - uuid: trade.uuid, - tradeId: trade.tradeId, - rateType: trade.rateType, - direction: trade.direction, - timestamp: trade.timestamp, - updatedAt: DateTime.now(), - payInCurrency: trade.payInCurrency, - payInAmount: trade.payInAmount, - payInAddress: trade.payInAddress, - payInNetwork: trade.payInNetwork, - payInExtraId: trade.payInExtraId, - payInTxid: trade.payInTxid, - payOutCurrency: trade.payOutCurrency, - payOutAmount: trade.payOutAmount, - payOutAddress: trade.payOutAddress, - payOutNetwork: trade.payOutNetwork, - payOutExtraId: trade.payOutExtraId, - payOutTxid: trade.payOutTxid, - refundAddress: trade.refundAddress, - refundExtraId: trade.refundExtraId, - status: "Completed", - exchangeName: exchangeName, - ); - return ExchangeResponse(value: updatedTrade); - } - return ExchangeResponse(exception: response.exception); - } - } - - // Majestic Bank supports tor. - @override - bool get supportsTor => true; -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'package:decimal/decimal.dart'; +// import 'package:uuid/uuid.dart'; +// +// import '../../../app_config.dart'; +// import '../../../exceptions/exchange/exchange_exception.dart'; +// import '../../../exceptions/exchange/majestic_bank/mb_exception.dart'; +// import '../../../models/exchange/majestic_bank/mb_order.dart'; +// import '../../../models/exchange/response_objects/estimate.dart'; +// import '../../../models/exchange/response_objects/range.dart'; +// import '../../../models/exchange/response_objects/trade.dart'; +// import '../../../models/isar/exchange_cache/currency.dart'; +// import '../../../models/isar/exchange_cache/pair.dart'; +// import '../exchange.dart'; +// import '../exchange_response.dart'; +// import 'majestic_bank_api.dart'; +// +// class MajesticBankExchange /*extends Exchange*/ { +// MajesticBankExchange._(); +// +// static MajesticBankExchange? _instance; +// static MajesticBankExchange get instance => +// _instance ??= MajesticBankExchange._(); +// +// static const exchangeName = "Majestic Bank"; +// +// static const kMajesticBankCurrencyNames = { +// "BCH": "Bitcoin Cash", +// "BTC": "Bitcoin", +// "DOGE": "Dogecoin", +// "EPIC": "Epic Cash", +// "FIRO": "Firo", +// "LTC": "Litecoin", +// "NMC": "Namecoin", +// "PART": "Particl", +// "WOW": "Wownero", +// "XMR": "Monero", +// }; +// +// @override +// bool get supportsRefundAddress => false; +// +// @override +// Future> createTrade({ +// required String from, +// required String to, +// required String? fromNetwork, +// required String? toNetwork, +// required bool fixedRate, +// required Decimal amount, +// required String addressTo, +// String? extraId, +// required String addressRefund, +// required String refundExtraId, +// Estimate? estimate, +// required bool reversed, +// }) async { +// ExchangeResponse? 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>> getAllCurrencies( +// bool fixedRate, +// ) async { +// final response = await MajesticBankAPI.instance.getLimits(); +// if (response.value == null) { +// return ExchangeResponse(exception: response.exception); +// } +// +// final List currencies = []; +// final limits = response.value!; +// +// for (final limit in limits) { +// final currency = Currency( +// exchangeName: MajesticBankExchange.exchangeName, +// ticker: limit.currency, +// name: +// kMajesticBankCurrencyNames[limit.currency] ?? +// limit.currency, // todo: add more names if MB adds more +// network: "", +// image: "", +// isFiat: false, +// rateType: SupportedRateType.both, +// isAvailable: true, +// isStackCoin: AppConfig.isStackCoin(limit.currency), +// tokenContract: null, +// ); +// currencies.add(currency); +// } +// +// return ExchangeResponse(value: currencies); +// } +// +// // @override +// // Future>> getPairedCurrencies( +// // String forCurrency, +// // bool fixedRate, +// // ) { +// // // TODO: change this if the api changes to allow getting by paired currency +// // return getAllCurrencies(fixedRate); +// // } +// // +// // @override +// // Future>> getAllPairs(bool fixedRate) async { +// // final response = await MajesticBankAPI.instance.getRates(); +// // if (response.value == null) { +// // return ExchangeResponse(exception: response.exception); +// // } +// // +// // final List pairs = []; +// // final rates = response.value!; +// // +// // for (final rate in rates) { +// // final pair = Pair( +// // exchangeName: MajesticBankExchange.exchangeName, +// // from: rate.fromCurrency, +// // to: rate.toCurrency, +// // rateType: SupportedRateType.both, +// // ); +// // pairs.add(pair); +// // } +// // +// // return ExchangeResponse(value: pairs); +// // } +// +// @override +// Future>> getEstimates( +// String from, +// String? fromNetwork, +// String to, +// String? toNetwork, +// 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, +// exchangeProvider: MajesticBankExchange.exchangeName, +// ); +// return ExchangeResponse(value: [estimate]); +// } +// +// // @override +// // Future>> getPairsFor( +// // 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> getRange( +// String from, +// String? fromNetwork, +// String to, +// String? toNetwork, +// 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> getTrade(String tradeId) async { +// // TODO: implement getTrade +// throw UnimplementedError(); +// } +// +// @override +// Future>> getTrades() async { +// // TODO: implement getTrades +// throw UnimplementedError(); +// } +// +// @override +// String get name => exchangeName; +// +// @override +// Future> 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 { +// if (response.exception?.type == ExchangeExceptionType.orderNotFound) { +// final updatedTrade = Trade( +// uuid: trade.uuid, +// tradeId: trade.tradeId, +// rateType: trade.rateType, +// direction: trade.direction, +// timestamp: trade.timestamp, +// updatedAt: DateTime.now(), +// payInCurrency: trade.payInCurrency, +// payInAmount: trade.payInAmount, +// payInAddress: trade.payInAddress, +// payInNetwork: trade.payInNetwork, +// payInExtraId: trade.payInExtraId, +// payInTxid: trade.payInTxid, +// payOutCurrency: trade.payOutCurrency, +// payOutAmount: trade.payOutAmount, +// payOutAddress: trade.payOutAddress, +// payOutNetwork: trade.payOutNetwork, +// payOutExtraId: trade.payOutExtraId, +// payOutTxid: trade.payOutTxid, +// refundAddress: trade.refundAddress, +// refundExtraId: trade.refundExtraId, +// status: "Completed", +// exchangeName: exchangeName, +// ); +// return ExchangeResponse(value: updatedTrade); +// } +// return ExchangeResponse(exception: response.exception); +// } +// } +// +// // Majestic Bank supports tor. +// @override +// bool get supportsTor => true; +// } diff --git a/lib/services/notifications_service.dart b/lib/services/notifications_service.dart index 93e09aceb..4eca542e0 100644 --- a/lib/services/notifications_service.dart +++ b/lib/services/notifications_service.dart @@ -50,8 +50,9 @@ class NotificationsService extends ChangeNotifier { // watched transactions List get _watchedTransactionNotifications { - return DB.instance - .values(boxName: DB.boxNameWatchedTransactions); + return DB.instance.values( + boxName: DB.boxNameWatchedTransactions, + ); } Future _addWatchedTxNotification(NotificationModel notification) async { @@ -73,8 +74,9 @@ class NotificationsService extends ChangeNotifier { // watched trades List get _watchedChangeNowTradeNotifications { - return DB.instance - .values(boxName: DB.boxNameWatchedTrades); + return DB.instance.values( + boxName: DB.boxNameWatchedTrades, + ); } Future _addWatchedTradeNotification( @@ -127,8 +129,9 @@ class NotificationsService extends ChangeNotifier { void _checkTransactions() async { for (final notification in _watchedTransactionNotifications) { try { - final CryptoCurrency coin = - AppConfig.getCryptoCurrencyByPrettyName(notification.coinName); + final CryptoCurrency coin = AppConfig.getCryptoCurrencyByPrettyName( + notification.coinName, + ); final txid = notification.txid!; final wallet = Wallets.sharedInstance.getWallet(notification.walletId); @@ -156,20 +159,21 @@ class NotificationsService extends ChangeNotifier { torEnabled: node.torEnabled, clearnetEnabled: node.clearnetEnabled, ); - final failovers = nodeService - .failoverNodesFor(currency: coin) - .map( - (e) => ElectrumXNode( - address: e.host, - port: e.port, - name: e.name, - id: e.id, - useSSL: e.useSSL, - torEnabled: node.torEnabled, - clearnetEnabled: node.clearnetEnabled, - ), - ) - .toList(); + final failovers = + nodeService + .failoverNodesFor(currency: coin) + .map( + (e) => ElectrumXNode( + address: e.host, + port: e.port, + name: e.name, + id: e.id, + useSSL: e.useSSL, + torEnabled: node.torEnabled, + clearnetEnabled: node.clearnetEnabled, + ), + ) + .toList(); final client = ElectrumXClient.from( node: eNode, @@ -193,13 +197,16 @@ class NotificationsService extends ChangeNotifier { // grab confirms string to compare final String newConfirms = "($confirmations/${wallet.cryptoCurrency.minConfirms})"; - final String oldConfirms = notification.title - .substring(notification.title.lastIndexOf("(")); + final String oldConfirms = notification.title.substring( + notification.title.lastIndexOf("("), + ); // only update if they don't match if (oldConfirms != newConfirms) { - final String newTitle = - notification.title.replaceFirst(oldConfirms, newConfirms); + final String newTitle = notification.title.replaceFirst( + oldConfirms, + newConfirms, + ); final updatedNotification = notification.copyWith( title: newTitle, @@ -230,8 +237,10 @@ class NotificationsService extends ChangeNotifier { for (final notification in _watchedChangeNowTradeNotifications) { final id = notification.changeNowId!; - final trades = - tradesService.trades.where((element) => element.tradeId == id); + final trades = tradesService.trades.where( + (element) => + element.tradeId == id && element.exchangeName != "Majestic Bank", + ); if (trades.isEmpty) { return; @@ -362,8 +371,11 @@ class NotificationsService extends ChangeNotifier { } Future markAsRead(int id, bool shouldNotifyListeners) async { - final model = DB.instance - .get(boxName: DB.boxNameNotifications, key: id)!; + final model = + DB.instance.get( + boxName: DB.boxNameNotifications, + key: id, + )!; await DB.instance.put( boxName: DB.boxNameNotifications, key: model.id, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index c12f215c0..679187c5c 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -11,7 +11,6 @@ import 'package:flutter/material.dart'; import '../services/exchange/change_now/change_now_exchange.dart'; -import '../services/exchange/majestic_bank/majestic_bank_exchange.dart'; import '../services/exchange/nanswap/nanswap_exchange.dart'; import '../services/exchange/simpleswap/simpleswap_exchange.dart'; import '../services/exchange/trocador/trocador_exchange.dart'; @@ -44,8 +43,8 @@ class _EXCHANGE { String get changeNow => "${_path}change_now_logo_1.svg"; String get simpleSwap => "${_path}simpleswap-icon.svg"; - String get majesticBankBlue => "${_path}mb_blue.svg"; - String get majesticBankGreen => "${_path}mb_green.svg"; + // String get majesticBankBlue => "${_path}mb_blue.svg"; + // String get majesticBankGreen => "${_path}mb_green.svg"; String get trocador => "${_path}trocador.svg"; String get nanswap => "${_path}nanswap.svg"; @@ -55,8 +54,8 @@ class _EXCHANGE { return simpleSwap; case ChangeNowExchange.exchangeName: return changeNow; - case MajesticBankExchange.exchangeName: - return majesticBankBlue; + // case MajesticBankExchange.exchangeName: + // return majesticBankBlue; case TrocadorExchange.exchangeName: return trocador; case NanswapExchange.exchangeName: From 33eea8ece46b9ad59e05d6ee7d35afed38fb18a4 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 11:01:35 -0600 Subject: [PATCH 4/7] fix mwebd proxy address formatting --- lib/services/mwebd_service.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/mwebd_service.dart b/lib/services/mwebd_service.dart index f8b3a6a32..89f2bee37 100644 --- a/lib/services/mwebd_service.dart +++ b/lib/services/mwebd_service.dart @@ -83,7 +83,7 @@ final class MwebdService { final proxy = proxyInfo == null ? "" - : "${proxyInfo.host.address}:${proxyInfo.port}"; + : "socks5://${proxyInfo.host.address}:${proxyInfo.port}"; final nets = _map.keys; for (final net in nets) { final old = _map.remove(net)!; @@ -158,7 +158,7 @@ final class MwebdService { final String proxy; if (Prefs.instance.useTor) { final proxyInfo = TorService.sharedInstance.getProxyInfo(); - proxy = "${proxyInfo.host.address}:${proxyInfo.port}"; + proxy = "socks5://${proxyInfo.host.address}:${proxyInfo.port}"; } else { proxy = ""; } From 949df69b86eede20cfd95ae8827aed68b2e96a8a Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 12:42:46 -0600 Subject: [PATCH 5/7] temp hack for legacy currencies in db --- lib/models/isar/exchange_cache/currency.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index f719f5a3c..67a7f4098 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -71,6 +71,11 @@ class Currency { @ignore String? _fuzzyCache; String getFuzzyNet() { + // hack for legacy support + if (exchangeName == "Majestic Bank") { + return ticker.toLowerCase(); + } + return _fuzzyCache ??= switch (Exchange.fromName( exchangeName, ).runtimeType) { From 4f5797f4c9c44f6466ce6b4c2cf32ce7f83a6f92 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 23 Jul 2025 12:43:53 -0600 Subject: [PATCH 6/7] tezos bandaid fixes --- lib/wallets/wallet/impl/tezos_wallet.dart | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/wallets/wallet/impl/tezos_wallet.dart b/lib/wallets/wallet/impl/tezos_wallet.dart index 2843d4a1a..54302a027 100644 --- a/lib/wallets/wallet/impl/tezos_wallet.dart +++ b/lib/wallets/wallet/impl/tezos_wallet.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:isar/isar.dart'; @@ -128,6 +129,7 @@ class TezosWallet extends Bip39Wallet { // customFee: customFee?.raw.toInt(), // customGasLimit: customGasLimit, // reveal: false, + customGasLimit: 10600, ); // if (reveal) { @@ -286,8 +288,38 @@ class TezosWallet extends Bip39Wallet { @override Future confirmSend({required TxData txData}) async { _hackedCheckTorNodePrefs(); + + final completer = Completer(); + final sub = mainDB.isar.transactions + .where() + .walletIdEqualTo(walletId) + .watch(fireImmediately: true) + .listen((event) { + if (!completer.isCompleted && + event + .where((e) => e.txid == txData.tezosOperationsList!.result.id) + .isNotEmpty) { + completer.complete(); + } + }); + await txData.tezosOperationsList!.inject(); - await txData.tezosOperationsList!.monitor(); + + final completerFuture = completer.future.timeout( + const Duration(minutes: 2), + onTimeout: () { + throw Exception("Tezos confirm send timeout"); + }, + ); + + while (!completer.isCompleted) { + await updateTransactions(); + await Future.delayed(const Duration(seconds: 3)); + } + + await completerFuture; + + unawaited(sub.cancel()); return txData.copyWith(txid: txData.tezosOperationsList!.result.id); } From f3898cd505f4d26beef7da9e6db75030b83dc420 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 24 Jul 2025 08:17:19 -0600 Subject: [PATCH 7/7] ltc pub spend with mweb disabled insuff. bal fix --- lib/pages/send_view/send_view.dart | 1 + .../my_stack_view/wallet_view/sub_widgets/desktop_send.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 76aebaf33..d610c0aa1 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -814,6 +814,7 @@ class _SendViewState extends ConsumerState { break; } } else if (wallet is MwebInterface && + ref.read(pWalletInfo(walletId)).isMwebEnabled && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { txDataFuture = wallet.prepareSendMweb( txData: TxData( diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index dd3a70f9d..b4e259f6c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -409,6 +409,7 @@ class _DesktopSendState extends ConsumerState { break; } } else if (wallet is MwebInterface && + ref.read(pWalletInfo(walletId)).isMwebEnabled && ref.read(publicPrivateBalanceStateProvider) == BalanceType.private) { txDataFuture = wallet.prepareSendMweb( txData: TxData(