| 1 | import 'package:cake_wallet/exchange/trade.dart'; |
| 2 | import 'package:cake_wallet/exchange/trade_state.dart'; |
| 3 | import 'package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart'; |
| 4 | import 'package:cake_wallet/order/order.dart'; |
| 5 | import 'package:cw_core/crypto_currency.dart'; |
| 6 | import 'package:hive/hive.dart'; |
| 7 | |
| 8 | class PickerRecentsLoader { |
| 9 | const PickerRecentsLoader._(); |
| 10 | |
| 11 | static const int defaultLimit = 6; |
| 12 | |
| 13 | static final Set<TradeState> _executedTradeStates = { |
| 14 | TradeState.complete, |
| 15 | TradeState.completed, |
| 16 | TradeState.finished, |
| 17 | TradeState.success, |
| 18 | TradeState.settled, |
| 19 | TradeState.traded, |
| 20 | }; |
| 21 | |
| 22 | static Future<List<CryptoCurrency>> load({ |
| 23 | required RecentsSource source, |
| 24 | required List<CryptoCurrency> visibleItems, |
| 25 | int limit = defaultLimit, |
| 26 | }) async { |
| 27 | switch (source) { |
| 28 | case RecentsSource.none: |
| 29 | return const []; |
| 30 | case RecentsSource.trades: |
| 31 | return _fromTrades(visibleItems, limit); |
| 32 | case RecentsSource.orders: |
| 33 | return _fromOrders(visibleItems, limit); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | static Future<List<CryptoCurrency>> _fromTrades( |
| 38 | List<CryptoCurrency> visibleItems, |
| 39 | int limit, |
| 40 | ) async { |
| 41 | final trades = await Trade.getAll(); |
| 42 | final ordered = trades.where((t) => _executedTradeStates.contains(t.state)).toList() |
| 43 | ..sort((a, b) => (b.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0)) |
| 44 | .compareTo(a.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0))); |
| 45 | |
| 46 | return _collect( |
| 47 | ordered.expand((t) => [t.from, t.to]), |
| 48 | visibleItems, |
| 49 | limit, |
| 50 | ); |
| 51 | } |
| 52 | |
| 53 | static Future<List<CryptoCurrency>> _fromOrders( |
| 54 | List<CryptoCurrency> visibleItems, |
| 55 | int limit, |
| 56 | ) async { |
| 57 | final orders = Hive.box<Order>(Order.boxName).values.toList() |
| 58 | ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); |
| 59 | |
| 60 | return _collect( |
| 61 | orders.expand((o) => [_tryResolve(o.from), _tryResolve(o.to)]), |
| 62 | visibleItems, |
| 63 | limit, |
| 64 | ); |
| 65 | } |
| 66 | |
| 67 | static List<CryptoCurrency> _collect( |
| 68 | Iterable<CryptoCurrency?> candidates, |
| 69 | List<CryptoCurrency> visibleItems, |
| 70 | int limit, |
| 71 | ) { |
| 72 | final visibleSet = visibleItems.toSet(); |
| 73 | final seen = <CryptoCurrency>{}; |
| 74 | final collected = <CryptoCurrency>[]; |
| 75 | |
| 76 | for (final candidate in candidates) { |
| 77 | if (candidate == null) continue; |
| 78 | if (!visibleSet.contains(candidate)) continue; |
| 79 | if (!seen.add(candidate)) continue; |
| 80 | collected.add(candidate); |
| 81 | if (collected.length >= limit) break; |
| 82 | } |
| 83 | |
| 84 | return collected; |
| 85 | } |
| 86 | |
| 87 | static CryptoCurrency? _tryResolve(String? raw) { |
| 88 | if (raw == null || raw.isEmpty) return null; |
| 89 | try { |
| 90 | return CryptoCurrency.fromString(raw); |
| 91 | } catch (_) { |
| 92 | return null; |
| 93 | } |
| 94 | } |
| 95 | } |