fix(mining-app): 统一贡献值页与兑换页的剩余积分股计算方式
贡献值页原先使用 sharePoolBalance API (Pool A + Pool B 余额) 显示剩余积分股, 兑换页使用公式 totalShares - totalMined - blackHoleAmount 计算。 两者显示结果不一致 (差异约 228,343 积分股)。 根本原因调查: - mining-wallet-service 的 Kafka 消费者在服务重启期间丢失了部分事件 - Pool B 仅处理了 15.7% 的挖矿分配事件 (28,261/180,497) - Pool A 遗漏了 66,591 笔销毁扣减事件 - 池账户余额是通过 Kafka 事件维护的记账台账,存在消费遗漏 - totalShares - totalMined - blackHoleAmount 公式基于实际挖矿和销毁数据计算,是数学上的 ground truth - 实际用户分配和销毁均 100% 准确,仅池账户记账有偏差 修复方案: - 贡献值页改用 marketOverviewProvider (同兑换页) - 使用公式 totalShares - totalMined - blackHoleAmount 计算剩余积分股 - 两个页面现在显示完全一致的数据 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a7dd926877
commit
0576733579
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -5,10 +6,12 @@ import '../../../core/constants/app_colors.dart';
|
|||
import '../../../core/router/routes.dart';
|
||||
import '../../../core/utils/format_utils.dart';
|
||||
import '../../../domain/entities/contribution.dart';
|
||||
import '../../../domain/entities/market_overview.dart';
|
||||
import '../../../domain/entities/share_account.dart';
|
||||
import '../../providers/user_providers.dart';
|
||||
import '../../providers/contribution_providers.dart';
|
||||
import '../../providers/mining_providers.dart';
|
||||
import '../../providers/trading_providers.dart';
|
||||
import '../../widgets/shimmer_loading.dart';
|
||||
|
||||
class ContributionPage extends ConsumerWidget {
|
||||
|
|
@ -25,8 +28,8 @@ class ContributionPage extends ConsumerWidget {
|
|||
final contributionAsync = ref.watch(contributionProvider(accountSequence));
|
||||
// 获取预估收益(基于用户每秒收益计算)
|
||||
final estimatedEarnings = ref.watch(estimatedEarningsProvider(accountSequence));
|
||||
// 获取积分股池余量
|
||||
final sharePoolAsync = ref.watch(sharePoolBalanceProvider);
|
||||
// 获取市场概览(用于计算剩余积分股 = totalShares - totalMined - blackHoleAmount)
|
||||
final marketAsync = ref.watch(marketOverviewProvider);
|
||||
// 获取挖矿账户信息(含首次挖矿时间,用于730天倒计时)
|
||||
final shareAccountAsync = ref.watch(shareAccountProvider(accountSequence));
|
||||
|
||||
|
|
@ -35,8 +38,8 @@ class ContributionPage extends ConsumerWidget {
|
|||
final contribution = contributionAsync.valueOrNull;
|
||||
final hasError = contributionAsync.hasError;
|
||||
final error = contributionAsync.error;
|
||||
final isSharePoolLoading = sharePoolAsync.isLoading;
|
||||
final sharePoolBalance = sharePoolAsync.valueOrNull;
|
||||
final isMarketLoading = marketAsync.isLoading;
|
||||
final market = marketAsync.valueOrNull;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.backgroundOf(context),
|
||||
|
|
@ -45,7 +48,7 @@ class ContributionPage extends ConsumerWidget {
|
|||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
ref.invalidate(contributionProvider(accountSequence));
|
||||
ref.invalidate(sharePoolBalanceProvider);
|
||||
ref.invalidate(marketOverviewProvider);
|
||||
ref.invalidate(shareAccountProvider(accountSequence));
|
||||
},
|
||||
child: hasError && contribution == null
|
||||
|
|
@ -74,7 +77,7 @@ class ContributionPage extends ConsumerWidget {
|
|||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
// 总贡献值卡片
|
||||
_buildTotalContributionCard(context, ref, contribution, isLoading, sharePoolBalance, isSharePoolLoading),
|
||||
_buildTotalContributionCard(context, ref, contribution, isLoading, market, isMarketLoading),
|
||||
const SizedBox(height: 16),
|
||||
// 三栏统计
|
||||
_buildThreeColumnStats(context, ref, contribution, isLoading),
|
||||
|
|
@ -165,8 +168,8 @@ class ContributionPage extends ConsumerWidget {
|
|||
WidgetRef ref,
|
||||
Contribution? contribution,
|
||||
bool isLoading,
|
||||
SharePoolBalance? sharePoolBalance,
|
||||
bool isSharePoolLoading,
|
||||
MarketOverview? market,
|
||||
bool isMarketLoading,
|
||||
) {
|
||||
final isDark = AppColors.isDark(context);
|
||||
final total = contribution?.totalContribution ?? '0';
|
||||
|
|
@ -219,13 +222,21 @@ class ContributionPage extends ConsumerWidget {
|
|||
'100亿销毁剩余量: ',
|
||||
style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)),
|
||||
),
|
||||
isSharePoolLoading
|
||||
isMarketLoading
|
||||
? const ShimmerText(
|
||||
placeholder: '----',
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: _orange),
|
||||
)
|
||||
: Text(
|
||||
hideAmounts ? '******' : formatAmount(sharePoolBalance?.total ?? '0'),
|
||||
hideAmounts
|
||||
? '******'
|
||||
: market != null
|
||||
? formatAmount(
|
||||
(Decimal.parse(market.totalShares) -
|
||||
Decimal.parse(market.totalMined) -
|
||||
Decimal.parse(market.blackHoleAmount))
|
||||
.toString())
|
||||
: '0',
|
||||
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: _orange),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue