v4.25.0 Release Candidate (#2153)
* v4.25.0 Release Candidate * update rest of platforms version [skip ci] * replace macos icons [skip ci] * fix: incorrect balance reporting (#2155) * fix: monero frozen coins, call updateSendingBalance, display "ALL" balance properly * fix: decred formatting on send page --------- Co-authored-by: cyan <cyjan@mrcyjanek.net>
Before ![]() (image error) Size: 110 KiB After ![]() (image error) Size: 206 KiB ![]() ![]() |
Before ![]() (image error) Size: 7.5 KiB After ![]() (image error) Size: 7 KiB ![]() ![]() |
Before ![]() (image error) Size: 678 B After ![]() (image error) Size: 1.1 KiB ![]() ![]() |
Before ![]() (image error) Size: 17 KiB After ![]() (image error) Size: 18 KiB ![]() ![]() |
Before ![]() (image error) Size: 1.5 KiB After ![]() (image error) Size: 1.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 41 KiB After ![]() (image error) Size: 53 KiB ![]() ![]() |
Before ![]() (image error) Size: 3.4 KiB After ![]() (image error) Size: 3.1 KiB ![]() ![]() |
|
@ -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
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|