feat: show Bitcoin master fingerprint in wallet keys (#3489)
* feat: show Bitcoin master fingerprint in wallet keys Add the BIP-32 master fingerprint (XFP) to the Bitcoin wallet keys shown under Settings > Seed & Keys > Keys, labeled "Master fingerprint". * fix: keep xPub in Keys tab by splitting silent payment keys into a dedicated list The Keys tab / Silent Payments tab split relied on a hardcoded item index (`items.sublist(0, 4)` / `sublist(4)`) that assumed the first four items were always WIF/private key/public key/xPub. Adding the master fingerprint as the first item pushed xPub into the Silent Payments tab. Route Bitcoin silent payment keys into their own `silentPaymentItems` list instead, and render each tab from its list.
Seth For Privacy committed
Aug 7, 2026 at 15:47 UTC
b60b5a59f7389e61554b1ce5ed32f4eb00df6c76
4 files changed
+29
-12
cw_bitcoin/lib/bitcoin_wallet_keys.dart
+15
-4
@@ -1,12 +1,23 @@
1
class BitcoinWalletKeys {
2
- const BitcoinWalletKeys(
3
- {required this.wif, required this.privateKey, required this.publicKey, required this.xpub});
2
+ const BitcoinWalletKeys({
3
+ required this.wif,
4
+ required this.privateKey,
5
+ required this.publicKey,
6
+ required this.xpub,
7
+ this.masterFingerprint = '',
8
+ });
9
10
final String wif;
11
final String privateKey;
12
final String publicKey;
13
final String xpub;
14
+ final String masterFingerprint;
15
10
- Map<String, String> toJson() =>
11
- {'wif': wif, 'privateKey': privateKey, 'publicKey': publicKey, 'xpub': xpub};
16
+ Map<String, String> toJson() => {
17
+ 'wif': wif,
18
+ 'privateKey': privateKey,
19
+ 'publicKey': publicKey,
20
+ 'xpub': xpub,
21
+ 'masterFingerprint': masterFingerprint,
22
+ };
23
}
cw_bitcoin/lib/electrum_wallet.dart
+1
@@ -471,6 +471,7 @@ abstract class ElectrumWalletBase
471
privateKey: privateKey ?? '',
472
publicKey: publicKey ?? '',
473
xpub: xpub,
474
+ masterFingerprint: _masterHD?.fingerPrint.toHex() ?? '',
475
);
476
}
477
lib/src/screens/wallet_keys/wallet_keys_page.dart
+3
-7
@@ -78,7 +78,7 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
78
79
showKeyTab = widget.walletKeysViewModel.items.isNotEmpty;
80
showSilentPaymentsTab =
81
- widget.walletKeysViewModel.isBitcoin && widget.walletKeysViewModel.items.length > 4;
81
+ widget.walletKeysViewModel.isBitcoin && widget.walletKeysViewModel.silentPaymentItems.isNotEmpty;
82
showLegacySeedTab = widget.walletKeysViewModel.legacySeedSplit.isNotEmpty;
83
isLegacySeedOnly = widget.walletKeysViewModel.isLegacySeedOnly;
84
@@ -157,16 +157,12 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
157
if (showKeyTab)
158
Padding(
159
padding: const EdgeInsets.only(left: 22, right: 22),
160
- child: _buildKeysTab(
161
- context,
162
- showSilentPaymentsTab
163
- ? widget.walletKeysViewModel.items.sublist(0, 4)
164
- : widget.walletKeysViewModel.items),
160
+ child: _buildKeysTab(context, widget.walletKeysViewModel.items),
161
),
162
if (showSilentPaymentsTab)
163
Padding(
164
padding: const EdgeInsets.only(left: 22, right: 22),
169
- child: _buildKeysTab(context, widget.walletKeysViewModel.items.sublist(4)),
165
+ child: _buildKeysTab(context, widget.walletKeysViewModel.silentPaymentItems),
166
),
167
if (showLegacySeedTab)
168
Padding(
lib/view_model/wallet_keys_view_model.dart
+10
-1
@@ -30,6 +30,7 @@ abstract class WalletKeysViewModelBase with Store {
30
_restoreHeight = _appStore.wallet!.walletInfo.restoreHeight,
31
_restoreHeightByTransactions = 0,
32
items = ObservableList<StandartListItem>(),
33
+ silentPaymentItems = ObservableList<StandartListItem>(),
34
_title = _getInitialTitle(_appStore.wallet!) {
35
_populateKeysItems();
36
@@ -87,6 +88,7 @@ abstract class WalletKeysViewModelBase with Store {
88
// this is incomplete, needs legacy seed toggle for XMR
89
bool get shouldShowHeightBox => [WalletType.bitcoin, WalletType.zcash].contains(_wallet.type);
90
final ObservableList<StandartListItem> items;
91
+ final ObservableList<StandartListItem> silentPaymentItems;
92
93
@observable
94
String _title;
@@ -150,6 +152,7 @@ abstract class WalletKeysViewModelBase with Store {
152
153
void _populateKeysItems() {
154
items.clear();
155
+ silentPaymentItems.clear();
156
157
Map<String, String>? keys;
158
@@ -217,6 +220,11 @@ abstract class WalletKeysViewModelBase with Store {
220
final electrumKeys = bitcoin!.getWalletKeys(_appStore.wallet!);
221
222
items.addAll([
223
+ if ((electrumKeys['masterFingerprint'] ?? '').isNotEmpty)
224
+ StandartListItem(
225
+ title: "Master fingerprint",
226
+ value: electrumKeys['masterFingerprint']!,
227
+ ),
228
if ((electrumKeys['wif'] ?? '').isNotEmpty)
229
StandartListItem(title: "WIF", value: electrumKeys['wif']!),
230
if ((electrumKeys['privateKey'] ?? '').isNotEmpty)
@@ -233,7 +241,8 @@ abstract class WalletKeysViewModelBase with Store {
241
}
242
243
if (keys != null) {
236
- items.addAll([
244
+ final keysList = _wallet.type == WalletType.bitcoin ? silentPaymentItems : items;
245
+ keysList.addAll([
246
if ((keys['primaryAddress'] ?? '').isNotEmpty)
247
StandartListItem(
248
key: ValueKey('${_walletName}_wallet_primary_address_item_key'),