111
This commit is contained in:
92
flutter_monisuo/lib/providers/trade_provider.dart
Normal file
92
flutter_monisuo/lib/providers/trade_provider.dart
Normal file
@@ -0,0 +1,92 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user