Skip to content

Commit

Permalink
feat: Update recovery phrase verification at initialisation #3190
Browse files Browse the repository at this point in the history
  • Loading branch information
bibash28 committed Dec 16, 2024
1 parent e93152d commit 379e0e8
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,5 @@ enum ResponseString {
RESPONSE_STRING_invalidClientErrorDescription,
RESPONSE_STRING_vpFormatsNotSupportedErrorDescription,
RESPONSE_STRING_invalidPresentationDefinitionUriErrorDescription,
RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage,
}
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,10 @@ extension ResponseStringX on ResponseString {
.RESPONSE_STRING_invalidPresentationDefinitionUriErrorDescription:
return globalMessage
.RESPONSE_STRING_invalidPresentationDefinitionUriErrorDescription;

case ResponseString.RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage:
return globalMessage
.RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage;
}
}
}
15 changes: 1 addition & 14 deletions lib/app/shared/enum/status/mnemonic_status.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@

import 'package:flutter/material.dart';

enum MnemonicStatus {
unselected,
selected,
wrongSelection,
}

extension MnemonicStatusX on MnemonicStatus {
bool get showOrder {
switch (this) {
case MnemonicStatus.unselected:
case MnemonicStatus.wrongSelection:
return false;
case MnemonicStatus.selected:
return true;
}
}

Color color(BuildContext context) {
switch (this) {
case MnemonicStatus.unselected:
return Theme.of(context).colorScheme.secondaryContainer;
case MnemonicStatus.wrongSelection:
return Theme.of(context).colorScheme.error;

case MnemonicStatus.selected:
return Theme.of(context).colorScheme.primary;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/app/shared/message_handler/global_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,7 @@ class GlobalMessage {

String get RESPONSE_STRING_invalidPresentationDefinitionUriErrorDescription =>
l10n.invalidPresentationDefinitionUriErrorDescription;

String get RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage =>
l10n.recoveryPhraseIncorrectErrorMessage;
}
6 changes: 6 additions & 0 deletions lib/app/shared/message_handler/response_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,12 @@ class ResponseMessage with MessageHandler {
.localise(
context,
);

case ResponseString.RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage:
return ResponseString
.RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage.localise(
context,
);
}
}
return '';
Expand Down
8 changes: 3 additions & 5 deletions lib/app/shared/widget/phrase_word.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import 'package:flutter/material.dart';
class PhraseWord extends StatelessWidget {
const PhraseWord({
super.key,
required this.order,
this.order,
required this.word,
this.color,
this.showOrder = true,
this.onTap,
});

final int order;
final int? order;
final String word;
final Color? color;
final bool showOrder;
final void Function()? onTap;

@override
Expand All @@ -40,7 +38,7 @@ class PhraseWord extends StatelessWidget {
height: 25,
child: Center(
child: MyText(
showOrder ? '$order. $word' : word,
order == null ? word : '$order. $word',
textAlign: TextAlign.center,
),
),
Expand Down
3 changes: 2 additions & 1 deletion lib/l10n/arb/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1172,5 +1172,6 @@
},
"reject": "Reject",
"operation": "Operation",
"chooseYourSSIProfileOrCustomizeYourOwn": "Choose your wallet profile or customize your own"
"chooseYourSSIProfileOrCustomizeYourOwn": "Choose your wallet profile or customize your own",
"recoveryPhraseIncorrectErrorMessage": " Please try again with correct order."
}
10 changes: 8 additions & 2 deletions lib/l10n/untranslated.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"ebsiV4DecentralizedId",
"reject",
"operation",
"chooseYourSSIProfileOrCustomizeYourOwn"
"chooseYourSSIProfileOrCustomizeYourOwn",
"recoveryPhraseIncorrectErrorMessage"
],

"es": [
Expand All @@ -16,6 +17,11 @@
"ebsiV4DecentralizedId",
"reject",
"operation",
"chooseYourSSIProfileOrCustomizeYourOwn"
"chooseYourSSIProfileOrCustomizeYourOwn",
"recoveryPhraseIncorrectErrorMessage"
],

"fr": [
"recoveryPhraseIncorrectErrorMessage"
]
}
122 changes: 85 additions & 37 deletions lib/onboarding/verify_phrase/cubit/onboarding_verify_phrase_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,63 +66,111 @@ class OnBoardingVerifyPhraseCubit extends Cubit<OnBoardingVerifyPhraseState> {
emit(state.copyWith(mnemonicStates: oldState, status: AppStatus.idle));
}

List<String> tempMnemonics = [];
List<int> selectionorder = [];

Future<void> verify({
required List<String> mnemonic,
required int index,
}) async {
final mnemonicState = state.mnemonicStates[index];
final int clickCount = tempMnemonics.length;

if (mnemonicState.order <= clickCount) return;

if (mnemonicState.mnemonicStatus != MnemonicStatus.wrongSelection) {
for (final mnemonicState in state.mnemonicStates) {
if (mnemonicState.mnemonicStatus == MnemonicStatus.wrongSelection) {
return;
}
}
}

final updatedList = List<MnemonicState>.from(state.mnemonicStates);
if (mnemonicState.order == clickCount + 1) {
tempMnemonics.add(mnemonic[mnemonicState.order - 1]);
updatedList[index] =
mnemonicState.copyWith(mnemonicStatus: MnemonicStatus.selected);
} else {
if (mnemonicState.mnemonicStatus == MnemonicStatus.unselected) {

switch (mnemonicState.mnemonicStatus) {
case MnemonicStatus.unselected:
// new selection
updatedList[index] = mnemonicState.copyWith(
mnemonicStatus: MnemonicStatus.wrongSelection,
mnemonicStatus: MnemonicStatus.selected,
userSelectedOrder: selectionorder.length + 1,
);
selectionorder.add(mnemonicState.order);
case MnemonicStatus.selected:
// remove selection
final order = mnemonicState.order;
updatedList[index] = mnemonicState.copyWith(
mnemonicStatus: MnemonicStatus.unselected,
userSelectedOrder: null,
);
} else {
updatedList[index] =
mnemonicState.copyWith(mnemonicStatus: MnemonicStatus.unselected);
}
}

emit(state.copyWith(status: AppStatus.idle, mnemonicStates: updatedList));

if (tempMnemonics.length >= 6) {
if (mnemonic[0] == tempMnemonics[0] &&
mnemonic[1] == tempMnemonics[1] &&
mnemonic[2] == tempMnemonics[2] &&
mnemonic[3] == tempMnemonics[3] &&
mnemonic[4] == tempMnemonics[4] &&
mnemonic[5] == tempMnemonics[5]) {
emit(state.copyWith(isVerified: true, status: AppStatus.idle));
} else {
emit(state.copyWith(isVerified: false, status: AppStatus.idle));
}
if (selectionorder.last != order) {
// if first or middle elements are removed then we need to reorder
// the selection

selectionorder.remove(order);

var count = 0;

for (int i = 0; i < updatedList.length; i++) {
if (index == i) continue; // already operated in this index

final element = updatedList[i];
if (selectionorder.contains(element.order)) {
// reorder remaining list
updatedList[i] = updatedList[i].copyWith(
mnemonicStatus: MnemonicStatus.selected,
userSelectedOrder: count + 1,
);
count++;
}
}
} else {
selectionorder.remove(order);
}
}

emit(
state.copyWith(
status: AppStatus.idle,
mnemonicStates: updatedList,
isVerified: selectionorder.length == 12,
),
);
}

Future<void> generateSSIAndCryptoAccount({
required List<String> mnemonic,
required bool isFromOnboarding,
}) async {
emit(state.loading());

try {
if (selectionorder.length == 12) {
var verified = true;
final updatedList = List<MnemonicState>.from(state.mnemonicStates);
for (var i = 0; i < 12; i++) {
if (updatedList[i].order == updatedList[i].userSelectedOrder) {
verified = true;
} else {
verified = false;
break;
}
}

if (!verified) {
selectionorder = [];
for (var i = 0; i < 12; i++) {
updatedList[i] = updatedList[i].copyWith(
mnemonicStatus: MnemonicStatus.unselected,
userSelectedOrder: null,
);
}

emit(
state.copyWith(
status: AppStatus.error,
mnemonicStates: updatedList,
message: StateMessage.error(
showDialog: true,
messageHandler: ResponseMessage(
message: ResponseString
.RESPONSE_STRING_recoveryPhraseIncorrectErrorMessage,
),
),
),
);
return;
}
}
if (isFromOnboarding) {
await generateAccount(
mnemonic: mnemonic,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class OnBoardingVerifyPhraseState extends Equatable {
}) {
return OnBoardingVerifyPhraseState(
status: status,
message: message ?? this.message,
message: message,
isVerified: isVerified ?? this.isVerified,
mnemonicStates: mnemonicStates ?? this.mnemonicStates,
);
Expand All @@ -75,25 +75,33 @@ class MnemonicState extends Equatable {
const MnemonicState({
this.mnemonicStatus = MnemonicStatus.unselected,
required this.order,
this.userSelectedOrder,
});

factory MnemonicState.fromJson(Map<String, dynamic> json) =>
_$MnemonicStateFromJson(json);

final MnemonicStatus mnemonicStatus;
final int order;
final int? userSelectedOrder;

MnemonicState copyWith({
required MnemonicStatus mnemonicStatus,
required int? userSelectedOrder,
}) {
return MnemonicState(
order: order,
mnemonicStatus: mnemonicStatus,
userSelectedOrder: userSelectedOrder,
);
}

Map<String, dynamic> toJson() => _$MnemonicStateToJson(this);

@override
List<Object?> get props => [mnemonicStatus, order];
List<Object?> get props => [
mnemonicStatus,
order,
userSelectedOrder,
];
}
12 changes: 3 additions & 9 deletions lib/onboarding/verify_phrase/view/onboarding_verify_phrase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,9 @@ class _OnBoardingVerifyPhraseViewState
Expanded(
child: PhraseWord(
key: Key(col1Mnemonics.order.toString()),
order: col1Mnemonics.order,
order: col1Mnemonics.userSelectedOrder,
word:
widget.mnemonic[col1Mnemonics.order - 1],
showOrder:
col1Mnemonics.mnemonicStatus.showOrder,
color: col1Mnemonics.mnemonicStatus
.color(context),
onTap: () {
Expand All @@ -208,11 +206,9 @@ class _OnBoardingVerifyPhraseViewState
Expanded(
child: PhraseWord(
key: Key(col2Mnemonics.order.toString()),
order: col2Mnemonics.order,
order: col2Mnemonics.userSelectedOrder,
word:
widget.mnemonic[col2Mnemonics.order - 1],
showOrder:
col2Mnemonics.mnemonicStatus.showOrder,
color: col2Mnemonics.mnemonicStatus
.color(context),
onTap: () {
Expand All @@ -227,11 +223,9 @@ class _OnBoardingVerifyPhraseViewState
Expanded(
child: PhraseWord(
key: Key(col3Mnemonics.order.toString()),
order: col3Mnemonics.order,
order: col3Mnemonics.userSelectedOrder,
word:
widget.mnemonic[col3Mnemonics.order - 1],
showOrder:
col3Mnemonics.mnemonicStatus.showOrder,
color: col3Mnemonics.mnemonicStatus
.color(context),
onTap: () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,12 +583,6 @@ void main() {

await tester.tap(find.byKey(Key(mnemonicState.order.toString())));

await tester.pumpAndSettle();
expect(
onBoardingVerifyPhraseCubit.state.mnemonicStates[index].mnemonicStatus,
MnemonicStatus.wrongSelection,
);

await tester.tap(find.byKey(Key(mnemonicState.order.toString())));

await tester.pumpAndSettle();
Expand Down

0 comments on commit 379e0e8

Please sign in to comment.