mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
Merge pull request #240 from cake-tech/CW-19
Fixes for validation of monero seed. Add French and Italian seeds val…
This commit is contained in:
commit
a1b4929bd9
8 changed files with 3383 additions and 32 deletions
1630
cw_monero/lib/mnemonics/french.dart
Normal file
1630
cw_monero/lib/mnemonics/french.dart
Normal file
File diff suppressed because it is too large
Load diff
1630
cw_monero/lib/mnemonics/italian.dart
Normal file
1630
cw_monero/lib/mnemonics/italian.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -169,26 +169,30 @@ class CWMonero extends Monero {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getMoneroWordList(String language) {
|
List<String> getMoneroWordList(String language) {
|
||||||
switch (language.toLowerCase()) {
|
switch (language.toLowerCase()) {
|
||||||
case 'english':
|
case 'english':
|
||||||
return EnglishMnemonics.words;
|
return EnglishMnemonics.words;
|
||||||
case 'chinese (simplified)':
|
case 'chinese (simplified)':
|
||||||
return ChineseSimplifiedMnemonics.words;
|
return ChineseSimplifiedMnemonics.words;
|
||||||
case 'dutch':
|
case 'dutch':
|
||||||
return DutchMnemonics.words;
|
return DutchMnemonics.words;
|
||||||
case 'german':
|
case 'german':
|
||||||
return GermanMnemonics.words;
|
return GermanMnemonics.words;
|
||||||
case 'japanese':
|
case 'japanese':
|
||||||
return JapaneseMnemonics.words;
|
return JapaneseMnemonics.words;
|
||||||
case 'portuguese':
|
case 'portuguese':
|
||||||
return PortugueseMnemonics.words;
|
return PortugueseMnemonics.words;
|
||||||
case 'russian':
|
case 'russian':
|
||||||
return RussianMnemonics.words;
|
return RussianMnemonics.words;
|
||||||
case 'spanish':
|
case 'spanish':
|
||||||
return SpanishMnemonics.words;
|
return SpanishMnemonics.words;
|
||||||
default:
|
case 'french':
|
||||||
return EnglishMnemonics.words;
|
return FrenchMnemonics.words;
|
||||||
}
|
case 'italian':
|
||||||
|
return ItalianMnemonics.words;
|
||||||
|
default:
|
||||||
|
return EnglishMnemonics.words;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
|
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
|
||||||
|
|
|
@ -18,7 +18,9 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||||
@required this.displayBlockHeightSelector,
|
@required this.displayBlockHeightSelector,
|
||||||
@required this.type,
|
@required this.type,
|
||||||
this.blockHeightFocusNode,
|
this.blockHeightFocusNode,
|
||||||
this.onHeightOrDateEntered})
|
this.onHeightOrDateEntered,
|
||||||
|
this.onSeedChange,
|
||||||
|
this.onLanguageChange})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
|
@ -26,6 +28,8 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||||
final bool displayBlockHeightSelector;
|
final bool displayBlockHeightSelector;
|
||||||
final FocusNode blockHeightFocusNode;
|
final FocusNode blockHeightFocusNode;
|
||||||
final Function(bool) onHeightOrDateEntered;
|
final Function(bool) onHeightOrDateEntered;
|
||||||
|
final void Function(String) onSeedChange;
|
||||||
|
final void Function(String) onLanguageChange;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletRestoreFromSeedFormState createState() =>
|
WalletRestoreFromSeedFormState createState() =>
|
||||||
|
@ -62,7 +66,10 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||||
validator: WalletNameValidator()),
|
validator: WalletNameValidator()),
|
||||||
Container(height: 20),
|
Container(height: 20),
|
||||||
SeedWidget(
|
SeedWidget(
|
||||||
key: seedWidgetStateKey, language: language, type: widget.type),
|
key: seedWidgetStateKey,
|
||||||
|
language: language,
|
||||||
|
type: widget.type,
|
||||||
|
onSeedChange: widget.onSeedChange),
|
||||||
if (widget.displayLanguageSelector)
|
if (widget.displayLanguageSelector)
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
@ -98,6 +105,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||||
this.language = language;
|
this.language = language;
|
||||||
seedWidgetStateKey.currentState.changeSeedLanguage(language);
|
seedWidgetStateKey.currentState.changeSeedLanguage(language);
|
||||||
_setLanguageLabel(language);
|
_setLanguageLabel(language);
|
||||||
|
widget.onLanguageChange?.call(language);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||||
|
@ -18,6 +19,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/core/validator.dart';
|
import 'package:cake_wallet/core/validator.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
import 'package:cake_wallet/core/seed_validator.dart';
|
||||||
|
|
||||||
class WalletRestorePage extends BasePage {
|
class WalletRestorePage extends BasePage {
|
||||||
WalletRestorePage(this.walletRestoreViewModel)
|
WalletRestorePage(this.walletRestoreViewModel)
|
||||||
|
@ -39,8 +41,44 @@ class WalletRestorePage extends BasePage {
|
||||||
type: walletRestoreViewModel.type,
|
type: walletRestoreViewModel.type,
|
||||||
key: walletRestoreFromSeedFormKey,
|
key: walletRestoreFromSeedFormKey,
|
||||||
blockHeightFocusNode: _blockHeightFocusNode,
|
blockHeightFocusNode: _blockHeightFocusNode,
|
||||||
onHeightOrDateEntered: (value) =>
|
onHeightOrDateEntered: (value) {
|
||||||
walletRestoreViewModel.isButtonEnabled = value));
|
if (_isValidSeed()) {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSeedChange: (String seed) {
|
||||||
|
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||||
|
final hasHeight = walletRestoreFromSeedFormKey
|
||||||
|
.currentState
|
||||||
|
.blockchainHeightKey
|
||||||
|
.currentState
|
||||||
|
.restoreHeightController
|
||||||
|
.text
|
||||||
|
.isNotEmpty;
|
||||||
|
if (hasHeight) {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLanguageChange: (_) {
|
||||||
|
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||||
|
final hasHeight = walletRestoreFromSeedFormKey
|
||||||
|
.currentState
|
||||||
|
.blockchainHeightKey
|
||||||
|
.currentState
|
||||||
|
.restoreHeightController
|
||||||
|
.text
|
||||||
|
.isNotEmpty;
|
||||||
|
|
||||||
|
if (hasHeight) {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||||
|
}
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
case WalletRestoreMode.keys:
|
case WalletRestoreMode.keys:
|
||||||
_pages.add(WalletRestoreFromKeysFrom(
|
_pages.add(WalletRestoreFromKeysFrom(
|
||||||
|
@ -169,6 +207,39 @@ class WalletRestorePage extends BasePage {
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isValidSeed() {
|
||||||
|
final seedWords = walletRestoreFromSeedFormKey
|
||||||
|
.currentState
|
||||||
|
.seedWidgetStateKey
|
||||||
|
.currentState
|
||||||
|
.text
|
||||||
|
.split(' ');
|
||||||
|
|
||||||
|
if (walletRestoreViewModel.type == WalletType.monero &&
|
||||||
|
seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((walletRestoreViewModel.type == WalletType.bitcoin ||
|
||||||
|
walletRestoreViewModel.type == WalletType.litecoin) &&
|
||||||
|
(seedWords.length != WalletRestoreViewModelBase.electrumSeedMnemonicLength &&
|
||||||
|
seedWords.length != WalletRestoreViewModelBase.electrumShortSeedMnemonicLength)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final words = walletRestoreFromSeedFormKey
|
||||||
|
.currentState
|
||||||
|
.seedWidgetStateKey
|
||||||
|
.currentState
|
||||||
|
.words
|
||||||
|
.toSet();
|
||||||
|
return seedWords
|
||||||
|
.toSet()
|
||||||
|
.difference(words)
|
||||||
|
.toSet()
|
||||||
|
.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _credentials() {
|
Map<String, dynamic> _credentials() {
|
||||||
final credentials = <String, dynamic>{};
|
final credentials = <String, dynamic>{};
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,11 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
class SeedWidget extends StatefulWidget {
|
class SeedWidget extends StatefulWidget {
|
||||||
SeedWidget({Key key, this.language, this.type}) : super(key: key);
|
SeedWidget({Key key, this.language, this.type, this.onSeedChange}) : super(key: key);
|
||||||
|
|
||||||
final String language;
|
final String language;
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
|
final void Function(String) onSeedChange;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SeedWidgetState createState() => SeedWidgetState(language, type);
|
SeedWidgetState createState() => SeedWidgetState(language, type);
|
||||||
|
@ -52,6 +53,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_showPlaceholder = true;
|
_showPlaceholder = true;
|
||||||
|
controller.addListener(() => widget.onSeedChange?.call(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeSeedLanguage(String language) {
|
void changeSeedLanguage(String language) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
|
import 'package:cake_wallet/core/mnemonic_length.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -35,18 +36,21 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
_walletCreationService.changeWalletType(type: type);
|
_walletCreationService.changeWalletType(type: type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const moneroSeedMnemonicLength = 25;
|
||||||
|
static const electrumSeedMnemonicLength = 24;
|
||||||
|
static const electrumShortSeedMnemonicLength = 12;
|
||||||
|
|
||||||
|
final List<WalletRestoreMode> availableModes;
|
||||||
|
final bool hasSeedLanguageSelector;
|
||||||
|
final bool hasBlockchainHeightLanguageSelector;
|
||||||
|
final WalletCreationService _walletCreationService;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
WalletRestoreMode mode;
|
WalletRestoreMode mode;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool isButtonEnabled;
|
bool isButtonEnabled;
|
||||||
|
|
||||||
final List<WalletRestoreMode> availableModes;
|
|
||||||
final bool hasSeedLanguageSelector;
|
|
||||||
final bool hasBlockchainHeightLanguageSelector;
|
|
||||||
|
|
||||||
final WalletCreationService _walletCreationService;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletCredentials getCredentials(dynamic options) {
|
WalletCredentials getCredentials(dynamic options) {
|
||||||
final password = generateWalletPassword(type);
|
final password = generateWalletPassword(type);
|
||||||
|
|
|
@ -141,6 +141,8 @@ import 'package:cw_monero/mnemonics/japanese.dart';
|
||||||
import 'package:cw_monero/mnemonics/russian.dart';
|
import 'package:cw_monero/mnemonics/russian.dart';
|
||||||
import 'package:cw_monero/mnemonics/spanish.dart';
|
import 'package:cw_monero/mnemonics/spanish.dart';
|
||||||
import 'package:cw_monero/mnemonics/portuguese.dart';
|
import 'package:cw_monero/mnemonics/portuguese.dart';
|
||||||
|
import 'package:cw_monero/mnemonics/french.dart';
|
||||||
|
import 'package:cw_monero/mnemonics/italian.dart';
|
||||||
""";
|
""";
|
||||||
const moneroCwPart = "part 'cw_monero.dart';";
|
const moneroCwPart = "part 'cw_monero.dart';";
|
||||||
const moneroContent = """
|
const moneroContent = """
|
||||||
|
|
Loading…
Reference in a new issue