mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
CW-723-Add-Monero-support-to-the-Shared-Seed-feature-in-Cake (#2131)
* feat: add exodus style bip39 to monero legacy seed * feat: restore monero wallet from bip39 and add test * bug: fix wrong naming in CI * feat: add monero bip39 UI flow * fix: monero.dart generation * fix: skip monero_wallet_service tests till CI is fixed * ci: copy monero_libwallet2_api_c.so to /usr/lib for testing ci: reduce timeout for cw_monero tests * fix: monero wallet creation credentials default to bip39 if mnemonic are set * fix: do not skip monero wallets services test * fix: Include non bip39 monero wallets on Wallet Group * fix: null pointer stemming from missing language selector if seed is selected * fix: Fixes to Bip39 Creation and restore - Do not restore from 0 for fresh bip39 wallet - disallow restoring bip39 wallet without date or height * fix: Fixes to Bip39 restore - Refresh height is now getting set correctly - Add new create monero wallet tests - Add seed-language English for Bip39 Monero wallets - Fix seed-type naming * feat (cw_monero): Store monero wallet after bip39 creation * feat (cw_monero): remove prints from monero_wallet_service_test.dart * fix: exception during seed language autodetect * feat (cw_monero): Add support for passphrases on bip39 seeds * feat (cw_monero): Add support for passphrases on bip39 seeds * fix: seed language selection for recovering bip39 wallets * style: improve readability of isLegacySeedOnly in wallet_keys_view_model.dart * feat: hide monero seed type selector from advanced settings when creating a child wallet * fix(cw_monero): use named arguments for bip39_seed tests --------- Co-authored-by: cyan <cyjan@mrcyjanek.net>
This commit is contained in:
co-authored by
cyan
parent
494207290e
commit
f58a5fb8fd
@@ -1,17 +1,17 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/enumerable_item.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
|
||||
class MoneroSeedType extends EnumerableItem<int> with Serializable<int> {
|
||||
const MoneroSeedType({required String title, required int raw}) : super(title: title, raw: raw);
|
||||
|
||||
static const all = [MoneroSeedType.legacy, MoneroSeedType.polyseed];
|
||||
static const all = [legacy, polyseed, bip39];
|
||||
|
||||
static const defaultSeedType = polyseed;
|
||||
|
||||
static const legacy = MoneroSeedType(raw: 0, title: 'Legacy (25 words)');
|
||||
static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed (16 words)');
|
||||
static const wowneroSeed = MoneroSeedType(raw: 2, title: 'Wownero (14 words)');
|
||||
static const legacy = MoneroSeedType(raw: 0, title: 'Legacy');
|
||||
static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed');
|
||||
static const wowneroSeed = MoneroSeedType(raw: 2, title: 'Wownero');
|
||||
static const bip39 = MoneroSeedType(raw: 3, title: 'BIP39');
|
||||
|
||||
static MoneroSeedType deserialize({required int raw}) {
|
||||
switch (raw) {
|
||||
@@ -21,24 +21,15 @@ class MoneroSeedType extends EnumerableItem<int> with Serializable<int> {
|
||||
return polyseed;
|
||||
case 2:
|
||||
return wowneroSeed;
|
||||
case 3:
|
||||
return bip39;
|
||||
default:
|
||||
throw Exception('Unexpected token: $raw for SeedType deserialize');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (this) {
|
||||
case MoneroSeedType.legacy:
|
||||
return S.current.seedtype_legacy;
|
||||
case MoneroSeedType.polyseed:
|
||||
return S.current.seedtype_polyseed;
|
||||
case MoneroSeedType.wowneroSeed:
|
||||
return S.current.seedtype_wownero;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
String toString() => title;
|
||||
}
|
||||
|
||||
class BitcoinSeedType extends EnumerableItem<int> with Serializable<int> {
|
||||
|
||||
@@ -252,11 +252,21 @@ class CWMonero extends Monero {
|
||||
WalletCredentials createMoneroNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
required bool isPolyseed,
|
||||
required int seedType,
|
||||
required String? passphrase,
|
||||
String? password}) =>
|
||||
String? password,
|
||||
String? mnemonic,
|
||||
}) =>
|
||||
MoneroNewWalletCredentials(
|
||||
name: name, password: password, language: language, isPolyseed: isPolyseed, passphrase: passphrase);
|
||||
name: name,
|
||||
password: password,
|
||||
language: language,
|
||||
seedType: seedType == 1
|
||||
? MoneroSeedType.polyseed
|
||||
: (seedType == 3 ? MoneroSeedType.bip39 : MoneroSeedType.legacy),
|
||||
passphrase: passphrase,
|
||||
mnemonic: mnemonic,
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getKeys(Object wallet) {
|
||||
|
||||
@@ -11,8 +11,8 @@ bool isBIP39Wallet(WalletType walletType) {
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return true;
|
||||
case WalletType.monero:
|
||||
return true;
|
||||
case WalletType.wownero:
|
||||
case WalletType.haven:
|
||||
case WalletType.zano:
|
||||
|
||||
@@ -144,7 +144,9 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
|
||||
),
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.isMoneroSeedTypeOptionsEnabled)
|
||||
if (widget
|
||||
.privacySettingsViewModel.isMoneroSeedTypeOptionsEnabled &&
|
||||
!widget.isChildWallet)
|
||||
Observer(builder: (_) {
|
||||
return SettingsChoicesCell(
|
||||
ChoicesListItem<MoneroSeedType>(
|
||||
|
||||
@@ -305,7 +305,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_walletNewVM.hasLanguageSelector) ...[
|
||||
if (_walletNewVM.showLanguageSelector) ...[
|
||||
if (_walletNewVM.hasSeedType) ...[
|
||||
Observer(
|
||||
builder: (BuildContext build) => Padding(
|
||||
@@ -401,7 +401,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
} else {
|
||||
await _walletNewVM.create(
|
||||
options: _walletNewVM.hasLanguageSelector
|
||||
? [_languageSelectorKey.currentState!.selected, isPolyseed]
|
||||
? [
|
||||
_languageSelectorKey.currentState?.selected ??
|
||||
defaultSeedLanguage,
|
||||
widget._seedSettingsViewModel.moneroSeedType
|
||||
]
|
||||
: null);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -11,13 +11,15 @@ import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
WalletRestoreFromSeedForm({Key? key,
|
||||
WalletRestoreFromSeedForm({
|
||||
Key? key,
|
||||
required this.displayLanguageSelector,
|
||||
required this.displayBlockHeightSelector,
|
||||
required this.type,
|
||||
@@ -47,21 +49,23 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
|
||||
@override
|
||||
WalletRestoreFromSeedFormState createState() =>
|
||||
WalletRestoreFromSeedFormState('English', displayWalletPassword: displayWalletPassword);
|
||||
WalletRestoreFromSeedFormState('English',
|
||||
displayWalletPassword: displayWalletPassword);
|
||||
}
|
||||
|
||||
class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
WalletRestoreFromSeedFormState(this.language, {required bool displayWalletPassword})
|
||||
WalletRestoreFromSeedFormState(this.language,
|
||||
{required bool displayWalletPassword})
|
||||
: seedWidgetStateKey = GlobalKey<SeedWidgetState>(),
|
||||
blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
|
||||
formKey = GlobalKey<FormState>(),
|
||||
languageController = TextEditingController(),
|
||||
nameTextEditingController = TextEditingController(),
|
||||
passwordTextEditingController = displayWalletPassword ? TextEditingController() : null,
|
||||
repeatedPasswordTextEditingController = displayWalletPassword
|
||||
? TextEditingController()
|
||||
: null,
|
||||
seedTypeController = TextEditingController();
|
||||
passwordTextEditingController =
|
||||
displayWalletPassword ? TextEditingController() : null,
|
||||
repeatedPasswordTextEditingController =
|
||||
displayWalletPassword ? TextEditingController() : null,
|
||||
seedTypeController = TextEditingController();
|
||||
|
||||
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
|
||||
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
|
||||
@@ -83,27 +87,30 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
_setLanguageLabel(language);
|
||||
|
||||
if (passwordTextEditingController != null) {
|
||||
passwordListener = () => widget.onPasswordChange?.call(passwordTextEditingController!.text);
|
||||
passwordListener = () =>
|
||||
widget.onPasswordChange?.call(passwordTextEditingController!.text);
|
||||
passwordTextEditingController?.addListener(passwordListener!);
|
||||
}
|
||||
|
||||
if (repeatedPasswordTextEditingController != null) {
|
||||
repeatedPasswordListener =
|
||||
() => widget.onRepeatedPasswordChange?.call(repeatedPasswordTextEditingController!.text);
|
||||
repeatedPasswordTextEditingController?.addListener(repeatedPasswordListener!);
|
||||
repeatedPasswordListener = () => widget.onRepeatedPasswordChange
|
||||
?.call(repeatedPasswordTextEditingController!.text);
|
||||
repeatedPasswordTextEditingController
|
||||
?.addListener(repeatedPasswordListener!);
|
||||
}
|
||||
|
||||
moneroSeedTypeReaction =
|
||||
reaction((_) => widget.seedSettingsViewModel.moneroSeedType, (MoneroSeedType item) {
|
||||
_setSeedType(item);
|
||||
_changeLanguage('English');
|
||||
});
|
||||
reaction((_) => widget.seedSettingsViewModel.moneroSeedType,
|
||||
(MoneroSeedType item) {
|
||||
_setSeedType(item);
|
||||
_changeLanguage('English');
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
void dispose() {
|
||||
moneroSeedTypeReaction();
|
||||
|
||||
if (passwordListener != null) {
|
||||
@@ -118,16 +125,22 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
}
|
||||
|
||||
void onSeedChange(String seed) {
|
||||
if ((widget.type == WalletType.monero || widget.type == WalletType.wownero) &&
|
||||
Polyseed.isValidSeed(seed)) {
|
||||
final lang = PolyseedLang.getByPhrase(seed);
|
||||
if ([WalletType.monero, WalletType.wownero].contains(widget.type) &&
|
||||
(seed.split(" ").length == 12 || Polyseed.isValidSeed(seed))) {
|
||||
try {
|
||||
final lang = PolyseedLang.getByPhrase(seed);
|
||||
|
||||
_changeSeedType(MoneroSeedType.polyseed);
|
||||
_changeLanguage(lang.nameEnglish);
|
||||
if (widget.type == WalletType.monero && seed.split(" ").length == 12) {
|
||||
_changeSeedType(MoneroSeedType.bip39);
|
||||
} else {
|
||||
_changeSeedType(MoneroSeedType.polyseed);
|
||||
}
|
||||
_changeLanguage(lang.nameEnglish, true);
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
}
|
||||
}
|
||||
if (widget.type == WalletType.wownero && seed
|
||||
.split(" ")
|
||||
.length == 14) {
|
||||
if (widget.type == WalletType.wownero && seed.split(" ").length == 14) {
|
||||
_changeSeedType(MoneroSeedType.wowneroSeed);
|
||||
_changeLanguage("English");
|
||||
}
|
||||
@@ -147,9 +160,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
BaseTextFormField(
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_name_textfield_key'),
|
||||
controller: nameTextEditingController,
|
||||
hintText: S
|
||||
.of(context)
|
||||
.wallet_name,
|
||||
hintText: S.of(context).wallet_name,
|
||||
suffixIcon: IconButton(
|
||||
key: ValueKey('wallet_restore_from_seed_wallet_name_refresh_button_key'),
|
||||
onPressed: () async {
|
||||
@@ -158,17 +169,17 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
|
||||
setState(() {
|
||||
nameTextEditingController.text = rName;
|
||||
nameTextEditingController.selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: nameTextEditingController.text.length));
|
||||
nameTextEditingController.selection =
|
||||
TextSelection.fromPosition(TextPosition(
|
||||
offset:
|
||||
nameTextEditingController.text.length));
|
||||
});
|
||||
},
|
||||
icon: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
color: Theme
|
||||
.of(context)
|
||||
.hintColor,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
width: 34,
|
||||
height: 34,
|
||||
@@ -194,14 +205,13 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
seedTextFieldKey: ValueKey('wallet_restore_from_seed_wallet_seeds_textfield_key'),
|
||||
pasteButtonKey: ValueKey('wallet_restore_from_seed_wallet_seeds_paste_button_key'),
|
||||
),
|
||||
if (widget.type == WalletType.monero || widget.type == WalletType.wownero)
|
||||
if ([WalletType.monero, WalletType.wownero].contains(widget.type))
|
||||
GestureDetector(
|
||||
key: ValueKey('wallet_restore_from_seed_seedtype_picker_button_key'),
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
Picker(
|
||||
builder: (_) => Picker(
|
||||
items: _getItems(),
|
||||
selectedAtIndex: isPolyseed
|
||||
? 1
|
||||
@@ -226,33 +236,30 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.displayWalletPassword)
|
||||
...[BaseTextFormField(
|
||||
if (widget.displayWalletPassword) ...[
|
||||
BaseTextFormField(
|
||||
key: ValueKey('password'),
|
||||
controller: passwordTextEditingController,
|
||||
hintText: S
|
||||
.of(context)
|
||||
.password,
|
||||
hintText: S.of(context).password,
|
||||
obscureText: true),
|
||||
BaseTextFormField(
|
||||
key: ValueKey('repeat_wallet_password'),
|
||||
controller: repeatedPasswordTextEditingController,
|
||||
hintText: S
|
||||
.of(context)
|
||||
.repeat_wallet_password,
|
||||
obscureText: true)
|
||||
],
|
||||
BaseTextFormField(
|
||||
key: ValueKey('repeat_wallet_password'),
|
||||
controller: repeatedPasswordTextEditingController,
|
||||
hintText: S.of(context).repeat_wallet_password,
|
||||
obscureText: true)
|
||||
],
|
||||
if (widget.displayLanguageSelector)
|
||||
if (!seedTypeController.value.text.contains("14") && widget.displayLanguageSelector)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
SeedLanguagePicker(
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: language,
|
||||
onItemSelected: _changeLanguage,
|
||||
seedType: isPolyseed ? MoneroSeedType.polyseed : MoneroSeedType.legacy,
|
||||
onItemSelected: (lang) =>
|
||||
_changeLanguage(lang, isPolyseed || isBip39),
|
||||
seedType:
|
||||
widget.seedSettingsViewModel.moneroSeedType,
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
@@ -274,7 +281,8 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
key: blockchainHeightKey,
|
||||
blockHeightTextFieldKey: ValueKey('wallet_restore_from_seed_blockheight_textfield_key'),
|
||||
onHeightOrDateEntered: widget.onHeightOrDateEntered,
|
||||
hasDatePicker: widget.type == WalletType.monero || widget.type == WalletType.wownero,
|
||||
hasDatePicker:
|
||||
[WalletType.monero, WalletType.wownero].contains(widget.type),
|
||||
walletType: widget.type,
|
||||
),
|
||||
]));
|
||||
@@ -282,28 +290,29 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
|
||||
bool get isPolyseed =>
|
||||
widget.seedSettingsViewModel.moneroSeedType == MoneroSeedType.polyseed &&
|
||||
(widget.type == WalletType.monero || widget.type == WalletType.wownero);
|
||||
[WalletType.monero, WalletType.wownero].contains(widget.type);
|
||||
|
||||
Widget get expandIcon =>
|
||||
Container(
|
||||
bool get isBip39 =>
|
||||
widget.seedSettingsViewModel.moneroSeedType == MoneroSeedType.bip39 &&
|
||||
WalletType.monero == widget.type;
|
||||
|
||||
Widget get expandIcon => Container(
|
||||
padding: EdgeInsets.all(18),
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
height: 8,
|
||||
color: Theme
|
||||
.of(context)
|
||||
.hintColor,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
);
|
||||
|
||||
void _changeLanguage(String language) {
|
||||
final setLang = isPolyseed
|
||||
void _changeLanguage(String language, [bool useBip39Wordlist = false]) {
|
||||
final setLang = useBip39Wordlist
|
||||
? "POLYSEED_$language"
|
||||
: seedTypeController.value.text.contains("14")
|
||||
? "WOWSEED_" + language
|
||||
: language;
|
||||
? "WOWSEED_" + language
|
||||
: language;
|
||||
setState(() {
|
||||
this.language = setLang;
|
||||
seedWidgetStateKey.currentState!.changeSeedLanguage(setLang);
|
||||
@@ -312,8 +321,8 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
});
|
||||
}
|
||||
|
||||
void _setLanguageLabel(String language) =>
|
||||
languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)';
|
||||
void _setLanguageLabel(String language) => languageController.text =
|
||||
'${language.replaceAll("POLYSEED_", "")} (Seed language)';
|
||||
|
||||
void _changeSeedType(MoneroSeedType item) {
|
||||
_setSeedType(item);
|
||||
@@ -328,9 +337,17 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
List<MoneroSeedType> _getItems() {
|
||||
switch (widget.type) {
|
||||
case WalletType.monero:
|
||||
return [MoneroSeedType.legacy, MoneroSeedType.polyseed];
|
||||
return [
|
||||
MoneroSeedType.legacy,
|
||||
MoneroSeedType.polyseed,
|
||||
MoneroSeedType.bip39
|
||||
];
|
||||
case WalletType.wownero:
|
||||
return [MoneroSeedType.legacy, MoneroSeedType.polyseed, MoneroSeedType.wowneroSeed];
|
||||
return [
|
||||
MoneroSeedType.legacy,
|
||||
MoneroSeedType.polyseed,
|
||||
MoneroSeedType.wowneroSeed
|
||||
];
|
||||
default:
|
||||
return [MoneroSeedType.legacy];
|
||||
}
|
||||
|
||||
@@ -527,25 +527,42 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
|
||||
}
|
||||
|
||||
bool _isValidSeed() {
|
||||
final seedPhrase =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text;
|
||||
final seedPhrase = walletRestoreFromSeedFormKey
|
||||
.currentState!.seedWidgetStateKey.currentState!.text;
|
||||
if (walletRestoreViewModel.isPolyseed(seedPhrase)) return true;
|
||||
|
||||
final seedWords = seedPhrase.split(' ');
|
||||
|
||||
if (seedWords.length == 14 && walletRestoreViewModel.type == WalletType.wownero) return true;
|
||||
if (seedWords.length == 26 && walletRestoreViewModel.type == WalletType.zano) return true;
|
||||
if (seedWords.length == 14 &&
|
||||
walletRestoreViewModel.type == WalletType.wownero) return true;
|
||||
if (seedWords.length == 26 &&
|
||||
walletRestoreViewModel.type == WalletType.zano) return true;
|
||||
|
||||
if ((walletRestoreViewModel.type == WalletType.monero ||
|
||||
walletRestoreViewModel.type == WalletType.wownero ||
|
||||
walletRestoreViewModel.type == WalletType.haven) &&
|
||||
seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) {
|
||||
return false;
|
||||
if (seedWords.length == 12 &&
|
||||
walletRestoreViewModel.type == WalletType.monero) {
|
||||
return walletRestoreFromSeedFormKey
|
||||
.currentState
|
||||
?.blockchainHeightKey
|
||||
.currentState
|
||||
?.restoreHeightController
|
||||
.text
|
||||
.isNotEmpty == true;
|
||||
}
|
||||
|
||||
if ([WalletType.monero, WalletType.wownero, WalletType.haven]
|
||||
.contains(walletRestoreViewModel.type) &&
|
||||
seedWords.length ==
|
||||
WalletRestoreViewModelBase.moneroSeedMnemonicLength) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// bip39:
|
||||
final validBip39SeedLengths = [12, 18, 24];
|
||||
final nonBip39WalletTypes = [WalletType.monero, WalletType.wownero, WalletType.haven, WalletType.decred];
|
||||
final nonBip39WalletTypes = [
|
||||
WalletType.wownero,
|
||||
WalletType.haven,
|
||||
WalletType.decred
|
||||
];
|
||||
// if it's a bip39 wallet and the length is not valid return false
|
||||
if (!nonBip39WalletTypes.contains(walletRestoreViewModel.type) &&
|
||||
!(validBip39SeedLengths.contains(seedWords.length))) {
|
||||
@@ -558,8 +575,9 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
|
||||
return false;
|
||||
}
|
||||
|
||||
final words =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.words.toSet();
|
||||
final words = walletRestoreFromSeedFormKey
|
||||
.currentState!.seedWidgetStateKey.currentState!.words
|
||||
.toSet();
|
||||
return seedWords.toSet().difference(words).toSet().isEmpty;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class SeedLanguagePickerOption {
|
||||
|
||||
final List<SeedLanguagePickerOption> seedLanguages = [
|
||||
SeedLanguagePickerOption('English', S.current.seed_language_english,
|
||||
Image.asset('assets/images/flags/usa.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
|
||||
Image.asset('assets/images/flags/usa.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed, MoneroSeedType.bip39]),
|
||||
SeedLanguagePickerOption('Chinese (Simplified)', S.current.seed_language_chinese,
|
||||
Image.asset('assets/images/flags/chn.png'), [MoneroSeedType.legacy, MoneroSeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional,
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cake_wallet/wallet_types.g.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -127,12 +128,16 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
|
||||
|
||||
bool isNonSeedWallet = wallet.isNonSeedWallet;
|
||||
|
||||
bool isNotMoneroBip39Wallet = wallet.type == WalletType.monero &&
|
||||
wallet.derivationInfo?.derivationType != DerivationType.bip39;
|
||||
|
||||
// Exclude if any of these conditions are true
|
||||
return isNonBIP39Wallet ||
|
||||
isNanoDerivationType ||
|
||||
isElectrumDerivationType ||
|
||||
isSameTypeAsSelectedWallet ||
|
||||
isNonSeedWallet;
|
||||
isNonSeedWallet ||
|
||||
isNotMoneroBip39Wallet;
|
||||
});
|
||||
|
||||
if (shouldExcludeGroup) continue;
|
||||
|
||||
@@ -63,14 +63,15 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
String get seed => _wallet.seed != null ? _wallet.seed! : '';
|
||||
|
||||
bool get isLegacySeedOnly =>
|
||||
(_wallet.type == WalletType.monero || _wallet.type == WalletType.wownero) &&
|
||||
[WalletType.monero, WalletType.wownero].contains(_wallet.type) &&
|
||||
_wallet.seed != null &&
|
||||
!Polyseed.isValidSeed(_wallet.seed!);
|
||||
!(Polyseed.isValidSeed(_wallet.seed!) ||
|
||||
_wallet.seed!.split(' ').length == 12);
|
||||
|
||||
String get legacySeed {
|
||||
if ((_wallet.type == WalletType.monero || _wallet.type == WalletType.wownero) &&
|
||||
_wallet.seed != null &&
|
||||
Polyseed.isValidSeed(_wallet.seed!)) {
|
||||
(Polyseed.isValidSeed(_wallet.seed!) || _wallet.seed!.split(' ').length == 12)) {
|
||||
final langName = PolyseedLang.getByPhrase(_wallet.seed!).nameEnglish;
|
||||
|
||||
if (_wallet.type == WalletType.monero) {
|
||||
|
||||
@@ -49,6 +49,9 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
bool get hasLanguageSelector =>
|
||||
[WalletType.monero, WalletType.haven, WalletType.wownero].contains(type);
|
||||
|
||||
bool get showLanguageSelector =>
|
||||
newWalletArguments?.mnemonic == null && hasLanguageSelector;
|
||||
|
||||
int get seedPhraseWordsLength {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
@@ -81,7 +84,9 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
}
|
||||
}
|
||||
|
||||
bool get hasSeedType => [WalletType.monero, WalletType.wownero].contains(type);
|
||||
bool get hasSeedType =>
|
||||
newWalletArguments?.mnemonic == null &&
|
||||
[WalletType.monero, WalletType.wownero].contains(type);
|
||||
|
||||
@override
|
||||
WalletCredentials getCredentials(dynamic _options) {
|
||||
@@ -92,11 +97,15 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return monero!.createMoneroNewWalletCredentials(
|
||||
name: name,
|
||||
language: options!.first as String,
|
||||
password: walletPassword,
|
||||
passphrase: passphrase,
|
||||
isPolyseed: options.last as bool);
|
||||
name: name,
|
||||
language: options!.first as String,
|
||||
password: walletPassword,
|
||||
passphrase: passphrase,
|
||||
seedType: newWalletArguments!.mnemonic != null
|
||||
? MoneroSeedType.bip39.raw
|
||||
: (options.last as MoneroSeedType).raw,
|
||||
mnemonic: newWalletArguments!.mnemonic,
|
||||
);
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.createBitcoinNewWalletCredentials(
|
||||
|
||||
Reference in New Issue
Block a user