feat: add `ToMoney` extension for double type and refactor currency amount conversions (#3391)

Konstantin Ullrich committed Jul 12, 2026 at 02:55 UTC 77f305af092d4be8383b73eadc469ecc56927294
3 files changed +20 -7
cw_core/lib/amount/money_double.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'dart:math';
2 +import 'package:cw_core/amount/money.dart';
3 +import 'package:cw_core/currency.dart';
4 +
5 +extension ToMoney on double {
6 + /// Turn a double representation of a currency amount to a proper Money representation
7 + /// truncating currencies with more than 20 decimals because double can not handle more
8 + Money? tryToMoney(Currency currency) =>
9 + Money.tryParse(toStringAsFixed(min(currency.decimals, 20)), currency);
10 +
11 + Money toMoney(Currency currency) =>
12 + Money.parse(toStringAsFixed(min(currency.decimals, 20)), currency);
13 +}
cw_solana/lib/solana_client.dart
+4 -4
@@ -3,6 +3,7 @@ import 'dart:convert';
3
4 import 'package:blockchain_utils/blockchain_utils.dart';
5 import 'package:cw_core/amount/money.dart';
6 +import 'package:cw_core/amount/money_double.dart';
7 import 'package:cw_core/crypto_currency.dart';
8 import 'package:cw_core/currency.dart';
9 import 'package:cw_core/node.dart';
@@ -654,7 +655,7 @@ class SolanaWalletClient {
655 from: outgoingFrom,
656 to: outgoingTo,
657 id: outgoingId,
657 - amount: Money.parse(outgoingAmount.toStringAsFixed(outgoingToken.decimals), outgoingToken),
658 + amount: outgoingAmount.toMoney(outgoingToken),
659 programId: outgoingMintAddress == null
660 ? SystemProgramConst.programId.address
661 : SPLTokenProgramConst.tokenProgramId.address,
@@ -672,7 +673,7 @@ class SolanaWalletClient {
673 from: incomingFrom,
674 to: incomingTo,
675 id: incomingId,
675 - amount: Money.parse(incomingAmount.toStringAsFixed(incomingToken.decimals), incomingToken),
676 + amount: incomingAmount.toMoney(incomingToken),
677 programId: incomingMintAddress == null
678 ? SystemProgramConst.programId.address
679 : SPLTokenProgramConst.tokenProgramId.address,
@@ -869,8 +870,7 @@ class SolanaWalletClient {
870 from: sender,
871 to: receiver,
872 id: signature,
872 - amount: Money.parse(amount.toStringAsFixed((splToken ?? CryptoCurrency.sol).decimals),
873 - splToken ?? CryptoCurrency.sol),
873 + amount: amount.toMoney(splToken ?? CryptoCurrency.sol),
874 programId: SPLTokenProgramConst.tokenProgramId.address,
875 blockTimeInInt: blockTime?.toInt() ?? 0,
876 fee: Money.fromInt(fee, CryptoCurrency.sol),
lib/view_model/exchange/exchange_view_model.dart
+3 -3
@@ -45,6 +45,7 @@ import 'package:cake_wallet/store/app_store.dart';
45 import 'package:cake_wallet/utils/exchange_provider_logger.dart';
46 import 'package:cw_core/amount/amount_sanitizer.dart';
47 import 'package:cw_core/amount/money.dart';
48 +import 'package:cw_core/amount/money_double.dart';
49 import "package:cw_core/wallet_info.dart";
50 import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
51 import 'package:cake_wallet/store/dashboard/trades_store.dart';
@@ -804,7 +805,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
805 }
806
807 final amount_ = _enteredAmount / (forcedProvider == null ? bestRate : forcedProviderRate);
807 - _depositAmount = Money.tryParse(amount_.toStringAsFixed(depositCurrency.decimals), depositCurrency);
808 + _depositAmount = amount_.tryToMoney(depositCurrency);
809 }
810
811 @action
@@ -863,8 +864,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
864 }
865
866 final amount_ = _enteredAmount * (forcedProvider == null ? bestRate : forcedProviderRate);
866 - _receiveAmount =
867 - Money.tryParse(amount_.toStringAsFixed(min(20, receiveCurrency.decimals)), receiveCurrency);
867 + _receiveAmount = amount_.tryToMoney(receiveCurrency);
868 }
869
870 bool checkIfInputMeetsMinOrMaxCondition(String input) {