What changed, and why it matters
This commit removes the Mimblewimble Extension Blocks (MWEB) privacy feature from the Litecoin wallet on desktop platforms (Windows, macOS, Linux). It keeps MWEB available only on Android and iOS. The change is a feature gating / platform restriction, not a fix for an active security vulnerability in the code itself.
Treat as a routine product/platform change. If MWEB support on desktop is being removed due to known bugs or security concerns, request the vendor's internal rationale or a public advisory before classifying as a security patch.
Security signals we found
Feature disabled on desktop platforms only
No cryptographic, networking, or input-handling code changed
No memory safety, injection, or authentication changes
No vendor disclosure of security relevance
Evidence from the diff
The patch renames isLitecoin to hasMWEB in privacy_settings_view_model.dart and gates it with Platform.isIOS || Platform.isAndroid, so the MWEB settings row is hidden on desktop. It also changes shouldShowMwebAd in dashboard_view_model.dart to return Platform.isAndroid || Platform.isIOS, preventing the MWEB opt-in advertisement from appearing on desktop. The rest of the diff is formatting/whitespace cleanup in dashboard_view_model.dart.
Changed components
lib/view_model/settings/privacy_settings_view_model.dartlib/view_model/dashboard/dashboard_view_model.dartlib/src/screens/settings/privacy_page.dartInspect captured patch +48 / −44
diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart
index c1622313..2a8c537e 100644
--- a/lib/src/screens/settings/privacy_page.dart
+++ b/lib/src/screens/settings/privacy_page.dart
@@ -82,7 +82,7 @@ class PrivacyPage extends BasePage {
label: S.of(context).silent_payments,
onTap: () =>
Navigator.of(context).pushNamed(Routes.silentPaymentsSettings)),
- if (_privacySettingsViewModel.isLitecoin)
+ if (_privacySettingsViewModel.hasMWEB)
ListItemRegularRow(
iconPath: "assets/new-ui/settings_row_icons/mweb.svg",
keyValue: "mweb",
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 3dbc0eaf..acc7b9f9 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -191,12 +191,12 @@ abstract class DashboardViewModelBase with Store {
value: () => tradeFilterStore.displaySwapXyz,
caption: ExchangeProviderDescription.swapsXyz.title,
onChanged: () =>
- tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.swapsXyz)),
+ tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.swapsXyz)),
FilterItem(
value: () => tradeFilterStore.displayNearIntents,
caption: ExchangeProviderDescription.nearIntents.title,
- onChanged: () =>
- tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.nearIntents)),
+ onChanged: () => tradeFilterStore
+ .toggleDisplayExchange(ExchangeProviderDescription.nearIntents)),
]
},
subname = '',
@@ -371,7 +371,13 @@ abstract class DashboardViewModelBase with Store {
@computed
bool get isSyncHeavy {
- if ([WalletType.monero, WalletType.wownero, WalletType.decred, WalletType.zcash, WalletType.zano].contains(wallet.type)) {
+ if ([
+ WalletType.monero,
+ WalletType.wownero,
+ WalletType.decred,
+ WalletType.zcash,
+ WalletType.zano
+ ].contains(wallet.type)) {
return true;
}
@@ -391,47 +397,42 @@ abstract class DashboardViewModelBase with Store {
final accountStyleSettings =
await BalanceCardStyleSettings.getAll(wallet.walletInfo.internalId);
- late final int numAccounts;
- if (wallet.type == WalletType.monero) {
- numAccounts = monero!.getAccountList(wallet).accounts.length;
- } else if (wallet.type == WalletType.wownero) {
- numAccounts = wow.wownero!.getAccountList(wallet).accounts.length;
- } else if (wallet.type == WalletType.bitcoin) {
- // bitcoin and lightning
- numAccounts = 2;
- } else {
- numAccounts = 1;
- }
+ late final int numAccounts;
+ if (wallet.type == WalletType.monero) {
+ numAccounts = monero!.getAccountList(wallet).accounts.length;
+ } else if (wallet.type == WalletType.wownero) {
+ numAccounts = wow.wownero!.getAccountList(wallet).accounts.length;
+ } else if (wallet.type == WalletType.bitcoin) {
+ // bitcoin and lightning
+ numAccounts = 2;
+ } else {
+ numAccounts = 1;
+ }
cardDesigns.clear();
- Map<int, int> newOrder = {};
+ Map<int, int> newOrder = {};
for (int i = 0; i < numAccounts; i++) {
late final int index;
- if(balanceViewModel.hasAccounts) {
+ if (balanceViewModel.hasAccounts) {
index = i;
- } else if(wallet.type == WalletType.bitcoin && i == 1) {
+ } else if (wallet.type == WalletType.bitcoin && i == 1) {
index = 0;
} else {
index = -1;
}
-
- final setting = accountStyleSettings
- .where((e) => e.accountIndex == index)
- .firstOrNull;
-
+ final setting = accountStyleSettings.where((e) => e.accountIndex == index).firstOrNull;
late final CryptoCurrency curr;
- if(wallet.type == WalletType.bitcoin && i == 1) {
+ if (wallet.type == WalletType.bitcoin && i == 1) {
curr = CryptoCurrency.btcln;
} else {
curr = wallet.currency;
}
-
cardDesigns.add(CardDesign.fromStyleSettings(setting, curr));
- if(setting?.cardOrder != null) {
- newOrder[setting!.cardOrder] = i;
+ if (setting?.cardOrder != null) {
+ newOrder[setting!.cardOrder] = i;
}
}
@@ -442,12 +443,11 @@ abstract class DashboardViewModelBase with Store {
while (newOrder.containsValue(free)) {
free++;
}
- if(wallet.type == WalletType.bitcoin) {
+ if (wallet.type == WalletType.bitcoin) {
newOrder[free] = 0;
} else {
newOrder[free] = i;
}
-
}
}
cardOrder = newOrder.asObservable();
@@ -490,9 +490,9 @@ abstract class DashboardViewModelBase with Store {
))
.where((item) => !transactions.contains(item));
- transactions.removeWhere((item) =>
- newTransactions.any((tx) => tx.transaction.txHash == item.transaction.txHash && tx.transaction.direction == item.transaction.direction)
- );
+ transactions.removeWhere((item) => newTransactions.any((tx) =>
+ tx.transaction.txHash == item.transaction.txHash &&
+ tx.transaction.direction == item.transaction.direction));
transactions.addAll(newTransactions);
// transactions.clear();
@@ -555,18 +555,18 @@ abstract class DashboardViewModelBase with Store {
@computed
bool get shouldShowMwebAd {
- if(wallet.type != WalletType.litecoin) return false;
+ if (wallet.type != WalletType.litecoin) return false;
- if(mwebEnabled) return false;
+ if (mwebEnabled) return false;
- if(settingsStore.mwebAdDismissed) return false;
+ if (settingsStore.mwebAdDismissed) return false;
- return true;
+ return Platform.isAndroid || Platform.isIOS;
}
@action
void dismissMwebAd(bool enableMweb) {
- if(enableMweb) setMwebEnabled();
+ if (enableMweb) setMwebEnabled();
settingsStore.mwebAdDismissed = true;
}
@@ -600,7 +600,7 @@ abstract class DashboardViewModelBase with Store {
continue;
}
- if(transaction.transaction.confirmations >= transaction.neededConfirmations) {
+ if (transaction.transaction.confirmations >= transaction.neededConfirmations) {
continue;
}
@@ -625,9 +625,10 @@ abstract class DashboardViewModelBase with Store {
bool get showApps => appStore.settingsStore.shouldShowMarketPlaceInDashboard;
@computed
- List<TradeListItem> get trades =>
- tradesStore.trades.where((trade) {
- final isSameChain = trade.trade.chainId != null ? trade.trade.chainId == wallet.chainId : true; // returning default as true here so it falls back to the default checks if there's no chainId
+ List<TradeListItem> get trades => tradesStore.trades.where((trade) {
+ final isSameChain = trade.trade.chainId != null
+ ? trade.trade.chainId == wallet.chainId
+ : true; // returning default as true here so it falls back to the default checks if there's no chainId
return trade.trade.walletId == wallet.id && isSameChain;
}).toList();
@@ -843,7 +844,8 @@ abstract class DashboardViewModelBase with Store {
@action
void toggleSwitchStatusDisplayMode() {
- if (status is SyncingSyncStatus && !((status as SyncingSyncStatus).shouldShowBlocksRemaining())) {
+ if (status is SyncingSyncStatus &&
+ !((status as SyncingSyncStatus).shouldShowBlocksRemaining())) {
if (settingsStore.syncStatusDisplayMode == SyncStatusDisplayMode.eta) {
settingsStore.syncStatusDisplayMode = SyncStatusDisplayMode.blocksRemaining;
} else {
diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart
index d77eb668..54b5b56b 100644
--- a/lib/view_model/settings/privacy_settings_view_model.dart
+++ b/lib/view_model/settings/privacy_settings_view_model.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:cake_wallet/store/settings_store.dart';
@@ -23,7 +25,7 @@ abstract class PrivacySettingsViewModelBase with Store {
bool get isBitcoin => _wallet.type == WalletType.bitcoin;
@computed
- bool get isLitecoin => _wallet.type == WalletType.litecoin;
+ bool get hasMWEB => _wallet.type == WalletType.litecoin && (Platform.isIOS || Platform.isAndroid);
@computed
bool get isAutoGenerateSubaddressesEnabled =>
Why this scored 22/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.