93 lines
2.6 KiB
Dart
93 lines
2.6 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/material.dart';
|
|
import '../data/models/coin.dart';
|
|
import '../data/models/order_book.dart';
|
|
import '../data/services/market_service.dart';
|
|
import '../data/services/trade_service.dart';
|
|
|
|
/// 交易頁狀態管理 — 輪詢價格 + 訂單簿
|
|
class TradeProvider extends ChangeNotifier {
|
|
final MarketService _marketService;
|
|
// ignore: unused_field
|
|
final TradeService _tradeService;
|
|
|
|
TradeProvider(this._marketService, this._tradeService);
|
|
|
|
Coin? _selectedCoin;
|
|
OrderBookDepth _depth = const OrderBookDepth(asks: [], bids: [], spread: 0, spreadPercent: 0);
|
|
bool _isLoadingDepth = false;
|
|
String? _error;
|
|
|
|
Timer? _pollTimer;
|
|
static const _pollInterval = Duration(seconds: 5);
|
|
|
|
Coin? get selectedCoin => _selectedCoin;
|
|
OrderBookDepth get depth => _depth;
|
|
bool get isLoadingDepth => _isLoadingDepth;
|
|
String? get error => _error;
|
|
|
|
/// 实时模拟价格(从 depth 轮询获取)
|
|
double get currentPrice => _depth.currentPrice;
|
|
double get change24h => _depth.change24h;
|
|
double get high24h => _depth.high24h;
|
|
double get low24h => _depth.low24h;
|
|
double get volume24h => _depth.volume24h;
|
|
|
|
/// 交易时段状态
|
|
String get tradingStatus => _depth.tradingStatus;
|
|
double? get targetLow => _depth.targetLow;
|
|
double? get targetHigh => _depth.targetHigh;
|
|
double? get targetClose => _depth.targetClose;
|
|
bool get isTradable => tradingStatus == 'trading';
|
|
|
|
void selectCoin(Coin coin) {
|
|
if (_selectedCoin?.code == coin.code) return;
|
|
_selectedCoin = coin;
|
|
_depth = const OrderBookDepth(asks: [], bids: [], spread: 0, spreadPercent: 0);
|
|
_error = null;
|
|
notifyListeners();
|
|
startPolling();
|
|
}
|
|
|
|
void clearSelection() {
|
|
_selectedCoin = null;
|
|
_depth = const OrderBookDepth(asks: [], bids: [], spread: 0, spreadPercent: 0);
|
|
stopPolling();
|
|
notifyListeners();
|
|
}
|
|
|
|
void startPolling() {
|
|
stopPolling();
|
|
_fetchDepth();
|
|
_pollTimer = Timer.periodic(_pollInterval, (_) => _fetchDepth());
|
|
}
|
|
|
|
void stopPolling() {
|
|
_pollTimer?.cancel();
|
|
_pollTimer = null;
|
|
}
|
|
|
|
Future<void> _fetchDepth() async {
|
|
if (_selectedCoin == null) return;
|
|
final response = await _marketService.getDepth(_selectedCoin!.code);
|
|
if (!response.success || response.data == null) return;
|
|
|
|
_depth = OrderBookDepth.fromJson(response.data!);
|
|
notifyListeners();
|
|
}
|
|
|
|
/// 刷新幣種價格(從 MarketProvider 的列表中找到最新價)
|
|
void updateCoinPrice(Coin updatedCoin) {
|
|
if (_selectedCoin?.code == updatedCoin.code) {
|
|
_selectedCoin = updatedCoin;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
stopPolling();
|
|
super.dispose();
|
|
}
|
|
}
|