From dd3f621bfe15b04d6b08f8797917e7a0a6d3d672 Mon Sep 17 00:00:00 2001 From: Saif Nbet Date: Fri, 27 Sep 2024 00:03:26 +0100 Subject: [PATCH] feat: Implement the calculation of tokens amounts --- .../proposal_details_model_extension.dart | 45 +- .../components/proposal_details_view.dart | 606 ++++++++++-------- 2 files changed, 361 insertions(+), 290 deletions(-) diff --git a/lib/core/extension/proposal_details_model_extension.dart b/lib/core/extension/proposal_details_model_extension.dart index 6868fb1a..ea68a637 100644 --- a/lib/core/extension/proposal_details_model_extension.dart +++ b/lib/core/extension/proposal_details_model_extension.dart @@ -2,11 +2,15 @@ import 'package:hypha_wallet/core/network/models/proposal_details_model.dart'; import 'package:intl/intl.dart'; extension ProposalDetailsModelExtension on ProposalDetailsModel { - double tokenMixToPercent() => tokenMixPercentage == null ? 0 : tokenMixPercentage! * .01; + double tokenMixToPercent() => + tokenMixPercentage == null ? 0 : tokenMixPercentage! * .01; - String formatCycleStartDate() => cycleStartDate != null ? DateFormat('EEEE, MMMM yyyy').format(cycleStartDate!) : ''; + String formatCycleStartDate() => cycleStartDate != null + ? DateFormat('EEEE, MMMM yyyy').format(cycleStartDate!) + : ''; - String cycleEndDate() => DateFormat('EEEE, MMMM yyyy').format(cycleStartDate!.add(Duration(days: cycleCount! * 7))); + String cycleEndDate() => DateFormat('EEEE, MMMM yyyy') + .format(cycleStartDate!.add(Duration(days: cycleCount! * 7))); String? tokenTitle(int index) { String input; @@ -39,27 +43,42 @@ extension ProposalDetailsModelExtension on ProposalDetailsModel { return null; } - // TODO(Saif): adjust this function String? tokenValue(int index, bool isOneCycleRewardsShown) { - String input; + String? input; + String? perPeriodInput; switch (index) { case 0: - input = utilityAmount ?? utilityAmountPerPeriod!; + input = utilityAmount; + perPeriodInput = utilityAmountPerPeriod; break; case 1: - input = voiceAmount ?? voiceAmountPerPeriod!; + input = voiceAmount; + perPeriodInput = voiceAmountPerPeriod; break; case 2: - input = cashAmount ?? cashAmountPerPeriod!; + input = cashAmount; + perPeriodInput = cashAmountPerPeriod; + break; default: return null; } - - final RegExp regExp = RegExp(r'(\S+)\s'); - final match = regExp.firstMatch(input); - - return match?.group(1); + final RegExp regExp = RegExp(r'(\d+(\.\d+)?)'); + if (input != null) { + final match = regExp.firstMatch(input); + if (isOneCycleRewardsShown || cycleCount == 1) return match?.group(1); + return (double.parse((match?.group(1))!) * cycleCount!) + .toStringAsFixed(3); + } + if (perPeriodInput != null) { + final match = regExp.firstMatch(perPeriodInput); + if (isOneCycleRewardsShown && cycleCount != 1) { + return (double.parse((match?.group(1))!) / cycleCount!) + .toStringAsFixed(3); + } + return match?.group(1); + } + return input; } } diff --git a/lib/ui/proposals/details/components/proposal_details_view.dart b/lib/ui/proposals/details/components/proposal_details_view.dart index 660068f2..771c32e9 100644 --- a/lib/ui/proposals/details/components/proposal_details_view.dart +++ b/lib/ui/proposals/details/components/proposal_details_view.dart @@ -5,7 +5,6 @@ import 'package:hypha_wallet/core/extension/base_proposal_model_extension.dart'; import 'package:hypha_wallet/core/extension/proposal_details_model_extension.dart'; import 'package:hypha_wallet/core/network/models/proposal_details_model.dart'; import 'package:hypha_wallet/core/network/models/vote_model.dart'; -import 'package:hypha_wallet/design/avatar_image/hypha_avatar_image.dart'; import 'package:hypha_wallet/design/background/hypha_page_background.dart'; import 'package:hypha_wallet/design/buttons/button_type.dart'; import 'package:hypha_wallet/design/buttons/hypha_app_button.dart'; @@ -14,7 +13,6 @@ import 'package:hypha_wallet/design/dividers/hypha_divider.dart'; import 'package:hypha_wallet/design/hypha_colors.dart'; import 'package:hypha_wallet/design/themes/extensions/theme_extension_provider.dart'; import 'package:hypha_wallet/ui/proposals/components/proposal_button.dart'; -import 'package:hypha_wallet/ui/proposals/components/proposal_creator.dart'; import 'package:hypha_wallet/ui/proposals/components/proposal_expiration_timer.dart'; import 'package:hypha_wallet/ui/proposals/components/proposal_header.dart'; import 'package:hypha_wallet/ui/proposals/components/proposal_percentage_indicator.dart'; @@ -30,7 +28,7 @@ class ProposalDetailsView extends StatefulWidget { } class _ProposalDetailsViewState extends State { - final ValueNotifier _isShownNotifier = ValueNotifier(null); + final ValueNotifier _isShownNotifier = ValueNotifier(true); final ValueNotifier _isOverflowingNotifier = ValueNotifier(false); final ValueNotifier _isExpandedNotifier = ValueNotifier(false); final ValueNotifier _detailsNotifier = ValueNotifier(null); @@ -47,9 +45,9 @@ class _ProposalDetailsViewState extends State { } } - void _initSwitchValue(ProposalDetailsModel proposalDetailsModel) { - _isShownNotifier.value = proposalDetailsModel.utilityAmount != null; - } + // void _initSwitchValue(ProposalDetailsModel proposalDetailsModel) { + // _isShownNotifier.value = proposalDetailsModel.utilityAmount != null; + // } @override Widget build(BuildContext context) { @@ -62,312 +60,366 @@ class _ProposalDetailsViewState extends State { title: const Text('Proposal Details'), ), body: BlocBuilder( - builder: (context, state) { - return HyphaBodyWidget(pageState: state.pageState, success: (context) { - final ProposalDetailsModel _proposalDetailsModel = state.proposalDetailsModel!; - final List passVoters = _proposalDetailsModel.fetchVotersByStatus(VoteStatus.pass); - final List failVoters = _proposalDetailsModel.fetchVotersByStatus(VoteStatus.fail); - _detailsNotifier.value = _proposalDetailsModel.description; - WidgetsBinding.instance.addPostFrameCallback((_) { - _checkIfTextIsOverflowing(); - _initSwitchValue(_proposalDetailsModel); - }); - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: ListView( - children: [ - const SizedBox(height: 20), - /// Header - ProposalHeader(_proposalDetailsModel.dao), - const Padding( - padding: EdgeInsets.only(top: 10, bottom: 20), - child: HyphaDivider(), - ), - /// Main Section - Wrap( - children: List.generate( - _proposalDetailsModel.commitment != null ? 3 : 2, - (index) => Padding( - padding: const EdgeInsets.only(right: 10), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), - decoration: BoxDecoration( - border: Border.all( - color: context.isDarkMode - ? HyphaColors.white - : HyphaColors.lightBlack, + builder: (context, state) { + return HyphaBodyWidget(pageState: state.pageState, success: (context) { + final ProposalDetailsModel _proposalDetailsModel = state.proposalDetailsModel!; + final List passVoters = _proposalDetailsModel.fetchVotersByStatus(VoteStatus.pass); + final List failVoters = _proposalDetailsModel.fetchVotersByStatus(VoteStatus.fail); + _detailsNotifier.value = _proposalDetailsModel.description; + WidgetsBinding.instance.addPostFrameCallback((_) { + _checkIfTextIsOverflowing(); + // _initSwitchValue(_proposalDetailsModel); + }); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: ListView( + children: [ + const SizedBox(height: 20), + /// Header + ProposalHeader(_proposalDetailsModel.dao), + const Padding( + padding: EdgeInsets.only(top: 10, bottom: 20), + child: HyphaDivider(), + ), + /// Main Section + Wrap( + children: List.generate( + _proposalDetailsModel.commitment != null ? 3 : 2, + (index) => Padding( + padding: const EdgeInsets.only(right: 10), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + border: Border.all( + color: context.isDarkMode + ? HyphaColors.white + : HyphaColors.lightBlack, + ), + borderRadius: BorderRadius.circular(20), + ), + // TODO(Zied-Saif): figure these out (B6 and Role) + child: Text( + index == 0 + ? 'Role ${_proposalDetailsModel.type}' + : index == 1 + ? 'B6' + : '${_proposalDetailsModel.commitment}%', + style: context.hyphaTextTheme.ralBold, ), - borderRadius: BorderRadius.circular(20), - ), - // TODO(Zied-Saif): figure these out (B6 and Role) - child: Text( - index == 0 - ? 'Role ${_proposalDetailsModel.type}' - : index == 1 - ? 'B6' - : '${_proposalDetailsModel.commitment}%', - style: context.hyphaTextTheme.ralBold, ), ), ), ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: Text( - _proposalDetailsModel.title ?? 'No title', - style: context.hyphaTextTheme.mediumTitles, - ), - ), - // TODO(Saif): display creator image - //ProposalCreator(_proposalDetailsModel.creator), - ...List.generate( - 2, - (index) => Padding( - padding: const EdgeInsets.only(top: 20), - child: ProposalPercentageIndicator( - index == 0 ? 'Commitment' : 'Token Mix Percentage', - index == 0 ? _proposalDetailsModel.commitmentToPercent() : _proposalDetailsModel.tokenMixToPercent(), - HyphaColors.lightBlue - ), - ), - ), - if (!(_proposalDetailsModel.cycleCount == null && _proposalDetailsModel.cycleStartDate == null)) ...[ - const SizedBox(height: 20), - Text( - 'Duration', - style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), - ), Padding( - padding: const EdgeInsets.symmetric(vertical: 10), + padding: const EdgeInsets.symmetric(vertical: 20), child: Text( - '${_proposalDetailsModel.cycleCount} Cycles', - style: context.hyphaTextTheme.reducedTitles, + _proposalDetailsModel.title ?? 'No title', + style: context.hyphaTextTheme.mediumTitles, ), ), + // TODO(Saif): display creator image + //ProposalCreator(_proposalDetailsModel.creator), ...List.generate( 2, - (index) => Text( - index == 0 ? 'Starting on ${_proposalDetailsModel.formatCycleStartDate()}' : - 'Ending on ${_proposalDetailsModel.cycleEndDate()}', - style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), + (index) => Padding( + padding: const EdgeInsets.only(top: 20), + child: ProposalPercentageIndicator( + index == 0 ? 'Commitment' : 'Token Mix Percentage', + index == 0 ? _proposalDetailsModel.commitmentToPercent() : _proposalDetailsModel.tokenMixToPercent(), + HyphaColors.lightBlue + ), ), ), - ], - const Padding( - padding: EdgeInsets.symmetric(vertical: 20), - child: HyphaDivider(), - ), - /// Rewards Section - if (_proposalDetailsModel.utilityAmount != null || _proposalDetailsModel.utilityAmountPerPeriod != null) ... [ - ValueListenableBuilder( - valueListenable: _isShownNotifier, - builder: (BuildContext context, bool? isShown, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Reward for 1 cycle', - style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), - ), - ...List.generate( - 3, - (index) => Padding( - padding: const EdgeInsets.only(top: 10), - child: Row( - children: [ - DaoImage(_proposalDetailsModel.dao), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _proposalDetailsModel.tokenTitle(index) ?? '', - style: context.hyphaTextTheme.reducedTitles, - overflow: TextOverflow.ellipsis, - ), - Text( - index == 0 ? 'Utility Token' : index == 1 ? 'Voice Token' : 'Cash Token', - style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - const SizedBox(width: 10), - Text( - _proposalDetailsModel.tokenValue(index, isShown ?? false) ?? '', - style: context.hyphaTextTheme.bigTitles.copyWith(fontWeight: FontWeight.normal), - ) - ], - ), - )), - const SizedBox(height: 10) - ], - ); - }, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - 'Show rewards for 1 cycle', - style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), - overflow: TextOverflow.ellipsis, - ), + if (!(_proposalDetailsModel.cycleCount == null && _proposalDetailsModel.cycleStartDate == null)) ...[ + const SizedBox(height: 20), + Text( + 'Duration', + style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${_proposalDetailsModel.cycleCount} Cycles', + style: context.hyphaTextTheme.reducedTitles, ), - const SizedBox(width: 10), - ValueListenableBuilder( - valueListenable: _isShownNotifier, - builder: (BuildContext context, bool? value, Widget? child) { - return _isShownNotifier.value != null ? Switch( - value: value!, - onChanged: (newValue) { - _isShownNotifier.value = newValue; - }, - ) : const SizedBox.shrink(); - }, + ), + ...List.generate( + 2, + (index) => Text( + index == 0 ? 'Starting on ${_proposalDetailsModel.formatCycleStartDate()}' : + 'Ending on ${_proposalDetailsModel.cycleEndDate()}', + style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), ), - ], - ), + ), + ], const Padding( padding: EdgeInsets.symmetric(vertical: 20), child: HyphaDivider(), ), - ], - /// Details Section - if (_proposalDetailsModel.description != null) ... [ - Text( - 'Proposal Details', - style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), - ), - ValueListenableBuilder( - valueListenable: _isExpandedNotifier, - builder: (context, isExpanded, child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(top: 10), - child: Text( - _proposalDetailsModel.description ?? '', - style: context.hyphaTextTheme.ralMediumBody, - maxLines: isExpanded ? null : 3, - overflow: isExpanded ? TextOverflow.visible : TextOverflow.ellipsis, + /// Rewards Section + if (_proposalDetailsModel.utilityAmount != null || + _proposalDetailsModel.utilityAmountPerPeriod != null || + _proposalDetailsModel.voiceAmount != null || + _proposalDetailsModel.voiceAmountPerPeriod != null || + _proposalDetailsModel.cashAmount != null || + _proposalDetailsModel.cashAmountPerPeriod != null) ...[ + ValueListenableBuilder( + valueListenable: _isShownNotifier, + builder: (BuildContext context, bool? isShown, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _isShownNotifier.value?'Reward for 1 cycle':'Reward per period', + style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: Row( - children: [ - const Expanded(child: HyphaDivider()), - ValueListenableBuilder( - valueListenable: _isOverflowingNotifier, - builder: (context, isOverflowing, child) { - return isOverflowing - ? ProposalButton( - isExpanded ? 'Collapse' : 'Expand', - isExpanded - ? Icons.keyboard_arrow_up_outlined - : Icons.keyboard_arrow_down_outlined, - () => _isExpandedNotifier.value = !isExpanded, - ) - : const SizedBox.shrink(); - }, - ), - ], + + _buildTokenRow( + context, + _proposalDetailsModel, + 0, // Token index for Utility + 'Utility Token', + _isShownNotifier.value, + ), + _buildTokenRow( + context, + _proposalDetailsModel, + 1, // Token index for Voice + 'Voice Token', + _isShownNotifier.value, ), + _buildTokenRow( + context, + _proposalDetailsModel, + 2, // Token index for Cash + 'Cash Token', + _isShownNotifier.value, + ), + + const SizedBox(height: 10), + ], + ); + }, + ), + if (_proposalDetailsModel.cycleCount!=null)Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + 'Show rewards for 1 cycle', + style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), + overflow: TextOverflow.ellipsis, ), - ], - ); - }, + ), + const SizedBox(width: 10), + ValueListenableBuilder( + valueListenable: _isShownNotifier, + builder: (BuildContext context, bool? value, Widget? child) { + return Switch( + value: value!, + onChanged: (newValue) { + _isShownNotifier.value = newValue; + }, + ); + }, + ), + ], + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: HyphaDivider(), + ), + ], + /// Details Section + if (_proposalDetailsModel.description != null) ... [ + Text( + 'Proposal Details', + style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), + ), + ValueListenableBuilder( + valueListenable: _isExpandedNotifier, + builder: (context, isExpanded, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 10), + child: Text( + _proposalDetailsModel.description ?? '', + style: context.hyphaTextTheme.ralMediumBody, + maxLines: isExpanded ? null : 3, + overflow: isExpanded ? TextOverflow.visible : TextOverflow.ellipsis, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + children: [ + const Expanded(child: HyphaDivider()), + ValueListenableBuilder( + valueListenable: _isOverflowingNotifier, + builder: (context, isOverflowing, child) { + return isOverflowing + ? ProposalButton( + isExpanded ? 'Collapse' : 'Expand', + isExpanded + ? Icons.keyboard_arrow_up_outlined + : Icons.keyboard_arrow_down_outlined, + () => _isExpandedNotifier.value = !isExpanded, + ) + : const SizedBox.shrink(); + }, + ), + ], + ), + ), + ], + ); + }, + ), + ], + /// Voting Scores Section + Text( + 'Voting Scores', + style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), ), - ], - /// Voting Scores Section - Text( - 'Voting Scores', - style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(color: HyphaColors.midGrey), - ), - if(passVoters.isNotEmpty) ... [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: Text( - '${passVoters.length} members voted Yes', - style: context.hyphaTextTheme.reducedTitles, + if(passVoters.isNotEmpty) ... [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${passVoters.length} members voted Yes', + style: context.hyphaTextTheme.reducedTitles, + ), + ), + ProposalVoters(passVoters) + ], + if(failVoters.isNotEmpty) ... [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${failVoters.length} members voted No', + style: context.hyphaTextTheme.reducedTitles, + ), + ), + ProposalVoters(failVoters) + ], + const SizedBox(height: 20), + ...List.generate( + 2, + (index) => Padding( + padding: const EdgeInsets.only(bottom: 20), + child: ProposalPercentageIndicator( + index == 0 ? 'Unity' : 'Quorum', + index == 0 ? _proposalDetailsModel.unityToPercent() : _proposalDetailsModel.quorumToPercent(), + _proposalDetailsModel.isPassing() ? HyphaColors.success : HyphaColors.error + ), ), ), - ProposalVoters(passVoters) - ], - if(failVoters.isNotEmpty) ... [ + const HyphaDivider(), + /// Expiration Timer Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: Text( - '${failVoters.length} members voted No', - style: context.hyphaTextTheme.reducedTitles, + padding: const EdgeInsets.symmetric(vertical: 20), + child: ProposalExpirationTimer( + _proposalDetailsModel.formatExpiration(), ), ), - ProposalVoters(failVoters) - ], - const SizedBox(height: 20), - ...List.generate( - 2, - (index) => Padding( - padding: const EdgeInsets.only(bottom: 20), - child: ProposalPercentageIndicator( - index == 0 ? 'Unity' : 'Quorum', - index == 0 ? _proposalDetailsModel.unityToPercent() : _proposalDetailsModel.quorumToPercent(), - _proposalDetailsModel.isPassing() ? HyphaColors.success : HyphaColors.error + const HyphaDivider(), + /// Vote Section + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Text( + 'Cast your Vote', + style: context.hyphaTextTheme.smallTitles, ), ), - ), - const HyphaDivider(), - /// Expiration Timer - Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: ProposalExpirationTimer( - _proposalDetailsModel.formatExpiration(), - ), - ), - const HyphaDivider(), - /// Vote Section - Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: Text( - 'Cast your Vote', - style: context.hyphaTextTheme.smallTitles, - ), - ), - ...List.generate( - 3, - (index) => Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: HyphaAppButton( - title: index == 0 - ? 'Yes' - : index == 1 - ? 'Abstain' - : 'No', - onPressed: () async {}, - buttonType: ButtonType.danger, - buttonColor: index == 0 - ? HyphaColors.success - : index == 1 - ? HyphaColors.lightBlack - : HyphaColors.error, + ...List.generate( + 3, + (index) => Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: HyphaAppButton( + title: index == 0 + ? 'Yes' + : index == 1 + ? 'Abstain' + : 'No', + onPressed: () async {}, + buttonType: ButtonType.danger, + buttonColor: index == 0 + ? HyphaColors.success + : index == 1 + ? HyphaColors.lightBlack + : HyphaColors.error, + ), ), ), - ), - const SizedBox(height: 20), - ], - ), - ); - }); - }, + const SizedBox(height: 20), + ], + ), + ); + }); + }, + ), ), + ); + } +} + +Widget _buildTokenRow( + BuildContext context, + ProposalDetailsModel proposalDetailsModel, + int tokenIndex, + String tokenType, + bool? isShown) { + String? amount; + + // Determine the amount and amountPerPeriod based on token type + switch (tokenType) { + case 'Utility Token': + amount = proposalDetailsModel.tokenValue(0, isShown!); + break; + case 'Voice Token': + amount = proposalDetailsModel.tokenValue(1, isShown!); + break; + case 'Cash Token': + amount = proposalDetailsModel.tokenValue(2, isShown!); + break; + } + + if (amount != null) { + return Padding( + padding: const EdgeInsets.only(top: 10), + child: Row( + children: [ + DaoImage(proposalDetailsModel.dao), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + proposalDetailsModel.tokenTitle(tokenIndex) ?? '', + style: context.hyphaTextTheme.reducedTitles, + overflow: TextOverflow.ellipsis, + ), + Text( + tokenType, + style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + const SizedBox(width: 10), + Text( + amount, + style: context.hyphaTextTheme.bigTitles.copyWith(fontWeight: FontWeight.normal), + ), + ], ), ); } + + return const SizedBox.shrink(); // Return an empty widget if there's no data } +