Flutter App
This commit is contained in:
176
flutter_app/lib/providers/price_provider.dart
Normal file
176
flutter_app/lib/providers/price_provider.dart
Normal file
@@ -0,0 +1,176 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../models/price_data.dart';
|
||||
import '../services/websocket_service.dart';
|
||||
import '../services/api_service.dart';
|
||||
import '../services/storage_service.dart';
|
||||
import '../services/notification_service.dart';
|
||||
|
||||
class PriceProvider with ChangeNotifier {
|
||||
final WebSocketService _wsService = WebSocketService();
|
||||
final ApiService _apiService = ApiService();
|
||||
final StorageService _storageService = StorageService();
|
||||
final NotificationService _notificationService = NotificationService();
|
||||
|
||||
LatestPrice? _latestPrice;
|
||||
HistoryData? _historyData;
|
||||
String _connectionStatus = 'Disconnected';
|
||||
List<PriceAlert> _alerts = [];
|
||||
double? _customAuecAmount;
|
||||
String _selectedRange = '7d';
|
||||
bool _isLoading = false;
|
||||
bool _isHistoryLoading = false;
|
||||
|
||||
LatestPrice? get latestPrice => _latestPrice;
|
||||
HistoryData? get historyData => _historyData;
|
||||
String get connectionStatus => _connectionStatus;
|
||||
List<PriceAlert> get alerts => _alerts;
|
||||
double? get customAuecAmount => _customAuecAmount;
|
||||
String get selectedRange => _selectedRange;
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isHistoryLoading => _isHistoryLoading;
|
||||
|
||||
PriceProvider() {
|
||||
_initialize();
|
||||
}
|
||||
|
||||
Timer? _pollTimer;
|
||||
|
||||
void _initialize() {
|
||||
// Load saved data
|
||||
_loadAlerts();
|
||||
_loadCustomAuecAmount();
|
||||
|
||||
// Connect WebSocket (currently disabled)
|
||||
_wsService.connect();
|
||||
|
||||
// Listen to WebSocket streams
|
||||
_wsService.latestPriceStream.listen((price) {
|
||||
_latestPrice = price;
|
||||
_checkAlerts(price);
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
_wsService.connectionStatusStream.listen((status) {
|
||||
_connectionStatus = status;
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
// Fetch initial data
|
||||
fetchInitialData();
|
||||
|
||||
// Start polling for updates every 5 minutes as backup to WebSocket
|
||||
_startPolling();
|
||||
}
|
||||
|
||||
void _startPolling() {
|
||||
_pollTimer = Timer.periodic(const Duration(minutes: 5), (timer) {
|
||||
fetchInitialData();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> fetchInitialData() async {
|
||||
final latest = await _apiService.fetchLatestPrice();
|
||||
if (latest != null) {
|
||||
_latestPrice = latest;
|
||||
notifyListeners();
|
||||
}
|
||||
await fetchHistory(_selectedRange);
|
||||
}
|
||||
|
||||
Future<void> fetchHistory(String range) async {
|
||||
_isHistoryLoading = true;
|
||||
_selectedRange = range;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
final history = await _apiService.fetchHistory(range);
|
||||
if (history != null) {
|
||||
_historyData = history;
|
||||
}
|
||||
_wsService.requestHistory(range);
|
||||
} catch (e) {
|
||||
if (kDebugMode) {
|
||||
print('Error fetching history: $e');
|
||||
}
|
||||
} finally {
|
||||
_isHistoryLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadAlerts() async {
|
||||
_alerts = await _storageService.getAlerts();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _loadCustomAuecAmount() async {
|
||||
_customAuecAmount = await _storageService.getCustomAuecAmount();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> addAlert(double auecAmount, double maxPrice) async {
|
||||
final alert = PriceAlert(
|
||||
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
auecAmount: auecAmount,
|
||||
maxPrice: maxPrice,
|
||||
enabled: true,
|
||||
);
|
||||
await _storageService.addAlert(alert);
|
||||
await _loadAlerts();
|
||||
}
|
||||
|
||||
Future<void> toggleAlert(String id) async {
|
||||
final alert = _alerts.firstWhere((a) => a.id == id);
|
||||
final updated = alert.copyWith(enabled: !alert.enabled);
|
||||
await _storageService.updateAlert(updated);
|
||||
await _loadAlerts();
|
||||
}
|
||||
|
||||
Future<void> deleteAlert(String id) async {
|
||||
await _storageService.deleteAlert(id);
|
||||
await _loadAlerts();
|
||||
}
|
||||
|
||||
Future<void> setCustomAuecAmount(double amount) async {
|
||||
await _storageService.setCustomAuecAmount(amount);
|
||||
_customAuecAmount = amount;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _checkAlerts(LatestPrice price) {
|
||||
for (final alert in _alerts) {
|
||||
if (!alert.enabled) continue;
|
||||
|
||||
final matchingSeller = price.allPrices.firstWhere(
|
||||
(p) {
|
||||
final totalPrice = (alert.auecAmount / 1000000) * p.pricePerMillion;
|
||||
return totalPrice <= alert.maxPrice;
|
||||
},
|
||||
orElse: () => price.allPrices.first,
|
||||
);
|
||||
|
||||
final totalPrice = (alert.auecAmount / 1000000) * matchingSeller.pricePerMillion;
|
||||
if (totalPrice <= alert.maxPrice) {
|
||||
// Trigger notification
|
||||
_notificationService.showPriceAlert(
|
||||
title: 'Price Alert Triggered!',
|
||||
body: '${(alert.auecAmount / 1000000000).toStringAsFixed(1)}B AUEC available for \$${totalPrice.toStringAsFixed(2)} from ${matchingSeller.sellerName}',
|
||||
auecAmount: alert.auecAmount,
|
||||
price: totalPrice,
|
||||
seller: matchingSeller.sellerName,
|
||||
);
|
||||
|
||||
// Disable alert
|
||||
toggleAlert(alert.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pollTimer?.cancel();
|
||||
_wsService.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user