hedgequantx 1.1.1 → 1.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,309 +0,0 @@
1
- /**
2
- * Local Storage Service
3
- * Stores user data locally on their machine
4
- * - Saved connections (PropFirm credentials)
5
- * - Session history
6
- * - User preferences
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
- const crypto = require('crypto');
12
- const os = require('os');
13
-
14
- // Storage directory in user's home folder
15
- const STORAGE_DIR = path.join(os.homedir(), '.hedgequantx');
16
- const CONNECTIONS_FILE = path.join(STORAGE_DIR, 'connections.enc');
17
- const SETTINGS_FILE = path.join(STORAGE_DIR, 'settings.json');
18
- const HISTORY_FILE = path.join(STORAGE_DIR, 'history.json');
19
-
20
- // Encryption key derived from machine ID
21
- const getEncryptionKey = () => {
22
- const machineId = `${os.hostname()}-${os.platform()}-${os.userInfo().username}`;
23
- return crypto.createHash('sha256').update(machineId).digest();
24
- };
25
-
26
- class LocalStorageService {
27
- constructor() {
28
- this._ensureStorageDir();
29
- }
30
-
31
- /**
32
- * Ensure storage directory exists
33
- */
34
- _ensureStorageDir() {
35
- if (!fs.existsSync(STORAGE_DIR)) {
36
- fs.mkdirSync(STORAGE_DIR, { recursive: true, mode: 0o700 });
37
- }
38
- }
39
-
40
- /**
41
- * Encrypt data
42
- */
43
- _encrypt(data) {
44
- const key = getEncryptionKey();
45
- const iv = crypto.randomBytes(16);
46
- const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
47
- let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
48
- encrypted += cipher.final('hex');
49
- return iv.toString('hex') + ':' + encrypted;
50
- }
51
-
52
- /**
53
- * Decrypt data
54
- */
55
- _decrypt(encryptedData) {
56
- try {
57
- const key = getEncryptionKey();
58
- const [ivHex, encrypted] = encryptedData.split(':');
59
- const iv = Buffer.from(ivHex, 'hex');
60
- const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
61
- let decrypted = decipher.update(encrypted, 'hex', 'utf8');
62
- decrypted += decipher.final('utf8');
63
- return JSON.parse(decrypted);
64
- } catch (error) {
65
- return null;
66
- }
67
- }
68
-
69
- // ==================== CONNECTIONS ====================
70
-
71
- /**
72
- * Save a PropFirm connection
73
- */
74
- saveConnection(connection) {
75
- const connections = this.getConnections();
76
-
77
- // Check if connection already exists
78
- const existingIndex = connections.findIndex(
79
- c => c.propfirm === connection.propfirm && c.username === connection.username
80
- );
81
-
82
- const connectionData = {
83
- id: connection.id || crypto.randomUUID(),
84
- propfirm: connection.propfirm,
85
- propfirmName: connection.propfirmName,
86
- username: connection.username,
87
- password: connection.password, // Encrypted in file
88
- lastUsed: Date.now(),
89
- createdAt: connection.createdAt || Date.now()
90
- };
91
-
92
- if (existingIndex >= 0) {
93
- connections[existingIndex] = connectionData;
94
- } else {
95
- connections.push(connectionData);
96
- }
97
-
98
- // Save encrypted
99
- const encrypted = this._encrypt(connections);
100
- fs.writeFileSync(CONNECTIONS_FILE, encrypted, { mode: 0o600 });
101
-
102
- return connectionData;
103
- }
104
-
105
- /**
106
- * Get all saved connections
107
- */
108
- getConnections() {
109
- try {
110
- if (!fs.existsSync(CONNECTIONS_FILE)) {
111
- return [];
112
- }
113
- const encrypted = fs.readFileSync(CONNECTIONS_FILE, 'utf8');
114
- return this._decrypt(encrypted) || [];
115
- } catch (error) {
116
- return [];
117
- }
118
- }
119
-
120
- /**
121
- * Get connection by ID
122
- */
123
- getConnection(id) {
124
- const connections = this.getConnections();
125
- return connections.find(c => c.id === id);
126
- }
127
-
128
- /**
129
- * Delete a connection
130
- */
131
- deleteConnection(id) {
132
- const connections = this.getConnections();
133
- const filtered = connections.filter(c => c.id !== id);
134
-
135
- if (filtered.length === connections.length) {
136
- return false; // Not found
137
- }
138
-
139
- const encrypted = this._encrypt(filtered);
140
- fs.writeFileSync(CONNECTIONS_FILE, encrypted, { mode: 0o600 });
141
- return true;
142
- }
143
-
144
- /**
145
- * Update last used timestamp
146
- */
147
- updateConnectionLastUsed(id) {
148
- const connections = this.getConnections();
149
- const connection = connections.find(c => c.id === id);
150
-
151
- if (connection) {
152
- connection.lastUsed = Date.now();
153
- const encrypted = this._encrypt(connections);
154
- fs.writeFileSync(CONNECTIONS_FILE, encrypted, { mode: 0o600 });
155
- }
156
- }
157
-
158
- // ==================== SETTINGS ====================
159
-
160
- /**
161
- * Save user settings
162
- */
163
- saveSettings(settings) {
164
- const currentSettings = this.getSettings();
165
- const merged = { ...currentSettings, ...settings };
166
- fs.writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2), { mode: 0o600 });
167
- return merged;
168
- }
169
-
170
- /**
171
- * Get user settings
172
- */
173
- getSettings() {
174
- try {
175
- if (!fs.existsSync(SETTINGS_FILE)) {
176
- return this._getDefaultSettings();
177
- }
178
- const data = fs.readFileSync(SETTINGS_FILE, 'utf8');
179
- return { ...this._getDefaultSettings(), ...JSON.parse(data) };
180
- } catch (error) {
181
- return this._getDefaultSettings();
182
- }
183
- }
184
-
185
- /**
186
- * Default settings
187
- */
188
- _getDefaultSettings() {
189
- return {
190
- defaultContracts: 1,
191
- defaultDailyTarget: 500,
192
- defaultMaxRisk: 250,
193
- autoConnect: false,
194
- theme: 'dark',
195
- notifications: true,
196
- analyticsEnabled: true // User can opt-out
197
- };
198
- }
199
-
200
- // ==================== HISTORY ====================
201
-
202
- /**
203
- * Add to trading history
204
- */
205
- addToHistory(entry) {
206
- const history = this.getHistory();
207
-
208
- history.push({
209
- id: crypto.randomUUID(),
210
- timestamp: Date.now(),
211
- ...entry
212
- });
213
-
214
- // Keep last 1000 entries
215
- const trimmed = history.slice(-1000);
216
- fs.writeFileSync(HISTORY_FILE, JSON.stringify(trimmed, null, 2), { mode: 0o600 });
217
-
218
- return entry;
219
- }
220
-
221
- /**
222
- * Get trading history
223
- */
224
- getHistory(limit = 100) {
225
- try {
226
- if (!fs.existsSync(HISTORY_FILE)) {
227
- return [];
228
- }
229
- const data = fs.readFileSync(HISTORY_FILE, 'utf8');
230
- const history = JSON.parse(data);
231
- return history.slice(-limit);
232
- } catch (error) {
233
- return [];
234
- }
235
- }
236
-
237
- /**
238
- * Get stats from history
239
- */
240
- getLocalStats() {
241
- const history = this.getHistory(1000);
242
- const trades = history.filter(h => h.type === 'trade');
243
-
244
- const totalTrades = trades.length;
245
- const wins = trades.filter(t => t.pnl > 0).length;
246
- const losses = trades.filter(t => t.pnl < 0).length;
247
- const totalPnl = trades.reduce((sum, t) => sum + (t.pnl || 0), 0);
248
-
249
- return {
250
- totalTrades,
251
- wins,
252
- losses,
253
- winRate: totalTrades > 0 ? ((wins / totalTrades) * 100).toFixed(1) : 0,
254
- totalPnl: totalPnl.toFixed(2),
255
- avgPnl: totalTrades > 0 ? (totalPnl / totalTrades).toFixed(2) : 0
256
- };
257
- }
258
-
259
- /**
260
- * Clear all history
261
- */
262
- clearHistory() {
263
- if (fs.existsSync(HISTORY_FILE)) {
264
- fs.unlinkSync(HISTORY_FILE);
265
- }
266
- }
267
-
268
- // ==================== UTILITIES ====================
269
-
270
- /**
271
- * Get storage path info
272
- */
273
- getStoragePath() {
274
- return STORAGE_DIR;
275
- }
276
-
277
- /**
278
- * Check if storage exists
279
- */
280
- hasStoredData() {
281
- return fs.existsSync(CONNECTIONS_FILE) || fs.existsSync(HISTORY_FILE);
282
- }
283
-
284
- /**
285
- * Export all data (for backup)
286
- */
287
- exportData() {
288
- return {
289
- connections: this.getConnections(),
290
- settings: this.getSettings(),
291
- history: this.getHistory(1000),
292
- exportedAt: Date.now()
293
- };
294
- }
295
-
296
- /**
297
- * Clear all data
298
- */
299
- clearAll() {
300
- if (fs.existsSync(CONNECTIONS_FILE)) fs.unlinkSync(CONNECTIONS_FILE);
301
- if (fs.existsSync(SETTINGS_FILE)) fs.unlinkSync(SETTINGS_FILE);
302
- if (fs.existsSync(HISTORY_FILE)) fs.unlinkSync(HISTORY_FILE);
303
- }
304
- }
305
-
306
- // Singleton
307
- const localStorage = new LocalStorageService();
308
-
309
- module.exports = { LocalStorageService, localStorage };