dev
dart 110 lines 3.65 KB
Raw
1 import "dart:convert";
2 import "dart:io";
3
4 import "package:cw_core/pathForWallet.dart";
5 import "package:cw_core/spl_token.dart";
6 import "package:cw_core/tron_token.dart";
7 import "package:cw_core/utils/file.dart";
8 import "package:cw_core/utils/print_verbose.dart";
9 import "package:cw_core/wallet_base.dart";
10 import "package:cw_core/wallet_credentials.dart";
11 import "package:cw_core/wallet_info.dart";
12 import "package:cw_core/wallet_type.dart";
13 import "package:path/path.dart" as p;
14
15 abstract class WalletService<N extends WalletCredentials, RFS extends WalletCredentials,
16 RFK extends WalletCredentials, RFH extends WalletCredentials> {
17 WalletType getType();
18
19 Future<WalletBase> create(N credentials, {bool? isTestnet});
20
21 Future<WalletBase> restoreFromHardwareWallet(RFH credentials);
22
23 Future<WalletBase> restoreFromSeed(RFS credentials, {bool? isTestnet});
24
25 Future<WalletBase> restoreFromKeys(RFK credentials, {bool? isTestnet});
26
27 Future<WalletBase> openWallet(String name, String password);
28
29 Future<bool> isWalletExit(String name);
30
31 Future<void> remove(String wallet);
32
33 Future<void> rename(String currentName, String password, String newName) async {
34 if (currentName == newName) {
35 return;
36 }
37
38 final currentWalletInfo = await WalletInfo.get(currentName, getType());
39 if (currentWalletInfo == null) {
40 throw Exception("Wallet not found");
41 }
42
43 await copyWalletFilesTo(fromName: currentName, toName: newName, type: getType());
44 await saveBackup(newName);
45
46 currentWalletInfo.id = WalletBase.idFor(newName, getType());
47 currentWalletInfo.name = newName;
48 await currentWalletInfo.save();
49
50 await _renameTokenRows(currentName, newName);
51
52 final oldDir = Directory(p.join(await pathForWalletTypeDir(type: getType()), currentName));
53 if (oldDir.existsSync()) {
54 try {
55 await oldDir.delete(recursive: true);
56 } catch (e) {
57 printV('rename: failed to delete old wallet dir "$currentName": $e');
58 }
59 }
60 }
61
62 Future<void> _renameTokenRows(String currentName, String newName) async {
63 if (getType() == WalletType.solana) {
64 await SPLToken.renameWallet(currentName, newName);
65 }
66
67 if (getType() == WalletType.tron) {
68 await TronToken.renameWallet(currentName, newName);
69 }
70 }
71
72 Future<void> restoreWalletFilesFromBackup(String name) async {
73 final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType());
74 final walletDirPath = await pathForWalletDir(name: name, type: getType());
75
76 if (File(backupWalletDirPath).existsSync()) {
77 await File(backupWalletDirPath).copy(walletDirPath);
78 }
79 }
80
81 Future<void> saveBackup(String name) async {
82 final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType());
83 final walletDirPath = await pathForWalletDir(name: name, type: getType());
84
85 if (File(walletDirPath).existsSync()) {
86 await File(walletDirPath).copy(backupWalletDirPath);
87 }
88 }
89
90 Future<String> getSeeds(String name, String password, WalletType type) async {
91 try {
92 final path = await pathForWallet(name: name, type: type);
93 final jsonSource = await read(path: path, password: password);
94 try {
95 final data = json.decode(jsonSource) as Map;
96 return data["mnemonic"] as String? ?? "";
97 } catch (_) {
98 // if not a valid json
99 return jsonSource.substring(0, 200);
100 }
101 } catch (_) {
102 // if the file couldn't be opened or read
103 return "";
104 }
105 }
106
107 /// Check if the Wallet requires a hardware wallet to be connected during
108 /// the opening flow. (Currently only the case for Monero)
109 Future<bool> requireHardwareWalletConnection(String name) async => false;
110 }