Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions lib/models/keys/cryptonote_key_restore_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'dart:convert';

class CryptonoteKeyRestoreData {
static const int currentVersion = 1;

const CryptonoteKeyRestoreData({
required this.address,
required this.privateViewKey,
required this.privateSpendKey,
});

final String address;
final String privateViewKey;
final String privateSpendKey;

factory CryptonoteKeyRestoreData.fromJsonEncodedString(String value) {
final json = jsonDecode(value);
if (json is! Map<String, dynamic>) {
throw const FormatException("Invalid Cryptonote key restore data");
}

final version = json["version"];
if (version != null && version != currentVersion) {
throw const FormatException(
"Unsupported Cryptonote key restore data version",
);
}

final address = json["address"];
final privateViewKey = json["privateViewKey"];
final privateSpendKey = json["privateSpendKey"];
if (address is! String ||
address.isEmpty ||
privateViewKey is! String ||
privateViewKey.isEmpty ||
privateSpendKey is! String ||
privateSpendKey.isEmpty) {
throw const FormatException("Invalid Cryptonote key restore data");
}

return CryptonoteKeyRestoreData(
address: address,
privateViewKey: privateViewKey,
privateSpendKey: privateSpendKey,
);
}

String toJsonEncodedString() => jsonEncode({
"version": currentVersion,
"address": address,
"privateViewKey": privateViewKey,
"privateSpendKey": privateSpendKey,
});

@override
String toString() =>
"CryptonoteKeyRestoreData(address: $address, private keys: <redacted>)";
}
23 changes: 14 additions & 9 deletions lib/models/keys/cw_key_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ import 'key_data_interface.dart';
class CWKeyData with KeyDataInterface {
CWKeyData({
required this.walletId,
required String? privateSpendKey,
required String? privateViewKey,
required String? publicSpendKey,
required String? publicViewKey,
required this.privateSpendKey,
required this.privateViewKey,
required this.publicSpendKey,
required this.publicViewKey,
}) : keys = List.unmodifiable([
(label: "Public View Key", key: publicViewKey),
(label: "Private View Key", key: privateViewKey),
(label: "Public Spend Key", key: publicSpendKey),
(label: "Private Spend Key", key: privateSpendKey),
]);
(label: "Public View Key", key: publicViewKey),
(label: "Private View Key", key: privateViewKey),
(label: "Public Spend Key", key: publicSpendKey),
(label: "Private Spend Key", key: privateSpendKey),
]);

@override
final String walletId;

final String privateSpendKey;
final String privateViewKey;
final String publicSpendKey;
final String publicViewKey;

final List<({String label, String key})> keys;
}
28 changes: 28 additions & 0 deletions lib/models/keys/wallet_backup_recovery_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'cryptonote_key_restore_data.dart';

const cryptonoteKeyRestoreDataBackupKey = "cryptonoteKeyRestoreData";

void writeCryptonoteKeyRestoreDataToBackup(
Map<String, dynamic> walletBackup,
CryptonoteKeyRestoreData data,
) {
walletBackup[cryptonoteKeyRestoreDataBackupKey] = data.toJsonEncodedString();
}

CryptonoteKeyRestoreData? readCryptonoteKeyRestoreDataFromBackup(
Map<String, dynamic> walletBackup,
) {
final encoded = walletBackup[cryptonoteKeyRestoreDataBackupKey];
if (encoded == null) {
return null;
}
if (encoded is! String) {
throw const FormatException("Invalid Cryptonote backup recovery data");
}
if (walletBackup["mnemonic"] != null ||
walletBackup["privateKey"] != null ||
walletBackup["viewOnlyWalletDataKey"] != null) {
throw const FormatException("Conflicting wallet backup recovery data");
}
return CryptonoteKeyRestoreData.fromJsonEncodedString(encoded);
}
60 changes: 60 additions & 0 deletions lib/models/keys/wallet_recovery_material.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'cryptonote_key_restore_data.dart';
import 'key_data_interface.dart';
import 'view_only_wallet_data.dart';

typedef FrostWalletRecoveryData = ({
String myName,
String config,
String keys,
({String config, String keys})? prevGen,
});

sealed class WalletRecoveryMaterial {
const WalletRecoveryMaterial({required this.walletId});

final String walletId;
}

final class MnemonicWalletRecoveryMaterial extends WalletRecoveryMaterial {
MnemonicWalletRecoveryMaterial({
required super.walletId,
required List<String> words,
this.supplementalKeyData,
}) : words = List.unmodifiable(words) {
if (words.isEmpty) {
throw ArgumentError.value(words, "words", "Mnemonic cannot be empty");
}
}

final List<String> words;
final KeyDataInterface? supplementalKeyData;
}

final class PrivateKeyWalletRecoveryMaterial extends WalletRecoveryMaterial {
const PrivateKeyWalletRecoveryMaterial({
required super.walletId,
required this.keyData,
this.cryptonoteKeyRestoreData,
});

final KeyDataInterface keyData;
final CryptonoteKeyRestoreData? cryptonoteKeyRestoreData;
}

final class ViewOnlyWalletRecoveryMaterial extends WalletRecoveryMaterial {
const ViewOnlyWalletRecoveryMaterial({
required super.walletId,
required this.keyData,
});

final ViewOnlyWalletData keyData;
}

final class FrostWalletRecoveryMaterial extends WalletRecoveryMaterial {
const FrostWalletRecoveryMaterial({
required super.walletId,
required this.data,
});

final FrostWalletRecoveryData data;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ import '../../../widgets/desktop/secondary_button.dart';
import '../../../widgets/stack_dialog.dart';

class ConfirmRecoveryDialog extends StatelessWidget {
const ConfirmRecoveryDialog({super.key, required this.onConfirm});

final VoidCallback onConfirm;
const ConfirmRecoveryDialog({super.key});

@override
Widget build(BuildContext context) {
Expand All @@ -32,23 +30,15 @@ class ConfirmRecoveryDialog extends StatelessWidget {
child: Column(
children: [
const DesktopDialogCloseButton(),
const SizedBox(
height: 5,
),
SvgPicture.asset(
Assets.svg.drd,
width: 99,
height: 70,
),
const SizedBox(height: 5),
SvgPicture.asset(Assets.svg.drd, width: 99, height: 70),
const Spacer(),
Text(
"Restore wallet",
style: STextStyles.desktopH2(context),
textAlign: TextAlign.center,
),
const SizedBox(
height: 16,
),
const SizedBox(height: 16),
Text(
"Restoring your wallet may take a while.\nPlease do not exit this screen once the process is started.",
style: STextStyles.desktopTextMedium(context).copyWith(
Expand All @@ -58,11 +48,7 @@ class ConfirmRecoveryDialog extends StatelessWidget {
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
padding: const EdgeInsets.only(left: 32, right: 32, bottom: 32),
child: Row(
children: [
Expanded(
Expand All @@ -73,15 +59,12 @@ class ConfirmRecoveryDialog extends StatelessWidget {
},
),
),
const SizedBox(
width: 16,
),
const SizedBox(width: 16),
Expanded(
child: PrimaryButton(
label: "Restore",
onPressed: () {
Navigator.of(context).pop();
onConfirm.call();
Navigator.of(context).pop(true);
},
),
),
Expand Down Expand Up @@ -109,8 +92,7 @@ class ConfirmRecoveryDialog extends StatelessWidget {
rightButton: PrimaryButton(
label: "Restore",
onPressed: () {
Navigator.of(context).pop();
onConfirm.call();
Navigator.of(context).pop(true);
},
),
),
Expand Down
Loading
Loading