Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
68e7009
feat: introduce `formatFixed` integration and sats display preference
konstantinullrich Nov 24, 2025
0ec9fa5
Merge branch 'main' into CW1011-Allow-users-to-view-bitcoin-amounts-i…
konstantinullrich Nov 25, 2025
eccd481
feat: enable display of Bitcoin amounts in satoshis and refactor amou…
konstantinullrich Nov 25, 2025
71c74e5
refactor: consolidate fee formatting logic and add support for MWEB a…
konstantinullrich Nov 25, 2025
fab275e
feat: add support for satoshi-based amount display and enhance fiat c…
konstantinullrich Nov 25, 2025
37ae4e4
Merge branch 'main' into CW1011-Allow-users-to-view-bitcoin-amounts-i…
konstantinullrich Nov 26, 2025
ea4cfa0
feat: add support for satoshi-based amount parsing, formatting, and d…
konstantinullrich Nov 26, 2025
10203dc
feat: implement `AmountParsingProxy` with unit tests for parsing and …
konstantinullrich Dec 2, 2025
32e8485
Merge branch 'refs/heads/main' into CW1011-Allow-users-to-view-bitcoi…
konstantinullrich Dec 2, 2025
7b3317a
feat: replace `preferBalanceInSats` with `displayAmountsInSatoshi` an…
konstantinullrich Dec 2, 2025
ef28f93
refactor: streamline amount formatting logic and enhance unspent coin…
konstantinullrich Dec 2, 2025
19107e8
refactor: replace direct bitcoin amount formatting with `AmountParsin…
konstantinullrich Dec 2, 2025
3f43e7e
refactor: replace `getIt<AmountParsingProxy>` with `_appStore.amountP…
konstantinullrich Dec 2, 2025
0dfcee4
refactor: remove redundant `AmountParsingProxy` registration in DI se…
konstantinullrich Dec 2, 2025
6490f40
feat: add getCryptoSymbol to simplify the Symbol selection between Sa…
konstantinullrich Dec 6, 2025
6882e99
Merge branch 'main' into CW1011-Allow-users-to-view-bitcoin-amounts-i…
konstantinullrich Dec 6, 2025
6debdaa
fix: merge conflict
konstantinullrich Dec 6, 2025
a2b4f5d
Revert "fix: merge conflict"
OmarHatem28 Dec 7, 2025
88c2443
fix import [skip ci]
OmarHatem28 Dec 7, 2025
bb445fd
Merge branch 'main' into CW1011-Allow-users-to-view-bitcoin-amounts-i…
konstantinullrich Dec 8, 2025
282647f
feat: remove number formatter from exchangeVM
konstantinullrich Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 7 additions & 30 deletions cw_bitcoin/lib/electrum_balance.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'dart:convert';
import 'package:cw_bitcoin/bitcoin_amount_format.dart';

import 'package:cw_core/balance.dart';

class ElectrumBalance extends Balance {
Expand All @@ -9,17 +9,11 @@ class ElectrumBalance extends Balance {
required this.frozen,
this.secondConfirmed = 0,
this.secondUnconfirmed = 0,
}) : super(
confirmed,
unconfirmed,
secondAvailable: secondConfirmed,
secondAdditional: secondUnconfirmed,
);
}) : super(confirmed, unconfirmed,
secondAvailable: secondConfirmed, secondAdditional: secondUnconfirmed, frozen: frozen);

static ElectrumBalance? fromJSON(String? jsonSource) {
if (jsonSource == null) {
return null;
}
if (jsonSource == null) return null;

final decoded = json.decode(jsonSource) as Map;

Expand All @@ -34,31 +28,14 @@ class ElectrumBalance extends Balance {

int confirmed;
int unconfirmed;
@override
final int frozen;

int secondConfirmed = 0;
int secondUnconfirmed = 0;

@override
String get formattedAvailableBalance => bitcoinAmountToString(amount: ((confirmed + unconfirmed) - frozen) );

@override
String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed);

@override
String get formattedUnAvailableBalance {
final frozenFormatted = bitcoinAmountToString(amount: frozen);
return frozenFormatted == '0.0' ? '' : frozenFormatted;
}

@override
String get formattedSecondAvailableBalance => bitcoinAmountToString(amount: secondConfirmed);

@override
String get formattedSecondAdditionalBalance => bitcoinAmountToString(amount: secondUnconfirmed);

@override
String get formattedFullAvailableBalance =>
bitcoinAmountToString(amount: (confirmed + unconfirmed) + secondConfirmed - frozen);
int get fullAvailableBalance => (confirmed + unconfirmed) + secondConfirmed - frozen;

String toJSON() => json.encode({
'confirmed': confirmed,
Expand Down
4 changes: 2 additions & 2 deletions cw_bitcoin/lib/electrum_transaction_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,11 @@ class ElectrumTransactionInfo extends TransactionInfo {

@override
String amountFormatted() =>
'${formatAmount(bitcoinAmountToString(amount: amount))} ${walletTypeToCryptoCurrency(type).title}';
'${walletTypeToCryptoCurrency(type).formatAmount(BigInt.from(amount))} ${walletTypeToCryptoCurrency(type).title}';

@override
String? feeFormatted() => fee != null
? '${formatAmount(bitcoinAmountToString(amount: fee!))} ${walletTypeToCryptoCurrency(type).title}'
? '${walletTypeToCryptoCurrency(type).formatAmount(BigInt.from(fee!))} ${walletTypeToCryptoCurrency(type).title}'
: '';

@override
Expand Down
23 changes: 15 additions & 8 deletions cw_bitcoin/lib/electrum_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_bitcoin/bitcoin_wallet.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:collection/collection.dart';
import 'package:cw_bitcoin/address_from_output.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_bitcoin/bitcoin_unspent.dart';
import 'package:cw_bitcoin/bitcoin_wallet.dart';
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
import 'package:cw_bitcoin/electrum.dart' as electrum;
import 'package:cw_bitcoin/electrum_balance.dart';
Expand All @@ -27,31 +30,37 @@ import 'package:cw_bitcoin/electrum_transaction_history.dart';
import 'package:cw_bitcoin/electrum_transaction_info.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_bitcoin/exceptions.dart';
import 'package:cw_bitcoin/litecoin_wallet.dart';
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
import 'package:cw_bitcoin/utils.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/encryption_file_utils.dart';
import 'package:cw_core/get_height_by_date.dart';
import 'package:cw_core/hardware/hardware_wallet_service.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/utils/socket_health_logger.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_keys_file.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/output_info.dart';
import 'package:flutter/foundation.dart';
import 'package:hex/hex.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:rxdart/subjects.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sp_scanner/sp_scanner.dart';
import 'package:hex/hex.dart';
import 'package:cw_core/utils/socket_health_logger.dart';

part 'electrum_wallet.g.dart';

Expand All @@ -76,8 +85,8 @@ abstract class ElectrumWalletBase
ElectrumBalance? initialBalance,
CryptoCurrency? currency,
bool? alwaysScan,
}) : accountHD =
getAccountHDWallet(currency, network, seedBytes, xpub, derivationInfo, walletInfo.hardwareWalletType),
}) : accountHD = getAccountHDWallet(
currency, network, seedBytes, xpub, derivationInfo, walletInfo.hardwareWalletType),
syncStatus = NotConnectedSyncStatus(),
_password = password,
_feeRates = <int>[],
Expand Down Expand Up @@ -772,7 +781,6 @@ abstract class ElectrumWalletBase
pubKeyHex = hd.childKey(Bip32KeyIndex(utx.bitcoinAddressRecord.index)).publicKey.toHex();
}


final derivationPath =
"${_hardenedDerivationPath(derivationInfo.derivationPath ?? electrum_path)}"
"/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}"
Expand Down Expand Up @@ -1141,7 +1149,6 @@ abstract class ElectrumWalletBase
bool hasSilentPayment = false,
UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any,
}) async {

final utxoDetailsAll = _createUTXOS(
sendAll: true,
paysToSilentPayment: hasSilentPayment,
Expand Down
14 changes: 7 additions & 7 deletions cw_core/lib/balance.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/// Balance Data class with all amounts in the lowest possible currency (e.g. satoshis or wei)
abstract class Balance {
const Balance(this.available, this.additional, {this.secondAvailable, this.secondAdditional});
const Balance(this.available, this.additional, {this.secondAvailable, this.secondAdditional, this.frozen});

final int available;

final int additional;

final int? secondAvailable;
final int? secondAdditional;

String get formattedAvailableBalance;
String get formattedAdditionalBalance;
final int? frozen;

int get fullAvailableBalance => available;

@deprecated
String get formattedUnAvailableBalance => '';
String get formattedSecondAvailableBalance => '';
String get formattedSecondAdditionalBalance => '';
String get formattedFullAvailableBalance => formattedAvailableBalance;
}
28 changes: 13 additions & 15 deletions cw_core/lib/crypto_currency.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'package:cw_core/currency.dart';
import 'package:cw_core/enumerable_item.dart';
import 'package:collection/collection.dart';
import 'package:cw_core/format_fixed.dart';
import 'package:cw_core/parse_fixed.dart';

import 'format_fixed.dart';

class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implements Currency {
const CryptoCurrency({
String title = '',
Expand Down Expand Up @@ -391,19 +390,18 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
int? decimals,
bool? enabled,
bool? isPotentialScam,
}) {
return CryptoCurrency(
title: title ?? this.title,
raw: raw ?? this.raw,
name: name ?? this.name,
fullName: fullName ?? this.fullName,
iconPath: iconPath ?? this.iconPath,
tag: tag ?? this.tag,
decimals: decimals ?? this.decimals,
enabled: enabled ?? this.enabled,
isPotentialScam: isPotentialScam ?? this.isPotentialScam,
);
}
}) =>
CryptoCurrency(
title: title ?? this.title,
raw: raw ?? this.raw,
name: name ?? this.name,
fullName: fullName ?? this.fullName,
iconPath: iconPath ?? this.iconPath,
tag: tag ?? this.tag,
decimals: decimals ?? this.decimals,
enabled: enabled ?? this.enabled,
isPotentialScam: isPotentialScam ?? this.isPotentialScam,
);

@override
String toString() => title;
Expand Down
14 changes: 2 additions & 12 deletions cw_core/lib/monero_balance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,15 @@ import 'package:cw_core/monero_amount_format.dart';

class MoneroBalance extends Balance {
MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
: formattedUnconfirmedBalance = moneroAmountToString(amount: fullBalance - unlockedBalance),
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance),
formattedFrozenBalance = moneroAmountToString(amount: frozenBalance),
super(unlockedBalance, fullBalance);
: formattedFrozenBalance = moneroAmountToString(amount: frozenBalance),
super(unlockedBalance, fullBalance, frozen: frozenBalance);

final int fullBalance;
final int unlockedBalance;
final int frozenBalance;
final String formattedUnconfirmedBalance;
final String formattedUnlockedBalance;
final String formattedFrozenBalance;

@override
String get formattedUnAvailableBalance =>
formattedFrozenBalance == '0.0' ? '' : formattedFrozenBalance;

@override
String get formattedAvailableBalance => formattedUnlockedBalance;

@override
String get formattedAdditionalBalance => formattedUnconfirmedBalance;
}
17 changes: 3 additions & 14 deletions cw_core/lib/wownero_balance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,15 @@ import 'package:cw_core/wownero_amount_format.dart';

class WowneroBalance extends Balance {
WowneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
: formattedUnconfirmedBalance = wowneroAmountToString(amount: fullBalance - unlockedBalance),
formattedUnlockedBalance = wowneroAmountToString(amount: unlockedBalance),
formattedFrozenBalance =
wowneroAmountToString(amount: frozenBalance),
super(unlockedBalance, fullBalance);
: formattedFrozenBalance = wowneroAmountToString(amount: frozenBalance),
super(unlockedBalance, fullBalance, frozen: frozenBalance);

final int fullBalance;
final int unlockedBalance;
final int frozenBalance;
final String formattedUnconfirmedBalance;
final String formattedUnlockedBalance;
final String formattedFrozenBalance;

@override
String get formattedUnAvailableBalance =>
formattedFrozenBalance == '0.0' ? '' : formattedFrozenBalance;

@override
String get formattedAvailableBalance => formattedUnlockedBalance;

@override
String get formattedAdditionalBalance => formattedUnconfirmedBalance;
}
}
15 changes: 4 additions & 11 deletions cw_evm/lib/evm_chain_transaction_info.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// ignore_for_file: overridden_fields, annotate_overrides

import 'dart:math';

import 'package:cw_core/format_amount.dart';
import 'package:cw_core/format_fixed.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_info.dart';

Expand Down Expand Up @@ -47,10 +45,8 @@ abstract class EVMChainTransactionInfo extends TransactionInfo {
String get feeCurrency;

@override
String amountFormatted() {
final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString());
return '${amount.substring(0, min(10, amount.length))} $tokenSymbol';
}
String amountFormatted() =>
'${formatFixed(ethAmount, exponent, fractionalDigits: 10)} $tokenSymbol';

@override
String fiatAmount() => _fiatAmount ?? '';
Expand All @@ -59,10 +55,7 @@ abstract class EVMChainTransactionInfo extends TransactionInfo {
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);

@override
String feeFormatted() {
final amount = (ethFee / BigInt.from(10).pow(18)).toString();
return '${amount.substring(0, min(18, amount.length))} $feeCurrency';
}
String feeFormatted() => '${formatFixed(ethFee, 18)} $feeCurrency';

Map<String, dynamic> toJson() => {
'id': id,
Expand Down
7 changes: 0 additions & 7 deletions cw_evm/lib/evm_erc20_balance.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'dart:convert';
import 'package:cw_core/format_fixed.dart';

import 'package:cw_core/balance.dart';

Expand All @@ -10,12 +9,6 @@ class EVMChainERC20Balance extends Balance {
final BigInt balance;
final int exponent;

@override
String get formattedAdditionalBalance => formatFixed(balance, exponent, fractionalDigits: 12);

@override
String get formattedAvailableBalance => formatFixed(balance, exponent, fractionalDigits: 12);

String toJSON() => json.encode({
'balanceInWei': balance.toString(),
'exponent': exponent,
Expand Down
19 changes: 8 additions & 11 deletions cw_monero/lib/monero_transaction_info.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/format_amount.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_info.dart';

class MoneroTransactionInfo extends TransactionInfo {
MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date,
this.isPending, this.amount, this.accountIndex, this.addressIndex, this.fee,
this.confirmations) :
id = "${txHash}_${amount}_${accountIndex}_${addressIndex}";
MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date, this.isPending,
this.amount, this.accountIndex, this.addressIndex, this.fee, this.confirmations)
: id = "${txHash}_${amount}_${accountIndex}_${addressIndex}";

final String id;
final String txHash;
Expand All @@ -25,8 +24,7 @@ class MoneroTransactionInfo extends TransactionInfo {
String? _fiatAmount;

@override
String amountFormatted() =>
'${formatAmount(moneroAmountToString(amount: amount))} XMR';
String amountFormatted() => '${CryptoCurrency.xmr.formatAmount(BigInt.from(amount))} XMR';

@override
String fiatAmount() => _fiatAmount ?? '';
Expand All @@ -35,6 +33,5 @@ class MoneroTransactionInfo extends TransactionInfo {
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);

@override
String feeFormatted() =>
'${formatAmount(moneroAmountToString(amount: fee))} XMR';
String feeFormatted() => '${CryptoCurrency.xmr.formatAmount(BigInt.from(fee))} XMR';
}
1 change: 1 addition & 0 deletions cw_monero/lib/monero_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';

import 'package:cw_core/format_fixed.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_priority.dart';
Expand Down
Loading
Loading