v6.3.0 Release Candidate (#3414)
What changed, and why it matters
This is a routine version-bump release candidate for Cake Wallet/Monero.com v6.3.0. The visible code changes include several privacy-related tweaks: Bitcoin transaction output ordering is now shuffled instead of fixed, a Tor/onion exchange provider now uses HTTPS instead of HTTP, default Tron and Monero nodes are switched/migrated away from TronGrid and HashVault, and a hardware-wallet passphrase field disables autocorrect. There are also UI fixes for destination tags and QR-code payment notes. The commit message itself mentions 'privacy fixes' but does not describe a specific vulnerability or disclose a security incident.
Treat this as a normal release-candidate review. The privacy fixes are worth highlighting in release notes, but there is no evidence of an exploitable vulnerability requiring an emergency advisory. Verify that the new default nodes (NOWNodes for Tron, Cake node for Monero) are trustworthy and that the HTTPS onion endpoint change does not break Tor-only users. Confirm the output-shuffle change does not interfere with hardware-wallet signing or transaction broadcast. Consider whether the silent-payment refactor needs additional regression tests for stealth-address display.
Security signals we found
Bitcoin output ordering changed from none to shuffle (privacy hardening)
Trocador exchange onion endpoint switched from HTTP to HTTPS (transport/privacy hardening)
Default Tron node migrated from TronGrid to NOWNodes; default Monero node migrated from HashVault to Cake node (trust-model change)
Hardware wallet passphrase input disables autocorrect/suggestions (input privacy hardening)
Silent payment stealth address derivation decoupled from output index (correctness/privacy)
Monero address iteration async bug fixed (forEach-async replaced with for loop)
Commit message mentions 'privacy fixes' without further detail
Evidence from the diff
The diff is a release-candidate merge with mixed functional and hardening changes. Security-relevant signals: (1) cw_bitcoin/lib/electrum_wallet.dart changes outputOrdering from BitcoinOrdering.none to BitcoinOrdering.shuffle in two places, which improves on-chain privacy by reducing deterministic output ordering. (2) lib/exchange/provider/trocador_exchange_provider.dart switches Uri.http to Uri.https for an onion authority, which is a hardening/privacy fix for the exchange provider. (3) lib/entities/default_settings_migration.dart bumps the migration version to 68 and migrates default nodes: Tron from api.trongrid.io to trx.nownodes.io, and Monero from nodes.hashvault.pro:18081 to a Cake-controlled node. (4) monero_hardware_wallet_passphrase_input.dart adds autocorrect: false and enableSuggestions: false to the passphrase field, reducing accidental leakage of the passphrase to keyboard dictionaries. (5) Silent-payment/stealth-address handling is refactored in cw_bitcoin/lib/pending_bitcoin_transaction.dart and lib/bitcoin/cw_bitcoin.dart so stealth addresses are derived from silent payment data rather than relying on output index, which appears to be a correctness/privacy fix. (6) cw_monero/lib/monero_wallet_addresses.dart replaces forEach(... async { ... }) with a for loop, fixing a likely async-iteration bug in address loading. No explicit CVE, advisory, or researcher attribution is present in the commit or supplied references.
Changed components
cw_bitcoin/lib/electrum_wallet.dartcw_bitcoin/lib/pending_bitcoin_transaction.dartcw_bitcoin/lib/bitcoin_wallet_addresses.dartlib/bitcoin/cw_bitcoin.dartlib/exchange/provider/trocador_exchange_provider.dartlib/entities/default_settings_migration.dartcw_monero/lib/monero_wallet_addresses.dartlib/src/screens/connect_device/monero_hardware_wallet_passphrase_input.dartlib/new-ui/pages/send_page.dartlib/new-ui/widgets/swap_page/swap_send_external_modal.dartassets/tron_node_list.ymlInspect captured patch +152 / −66
diff --git a/assets/tron_node_list.yml b/assets/tron_node_list.yml
index 3837ec4..ae30489 100644
--- a/assets/tron_node_list.yml
+++ b/assets/tron_node_list.yml
@@ -1,6 +1,5 @@
-
uri: api.trongrid.io
- isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
label: "TronGrid"
@@ -10,6 +9,7 @@
label: "PublicNode"
-
uri: trx.nownodes.io
+ isDefault: true
useSSL: true
isEnabledForAutoSwitching: true
label: "NOWNodes"
\ No newline at end of file
diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
index 0bc7f8c..c4c41f9 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
@@ -124,7 +124,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
Future<PaymentURI> getPaymentRequestUri(String amount) async {
if (addressPageType is LightningAddressType && lightningWallet != null) {
- final amountSats = amount.isNotEmpty ? parseFixed(amount, 8) : null;
+ final amountSats = amount.isNotEmpty ? tryParseFixed(amount, 8) : null;
final lnUrl = getLnurlOfLightningAddress(address);
if (amountSats == null) {
return LightningPaymentRequest(address: address, lnURL: lnUrl, amount: amount);
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index bc7d45e..3ebbfa4 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -1536,7 +1536,7 @@ abstract class ElectrumWalletBase
network: network,
memo: estimatedTx.memo,
inputOrdering: BitcoinOrdering.shuffle,
- outputOrdering: BitcoinOrdering.none,
+ outputOrdering: BitcoinOrdering.shuffle,
enableRBF: !estimatedTx.spendsUnconfirmedTX,
);
}
@@ -1594,6 +1594,7 @@ abstract class ElectrumWalletBase
isSendAll: estimatedTx.isSendAll,
hasTaprootInputs: hasTaprootInputs,
utxos: estimatedTx.utxos,
+ derivedOutputs: updatedOutputs,
publicKeys: estimatedTx.publicKeys,
isViewOnly: keys.privateKey.isEmpty,
)..addListener((transaction) async {
@@ -2297,7 +2298,7 @@ abstract class ElectrumWalletBase
network: network,
memo: memo,
inputOrdering: BitcoinOrdering.shuffle,
- outputOrdering: BitcoinOrdering.none,
+ outputOrdering: BitcoinOrdering.shuffle,
enableRBF: true,
);
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index 5652342..c92e807 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -31,6 +31,7 @@ class PendingBitcoinTransaction with PendingTransaction {
this.hasTaprootInputs = false,
this.isMweb = false,
this.utxos = const [],
+ this.derivedOutputs = const [],
this.publicKeys,
this.commitOverride,
this.unsignedPsbt,
@@ -47,6 +48,9 @@ class PendingBitcoinTransaction with PendingTransaction {
final bool hasTaprootInputs;
final bool isViewOnly;
List<UtxoWithAddress> utxos;
+
+ final List<BitcoinOutput> derivedOutputs;
+
bool isMweb;
String? changeAddressOverride;
String? idOverride;
@@ -79,6 +83,13 @@ class PendingBitcoinTransaction with PendingTransaction {
bool get hasSilentPayment => _tx.hasSilentPayment;
+ List<String?> get stealthAddresses => derivedOutputs
+ .where((out) => !out.isChange)
+ .map((out) => out.isSilentPayment
+ ? out.address.toAddress(network ?? BitcoinNetwork.mainnet)
+ : null)
+ .toList();
+
PendingChange? get change {
try {
final change = _tx.outputs.firstWhere((out) => out.isChange);
diff --git a/cw_monero/lib/monero_wallet_addresses.dart b/cw_monero/lib/monero_wallet_addresses.dart
index ee211ef..01f711b 100644
--- a/cw_monero/lib/monero_wallet_addresses.dart
+++ b/cw_monero/lib/monero_wallet_addresses.dart
@@ -90,7 +90,7 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
addressesMap.clear();
addressInfos.clear();
- accountList.accounts.forEach((account) async {
+ for (final account in accountList.accounts) {
await _subaddressList.update(accountIndex: account.id);
_subaddressList.subaddresses.forEach((subaddress) {
addressesMap[subaddress.address] = subaddress.label;
@@ -102,7 +102,7 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
address: subaddress.address,
label: subaddress.label));
});
- });
+ }
await saveAddressesInBox();
} catch (e) {
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index d46513d..295e3b9 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -188,8 +188,6 @@ PODS:
- Flutter
- wakelock_plus (0.0.1):
- Flutter
- - warp_api (0.0.1):
- - Flutter
- YttriumWrapper (0.8.35)
DEPENDENCIES:
@@ -236,7 +234,6 @@ DEPENDENCIES:
- universal_ble (from `.symlinks/plugins/universal_ble/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
- - warp_api (from `.symlinks/plugins/warp_api/ios`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
@@ -341,8 +338,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
wakelock_plus:
:path: ".symlinks/plugins/wakelock_plus/ios"
- warp_api:
- :path: ".symlinks/plugins/warp_api/ios"
SPEC CHECKSUMS:
AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
@@ -351,17 +346,17 @@ SPEC CHECKSUMS:
breez_sdk_spark_flutter: ed3b6709b8ce9b40309d8728640eade5b19e8a0d
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90
- cw_decred: 9c0e1df74745b51a1289ec5e91fb9e24b68fa14a
- cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
- device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
- device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
- devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
+ cw_decred: a02cf30175a46971c1e2fa22c48407534541edc6
+ cw_mweb: 3aea2fb35b2bd04d8b2d21b83216f3b8fb768d85
+ device_display_brightness: 04374ebd653619292c1d996f00f42877ea19f17f
+ device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89
+ devicelocale: bd64aa714485a8afdaded0892c1e7d5b7f680cf8
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
dnssec_proof: d461cac7bd3301eb7447f87936745a0c1ae0a67e
fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3
file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517
- Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
@@ -374,32 +369,32 @@ SPEC CHECKSUMS:
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
- image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
+ image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
- local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
+ local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
- package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
+ package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
payjoin_flutter: d9d4c8aa16bd5dfedb9b21d0edc8199e0187d96e
permission_handler_apple: 92d754bbaa7361d436db2d6c3c1c2a0fdcec462e
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
- quick_actions_ios: 4b07fb49d8d8f3518d7565fbb7a91014067a7d82
+ quick_actions_ios: 500fcc11711d9f646739093395c4ae8eec25f779
reown_yttrium: cee334ade64725b1d83f7b34c706a6aae2696d58
rive_common: dd421daaf9ae69f0125aa761dd96abd278399952
rlz: 3f4022361f540a5c26d9d2474fea1d2455b69d8d
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
- sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
- share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
- shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
- sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12
- sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
+ sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b
+ share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
+ shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
+ sp_scanner: b1bc9321690980bdb44bba7ec85d5543e716d1b5
+ sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
- sqlite3_flutter_libs: 86f82662868ee26ff3451f73cac9c5fc2a1f57fa
+ sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
torch_dart: f4620705d10f05492fab047f2fa1c3a600e7d17d
uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152
- universal_ble: 45519b2aeafe62761e2c6309f8927edb5288b914
- url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
+ universal_ble: a322ebabee64f0ec27a313e89a5dd6967f37a60f
+ url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
YttriumWrapper: 31e937fe9fbe0f1314d2ca6be9ce9b379a059966
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index 48dbfda..ae10183 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -687,28 +687,20 @@ class CWBitcoin extends Bitcoin {
}
List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs) {
- if (pendingTransaction is PendingLightningTransaction) return outputs;
-
- final pendingTx = pendingTransaction as PendingBitcoinTransaction;
-
- if (!pendingTx.hasSilentPayment) {
+ if (pendingTransaction is! PendingBitcoinTransaction || !pendingTransaction.hasSilentPayment) {
return outputs;
}
- final updatedOutputs = outputs.map((output) {
- try {
- final pendingOut = pendingTx.outputs[outputs.indexOf(output)];
- final updatedOutput = output;
-
- updatedOutput.stealthAddress = P2trAddress.fromScriptPubkey(script: pendingOut.scriptPubKey)
- .toAddress(BitcoinNetwork.mainnet);
- return updatedOutput;
- } catch (_) {}
-
- return output;
- }).toList();
+ final stealthAddresses = pendingTransaction.stealthAddresses;
+ if (stealthAddresses.length != outputs.length) {
+ printV("well, that shouldn't happen");
+ return outputs;
+ }
- return updatedOutputs;
+ for (var i = 0; i < outputs.length; i++) {
+ outputs[i].stealthAddress = stealthAddresses[i];
+ }
+ return outputs;
}
@override
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 910ea06..ef8a213 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -10,7 +10,6 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/entities/fs_migration.dart';
import 'package:cake_wallet/entities/haven_seed_store.dart';
-import 'package:cake_wallet/entities/node_list.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cake_wallet/monero/monero.dart';
@@ -46,7 +45,7 @@ const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002';
const nanoDefaultNodeUri = 'rpc.nano.to';
const nanoDefaultPowNodeUri = 'rpc.nano.to';
const solanaDefaultNodeUri = 'solana-mainnet.core.chainstack.com';
-const tronDefaultNodeUri = 'api.trongrid.io';
+const tronDefaultNodeUri = 'trx.nownodes.io';
const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002';
const wowneroDefaultNodeUri = 'node3.monerodevs.org:34568';
const zanoDefaultNodeUri = '37.27.100.59:10500';
@@ -607,6 +606,28 @@ Future<void> defaultSettingsMigration(
enabled: true,
);
break;
+ case 68:
+ await _changeDefaultNode(
+ sharedPreferences: sharedPreferences,
+ type: WalletType.tron,
+ newDefaultUri: tronDefaultNodeUri,
+ currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
+ useSSL: true,
+ oldUri: [
+ 'tron-rpc.publicnode.com:443',
+ 'api.trongrid.io',
+ ],
+ );
+ await _changeDefaultNode(
+ sharedPreferences: sharedPreferences,
+ type: WalletType.monero,
+ newDefaultUri: newCakeWalletMoneroUri,
+ currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
+ useSSL: true,
+ trusted: true,
+ oldUri: ['nodes.hashvault.pro:18081'],
+ );
+ break;
default:
break;
}
@@ -663,7 +684,7 @@ Future<void> _changeDefaultNode({
} else {
final currentNode = nodes.firstWhereOrNull((node) => node.id == currentNodeId);
shouldReplace =
- currentNode == null || (oldUri?.any((e) => currentNode!.uriRaw.contains(e)) ?? true);
+ currentNode == null || (oldUri?.any((e) => currentNode.uriRaw.contains(e)) ?? true);
}
if (shouldReplace) {
diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart
index a9d977d..8b027b3 100644
--- a/lib/exchange/provider/trocador_exchange_provider.dart
+++ b/lib/exchange/provider/trocador_exchange_provider.dart
@@ -539,7 +539,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
}
Future<Uri> _getUri(String path, Map<String, String> queryParams) async {
- final uri = Uri.http(onionApiAuthority, path, queryParams);
+ final uri = Uri.https(onionApiAuthority, path, queryParams);
if (useTorOnly) return uri;
diff --git a/lib/main.dart b/lib/main.dart
index b6f9714..f292731 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -315,7 +315,7 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
payjoinSessionSource: payjoinSessionSource,
anonpayInvoiceInfo: anonpayInvoiceInfo,
havenSeedStore: havenSeedStore,
- initialMigrationVersion: 67,
+ initialMigrationVersion: 68,
);
}
diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart
index 3ab8092..721e218 100644
--- a/lib/new-ui/pages/send_page.dart
+++ b/lib/new-ui/pages/send_page.dart
@@ -241,7 +241,9 @@ class _NewSendPageState extends State<NewSendPage> {
widget.initialPaymentRequest!.scheme.toLowerCase()) {
_addressControllers[0].text = widget.initialPaymentRequest!.address;
_amountControllers[0].text = widget.initialPaymentRequest!.amount;
- _memoControllers[0].text = widget.initialPaymentRequest!.note;
+ // _memoControllers[0].text = widget.initialPaymentRequest!.note;
+ _applyNote(widget.initialPaymentRequest!.note, 0);
+
final contractAddress = widget.initialPaymentRequest!.contractAddress;
if (contractAddress != null && contractAddress.isNotEmpty) {
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -1308,7 +1310,9 @@ class _NewSendPageState extends State<NewSendPage> {
);
} catch (e) {}
}
- _memoControllers[_selectedOutput].text = paymentRequest.note;
+ // _memoControllers[_selectedOutput].text = paymentRequest.note;
+
+ _applyNote(paymentRequest.note, _selectedOutput);
}
Future<void> _handleSwapFlow(
@@ -1456,6 +1460,15 @@ class _NewSendPageState extends State<NewSendPage> {
String _wrapAmount(String amount, int maxChars) =>
amount.length <= maxChars ? amount : "${amount.substring(0, maxChars - 3)}...";
+
+ // TODO: make a separate variable for memo in payment request model
+ void _applyNote(String note, int selectedOutput) {
+ if (widget.sendViewModel.hasMemos && note.length <= widget.sendViewModel.maxMemoLength) {
+ widget.sendViewModel.outputs[selectedOutput].memo = note;
+ } else {
+ widget.sendViewModel.outputs[selectedOutput].note = note;
+ }
+ }
}
class SendHelpPage extends StatelessWidget {
diff --git a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart
index 71d3430..f48d96a 100644
--- a/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart
+++ b/lib/new-ui/widgets/swap_page/swap_send_external_modal.dart
@@ -1,4 +1,5 @@
import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/new-ui/widgets/copy_wrapper.dart';
import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart';
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
import 'package:cake_wallet/new-ui/widgets/swap_page/swap_modal_header.dart';
@@ -9,6 +10,7 @@ import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/payment_uris.dart';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
class SwapSendExternalModal extends StatefulWidget {
const SwapSendExternalModal(
@@ -166,10 +168,59 @@ class _SwapSendExternalModalState extends State<SwapSendExternalModal> {
),
)),
if (widget.exchangeTradeViewModel.trade.extraId != null)
- Text(
- "${S.of(context).destination_tag} ${widget.exchangeTradeViewModel.trade.extraId}",
- style: TextStyle(
- fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
+ CopyWrapper(
+ data: ClipboardData(
+ text: widget.exchangeTradeViewModel.trade.extraId!),
+ builder: (context, copied) => Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.surfaceContainer,
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ spacing: 8,
+ children: [
+ Text(
+ S.of(context).destination_tag,
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ color: Theme.of(context).colorScheme.onSurfaceVariant),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 8,
+ children: [
+ Flexible(
+ child: Text(
+ widget.exchangeTradeViewModel.trade.extraId!,
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.w600,
+ color: Theme.of(context).colorScheme.primary),
+ ),
+ ),
+ AnimatedSwitcher(
+ duration: const Duration(milliseconds: 200),
+ child: Icon(
+ copied ? Icons.check : Icons.copy,
+ key: ValueKey(copied),
+ size: 18,
+ color: Theme.of(context).colorScheme.primary,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
),
Row(
spacing: 8,
diff --git a/lib/src/screens/connect_device/monero_hardware_wallet_passphrase_input.dart b/lib/src/screens/connect_device/monero_hardware_wallet_passphrase_input.dart
index 6dd277e..5db5200 100644
--- a/lib/src/screens/connect_device/monero_hardware_wallet_passphrase_input.dart
+++ b/lib/src/screens/connect_device/monero_hardware_wallet_passphrase_input.dart
@@ -34,6 +34,8 @@ class MoneroHardwareWalletPassphraseInputModal extends StatelessWidget {
BaseTextFormField(
controller: controller,
hintText: S.of(context).passphrase_raw,
+ autocorrect: false,
+ enableSuggestions: false,
),
const SizedBox(),
NewPrimaryButton(
diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh
index bac26a1..014e2d4 100644
--- a/scripts/android/app_env.sh
+++ b/scripts/android/app_env.sh
@@ -14,15 +14,15 @@ TYPES=($MONERO_COM $CAKEWALLET)
APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com"
-MONERO_COM_VERSION="6.2.1"
-MONERO_COM_BUILD_NUMBER=4161
+MONERO_COM_VERSION="6.3.0"
+MONERO_COM_BUILD_NUMBER=4162
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="6.2.1"
-CAKEWALLET_BUILD_NUMBER=4413
+CAKEWALLET_VERSION="6.3.0"
+CAKEWALLET_BUILD_NUMBER=4414
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet"
diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh
index a8d022d..4c0650f 100644
--- a/scripts/ios/app_env.sh
+++ b/scripts/ios/app_env.sh
@@ -12,13 +12,13 @@ TYPES=($MONERO_COM $CAKEWALLET)
APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com"
-MONERO_COM_VERSION="6.2.1"
-MONERO_COM_BUILD_NUMBER=167
+MONERO_COM_VERSION="6.3.0"
+MONERO_COM_BUILD_NUMBER=168
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
-CAKEWALLET_VERSION="6.2.1"
-CAKEWALLET_BUILD_NUMBER=423
+CAKEWALLET_VERSION="6.3.0"
+CAKEWALLET_BUILD_NUMBER=424
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
Why this scored 45/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.