dev
dart 107 lines 3.16 KB
Raw
1 import 'dart:convert';
2 import 'dart:core';
3 import 'package:cw_core/encryption_file_utils.dart';
4 import 'package:cw_core/pathForWallet.dart';
5 import 'package:cw_core/utils/print_verbose.dart';
6 import 'package:cw_core/wallet_info.dart';
7 import 'package:cw_solana/solana_transaction_info.dart';
8 import 'package:mobx/mobx.dart';
9 import 'package:cw_core/transaction_history.dart';
10
11 part 'solana_transaction_history.g.dart';
12
13 const transactionsHistoryFileName = 'solana_transactions.json';
14
15 class SolanaTransactionHistory = SolanaTransactionHistoryBase with _$SolanaTransactionHistory;
16
17 abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase<SolanaTransactionInfo>
18 with Store {
19 SolanaTransactionHistoryBase(
20 {required this.walletInfo, required String password, required this.encryptionFileUtils})
21 : _password = password {
22 transactions = ObservableMap<String, SolanaTransactionInfo>();
23 }
24
25 final WalletInfo walletInfo;
26 final EncryptionFileUtils encryptionFileUtils;
27 String _password;
28
29 Future<void> init() async {
30 clear();
31 await _load();
32 }
33
34 Future<void> _saveQueue = Future.value();
35
36 @override
37 Future<void> save() => saveAndConfirm();
38
39 Future<bool> saveAndConfirm() {
40 final write = _saveQueue.then((_) async {
41 try {
42 await _write();
43
44 return true;
45 } catch (e, s) {
46 printV('Error while saving solana transaction history: ${e.toString()}');
47 printV(s);
48
49 return false;
50 }
51 });
52
53 _saveQueue = write;
54
55 return write;
56 }
57
58 Future<void> _write() async {
59 final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
60 final path = '$dirPath/$transactionsHistoryFileName';
61 final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson()));
62 final data = json.encode({'transactions': transactionMaps});
63 await encryptionFileUtils.write(path: path, password: _password, data: data);
64 }
65
66 @override
67 void addOne(SolanaTransactionInfo transaction) => transactions[transaction.id] = transaction;
68
69 @override
70 void addMany(Map<String, SolanaTransactionInfo> transactions) =>
71 this.transactions.addAll(transactions);
72
73 Future<Map<String, dynamic>> _read() async {
74 final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);
75 final path = '$dirPath/$transactionsHistoryFileName';
76 final content = await encryptionFileUtils.read(path: path, password: _password);
77 if (content.isEmpty) {
78 return {};
79 }
80 return json.decode(content) as Map<String, dynamic>;
81 }
82
83 Future<void> _load() async {
84 try {
85 final content = await _read();
86 final txs = content['transactions'] as Map<String, dynamic>? ?? {};
87
88 txs.entries.forEach((entry) {
89 final val = entry.value;
90
91 if (val is! Map<String, dynamic>) {
92 return;
93 }
94
95 try {
96 _update(SolanaTransactionInfo.fromJson(val));
97 } catch (e) {
98 printV("Skipping unreadable solana transaction ${entry.key}: ${e.toString()}");
99 }
100 });
101 } catch (e) {
102 printV(e);
103 }
104 }
105
106 void _update(SolanaTransactionInfo transaction) => transactions[transaction.id] = transaction;
107 }