v4.25.0 Release Candidate ()

* v4.25.0 Release Candidate

* update rest of platforms version [skip ci]

* replace macos icons [skip ci]

* fix: incorrect balance reporting ()

* fix: monero frozen coins, call updateSendingBalance, display "ALL" balance properly

* fix: decred formatting on send page

---------

Co-authored-by: cyan <cyjan@mrcyjanek.net>
This commit is contained in:
Omar Hatem 2025-04-04 00:49:44 +02:00 committed by GitHub
parent 2b493ff6dc
commit 24ec5fa7fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 99 additions and 79 deletions

Binary file not shown.

Before

(image error) Size: 110 KiB

After

(image error) Size: 206 KiB

Binary file not shown.

Before

(image error) Size: 7.5 KiB

After

(image error) Size: 7 KiB

Binary file not shown.

Before

(image error) Size: 678 B

After

(image error) Size: 1.1 KiB

Binary file not shown.

Before

(image error) Size: 17 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 1.6 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 53 KiB

Binary file not shown.

Before

(image error) Size: 3.4 KiB

After

(image error) Size: 3.1 KiB

View file

@ -1,5 +1,3 @@
Add background sync to Monero
Enhance Backup files
Improve app usability and user experience
User interface enhancements
UI/UX enhancements
Performance improvements
Bug fixes

View file

@ -1,8 +1,4 @@
Add background sync to Monero
Add Decred Wallet
Remove Haven Wallet
Fix and Improve Solana Wallet
Enhance Backup files
Improve app usability and user experience
User interface enhancements
New App Logo
UI/UX enhancements
Performance improvements
Bug fixes

View file

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:cw_core/exceptions.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_decred/amount_format.dart';
import 'package:cw_decred/pending_transaction.dart';
import 'package:cw_decred/transaction_credentials.dart';
import 'package:flutter/foundation.dart';
@ -122,6 +123,9 @@ abstract class DecredWalletBase
return _pubkey;
}
@override
String formatCryptoAmount(String amount) => decredAmountToString(amount: int.parse(amount));
Future<void> init() async {
final getSeed = () async {
if (!watchingOnly) {

View file

@ -4,21 +4,32 @@ import 'package:cw_monero/api/coins_info.dart';
import 'package:monero/monero.dart' as monero;
class MoneroUnspent extends Unspent {
static Future<MoneroUnspent> fromUnspent(String address, String hash, String keyImage, int value, bool isFrozen, bool isUnlocked) async {
return MoneroUnspent(
address: address,
hash: hash,
keyImage: keyImage,
value: value,
isFrozen: isFrozen,
isUnlocked: isUnlocked);
}
MoneroUnspent(
String address, String hash, String keyImage, int value, bool isFrozen, this.isUnlocked)
{required String address,
required String hash,
required String keyImage,
required int value,
required bool isFrozen,
required this.isUnlocked})
: super(address, hash, value, 0, keyImage) {
getCoinByKeyImage(keyImage).then((coinId) {
if (coinId == null) return;
getCoin(coinId).then((coin) {
_frozen = monero.CoinsInfo_frozen(coin);
});
});
_frozen = isFrozen;
}
bool _frozen = false;
@override
set isFrozen(bool freeze) {
_frozen = freeze;
printV("set isFrozen: $freeze ($keyImage): $freeze");
getCoinByKeyImage(keyImage!).then((coinId) async {
if (coinId == null) return;

View file

@ -592,7 +592,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
final coin = await getCoin(i);
final coinSpent = monero.CoinsInfo_spent(coin);
if (coinSpent == false && monero.CoinsInfo_subaddrAccount(coin) == walletAddresses.account!.id) {
final unspent = MoneroUnspent(
final unspent = await MoneroUnspent.fromUnspent(
monero.CoinsInfo_address(coin),
monero.CoinsInfo_hash(coin),
monero.CoinsInfo_keyImage(coin),

View file

@ -45,20 +45,17 @@ class TransactionsPage extends StatelessWidget {
Observer(builder: (_) {
final status = dashboardViewModel.status;
if (status is SyncingSyncStatus) {
return Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
child: DashBoardRoundedCardWidget(
key: ValueKey('transactions_page_syncing_alert_card_key'),
onTap: () {
try {
final uri = Uri.parse(
"https://docs.cakewallet.com/faq/funds-not-appearing");
launchUrl(uri, mode: LaunchMode.externalApplication);
} catch (_) {}
},
title: S.of(context).syncing_wallet_alert_title,
subTitle: S.of(context).syncing_wallet_alert_content,
),
return DashBoardRoundedCardWidget(
key: ValueKey('transactions_page_syncing_alert_card_key'),
onTap: () {
try {
final uri = Uri.parse(
"https://docs.cakewallet.com/faq/funds-not-appearing");
launchUrl(uri, mode: LaunchMode.externalApplication);
} catch (_) {}
},
title: S.of(context).syncing_wallet_alert_title,
subTitle: S.of(context).syncing_wallet_alert_content,
);
} else {
return Container();
@ -72,7 +69,6 @@ class TransactionsPage extends StatelessWidget {
child: Observer(
builder: (_) {
final items = dashboardViewModel.items;
final amount = items.length + 1;
return items.isNotEmpty
? ListView.builder(
key: ValueKey('transactions_page_list_view_builder_key'),

View file

@ -94,6 +94,9 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
sendViewModel.updateSendingBalance();
});
/// if the current wallet doesn't match the one in the qr code
if (initialPaymentRequest != null &&
@ -244,38 +247,47 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
currencyValueValidator: output.sendAll
? sendViewModel.allAmountValidator
: sendViewModel.amountValidator,
allAmountCallback: () async => output.setSendAll(sendViewModel.sendingBalance)),
allAmountCallback: () async => output.setSendAll(await sendViewModel.sendingBalance)),
Divider(
height: 1,
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
Observer(
builder: (_) => Padding(
padding: EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Text(
S.of(context).available_balance + ':',
style: TextStyle(
builder: (_) {
// force rebuild on mobx
final _ = sendViewModel.coinTypeToSpendFrom;
return Padding(
padding: EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Text(
S.of(context).available_balance + ':',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color:
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
),
),
FutureBuilder<String>(
future: sendViewModel.sendingBalance,
builder: (context, snapshot) {
return Text(
snapshot.data ?? sendViewModel.balance, // default to balance while loading
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color:
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
),
),
Text(
sendViewModel.sendingBalance,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color:
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
)
],
),
),
);
},
)
],
),
);
},
),
if (!sendViewModel.isFiatDisabled)
CurrencyAmountTextField(
@ -509,9 +521,9 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
}
});
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) {
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) async {
if (output.sendAll) {
output.setSendAll(sendViewModel.sendingBalance);
output.setSendAll(await sendViewModel.sendingBalance);
}
output.setCryptoAmount(cryptoAmountController.text);

View file

@ -245,7 +245,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
@computed
String get sendingBalance {
Future<String> get sendingBalance async {
// only for electrum, monero, wownero, decred wallets atm:
switch (wallet.type) {
case WalletType.bitcoin:
@ -255,7 +255,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
case WalletType.wownero:
case WalletType.decred:
return wallet.formatCryptoAmount(
unspentCoinsListViewModel.getSendingBalance(coinTypeToSpendFrom).toString());
(await unspentCoinsListViewModel.getSendingBalance(coinTypeToSpendFrom)).toString());
default:
return balance;
}

View file

@ -149,12 +149,15 @@ abstract class UnspentCoinsListViewModelBase with Store {
}
@action
int getSendingBalance(UnspentCoinType overrideCoinTypeToSpendFrom) {
Future<int> getSendingBalance(UnspentCoinType overrideCoinTypeToSpendFrom) async {
// return items.where((element) => element.isSending).fold(0, (previousValue, element) => previousValue + element.value);
// go through all unspent coins and add up the value minus frozen and non sending:
int total = 0;
await _updateUnspents();
Set<String> seen = {};
for (final item in _getSpecificUnspents(overrideCoinTypeToSpendFrom)) {
if (seen.contains(item.hash)) continue;
seen.add(item.hash);
if (item.isFrozen || !item.isSending) continue;
total += item.value;
}

View file

@ -14,15 +14,15 @@ TYPES=($MONERO_COM $CAKEWALLET)
APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.21.0"
MONERO_COM_BUILD_NUMBER=116
MONERO_COM_VERSION="4.25.0"
MONERO_COM_BUILD_NUMBER=118
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="5.0.0"
CAKEWALLET_BUILD_NUMBER=254
CAKEWALLET_VERSION="4.25.0"
CAKEWALLET_BUILD_NUMBER=255
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet"

View file

@ -12,13 +12,13 @@ TYPES=($MONERO_COM $CAKEWALLET)
APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.21.0"
MONERO_COM_BUILD_NUMBER=114
MONERO_COM_VERSION="4.25.0"
MONERO_COM_BUILD_NUMBER=115
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="5.0.0"
CAKEWALLET_BUILD_NUMBER=308
CAKEWALLET_VERSION="4.25.0"
CAKEWALLET_BUILD_NUMBER=309
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"

View file

@ -14,8 +14,8 @@ if [ -n "$1" ]; then
fi
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.14.0"
CAKEWALLET_BUILD_NUMBER=50
CAKEWALLET_VERSION="4.25.0"
CAKEWALLET_BUILD_NUMBER=51
if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then
echo "Wrong app type."

View file

@ -16,13 +16,13 @@ if [ -n "$1" ]; then
fi
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.11.0"
MONERO_COM_BUILD_NUMBER=46
MONERO_COM_VERSION="4.25.0"
MONERO_COM_BUILD_NUMBER=47
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.17.0"
CAKEWALLET_BUILD_NUMBER=108
CAKEWALLET_VERSION="4.25.0"
CAKEWALLET_BUILD_NUMBER=109
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -1,5 +1,5 @@
#define MyAppName "Cake Wallet"
#define MyAppVersion "0.5.0"
#define MyAppVersion "4.25.0"
#define MyAppPublisher "Cake Labs LLC"
#define MyAppURL "https://cakewallet.com/"
#define MyAppExeName "CakeWallet.exe"