funding_rate_provider.dart 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import 'package:flutter/foundation.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import '../core/network/dio_client.dart';
  4. import '../data/models/market/funding_rate.dart';
  5. import '../data/services/funding_rate_service.dart';
  6. // ── State ─────────────────────────────────────────────────
  7. class FundingRateState {
  8. final bool isLoading;
  9. final FundingRateCurrent? current;
  10. final List<FundingRateHistoryItem> history;
  11. final String? error;
  12. const FundingRateState({
  13. this.isLoading = false,
  14. this.current,
  15. this.history = const [],
  16. this.error,
  17. });
  18. FundingRateState copyWith({
  19. bool? isLoading,
  20. FundingRateCurrent? current,
  21. List<FundingRateHistoryItem>? history,
  22. String? error,
  23. }) {
  24. return FundingRateState(
  25. isLoading: isLoading ?? this.isLoading,
  26. current: current ?? this.current,
  27. history: history ?? this.history,
  28. error: error,
  29. );
  30. }
  31. }
  32. // ── Notifier ──────────────────────────────────────────────
  33. class FundingRateNotifier extends FamilyNotifier<FundingRateState, int> {
  34. late FundingRateService _service;
  35. @override
  36. FundingRateState build(int contractCoinId) {
  37. _service = FundingRateService(ref.read(dioClientProvider));
  38. Future.microtask(() => load());
  39. return const FundingRateState(isLoading: true);
  40. }
  41. Future<void> load() async {
  42. if (!state.isLoading) {
  43. state = state.copyWith(isLoading: true);
  44. }
  45. try {
  46. final results = await Future.wait([
  47. _service.getCurrent(arg),
  48. // 多页拉取,service 内部保证覆盖最近 7 天
  49. _service.getHistory(contractCoinId: arg, days: 7),
  50. ]);
  51. final current = results[0] as FundingRateCurrent?;
  52. final rawHistory = results[1] as List<FundingRateHistoryItem>;
  53. // 二次过滤(防止跨页边界多出的旧数据),按时间升序排列
  54. final cutoff = DateTime.now().subtract(const Duration(days: 7));
  55. final sorted = rawHistory
  56. .where((e) => e.fundingTime.isAfter(cutoff))
  57. .toList()
  58. ..sort((a, b) => a.fundingTime.compareTo(b.fundingTime));
  59. state = FundingRateState(
  60. isLoading: false,
  61. current: current,
  62. history: sorted,
  63. );
  64. } catch (e) {
  65. debugPrint('[FundingRate] load error: $e');
  66. state = state.copyWith(isLoading: false, error: e.toString());
  67. }
  68. }
  69. }
  70. final fundingRateProvider =
  71. NotifierProviderFamily<FundingRateNotifier, FundingRateState, int>(
  72. FundingRateNotifier.new,
  73. );