diff --git a/lib/core/trade_monitor.dart b/lib/core/trade_monitor.dart deleted file mode 100644 index 25eedfbbf..000000000 --- a/lib/core/trade_monitor.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'dart:async'; -import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/store/dashboard/trades_store.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/entities/exchange_api_mode.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/swaptrade_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; -import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; -import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:hive/hive.dart'; - -class TradeMonitor { - static const int _tradeCheckIntervalMinutes = 1; - static const int _maxTradeAgeHours = 24; - - TradeMonitor({ - required this.tradesStore, - required this.settingsStore, - required this.trades, - }); - - final TradesStore tradesStore; - final Box trades; - final SettingsStore settingsStore; - final Map _tradeTimers = {}; - - ExchangeProvider? _getProviderByDescription(ExchangeProviderDescription description) { - switch (description) { - case ExchangeProviderDescription.changeNow: - return ChangeNowExchangeProvider(settingsStore: settingsStore); - case ExchangeProviderDescription.sideShift: - return SideShiftExchangeProvider(); - case ExchangeProviderDescription.simpleSwap: - return SimpleSwapExchangeProvider(); - case ExchangeProviderDescription.trocador: - return TrocadorExchangeProvider(); - case ExchangeProviderDescription.exolix: - return ExolixExchangeProvider(); - case ExchangeProviderDescription.thorChain: - return ThorChainExchangeProvider(tradesStore: trades); - case ExchangeProviderDescription.swapTrade: - return SwapTradeExchangeProvider(); - case ExchangeProviderDescription.letsExchange: - return LetsExchangeExchangeProvider(); - case ExchangeProviderDescription.stealthEx: - return StealthExExchangeProvider(); - case ExchangeProviderDescription.chainflip: - return ChainflipExchangeProvider(tradesStore: trades); - case ExchangeProviderDescription.xoSwap: - return XOSwapExchangeProvider(); - } - return null; - } - - void monitorActiveTrades(String walletId) { - final now = DateTime.now(); - final trades = tradesStore.trades; - final tradesToCancel = []; - - for (final item in trades) { - final trade = item.trade; - - if (_shouldCancelTradeTimer(trade, walletId, now)) { - if (_tradeTimers.containsKey(trade.id)) { - tradesToCancel.add(trade.id); - } - continue; - } - - if (!_tradeTimers.containsKey(trade.id)) { - printV('Starting trade monitoring for ${trade.id}'); - _startTradeMonitoring(trade); - } - } - - _cancelTradeTimers(tradesToCancel); - } - - bool _shouldCancelTradeTimer(Trade trade, String walletId, DateTime now) { - if (trade.walletId != walletId) return true; - - final createdAt = trade.createdAt; - if (createdAt == null) return true; - - if (now.difference(createdAt).inHours > _maxTradeAgeHours) return true; - - return _isFinalState(trade.state); - } - - void _startTradeMonitoring(Trade trade) { - if (_tradeTimers.containsKey(trade.id)) return; - - _checkTradeStatus(trade); - - final timer = Timer.periodic( - Duration(minutes: _tradeCheckIntervalMinutes), - (_) => _checkTradeStatus(trade) - ); - - _tradeTimers[trade.id] = timer; - } - - Future _checkTradeStatus(Trade trade) async { - printV('Checking trade status for ${trade.id}'); - - if (_isTradeOld(trade)) { - printV('The trade ${trade.id} is older than $_maxTradeAgeHours hours, we will cancel the timer'); - _cancelTradeTimer(trade.id); - return; - } - - final provider = _getProviderByDescription(trade.provider); - if (provider == null) { - printV('No provider found for trade ${trade.id}'); - return; - } - - if (!_isExchangeModeEnabled(provider)) { - return; - } - - try { - await _updateTradeStatus(trade, provider); - } catch (e) { - printV('Error fetching status for ${trade.id}: $e'); - } - } - - bool _isTradeOld(Trade trade) { - final now = DateTime.now(); - final createdAt = trade.createdAt; - return createdAt != null && now.difference(createdAt).inHours > _maxTradeAgeHours; - } - - bool _isExchangeModeEnabled(ExchangeProvider provider) { - final exchangeApiMode = settingsStore.exchangeStatus; - - if (exchangeApiMode == ExchangeApiMode.disabled) { - printV('Exchange API mode is disabled'); - return false; - } - - if (exchangeApiMode == ExchangeApiMode.torOnly && !provider.supportsOnionAddress) { - printV('Skipping ${provider.description}, no TOR support'); - return false; - } - - return true; - } - - Future _updateTradeStatus(Trade trade, ExchangeProvider provider) async { - final updated = await provider.findTradeById(id: trade.id); - trade - ..stateRaw = updated.state.raw - ..receiveAmount = updated.receiveAmount ?? trade.receiveAmount - ..outputTransaction = updated.outputTransaction ?? trade.outputTransaction; - printV('Trade ${trade.id} updated: ${trade.state}'); - await trade.save(); - - if (_isFinalState(updated.state)) { - printV('Trade ${trade.id} is in final state'); - _cancelTradeTimer(trade.id); - } - } - - void _cancelTradeTimer(String tradeId) { - _tradeTimers[tradeId]?.cancel(); - _tradeTimers.remove(tradeId); - } - - void _cancelTradeTimers(List tradeIds) { - for (final tradeId in tradeIds) { - _cancelTradeTimer(tradeId); - } - } - - void cancelAllTradeTimers() { - for (final timer in _tradeTimers.values) { - timer.cancel(); - } - _tradeTimers.clear(); - } - - bool _isFinalState(TradeState state) { - return { - TradeState.completed.raw, - TradeState.success.raw, - TradeState.confirmed.raw, - TradeState.settled.raw, - TradeState.finished.raw, - TradeState.expired.raw, - TradeState.failed.raw, - TradeState.notFound.raw, - }.contains(state.raw); - } - - void dispose() { - cancelAllTradeTimers(); - } -} diff --git a/lib/di.dart b/lib/di.dart index e4c94cf85..140a26698 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -275,7 +275,6 @@ import 'src/screens/buy/buy_sell_page.dart'; import 'cake_pay/cake_pay_payment_credantials.dart'; import 'package:cake_wallet/view_model/dev/background_sync_logs_view_model.dart'; import 'package:cake_wallet/src/screens/dev/background_sync_logs_page.dart'; -import 'package:cake_wallet/core/trade_monitor.dart'; final getIt = GetIt.instance; @@ -508,41 +507,19 @@ Future setup({ settingsStore: getIt.get(), fiatConvertationStore: getIt.get())); - getIt.registerFactory( - () => ExchangeViewModel( - getIt.get(), - _tradesSource, - getIt.get(), - getIt.get(), - getIt.get().settingsStore, - getIt.get(), - getIt.get(), - getIt.get(), - ), - ); - - getIt.registerSingleton( - TradeMonitor( - tradesStore: getIt.get(), - settingsStore: getIt.get(), - trades: _tradesSource - ), - ); - getIt.registerFactory(() => DashboardViewModel( - tradeMonitor: getIt.get(), - balanceViewModel: getIt.get(), - appStore: getIt.get(), - tradesStore: getIt.get(), - tradeFilterStore: getIt.get(), - transactionFilterStore: getIt.get(), - settingsStore: settingsStore, - yatStore: getIt.get(), - ordersStore: getIt.get(), - anonpayTransactionsStore: getIt.get(), - payjoinTransactionsStore: getIt.get(), - sharedPreferences: getIt.get(), - keyService: getIt.get())); + balanceViewModel: getIt.get(), + appStore: getIt.get(), + tradesStore: getIt.get(), + tradeFilterStore: getIt.get(), + transactionFilterStore: getIt.get(), + settingsStore: settingsStore, + yatStore: getIt.get(), + ordersStore: getIt.get(), + anonpayTransactionsStore: getIt.get(), + payjoinTransactionsStore: getIt.get(), + sharedPreferences: getIt.get(), + keyService: getIt.get())); getIt.registerFactory( () => AuthService( @@ -1074,6 +1051,19 @@ Future setup({ getIt.registerFactoryParam((title, uri) => WebViewPage(title, uri)); + getIt.registerFactory( + () => ExchangeViewModel( + getIt.get(), + _tradesSource, + getIt.get(), + getIt.get(), + getIt.get(), + getIt.get(), + getIt.get(), + getIt.get(), + ), + ); + getIt.registerFactory( () => FeesViewModel( getIt.get(), diff --git a/lib/main.dart b/lib/main.dart index d0a52b9f1..167373d87 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -51,7 +51,6 @@ import 'package:cw_core/root_dir.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cw_core/window_size.dart'; import 'package:logging/logging.dart'; -import 'package:cake_wallet/core/trade_monitor.dart'; final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index 7a3aa156a..47e900959 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -166,19 +166,17 @@ class TransactionsPage extends StatelessWidget { return Observer( builder: (_) => TradeRow( - key: item.key, - onTap: () => Navigator.of(context) - .pushNamed(Routes.tradeDetails, arguments: trade), - swapState: trade.state, + key: item.key, + onTap: () => Navigator.of(context) + .pushNamed(Routes.tradeDetails, arguments: trade), provider: trade.provider, - from: trade.from, - to: trade.to, - createdAtFormattedDate: trade.createdAt != null - ? DateFormat('HH:mm').format(trade.createdAt!) - : null, - formattedAmount: item.tradeFormattedAmount, - formattedReceiveAmount: item.tradeFormattedReceiveAmount - ), + from: trade.from, + to: trade.to, + createdAtFormattedDate: trade.createdAt != null + ? DateFormat('HH:mm').format(trade.createdAt!) + : null, + formattedAmount: item.tradeFormattedAmount, + formattedReceiveAmount: item.tradeFormattedReceiveAmount), ); } if (item is OrderListItem) { diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index e50cb9718..9f04d587d 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -1,9 +1,7 @@ -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/utils/image_utill.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; class TradeRow extends StatelessWidget { TradeRow({ @@ -14,7 +12,6 @@ class TradeRow extends StatelessWidget { this.onTap, this.formattedAmount, this.formattedReceiveAmount, - required this.swapState, super.key, }); @@ -25,7 +22,6 @@ class TradeRow extends StatelessWidget { final String? createdAtFormattedDate; final String? formattedAmount; final String? formattedReceiveAmount; - final TradeState swapState; @override Widget build(BuildContext context) { @@ -33,39 +29,25 @@ class TradeRow extends StatelessWidget { final receiveAmountCrypto = to.toString(); return InkWell( - onTap: onTap, - child: Container( - padding: EdgeInsets.fromLTRB(24, 8, 24, 8), - color: Colors.transparent, - child: Row( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Stack( - clipBehavior: Clip.none, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(50), - child: ImageUtil.getImageFromPath( - imagePath: provider.image, height: 36, width: 36),), - Positioned( - right: 0, - bottom: 2, - child: Container( - height: 8, - width: 8, - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: _statusColor(context, swapState), - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ], + onTap: onTap, + child: Container( + padding: EdgeInsets.fromLTRB(24, 8, 24, 8), + color: Colors.transparent, + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(50), + child: ImageUtil.getImageFromPath( + imagePath: provider.image, + height: 36, + width: 36, ), - SizedBox(width: 12), - Expanded( - child: Column( + ), + SizedBox(width: 12), + Expanded( + child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( @@ -122,21 +104,4 @@ class TradeRow extends StatelessWidget { ), ); } - - Color _statusColor(BuildContext context, TradeState status) { - switch (status) { - case TradeState.complete: - case TradeState.completed: - case TradeState.finished: - case TradeState.success: - case TradeState.settled: - return PaletteDark.brightGreen; - case TradeState.failed: - case TradeState.expired: - case TradeState.notFound: - return Palette.darkRed; - default: - return const Color(0xffff6600); - } - } } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 6eeefa4d9..0202d0d13 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -23,6 +23,7 @@ import 'package:cake_wallet/store/dashboard/trades_store.dart'; import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/themes/core/material_base_theme.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; @@ -55,8 +56,6 @@ import 'package:mobx/mobx.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:cake_wallet/core/trade_monitor.dart'; - part 'dashboard_view_model.g.dart'; class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel; @@ -64,7 +63,6 @@ class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel; abstract class DashboardViewModelBase with Store { DashboardViewModelBase( {required this.balanceViewModel, - required this.tradeMonitor, required this.appStore, required this.tradesStore, required this.tradeFilterStore, @@ -300,10 +298,6 @@ abstract class DashboardViewModelBase with Store { _checkMweb(); reaction((_) => settingsStore.mwebAlwaysScan, (bool value) => _checkMweb()); - - reaction((_) => tradesStore.trades, (_) => tradeMonitor.monitorActiveTrades(wallet.id)); - - tradeMonitor.monitorActiveTrades(wallet.id); } bool _isTransactionDisposerCallbackRunning = false; @@ -779,8 +773,6 @@ abstract class DashboardViewModelBase with Store { BalanceViewModel balanceViewModel; - TradeMonitor tradeMonitor; - AppStore appStore; SettingsStore settingsStore;