feat: show gas conversion rate for dEURO savings (#2351)

* feat: show gas currency on EVM chains * feat: show gas conversion rate for dEURO savings * Update lib/polygon/cw_polygon.dart [skip ci] * Update cw_evm/lib/evm_chain_wallet.dart [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

cyan committed Jul 3, 2025 at 03:09 UTC ae3c4d24f90aa8b5d4adec1e9847110ed20a8e62
10 files changed +96 -9
cw_ethereum/lib/deuro/deuro_savings.dart
+3
@@ -89,6 +89,7 @@ class DEuro {
89 final sendTransaction = () => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction);
90
91 return PendingEVMChainTransaction(
92 + feeCurrency: "ETH",
93 sendTransaction: sendTransaction,
94 signedTransaction: signedTransaction,
95 fee: BigInt.from(fee.estimatedGasFee),
@@ -131,6 +132,7 @@ class DEuro {
132 signedTransaction: signedTransaction,
133 fee: BigInt.from(fee.estimatedGasFee),
134 amount: amount.toString(),
135 + feeCurrency: "ETH",
136 exponent: 18);
137 } catch (e) {
138 if (e.toString().contains('insufficient funds for gas')) {
@@ -156,6 +158,7 @@ class DEuro {
158 _savingsGateway.self.address.hexEip55,
159 CryptoCurrency.deuro,
160 priority,
161 + "ETH"
162 )) as PendingEVMChainTransaction;
163 } catch (e) {
164 if (e.toString().contains('insufficient funds for gas')) {
cw_evm/lib/evm_chain_client.dart
+4
@@ -161,6 +161,7 @@ abstract class EVMChainClient {
161 required int maxFeePerGas,
162 required EVMChainTransactionPriority priority,
163 required CryptoCurrency currency,
164 + required String feeCurrency,
165 required int exponent,
166 String? contractAddress,
167 String? data,
@@ -210,6 +211,7 @@ abstract class EVMChainClient {
211 signedTransaction: prepareSignedTransactionForSending(signedTransaction),
212 amount: amount.toString(),
213 fee: gasFee,
214 + feeCurrency: feeCurrency,
215 sendTransaction: _sendTransaction,
216 exponent: exponent,
217 );
@@ -220,6 +222,7 @@ abstract class EVMChainClient {
222 required String spender,
223 required BigInt amount,
224 required BigInt gasFee,
225 + required String feeCurrency,
226 required int estimatedGasUnits,
227 required int maxFeePerGas,
228 required EVMChainTransactionPriority priority,
@@ -255,6 +258,7 @@ abstract class EVMChainClient {
258 signedTransaction: prepareSignedTransactionForSending(signedTransaction),
259 amount: amount.toString(),
260 fee: gasFee,
261 + feeCurrency: feeCurrency,
262 sendTransaction: () => sendTransaction(signedTransaction),
263 exponent: exponent,
264 isInfiniteApproval: amount.toRadixString(16) == 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
cw_evm/lib/evm_chain_wallet.dart
+7 -1
@@ -515,6 +515,11 @@ abstract class EVMChainWalletBase
515 gasFee: estimatedFeesForTransaction,
516 priority: _credentials.priority!,
517 currency: transactionCurrency,
518 + feeCurrency: switch (_client.chainId) {
519 + 1 => "ETH",
520 + 137 => "POL",
521 + _ => ""
522 + },
523 maxFeePerGas: maxFeePerGasForTransaction,
524 exponent: exponent,
525 contractAddress:
@@ -527,7 +532,7 @@ abstract class EVMChainWalletBase
532 }
533
534 Future<PendingTransaction> createApprovalTransaction(BigInt amount, String spender,
530 - CryptoCurrency token, EVMChainTransactionPriority priority) async {
535 + CryptoCurrency token, EVMChainTransactionPriority priority, String feeCurrency) async {
536 final CryptoCurrency transactionCurrency =
537 balance.keys.firstWhere((element) => element.title == token.title);
538 assert(transactionCurrency is Erc20Token);
@@ -553,6 +558,7 @@ abstract class EVMChainWalletBase
558 priority: priority,
559 gasFee: BigInt.from(gasFeesModel.estimatedGasFee),
560 maxFeePerGas: gasFeesModel.maxFeePerGas,
561 + feeCurrency: feeCurrency,
562 estimatedGasUnits: gasFeesModel.estimatedGasUnits,
563 exponent: transactionCurrency.decimal,
564 contractAddress: transactionCurrency.contractAddress,
cw_evm/lib/pending_evm_chain_transaction.dart
+3 -1
@@ -9,6 +9,7 @@ class PendingEVMChainTransaction with PendingTransaction {
9 final Function sendTransaction;
10 final Uint8List signedTransaction;
11 final BigInt fee;
12 + final String feeCurrency;
13 final String amount;
14 final int exponent;
15 final bool isInfiniteApproval;
@@ -17,6 +18,7 @@ class PendingEVMChainTransaction with PendingTransaction {
18 required this.sendTransaction,
19 required this.signedTransaction,
20 required this.fee,
21 + required this.feeCurrency,
22 required this.amount,
23 required this.exponent,
24 this.isInfiniteApproval = false,
@@ -35,7 +37,7 @@ class PendingEVMChainTransaction with PendingTransaction {
37 @override
38 String get feeFormatted {
39 final _fee = (fee / BigInt.from(pow(10, 18))).toString();
38 - return _fee.substring(0, min(10, _fee.length));
40 + return "${_fee.substring(0, min(10, _fee.length))} $feeCurrency";
41 }
42
43 @override
lib/di.dart
+6 -1
@@ -1518,7 +1518,12 @@ Future<void> setup({
1518
1519 getIt.registerFactory(() => StartTorPage(StartTorViewModel(),));
1520
1521 - getIt.registerFactory(() => DEuroViewModel(getIt<AppStore>()));
1521 + getIt.registerFactory(() => DEuroViewModel(
1522 + getIt<AppStore>(),
1523 + getIt<BalanceViewModel>(),
1524 + getIt<SettingsStore>(),
1525 + getIt<FiatConversionStore>(),
1526 + ));
1527
1528 getIt.registerFactory(() => DEuroSavingsPage(getIt<DEuroViewModel>()));
1529
lib/ethereum/cw_ethereum.dart
+1 -1
@@ -213,7 +213,7 @@ class CWEthereum extends Ethereum {
213 Future<PendingTransaction> createTokenApproval(WalletBase wallet, BigInt amount, String spender,
214 CryptoCurrency token, TransactionPriority priority) =>
215 (wallet as EVMChainWallet).createApprovalTransaction(
216 - amount, spender, token, priority as EVMChainTransactionPriority);
216 + amount, spender, token, priority as EVMChainTransactionPriority, "ETH");
217
218 // Integrations
219 @override
lib/polygon/cw_polygon.dart
+1 -1
@@ -189,7 +189,7 @@ class CWPolygon extends Polygon {
189 Future<PendingTransaction> createTokenApproval(WalletBase wallet,
190 BigInt amount, String spender, CryptoCurrency token, TransactionPriority priority) =>
191 (wallet as EVMChainWallet)
192 - .createApprovalTransaction(amount, spender, token, priority as EVMChainTransactionPriority);
192 + .createApprovalTransaction(amount, spender, token, priority as EVMChainTransactionPriority, "POL");
193
194 @override
195 void setLedgerConnection(
lib/src/screens/integrations/deuro/savings_page.dart
+2 -2
@@ -125,10 +125,10 @@ class DEuroSavingsPage extends BasePage {
125 currency: CryptoCurrency.deuro,
126 amount: S.of(bottomSheetContext).send_amount,
127 amountValue: tx.amountFormatted,
128 - fiatAmountValue: "",
128 + fiatAmountValue: _dEuroViewModel.pendingTransactionFiatAmountFormatted,
129 fee: S.of(bottomSheetContext).send_estimated_fee,
130 feeValue: tx.feeFormatted,
131 - feeFiatAmount: "",
131 + feeFiatAmount: _dEuroViewModel.pendingTransactionFeeFiatAmountFormatted,
132 outputs: [],
133 onSlideComplete: () async {
134 Navigator.of(bottomSheetContext).pop(true);
lib/view_model/integrations/deuro_view_model.dart
+67 -1
@@ -1,8 +1,15 @@
1 import 'package:cake_wallet/core/execution_state.dart';
2 +import 'package:cake_wallet/entities/calculate_fiat_amount.dart';
3 +import 'package:cake_wallet/entities/fiat_currency.dart';
4 import 'package:cake_wallet/ethereum/ethereum.dart';
5 import 'package:cake_wallet/store/app_store.dart';
6 +import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
7 +import 'package:cake_wallet/store/settings_store.dart';
8 +import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
9 import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
10 +import 'package:cw_core/crypto_currency.dart';
11 import 'package:cw_core/pending_transaction.dart';
12 +import 'package:cw_core/utils/print_verbose.dart';
13 import 'package:cw_core/wallet_type.dart';
14 import 'package:cw_core/parse_fixed.dart';
15 import 'package:mobx/mobx.dart';
@@ -14,10 +21,69 @@ class DEuroViewModel = DEuroViewModelBase with _$DEuroViewModel;
21 abstract class DEuroViewModelBase with Store {
22 final AppStore _appStore;
23
17 - DEuroViewModelBase(this._appStore) {
24 + DEuroViewModelBase(this._appStore, this.balanceViewModel, this._settingsStore, this._fiatConversationStore) {
25 reloadInterestRate();
26 reloadSavingsUserData();
27 }
28 + final BalanceViewModel balanceViewModel;
29 + final SettingsStore _settingsStore;
30 + final FiatConversionStore _fiatConversationStore;
31 +
32 + @computed
33 + bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
34 +
35 + @computed
36 + String get pendingTransactionFiatAmountFormatted =>
37 + isFiatDisabled ? '' : pendingTransactionFiatAmount + ' ' + fiat.title;
38 +
39 + @computed
40 + String get pendingTransactionFeeFiatAmountFormatted =>
41 + isFiatDisabled ? '' : pendingTransactionFeeFiatAmount + ' ' + fiat.title;
42 +
43 + FiatCurrency get fiat => _settingsStore.fiatCurrency;
44 +
45 +
46 + @computed
47 + String get pendingTransactionFiatAmount {
48 + if (transaction == null) {
49 + return '0.00';
50 + }
51 +
52 + try {
53 + final keys = _fiatConversationStore.prices.keys.toList();
54 + CryptoCurrency deuro = CryptoCurrency.deuro;
55 + for (var i = 0; i < keys.length; i++) {
56 + if (keys[i].title == "DEURO") {
57 + deuro = keys[i];
58 + }
59 + }
60 + final fiat = calculateFiatAmount(
61 + price: _fiatConversationStore.prices[deuro]!,
62 + cryptoAmount: transaction!.amountFormatted);
63 + return fiat;
64 + } catch (e) {
65 + printV(e);
66 + return '0.02';
67 + }
68 + }
69 +
70 + @computed
71 + String get pendingTransactionFeeFiatAmount {
72 + try {
73 + if (transaction != null) {
74 + final currency = CryptoCurrency.eth;
75 + final fiat = calculateFiatAmount(
76 + price: _fiatConversationStore.prices[currency]!,
77 + cryptoAmount: transaction!.feeFormatted.substring(0, transaction!.feeFormatted.indexOf(" ")),
78 + );
79 + return fiat;
80 + } else {
81 + return '0.00';
82 + }
83 + } catch (_) {
84 + return '0.00';
85 + }
86 + }
87
88 @observable
89 String savingsBalance = '0.00';
lib/view_model/send/send_view_model.dart
+2 -1
@@ -183,7 +183,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
183 final currency = pendingTransactionFeeCurrency(walletType);
184 final fiat = calculateFiatAmount(
185 price: _fiatConversationStore.prices[currency]!,
186 - cryptoAmount: pendingTransaction!.feeFormatted);
186 + cryptoAmount: pendingTransaction!.feeFormatted.substring(0, pendingTransaction!.feeFormatted.indexOf(" ")),
187 + );
188 return fiat;
189 } else {
190 return '0.00';