cake_wallet/lib/reactions/fiat_historical_rate_update.dart

110 lines
3.7 KiB
Dart
Raw Normal View History

2024-05-03 08:46:41 +00:00
import 'dart:async';
import 'package:cake_wallet/core/fiat_conversion_service.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/transaction_description.dart';
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
2024-05-08 11:16:44 +00:00
import 'package:cw_core/amount_converter.dart';
2024-05-03 13:39:27 +00:00
import 'package:cw_core/wallet_base.dart';
2024-05-08 11:16:44 +00:00
import 'package:cw_core/wallet_type.dart';
2024-05-03 08:46:41 +00:00
import 'package:hive/hive.dart';
Future<void> historicalRateUpdate(
2024-05-03 13:39:27 +00:00
WalletBase wallet,
2024-05-03 08:46:41 +00:00
SettingsStore settingsStore,
FiatConversionStore fiatConversionStore,
Box<TransactionDescription> transactionDescription) async {
2024-05-08 11:16:44 +00:00
int accuracyMinutes = 0;
switch (wallet.type) {
case WalletType.monero:
case WalletType.polygon:
case WalletType.nano:
case WalletType.solana:
case WalletType.haven:
case WalletType.tron:
accuracyMinutes = 540; // 9 hours
break;
case WalletType.ethereum:
accuracyMinutes = 360; // 6 hours
break;
case WalletType.bitcoin:
case WalletType.bitcoinCash:
case WalletType.litecoin:
accuracyMinutes = 180; // 3 hours
break;
default:
accuracyMinutes = 180; // 3 hours
}
final historicalRateStorageDurationMinutes = 86400; // 2 months
final intervalCount = historicalRateStorageDurationMinutes ~/ accuracyMinutes;
final totalAllowedAgeMinutes = historicalRateStorageDurationMinutes + accuracyMinutes;
final currentTime = DateTime.now();
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
final result = await FiatConversionService.fetchHistoricalPrice(
crypto: wallet.currency,
fiat: settingsStore.fiatCurrency,
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly,
intervalCount: intervalCount,
intervalMinutes: accuracyMinutes);
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
if (result == null) return;
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
Map<DateTime, double> convertedRates = {};
result.forEach((key, value) {
DateTime keyAsDateTime = DateTime.parse(key).toUtc();
convertedRates[keyAsDateTime] = value as double;
});
final transactions = wallet.transactionHistory.transactions.values.toList();
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
for (var tx in transactions) {
final txAgeMinutes = currentTime.difference(tx.date).inMinutes;
if (txAgeMinutes > totalAllowedAgeMinutes) continue;
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
var description = transactionDescription.get(tx.id);
final fiatName = settingsStore.fiatCurrency.toString();
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
if (description == null ||
description.historicalRates.isEmpty ||
!description.historicalRates.containsKey(fiatName)) {
try {
List<DateTime> historyTimestamps = convertedRates.keys.toList();
final txHistoryTimestamps = tx.date.toUtc();
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
final closestTimestamp = findClosestTimestamp(historyTimestamps, txHistoryTimestamps);
2024-05-03 08:46:41 +00:00
2024-05-08 11:16:44 +00:00
if (closestTimestamp != null &&
txHistoryTimestamps.difference(closestTimestamp).abs() <=
Duration(minutes: accuracyMinutes)) {
final rate = convertedRates[closestTimestamp];
if (rate != null) {
2024-05-03 08:46:41 +00:00
description ??= TransactionDescription(id: tx.id);
Map<String, String> rates = description.historicalRates;
2024-05-08 11:16:44 +00:00
rates[fiatName] =
(rate * AmountConverter.amountIntToDouble(wallet.currency, tx.amount)).toString();
2024-05-03 08:46:41 +00:00
description.historicalRates = rates;
await transactionDescription.put(tx.id, description);
}
}
2024-05-08 11:16:44 +00:00
} catch (e) {
print("Error fetching historical price: $e");
2024-05-03 08:46:41 +00:00
}
}
}
}
2024-05-08 11:16:44 +00:00
DateTime? findClosestTimestamp(List<DateTime> timestamps, DateTime target) {
DateTime? closest;
for (var timestamp in timestamps) {
if (closest == null ||
(target.difference(timestamp).abs() < target.difference(closest).abs())) {
closest = timestamp;
}
}
return closest;
}