import 'dart:async'; import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:stackwallet/services/price.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:tuple/tuple.dart'; class PriceService extends ChangeNotifier { late final String baseTicker; final Set tokenContractAddressesToCheck = {}; final Duration updateInterval = const Duration(seconds: 60); Timer? _timer; final Map> _cachedPrices = { for (final coin in Coin.values) coin: Tuple2(Decimal.zero, 0.0) }; final Map> _cachedTokenPrices = {}; final _priceAPI = PriceAPI(Client()); Tuple2 getPrice(Coin coin) => _cachedPrices[coin]!; Tuple2 getTokenPrice(String contractAddress) => _cachedTokenPrices[contractAddress.toLowerCase()] ?? Tuple2(Decimal.zero, 0); PriceService(this.baseTicker); Future updatePrice() async { final priceMap = await _priceAPI.getPricesAnd24hChange(baseCurrency: baseTicker); bool shouldNotify = false; for (final map in priceMap.entries) { if (_cachedPrices[map.key] != map.value) { _cachedPrices[map.key] = map.value; shouldNotify = true; } } if (tokenContractAddressesToCheck.isNotEmpty) { final tokenPriceMap = await _priceAPI.getPricesAnd24hChangeForEthTokens( contractAddresses: tokenContractAddressesToCheck, baseCurrency: baseTicker, ); for (final map in tokenPriceMap.entries) { if (_cachedTokenPrices[map.key] != map.value) { _cachedTokenPrices[map.key] = map.value; shouldNotify = true; } } } if (shouldNotify) { notifyListeners(); } } void cancel() { _timer?.cancel(); _timer = null; } void start(bool rightAway) { if (rightAway) { updatePrice(); } _timer?.cancel(); _timer = Timer.periodic(updateInterval, (_) { updatePrice(); }); } @override void dispose() { cancel(); super.dispose(); } }