dev
dart 160 lines 4.97 KB
Raw
1 import 'dart:io';
2
3 import 'package:bip39/bip39.dart' as bip39;
4 import 'package:cw_core/encryption_file_utils.dart';
5 import 'package:cw_core/balance.dart';
6 import 'package:cw_core/pathForWallet.dart';
7 import 'package:cw_core/spl_token.dart';
8 import 'package:cw_core/transaction_history.dart';
9 import 'package:cw_core/transaction_info.dart';
10 import 'package:cw_core/wallet_base.dart';
11 import 'package:cw_core/wallet_info.dart';
12 import 'package:cw_core/wallet_service.dart';
13 import 'package:cw_core/wallet_type.dart';
14 import 'package:cw_solana/solana_mnemonics.dart';
15 import 'package:cw_solana/solana_wallet.dart';
16 import 'package:cw_solana/solana_wallet_creation_credentials.dart';
17 import 'package:shared_preferences/shared_preferences.dart';
18
19 class SolanaWalletService extends WalletService<
20 SolanaNewWalletCredentials,
21 SolanaRestoreWalletFromSeedCredentials,
22 SolanaRestoreWalletFromPrivateKey,
23 SolanaNewWalletCredentials> {
24 SolanaWalletService(this.isDirect);
25
26 final bool isDirect;
27
28 @override
29 Future<SolanaWallet> create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async {
30 final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
31
32 final mnemonic = credentials.mnemonic ?? bip39.generateMnemonic(strength: strength);
33
34 final wallet = SolanaWallet(
35 walletInfo: credentials.walletInfo!,
36 derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
37 mnemonic: mnemonic,
38 password: credentials.password!,
39 passphrase: credentials.passphrase,
40 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
41 );
42
43 await wallet.init();
44 await wallet.addInitialTokens();
45 await wallet.save();
46 return wallet;
47 }
48
49 @override
50 WalletType getType() => WalletType.solana;
51
52 @override
53 Future<bool> isWalletExit(String name) async =>
54 File(await pathForWallet(name: name, type: getType())).existsSync();
55
56 @override
57 Future<SolanaWallet> openWallet(String name, String password) async {
58 final walletInfo = await WalletInfo.get(name, getType());
59 if (walletInfo == null) {
60 throw Exception('Wallet not found');
61 }
62
63 try {
64 final wallet = await SolanaWalletBase.open(
65 name: name,
66 password: password,
67 walletInfo: walletInfo,
68 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
69 );
70
71 await wallet.init();
72 await wallet.addInitialTokens();
73 await wallet.save();
74 saveBackup(name);
75 return wallet;
76 } catch (_) {
77 await restoreWalletFilesFromBackup(name);
78
79 final wallet = await SolanaWalletBase.open(
80 name: name,
81 password: password,
82 walletInfo: walletInfo,
83 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
84 );
85
86 await wallet.init();
87 await wallet.addInitialTokens();
88 await wallet.save();
89 return wallet;
90 }
91 }
92
93 @override
94 Future<void> remove(String wallet) async {
95 await File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
96 final walletInfo = await WalletInfo.get(wallet, getType());
97 if (walletInfo == null) {
98 throw Exception('Wallet not found');
99 }
100 await WalletInfo.delete(walletInfo);
101 final nameStillUsed = await WalletInfo.get(wallet, getType()) != null;
102 if (!nameStillUsed) {
103 await SPLToken.deleteAllForWallet(wallet);
104 }
105
106 final prefs = await SharedPreferences.getInstance();
107 for (final key
108 in prefs.getKeys().where((k) => k.startsWith('solana_last_synced_signature_${wallet}_'))) {
109 await prefs.remove(key);
110 }
111 }
112
113 @override
114 Future<SolanaWallet> restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials,
115 {bool? isTestnet}) async {
116 final wallet = SolanaWallet(
117 password: credentials.password!,
118 privateKey: credentials.privateKey,
119 walletInfo: credentials.walletInfo!,
120 derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
121 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
122 );
123
124 await wallet.init();
125 await wallet.addInitialTokens();
126 await wallet.save();
127
128 return wallet;
129 }
130
131 @override
132 Future<SolanaWallet> restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials,
133 {bool? isTestnet}) async {
134 if (!bip39.validateMnemonic(credentials.mnemonic)) {
135 throw SolanaMnemonicIsIncorrectException();
136 }
137
138 final wallet = SolanaWallet(
139 password: credentials.password!,
140 mnemonic: credentials.mnemonic,
141 walletInfo: credentials.walletInfo!,
142 derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
143 passphrase: credentials.passphrase,
144 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
145 );
146
147 await wallet.init();
148 await wallet.addInitialTokens();
149 await wallet.save();
150
151 return wallet;
152 }
153
154 @override
155 Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
156 restoreFromHardwareWallet(SolanaNewWalletCredentials credentials) {
157 // TODO: implement restoreFromHardwareWallet
158 throw UnimplementedError();
159 }
160 }