Skip to content

Commit 8b56c52

Browse files
CW-711 passphrase for XMR/WOWcreation (#1992)
* add monero passphrase add wownero passphrase add passphrase to seed screen * obscure passphrase by default disable passphrase create for zano * Update lib/view_model/wallet_keys_view_model.dart [skip ci] * Update lib/src/screens/wallet_keys/wallet_keys_page.dart [skip ci] * Update lib/view_model/advanced_privacy_settings_view_model.dart * dynamic passphrase icon * fix polyseed not being encrypted by passphrase --------- Co-authored-by: Omar Hatem <[email protected]>
1 parent 96921d5 commit 8b56c52

15 files changed

+138
-20
lines changed

cw_monero/lib/api/wallet.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ String getSeed() {
4545
if (cakepolyseed != "") {
4646
if (cakepassphrase != "") {
4747
try {
48-
final lang = PolyseedLang.getByPhrase(cakepassphrase);
48+
final lang = PolyseedLang.getByPhrase(cakepolyseed);
4949
final coin = PolyseedCoin.POLYSEED_MONERO;
5050
final ps = Polyseed.decode(cakepolyseed, lang, coin);
51-
final passphrase = getPassphrase();
52-
if (ps.isEncrypted || passphrase == "") return ps.encode(lang, coin);
53-
ps.crypt(getPassphrase());
51+
if (ps.isEncrypted || cakepassphrase == "") return ps.encode(lang, coin);
52+
ps.crypt(cakepassphrase);
5453
return ps.encode(lang, coin);
5554
} catch (e) {
5655
printV(e);

cw_monero/lib/api/wallet_manager.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void createWalletSync(
7070
{required String path,
7171
required String password,
7272
required String language,
73+
required String passphrase,
7374
int nettype = 0}) {
7475
txhistory = null;
7576
final newWptr = monero.WalletManager_createWallet(wmPtr,
@@ -80,6 +81,7 @@ void createWalletSync(
8081
throw WalletCreationException(message: monero.Wallet_errorString(newWptr));
8182
}
8283
wptr = newWptr;
84+
monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase);
8385
monero.Wallet_store(wptr!, path: path);
8486
openedWalletsByPath[path] = wptr!;
8587
_lastOpenedWallet = path;
@@ -390,8 +392,9 @@ void _createWallet(Map<String, dynamic> args) {
390392
final path = args['path'] as String;
391393
final password = args['password'] as String;
392394
final language = args['language'] as String;
395+
final passphrase = args['passphrase'] as String;
393396

394-
createWalletSync(path: path, password: password, language: language);
397+
createWalletSync(path: path, password: password, language: language, passphrase: passphrase);
395398
}
396399

397400
void _restoreFromSeed(Map<String, dynamic> args) {
@@ -459,11 +462,13 @@ Future<void> createWallet(
459462
{required String path,
460463
required String password,
461464
required String language,
465+
required String passphrase,
462466
int nettype = 0}) async =>
463467
_createWallet({
464468
'path': path,
465469
'password': password,
466470
'language': language,
471+
'passphrase': passphrase,
467472
'nettype': nettype
468473
});
469474

cw_monero/lib/monero_wallet.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
135135
passphrase: monero_wallet.getPassphrase());
136136

137137
int? get restoreHeight =>
138-
transactionHistory.transactions.values.firstOrNull?.height;
138+
transactionHistory.transactions.values.firstOrNull?.height ?? monero.Wallet_getRefreshFromBlockHeight(wptr!);
139139

140140
monero_wallet.SyncListener? _listener;
141141
ReactionDisposer? _onAccountChangeReaction;

cw_monero/lib/monero_wallet_service.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ import 'package:polyseed/polyseed.dart';
2626

2727
class MoneroNewWalletCredentials extends WalletCredentials {
2828
MoneroNewWalletCredentials(
29-
{required String name, required this.language, required this.isPolyseed, String? password})
29+
{required String name, required this.language, required this.isPolyseed, String? password, this.passphrase})
3030
: super(name: name, password: password);
3131

3232
final String language;
3333
final bool isPolyseed;
34+
final String? passphrase;
3435
}
3536

3637
class MoneroRestoreWalletFromHardwareCredentials extends WalletCredentials {
@@ -92,7 +93,7 @@ class MoneroWalletService extends WalletService<
9293
@override
9394
WalletType getType() => WalletType.monero;
9495

95-
@override
96+
@override
9697
Future<MoneroWallet> create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async {
9798
try {
9899
final path = await pathForWallet(name: credentials.name, type: getType());
@@ -112,7 +113,7 @@ class MoneroWalletService extends WalletService<
112113
}
113114

114115
await monero_wallet_manager.createWallet(
115-
path: path, password: credentials.password!, language: credentials.language);
116+
path: path, password: credentials.password!, language: credentials.language, passphrase: credentials.passphrase??"");
116117
final wallet = MoneroWallet(
117118
walletInfo: credentials.walletInfo!,
118119
unspentCoinsInfo: unspentCoinsInfoSource,
@@ -382,6 +383,10 @@ class MoneroWalletService extends WalletService<
382383
restoreHeight: height,
383384
spendKey: spendKey);
384385

386+
387+
monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
388+
monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase??'');
389+
385390
final wallet = MoneroWallet(
386391
walletInfo: walletInfo,
387392
unspentCoinsInfo: unspentCoinsInfoSource,

cw_wownero/lib/api/wallet.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ String getSeed() {
4444
if (cakepolyseed != "") {
4545
if (cakepassphrase != "") {
4646
try {
47-
final lang = PolyseedLang.getByPhrase(cakepassphrase);
47+
final lang = PolyseedLang.getByPhrase(cakepolyseed);
4848
final coin = PolyseedCoin.POLYSEED_WOWNERO;
4949
final ps = Polyseed.decode(cakepolyseed, lang, coin);
5050
final passphrase = getPassphrase();

cw_wownero/lib/api/wallet_manager.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ void createWalletSync(
6666
{required String path,
6767
required String password,
6868
required String language,
69+
required String passphrase,
6970
int nettype = 0}) {
7071
txhistory = null;
7172
final newWptr = wownero.WalletManager_createWallet(wmPtr,
@@ -76,6 +77,8 @@ void createWalletSync(
7677
throw WalletCreationException(message: wownero.Wallet_errorString(newWptr));
7778
}
7879
wptr = newWptr;
80+
wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase);
81+
7982
wownero.Wallet_store(wptr!, path: path);
8083
openedWalletsByPath[path] = wptr!;
8184

@@ -362,8 +365,9 @@ void _createWallet(Map<String, dynamic> args) {
362365
final path = args['path'] as String;
363366
final password = args['password'] as String;
364367
final language = args['language'] as String;
368+
final passphrase = args['passphrase'] as String;
365369

366-
createWalletSync(path: path, password: password, language: language);
370+
createWalletSync(path: path, password: password, language: language, passphrase: passphrase);
367371
}
368372

369373
void _restoreFromSeed(Map<String, dynamic> args) {
@@ -431,11 +435,13 @@ Future<void> createWallet(
431435
{required String path,
432436
required String password,
433437
required String language,
438+
required String passphrase,
434439
int nettype = 0}) async =>
435440
_createWallet({
436441
'path': path,
437442
'password': password,
438443
'language': language,
444+
'passphrase': passphrase,
439445
'nettype': nettype
440446
});
441447

cw_wownero/lib/wownero_wallet.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'package:cw_core/wallet_base.dart';
2020
import 'package:cw_core/wallet_info.dart';
2121
import 'package:cw_core/wownero_amount_format.dart';
2222
import 'package:cw_core/wownero_balance.dart';
23+
import 'package:cw_wownero/api/account_list.dart';
2324
import 'package:cw_wownero/api/coins_info.dart';
2425
import 'package:cw_wownero/api/structs/pending_transaction.dart';
2526
import 'package:cw_wownero/api/transaction_history.dart' as transaction_history;
@@ -131,6 +132,10 @@ abstract class WowneroWalletBase
131132
publicViewKey: wownero_wallet.getPublicViewKey(),
132133
passphrase: wownero_wallet.getPassphrase());
133134

135+
int? get restoreHeight =>
136+
transactionHistory.transactions.values.firstOrNull?.height ?? wownero.Wallet_getRefreshFromBlockHeight(wptr!);
137+
138+
134139
wownero_wallet.SyncListener? _listener;
135140
ReactionDisposer? _onAccountChangeReaction;
136141
ReactionDisposer? _onTxHistoryChangeReaction;

cw_wownero/lib/wownero_wallet_service.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:cw_core/wallet_info.dart';
1010
import 'package:cw_core/wallet_service.dart';
1111
import 'package:cw_core/wallet_type.dart';
1212
import 'package:cw_core/get_height_by_date.dart';
13+
import 'package:cw_wownero/api/account_list.dart';
1314
import 'package:cw_wownero/api/exceptions/wallet_opening_exception.dart';
1415
import 'package:cw_wownero/api/wallet_manager.dart' as wownero_wallet_manager;
1516
import 'package:cw_wownero/api/wallet_manager.dart';
@@ -21,11 +22,12 @@ import 'package:monero/wownero.dart' as wownero;
2122

2223
class WowneroNewWalletCredentials extends WalletCredentials {
2324
WowneroNewWalletCredentials(
24-
{required String name, required this.language, required this.isPolyseed, String? password})
25+
{required String name, required this.language, required this.isPolyseed, this.passphrase, String? password})
2526
: super(name: name, password: password);
2627

2728
final String language;
2829
final bool isPolyseed;
30+
final String? passphrase;
2931
}
3032

3133
class WowneroRestoreWalletFromSeedCredentials extends WalletCredentials {
@@ -95,7 +97,7 @@ class WowneroWalletService extends WalletService<
9597
}
9698

9799
await wownero_wallet_manager.createWallet(
98-
path: path, password: credentials.password!, language: credentials.language);
100+
path: path, password: credentials.password!, language: credentials.language, passphrase: credentials.passphrase??'');
99101
final wallet = WowneroWallet(
100102
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
101103
await wallet.init();
@@ -345,6 +347,9 @@ class WowneroWalletService extends WalletService<
345347
restoreHeight: height,
346348
spendKey: spendKey);
347349

350+
wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
351+
wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase??'');
352+
348353
final wallet = WowneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, password: password);
349354
await wallet.init();
350355

lib/monero/cw_monero.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,10 @@ class CWMonero extends Monero {
253253
required String name,
254254
required String language,
255255
required bool isPolyseed,
256+
required String? passphrase,
256257
String? password}) =>
257258
MoneroNewWalletCredentials(
258-
name: name, password: password, language: language, isPolyseed: isPolyseed);
259+
name: name, password: password, language: language, isPolyseed: isPolyseed, passphrase: passphrase);
259260

260261
@override
261262
Map<String, String> getKeys(Object wallet) {

lib/src/screens/wallet_keys/wallet_keys_page.dart

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:math';
2+
13
import 'package:cake_wallet/entities/qr_view_data.dart';
24
import 'package:cake_wallet/generated/i18n.dart';
35
import 'package:cake_wallet/routes.dart';
@@ -15,6 +17,8 @@ import 'package:cake_wallet/utils/show_bar.dart';
1517
import 'package:cake_wallet/view_model/wallet_keys_view_model.dart';
1618
import 'package:flutter/material.dart';
1719
import 'package:flutter/services.dart';
20+
import 'package:flutter_mobx/flutter_mobx.dart';
21+
import 'package:mobx/mobx.dart';
1822
import 'package:qr_flutter/qr_flutter.dart';
1923

2024
class WalletKeysPage extends BasePage {
@@ -162,6 +166,8 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
162166
children: [
163167
if (isLegacySeedOnly || isLegacySeed) _buildHeightBox(),
164168
const SizedBox(height: 20),
169+
(_buildPassphraseBox() ?? Container()),
170+
if (widget.walletKeysViewModel.passphrase.isNotEmpty) const SizedBox(height: 20),
165171
Expanded(
166172
child: SeedPhraseGridWidget(
167173
list: isLegacySeed
@@ -262,6 +268,64 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
262268
),
263269
);
264270
}
271+
272+
273+
Widget? _buildPassphraseBox() {
274+
if (widget.walletKeysViewModel.passphrase.isEmpty) return null;
275+
return Container(
276+
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 14),
277+
decoration: BoxDecoration(
278+
borderRadius: BorderRadius.circular(8),
279+
color: Theme.of(context).cardColor,
280+
),
281+
child: Row(
282+
mainAxisAlignment: MainAxisAlignment.center,
283+
children: [
284+
Text(
285+
S.of(context).passphrase_view_keys,
286+
textAlign: TextAlign.center,
287+
style: TextStyle(
288+
fontSize: 14,
289+
fontWeight: FontWeight.w500,
290+
color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor.withOpacity(0.5),
291+
),
292+
),
293+
const SizedBox(width: 6),
294+
Expanded(
295+
child: Row(
296+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
297+
children: [
298+
Observer(builder: (BuildContext context) {
299+
return Text(
300+
(widget.walletKeysViewModel.obscurePassphrase) ?
301+
"*****" :
302+
widget.walletKeysViewModel.passphrase,
303+
style: TextStyle(
304+
fontSize: 14,
305+
fontWeight: FontWeight.w500,
306+
color: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
307+
),
308+
);
309+
}),
310+
Observer(builder: (BuildContext context) {
311+
return GestureDetector(
312+
onTap: () {
313+
widget.walletKeysViewModel.obscurePassphrase = !widget.walletKeysViewModel.obscurePassphrase;
314+
},
315+
child: Icon(
316+
widget.walletKeysViewModel.obscurePassphrase ? Icons.visibility_off : Icons.visibility,
317+
size: 16,
318+
color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.7),
319+
)
320+
);
321+
}),
322+
],
323+
),
324+
),
325+
],
326+
),
327+
);
328+
}
265329

266330

267331
Widget _buildBottomActionPanel({

0 commit comments

Comments
 (0)