فهرست منبع

fix(asset): 锁仓 Tab 释放总量对接 releasedTotal(iBit)

解析 wallet-new 与 staking/wallet 的 releasedTotal,修复误用 locked 显示释放总量的问题。

Co-authored-by: Cursor <cursoragent@cursor.com>
jean 1 ماه پیش
والد
کامیت
5e038bec69

+ 18 - 3
lib/core/utils/spot_transfer_asset.dart

@@ -104,19 +104,30 @@ String stakingOverviewAvailableFromAccounts(List<AccountInfo> list) {
   return row.balance.toString();
 }
 
+String stakingOverviewReleasedFromAccounts(List<AccountInfo> list) {
+  final row = pickStakingAccount(list);
+  if (row == null) {
+    return '0';
+  }
+  return row.releasedTotal.toString();
+}
+
 /// 总览锁仓余额合并 wallet-new 与 staking/wallet(对齐 Web applyStakingOverviewBalances)
-({String available, String locked}) mergeStakingOverviewBalances({
+({String available, String locked, String released}) mergeStakingOverviewBalances({
   required String walletAvailable,
   required String walletLocked,
+  required String walletReleased,
   StakingWalletBalance? apiWallet,
 }) {
   var available = walletAvailable;
   var locked = walletLocked;
+  var released = walletReleased;
   if (apiWallet == null) {
-    return (available: available, locked: locked);
+    return (available: available, locked: locked, released: released);
   }
   final apiAvailable = apiWallet.availableBalance;
   final apiLocked = apiWallet.lockedBalance;
+  final apiReleased = apiWallet.releasedTotal;
   if ((double.tryParse(available) ?? 0) <= 0 &&
       (double.tryParse(apiAvailable) ?? 0) > 0) {
     available = apiAvailable;
@@ -125,5 +136,9 @@ String stakingOverviewAvailableFromAccounts(List<AccountInfo> list) {
       (double.tryParse(apiLocked) ?? 0) > 0) {
     locked = apiLocked;
   }
-  return (available: available, locked: locked);
+  if ((double.tryParse(released) ?? 0) <= 0 &&
+      (double.tryParse(apiReleased) ?? 0) > 0) {
+    released = apiReleased;
+  }
+  return (available: available, locked: locked, released: released);
 }

+ 7 - 0
lib/data/models/asset/today_pnl.dart

@@ -7,6 +7,8 @@ class AccountInfo {
   final Decimal frozenBalance;
   final Decimal frozenMargin;
   final Decimal currentCapital;
+  /// 已释放总量(与质押币种同单位,如 iBit;质押账户专用)
+  final Decimal releasedTotal;
 
   const AccountInfo({
     required this.name,
@@ -14,6 +16,7 @@ class AccountInfo {
     required this.frozenBalance,
     required this.frozenMargin,
     required this.currentCapital,
+    this.releasedTotal = Decimal.zero,
   });
 
   factory AccountInfo.fromJson(Map<String, dynamic> json) {
@@ -23,6 +26,10 @@ class AccountInfo {
       frozenBalance: Decimal.tryParse(json['frozenBalance']?.toString() ?? '0') ?? Decimal.zero,
       frozenMargin: Decimal.tryParse(json['frozenMargin']?.toString() ?? '0') ?? Decimal.zero,
       currentCapital: Decimal.tryParse(json['currentCapital']?.toString() ?? '0') ?? Decimal.zero,
+      releasedTotal: Decimal.tryParse(
+            json['releasedTotal']?.toString() ?? json['released_total']?.toString() ?? '0',
+          ) ??
+          Decimal.zero,
     );
   }
 }

+ 5 - 0
lib/data/models/finance/staking_wallet_balance.dart

@@ -2,6 +2,8 @@ class StakingWalletBalance {
   final String coinUnit;
   final String availableBalance;
   final String lockedBalance;
+  /// 已释放总量(与 coinUnit 同单位,如 iBit)
+  final String releasedTotal;
   final String? availableBalanceUsdt;
   final String? lockedBalanceUsdt;
 
@@ -9,6 +11,7 @@ class StakingWalletBalance {
     required this.coinUnit,
     required this.availableBalance,
     required this.lockedBalance,
+    this.releasedTotal = '0',
     this.availableBalanceUsdt,
     this.lockedBalanceUsdt,
   });
@@ -18,6 +21,7 @@ class StakingWalletBalance {
       coinUnit: coinUnit.toUpperCase(),
       availableBalance: '0',
       lockedBalance: '0',
+      releasedTotal: '0',
     );
   }
 
@@ -26,6 +30,7 @@ class StakingWalletBalance {
       coinUnit: '${json['coinUnit'] ?? ''}'.toUpperCase(),
       availableBalance: '${json['availableBalance'] ?? '0'}',
       lockedBalance: '${json['lockedBalance'] ?? '0'}',
+      releasedTotal: '${json['releasedTotal'] ?? json['released_total'] ?? '0'}',
       availableBalanceUsdt: json['availableBalanceUsdt']?.toString(),
       lockedBalanceUsdt: json['lockedBalanceUsdt']?.toString(),
     );

+ 4 - 3
lib/presentation/screens/asset/asset_staking_tab.dart

@@ -19,11 +19,12 @@ class AssetStakingTab extends StatelessWidget {
     final cs = Theme.of(context).colorScheme;
     final l10n = AppLocalizations.of(context)!;
     final obscure = state.obscureBalance;
+    final released = double.tryParse(state.stakingOverviewReleased) ?? 0;
     final locked = double.tryParse(state.stakingOverviewLocked) ?? 0;
     final available = double.tryParse(state.stakingOverviewAvailable) ?? 0;
     final totalLocked = locked + available;
-    final lockedDisplay =
-        obscure ? '******' : formatPrice(locked, decimalPlaces: 2);
+    final releasedDisplay =
+        obscure ? '******' : formatPrice(released, decimalPlaces: 2);
     final totalDisplay =
         obscure ? '******' : formatPrice(totalLocked, decimalPlaces: 2);
 
@@ -74,7 +75,7 @@ class AssetStakingTab extends StatelessWidget {
                     crossAxisAlignment: CrossAxisAlignment.end,
                     children: [
                       Text(
-                        lockedDisplay,
+                        releasedDisplay,
                         style: TextStyle(
                           color: cs.onSurface,
                           fontSize: 32,

+ 10 - 0
lib/providers/asset_provider.dart

@@ -38,6 +38,9 @@ class AssetState {
   /// 锁仓账户 iBit 可用量(总锁仓余额计算用)
   final String stakingOverviewAvailable;
 
+  /// 已释放总量(后端 releasedTotal,iBit,勿与 locked 混淆)
+  final String stakingOverviewReleased;
+
   /// 锁仓订单列表(锁仓 Tab 展示)
   final List<StakingOrderItem> stakingOrders;
   final bool stakingOrdersLoading;
@@ -59,6 +62,7 @@ class AssetState {
     this.fundWallets = const [],
     this.stakingOverviewLocked = '0',
     this.stakingOverviewAvailable = '0',
+    this.stakingOverviewReleased = '0',
     this.stakingOrders = const [],
     this.stakingOrdersLoading = false,
     this.stakingOrderStatusFilter = StakingOrderStatusFilter.all,
@@ -136,6 +140,7 @@ class AssetState {
     List<SpotWalletAsset>? fundWallets,
     String? stakingOverviewLocked,
     String? stakingOverviewAvailable,
+    String? stakingOverviewReleased,
     List<StakingOrderItem>? stakingOrders,
     bool? stakingOrdersLoading,
     StakingOrderStatusFilter? stakingOrderStatusFilter,
@@ -157,6 +162,8 @@ class AssetState {
             stakingOverviewLocked ?? this.stakingOverviewLocked,
         stakingOverviewAvailable:
             stakingOverviewAvailable ?? this.stakingOverviewAvailable,
+        stakingOverviewReleased:
+            stakingOverviewReleased ?? this.stakingOverviewReleased,
         stakingOrders: stakingOrders ?? this.stakingOrders,
         stakingOrdersLoading:
             stakingOrdersLoading ?? this.stakingOrdersLoading,
@@ -432,9 +439,11 @@ class AssetNotifier extends AutoDisposeNotifier<AssetState> {
       final accounts = todayPnl.accountInfoList;
       final walletAvailable = stakingOverviewAvailableFromAccounts(accounts);
       final walletLocked = stakingOverviewLockedFromAccounts(accounts);
+      final walletReleased = stakingOverviewReleasedFromAccounts(accounts);
       final merged = mergeStakingOverviewBalances(
         walletAvailable: walletAvailable,
         walletLocked: walletLocked,
+        walletReleased: walletReleased,
         apiWallet: stakingWallet,
       );
 
@@ -448,6 +457,7 @@ class AssetNotifier extends AutoDisposeNotifier<AssetState> {
         fundWallets: fundWallets,
         stakingOverviewLocked: merged.locked,
         stakingOverviewAvailable: merged.available,
+        stakingOverviewReleased: merged.released,
         isLoading: false,
       );
     } catch (e) {