CW-1130-deuro-fixes-improvements (#2392)

* feat: add support for Ethereum EIP-681 URIs in PaymentRequest and implement test coverage * test: add unit test for EIP-681 URI handling with contract and no chainId [skip-ci] * fix(CW-1114): rounding error for really large numbers * fix: wrong decimals for eth fee display * fix: limit fractional digits to a maximum of `decimals` in `format_fixed` function [skip-ci] * test: add unit tests for `formatFixed` function * refactor: replace custom balance formatting with `formatFixed` utility function * refactor: improve dEuroViewModel formatting and computation logic * refactor: extract and simplify interest action handlers in dEuro savings page * fix: deuro add should show edit Add bottom sheet * feat: block user from entering amount bigger than the max * feat: use new tooltip bottomsheet for dEuro * feat: add pull down to refresh dEuro savings --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

Konstantin Ullrich committed Jul 19, 2025 at 00:47 UTC 43f2225e0c2b5e4c3f07eca7e7667fdefc1c077f
5 files changed +216 -144
cw_evm/lib/evm_erc20_balance.dart
+3 -11
@@ -1,6 +1,5 @@
1 import 'dart:convert';
2 -import 'dart:math';
3 -import 'package:intl/intl.dart';
2 +import 'package:cw_core/format_fixed.dart';
3
4 import 'package:cw_core/balance.dart';
5
@@ -12,17 +11,10 @@ class EVMChainERC20Balance extends Balance {
11 final int exponent;
12
13 @override
15 - String get formattedAdditionalBalance => _balance();
14 + String get formattedAdditionalBalance => formatFixed(balance, exponent, fractionalDigits: 12);
15
16 @override
18 - String get formattedAvailableBalance => _balance();
19 -
20 - String _balance() {
21 - NumberFormat formatter = NumberFormat('0.00##########', 'en_US');
22 - double numBalance = (balance / BigInt.from(10).pow(exponent)).toDouble();
23 - String formattedBalance = formatter.format(numBalance);
24 - return formattedBalance;
25 - }
17 + String get formattedAvailableBalance => formatFixed(balance, exponent, fractionalDigits: 12);
18
19 String toJSON() => json.encode({
20 'balanceInWei': balance.toString(),
lib/src/screens/integrations/deuro/savings_page.dart
+93 -81
@@ -9,7 +9,9 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
9 import 'package:cake_wallet/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart';
10 import 'package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
11 import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
12 +import 'package:cake_wallet/src/widgets/bottom_sheet/tooltip_bottom_sheet.dart';
13 import 'package:cake_wallet/src/widgets/gradient_background.dart';
14 +import 'package:cake_wallet/utils/responsive_layout_util.dart';
15 import 'package:cake_wallet/utils/show_pop_up.dart';
16 import 'package:cake_wallet/view_model/integrations/deuro_view_model.dart';
17 import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
@@ -37,86 +39,71 @@ class DEuroSavingsPage extends BasePage {
39 @override
40 String get title => S.current.deuro_savings;
41
40 - Widget trailing(BuildContext context) => MergeSemantics(
41 - child: SizedBox(
42 - height: 37,
43 - width: 37,
44 - child: ButtonTheme(
45 - minWidth: double.minPositive,
46 - child: Semantics(
47 - label: "Refresh",
48 - child: TextButton(
49 - style: TextButton.styleFrom(
50 - foregroundColor: Theme.of(context).colorScheme.onSurface,
51 - overlayColor: WidgetStateColor.resolveWith((states) => Colors.transparent),
52 - ),
53 - onPressed: _dEuroViewModel.reloadSavingsUserData,
54 - child: Icon(
55 - Icons.refresh,
56 - color: pageIconColor(context),
57 - size: 20,
58 - ),
59 - ),
60 - ),
61 - ),
62 - ),
63 - );
64 -
42 @override
43 Widget body(BuildContext context) {
44 WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context, _dEuroViewModel));
45
69 - return Container(
70 - width: double.infinity,
71 - child: Column(
72 - children: <Widget>[
73 - Observer(
74 - builder: (_) => SavingsCard(
75 - isDarkTheme: currentTheme.isDark,
76 - interestRate: "${_dEuroViewModel.interestRate}%",
77 - savingsBalance: _dEuroViewModel.savingsBalance,
78 - fiatSavingsBalance: _dEuroViewModel.fiatSavingsBalance,
79 - currency: CryptoCurrency.deuro,
80 - fiatCurrency: _dEuroViewModel.isFiatDisabled ? null : _dEuroViewModel.fiat,
81 - onAddSavingsPressed: () => _onSavingsAdd(context),
82 - onRemoveSavingsPressed: () => _onSavingsRemove(context),
83 - onApproveSavingsPressed: _dEuroViewModel.prepareApproval,
84 - onTooltipPressed: () => _onSavingsTooltipPressed(context),
85 - isEnabled: _dEuroViewModel.isEnabled,
86 - isLoading: _dEuroViewModel.isLoading,
87 - ),
88 - ),
89 - Observer(
90 - builder: (_) => InterestCardWidget(
91 - isDarkTheme: currentTheme.isDark,
92 - title: S.of(context).deuro_savings_collect_interest,
93 - fiatAccruedInterest: _dEuroViewModel.fiatAccruedInterest,
94 - fiatCurrency: _dEuroViewModel.isFiatDisabled ? null : _dEuroViewModel.fiat,
95 - accruedInterest: _dEuroViewModel.accruedInterest,
96 - onCollectInterest: _dEuroViewModel.prepareCollectInterest,
97 - onReinvestInterest: _dEuroViewModel.prepareReinvestInterest,
98 - onTooltipPressed: () => _onInterestTooltipPressed(context),
99 - isEnabled: _dEuroViewModel.isEnabled,
100 - ),
101 - ),
102 - Spacer(),
103 - SafeArea(
104 - child: Padding(
105 - padding: EdgeInsets.only(bottom: 30),
106 - child: Row(
107 - mainAxisAlignment: MainAxisAlignment.center,
108 - children: [
109 - InfoChip(
110 - label: S.of(context).deuro_about_deuro,
111 - icon: CupertinoIcons.info,
112 - onPressed: () => _showWelcomeTooltip(context),
46 + return RefreshIndicator(
47 + displacement: responsiveLayoutUtil.screenHeight * 0.1,
48 + onRefresh: _dEuroViewModel.reloadSavingsUserData,
49 + child: CustomScrollView(
50 + slivers: <Widget>[
51 + SliverFillRemaining(
52 + child: SizedBox(
53 + width: double.infinity,
54 + child: Column(
55 + children: <Widget>[
56 + Observer(
57 + builder: (_) => SavingsCard(
58 + isDarkTheme: currentTheme.isDark,
59 + interestRate: "${_dEuroViewModel.interestRateFormated}%",
60 + savingsBalance: _dEuroViewModel.savingsBalanceFormated,
61 + fiatSavingsBalance: _dEuroViewModel.fiatSavingsBalanceFormated,
62 + currency: CryptoCurrency.deuro,
63 + fiatCurrency: _dEuroViewModel.isFiatDisabled ? null : _dEuroViewModel.fiat,
64 + onAddSavingsPressed: () => _onSavingsAdd(context),
65 + onRemoveSavingsPressed: () => _onSavingsRemove(context),
66 + onApproveSavingsPressed: _dEuroViewModel.prepareApproval,
67 + onTooltipPressed: () => _onSavingsTooltipPressed(context),
68 + isEnabled: _dEuroViewModel.isEnabled,
69 + isLoading: _dEuroViewModel.isLoading,
70 + ),
71 + ),
72 + Observer(
73 + builder: (_) => InterestCardWidget(
74 + isDarkTheme: currentTheme.isDark,
75 + title: S.of(context).deuro_savings_collect_interest,
76 + fiatAccruedInterest: _dEuroViewModel.fiatAccruedInterestFormated,
77 + fiatCurrency: _dEuroViewModel.isFiatDisabled ? null : _dEuroViewModel.fiat,
78 + accruedInterest: _dEuroViewModel.accruedInterestFormated,
79 + onCollectInterest: _onCollectInterest,
80 + onReinvestInterest: _onReinvestInterest,
81 + onTooltipPressed: () => _onInterestTooltipPressed(context),
82 + isEnabled: _dEuroViewModel.isSavingsActionsEnabled,
83 + ),
84 + ),
85 + Spacer(),
86 + SafeArea(
87 + child: Padding(
88 + padding: EdgeInsets.only(bottom: 30),
89 + child: Row(
90 + mainAxisAlignment: MainAxisAlignment.center,
91 + children: [
92 + InfoChip(
93 + label: S.of(context).deuro_about_deuro,
94 + icon: CupertinoIcons.info,
95 + onPressed: () => _showWelcomeTooltip(context),
96 + ),
97 + SizedBox(width: 10),
98 + InfoChip(
99 + label: S.of(context).website,
100 + icon: CupertinoIcons.globe,
101 + onPressed: () => launchUrlString("https://deuro.com/"),
102 + )
103 + ],
104 + ),
105 + ),
106 ),
114 - SizedBox(width: 10),
115 - InfoChip(
116 - label: S.of(context).website,
117 - icon: CupertinoIcons.globe,
118 - onPressed: () => launchUrlString("https://deuro.com/"),
119 - )
107 ],
108 ),
109 ),
@@ -126,14 +113,36 @@ class DEuroSavingsPage extends BasePage {
113 );
114 }
115
116 + bool _editSheetIsOpen = false;
117 +
118 Future<void> _onSavingsAdd(BuildContext context) async {
119 + if (_editSheetIsOpen) return;
120 + _editSheetIsOpen = true;
121 final amount = await _showEditBottomSheet(context, isAdding: true);
122 if (amount != null) _dEuroViewModel.prepareSavingsEdit(amount, true);
123 + _editSheetIsOpen = false;
124 }
125
126 Future<void> _onSavingsRemove(BuildContext context) async {
127 + if (_editSheetIsOpen) return;
128 + _editSheetIsOpen = true;
129 final amount = await _showEditBottomSheet(context, isAdding: false);
130 if (amount != null) _dEuroViewModel.prepareSavingsEdit(amount, false);
131 + _editSheetIsOpen = false;
132 + }
133 +
134 + Future<void> _onReinvestInterest() async {
135 + if (_editSheetIsOpen) return;
136 + _editSheetIsOpen = true;
137 + await _dEuroViewModel.prepareReinvestInterest();
138 + _editSheetIsOpen = false;
139 + }
140 +
141 + Future<void> _onCollectInterest() async {
142 + if (_editSheetIsOpen) return;
143 + _editSheetIsOpen = true;
144 + await _dEuroViewModel.prepareCollectInterest();
145 + _editSheetIsOpen = false;
146 }
147
148 bool _isReactionsSet = false;
@@ -175,10 +184,10 @@ class DEuroSavingsPage extends BasePage {
184 currency: CryptoCurrency.deuro,
185 amount: S.of(bottomSheetContext).send_amount,
186 amountValue: _dEuroViewModel.actionType == DEuroActionType.reinvest
178 - ? _dEuroViewModel.accruedInterest
187 + ? _dEuroViewModel.accruedInterestFormated
188 : tx.amountFormatted,
189 fiatAmountValue: _dEuroViewModel.actionType == DEuroActionType.reinvest
181 - ? _dEuroViewModel.fiatAccruedInterest
190 + ? _dEuroViewModel.fiatAccruedInterestFormated
191 : _dEuroViewModel.pendingTransactionFiatAmountFormatted,
192 fee: S.of(bottomSheetContext).send_estimated_fee,
193 feeValue: tx.feeFormatted,
@@ -301,11 +310,11 @@ class DEuroSavingsPage extends BasePage {
310
311 showModalBottomSheet<void>(
312 context: context,
304 - builder: (BuildContext bottomSheetContext) => InfoBottomSheet(
313 + builder: (BuildContext bottomSheetContext) => TooltipSheet(
314 currentTheme: currentTheme,
315 titleText: title,
316 titleIconPath: CryptoCurrency.deuro.iconPath,
308 - content: content,
317 + tooltip: content,
318 footerType: FooterType.doubleActionButton,
319 doubleActionRightButtonText: S.of(context).close,
320 rightActionButtonKey: ValueKey('deuro_page_tooltip_dialog_${key}_ok_button_key'),
@@ -358,7 +367,8 @@ class DEuroSavingsPage extends BasePage {
367 content: S.of(context).deuro_tooltip_no_eth,
368 singleActionButtonKey: ValueKey('deuro_page_tooltip_dialog_no_eth_ok_button_key'),
369 singleActionButtonText: S.of(context).close,
361 - onSingleActionButtonPressed: () => Navigator.of(bottomSheetContext).pop(), footerType: FooterType.singleActionButton,
370 + onSingleActionButtonPressed: () => Navigator.of(bottomSheetContext).pop(),
371 + footerType: FooterType.singleActionButton,
372 ),
373 );
374 }
@@ -375,7 +385,9 @@ class DEuroSavingsPage extends BasePage {
385 balanceTitle: isAdding
386 ? S.of(context).deuro_savings_available_to_add
387 : S.of(context).deuro_savings_available_to_remove,
378 - balance: isAdding ? _dEuroViewModel.accountBalance : _dEuroViewModel.savingsBalance,
388 + balance: isAdding
389 + ? _dEuroViewModel.accountBalanceFormated
390 + : _dEuroViewModel.savingsBalanceFormated,
391 footerType: FooterType.none,
392 maxHeight: MediaQuery.of(context).size.height * 0.8,
393 ),
lib/src/screens/integrations/deuro/widgets/savings_edit_sheet.dart
+35 -10
@@ -3,6 +3,7 @@ import 'package:cake_wallet/generated/i18n.dart';
3 import 'package:cake_wallet/src/screens/integrations/deuro/widgets/numpad.dart';
4 import 'package:cake_wallet/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart';
5 import 'package:cake_wallet/src/widgets/primary_button.dart';
6 +import 'package:cw_core/parse_fixed.dart';
7 import 'package:flutter/material.dart';
8
9 class SavingsEditSheet extends BaseBottomSheet {
@@ -14,7 +15,8 @@ class SavingsEditSheet extends BaseBottomSheet {
15 super.titleIconPath,
16 this.balance,
17 this.balanceTitle,
17 - required super.footerType, required super.maxHeight,
18 + required super.footerType,
19 + required super.maxHeight,
20 });
21
22 @override
@@ -53,8 +55,35 @@ class _SavingsEditBodyState extends State<_SavingsEditBody> {
55 }
56
57 String amount = '0';
58 + bool isValid = false;
59 final FocusNode _numpadFocusNode = FocusNode();
60
61 + void _onPressedAll() => setState(() {
62 + amount = widget.balance!;
63 + isValid = _validate();
64 + });
65 +
66 + void _onNumberPressed(int i) => setState(() {
67 + amount = amount == '0' ? i.toString() : '${amount}${i}';
68 + isValid = _validate();
69 + });
70 +
71 + void _onDeletePressed() => setState(() {
72 + amount = amount.length > 1 ? amount.substring(0, amount.length - 1) : '0';
73 + isValid = _validate();
74 + });
75 +
76 + void _onDecimalPressed() => setState(() {
77 + amount = '${amount.replaceAll('.', '')}.';
78 + isValid = _validate();
79 + });
80 +
81 + bool _validate() {
82 + final amountBigInt = parseFixed(amount, 18);
83 + final balanceBigInt = parseFixed(widget.balance!, 18);
84 + return balanceBigInt >= amountBigInt && amountBigInt > BigInt.zero;
85 + }
86 +
87 @override
88 Widget build(BuildContext context) => SafeArea(
89 child: Column(children: [
@@ -80,18 +109,14 @@ class _SavingsEditBodyState extends State<_SavingsEditBody> {
109 AssetBalanceRow(
110 title: widget.balanceTitle!,
111 amount: widget.balance!,
83 - onAllPressed: () => setState(() => amount = widget.balance!),
112 + onAllPressed: _onPressedAll,
113 ),
114 ],
115 NumberPad(
116 focusNode: _numpadFocusNode,
88 - onNumberPressed: (i) => setState(
89 - () => amount = amount == '0' ? i.toString() : '${amount}${i}',
90 - ),
91 - onDeletePressed: () => setState(
92 - () => amount = amount.length > 1 ? amount.substring(0, amount.length - 1) : '0',
93 - ),
94 - onDecimalPressed: () => setState(() => amount = '${amount.replaceAll('.', '')}.'),
117 + onNumberPressed: _onNumberPressed,
118 + onDeletePressed: _onDeletePressed,
119 + onDecimalPressed: _onDecimalPressed,
120 ),
121 Padding(
122 padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
@@ -101,7 +126,7 @@ class _SavingsEditBodyState extends State<_SavingsEditBody> {
126 color: Theme.of(context).colorScheme.primary,
127 textColor: Theme.of(context).colorScheme.onPrimary,
128 isLoading: false,
104 - isDisabled: false,
129 + isDisabled: !isValid,
130 ),
131 )
132 ]),
lib/src/widgets/bottom_sheet/tooltip_bottom_sheet.dart new
+46
@@ -0,0 +1,46 @@
1 +import 'package:auto_size_text/auto_size_text.dart';
2 +import 'package:cake_wallet/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart';
3 +import 'package:flutter/material.dart';
4 +
5 +class TooltipSheet extends BaseBottomSheet {
6 + final String tooltip;
7 +
8 + const TooltipSheet({
9 + required super.currentTheme,
10 + required super.titleText,
11 + super.titleIconPath,
12 + required this.tooltip,
13 + required super.footerType,
14 + super.maxHeight = 900,
15 + super.singleActionButtonText,
16 + super.onSingleActionButtonPressed,
17 + super.singleActionButtonKey,
18 + super.doubleActionLeftButtonText,
19 + super.doubleActionRightButtonText,
20 + super.onLeftActionButtonPressed,
21 + super.onRightActionButtonPressed,
22 + super.leftActionButtonKey,
23 + super.rightActionButtonKey,
24 + });
25 +
26 + @override
27 + Widget contentWidget(BuildContext context) => Container(
28 + decoration: BoxDecoration(
29 + borderRadius: BorderRadius.circular(10),
30 + color: Theme.of(context).colorScheme.surfaceContainer),
31 + margin: const EdgeInsets.all(12),
32 + padding: const EdgeInsets.all(12),
33 + child: AutoSizeText(
34 + tooltip,
35 + textAlign: TextAlign.center,
36 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
37 + fontSize: 16,
38 + fontWeight: FontWeight.w500,
39 + color: Theme.of(context).colorScheme.onSurfaceVariant,
40 + decoration: TextDecoration.none,
41 + ),
42 + ),
43 + );
44 +
45 + Widget footerWidget(BuildContext context) => SizedBox.shrink();
46 +}
lib/view_model/integrations/deuro_view_model.dart
+39 -42
@@ -21,6 +21,8 @@ class DEuroViewModel = DEuroViewModelBase with _$DEuroViewModel;
21 abstract class DEuroViewModelBase with Store {
22 final AppStore _appStore;
23
24 + static BigInt get MIN_ACCRUED_INTEREST => BigInt.parse("1000000000000");
25 +
26 DEuroViewModelBase(
27 this._appStore,
28 this.balanceViewModel,
@@ -44,39 +46,31 @@ abstract class DEuroViewModelBase with Store {
46 @action
47 void acceptDisclaimer() => _settingsStore.shouldShowDEuroDisclaimer = false;
48
47 - @computed
48 - String get pendingTransactionFiatAmountFormatted =>
49 - isFiatDisabled ? '' : '$pendingTransactionFiatAmount ${fiat.title}';
50 -
51 - @computed
52 - String get pendingTransactionFeeFiatAmountFormatted =>
53 - isFiatDisabled ? '' : '$pendingTransactionFeeFiatAmount ${fiat.title}';
54 -
49 FiatCurrency get fiat => _settingsStore.fiatCurrency;
50
51 @computed
58 - String get pendingTransactionFiatAmount =>
59 - transaction == null ? '0.00' : _getDEuroFiatAmount(transaction!.amountFormatted);
52 + String get pendingTransactionFiatAmountFormatted {
53 + final amount = transaction == null ? '0.00' : _getDEuroFiatAmount(transaction!.amountFormatted);
54 + return isFiatDisabled ? '' : '$amount ${fiat.title}';
55 + }
56
57 @computed
62 - String get pendingTransactionFeeFiatAmount {
58 + String get pendingTransactionFeeFiatAmountFormatted {
59 + var amount = '0.00';
60 try {
61 if (transaction != null) {
65 - final currency = CryptoCurrency.eth;
66 - return calculateFiatAmount(
67 - price: _fiatConversationStore.prices[currency]!,
68 - cryptoAmount: transaction!.feeFormattedValue,
69 - );
70 - } else {
71 - return '0.00';
62 + final feeCurrency = CryptoCurrency.eth;
63 + amount = calculateFiatAmount(
64 + price: _fiatConversationStore.prices[feeCurrency]!,
65 + cryptoAmount: transaction!.feeFormattedValue,
66 + );
67 }
73 - } catch (_) {
74 - return '0.00';
75 - }
68 + } catch (_) {}
69 + return isFiatDisabled ? '' : '$amount ${fiat.title}';
70 }
71
72 @computed
79 - String get accountBalance {
73 + String get accountBalanceFormated {
74 final dEuroKey = balanceViewModel.balances.keys
75 .firstWhereOrNull((e) => e.title == CryptoCurrency.deuro.title);
76 if (dEuroKey == null) return '0.00';
@@ -84,22 +78,30 @@ abstract class DEuroViewModelBase with Store {
78 }
79
80 @observable
87 - String savingsBalance = '0.00';
81 + BigInt savingsBalance = BigInt.zero;
82
83 @computed
90 - String get fiatSavingsBalance => _getDEuroFiatAmount(savingsBalance);
84 + String get savingsBalanceFormated =>
85 + ethereum!.formatterEthereumAmountToDouble(amount: savingsBalance).toStringAsFixed(6);
86 +
87 + @computed
88 + String get fiatSavingsBalanceFormated => _getDEuroFiatAmount(savingsBalanceFormated);
89
90 @observable
91 ExecutionState state = InitialExecutionState();
92
93 @observable
96 - String interestRate = '0';
94 + String interestRateFormated = '0';
95
96 @observable
99 - String accruedInterest = '0.00';
97 + BigInt accruedInterest = BigInt.zero;
98 +
99 + @computed
100 + String get accruedInterestFormated =>
101 + ethereum!.formatterEthereumAmountToDouble(amount: accruedInterest).toStringAsFixed(6);
102
103 @computed
102 - String get fiatAccruedInterest => _getDEuroFiatAmount(accruedInterest);
104 + String get fiatAccruedInterestFormated => _getDEuroFiatAmount(accruedInterestFormated);
105
106 @observable
107 BigInt approvedTokens = BigInt.zero;
@@ -107,6 +109,9 @@ abstract class DEuroViewModelBase with Store {
109 @computed
110 bool get isEnabled => approvedTokens > BigInt.zero;
111
112 + @computed
113 + bool get isSavingsActionsEnabled => isEnabled && accruedInterest >= MIN_ACCRUED_INTEREST;
114 +
115 @observable
116 bool isLoading = true;
117
@@ -121,17 +126,9 @@ abstract class DEuroViewModelBase with Store {
126
127 @action
128 Future<void> reloadSavingsUserData() async {
124 - final savingsBalanceRaw = ethereum!.getDEuroSavingsBalance(_appStore.wallet!);
125 - final accruedInterestRaw = ethereum!.getDEuroAccruedInterest(_appStore.wallet!);
126 -
129 approvedTokens = await ethereum!.getDEuroSavingsApproved(_appStore.wallet!);
128 -
129 - savingsBalance = ethereum!
130 - .formatterEthereumAmountToDouble(amount: await savingsBalanceRaw)
131 - .toStringAsFixed(6);
132 - accruedInterest = ethereum!
133 - .formatterEthereumAmountToDouble(amount: await accruedInterestRaw)
134 - .toStringAsFixed(6);
130 + savingsBalance = await ethereum!.getDEuroSavingsBalance(_appStore.wallet!);
131 + accruedInterest = await ethereum!.getDEuroAccruedInterest(_appStore.wallet!);
132 isLoading = false;
133 }
134
@@ -139,7 +136,7 @@ abstract class DEuroViewModelBase with Store {
136 Future<void> reloadInterestRate() async {
137 final interestRateRaw = await ethereum!.getDEuroInterestRate(_appStore.wallet!);
138
142 - interestRate = (interestRateRaw / BigInt.from(10000)).toString();
139 + interestRateFormated = (interestRateRaw / BigInt.from(10000)).toString();
140 }
141
142 @action
@@ -175,7 +172,7 @@ abstract class DEuroViewModelBase with Store {
172 }
173 }
174
178 - Future<void> prepareCollectInterest() => prepareSavingsEdit(accruedInterest, false);
175 + Future<void> prepareCollectInterest() => prepareSavingsEdit(accruedInterestFormated, false);
176
177 Future<void> prepareReinvestInterest() async {
178 try {
@@ -230,13 +227,13 @@ abstract class DEuroViewModelBase with Store {
227
228 String _getDEuroFiatAmount(String amount) {
229 try {
233 - CryptoCurrency deuro = CryptoCurrency.deuro;
230 + var dEuro = CryptoCurrency.deuro;
231 final keys = _fiatConversationStore.prices.keys.toList();
232 for (final key in keys) {
236 - if (key.title == "DEURO") deuro = key;
233 + if (key.title == "DEURO") dEuro = key;
234 }
235 return calculateFiatAmount(
239 - price: _fiatConversationStore.prices[deuro]!,
236 + price: _fiatConversationStore.prices[dEuro]!,
237 cryptoAmount: amount,
238 );
239 } catch (_) {