shogun-core 3.2.3 → 3.3.1

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.
Files changed (110) hide show
  1. package/README.md +12 -0
  2. package/dist/browser/shogun-core.js +909 -1804
  3. package/dist/browser/shogun-core.js.map +1 -1
  4. package/dist/{src/gundb → gundb}/db.js +55 -11
  5. package/dist/{src/index.js → index.js} +1 -7
  6. package/dist/{src/managers → managers}/CoreInitializer.js +41 -13
  7. package/dist/{src/storage → storage}/storage.js +22 -9
  8. package/dist/types/{src/gundb → gundb}/db.d.ts +10 -3
  9. package/dist/types/{src/index.d.ts → index.d.ts} +0 -3
  10. package/dist/types/{src/interfaces → interfaces}/shogun.d.ts +2 -0
  11. package/dist/types/{src/storage → storage}/storage.d.ts +2 -1
  12. package/dist/types/{src/types → types}/shogun.d.ts +2 -0
  13. package/package.json +22 -9
  14. package/dist/browser/_e6ae.shogun-core.js +0 -14
  15. package/dist/browser/_e6ae.shogun-core.js.map +0 -1
  16. package/dist/ship/examples/messenger-cli.js +0 -629
  17. package/dist/ship/implementation/SHIP_01.js +0 -650
  18. package/dist/ship/interfaces/ISHIP_01.js +0 -71
  19. package/dist/types/ship/examples/messenger-cli.d.ts +0 -31
  20. package/dist/types/ship/implementation/SHIP_01.d.ts +0 -113
  21. package/dist/types/ship/interfaces/ISHIP_01.d.ts +0 -305
  22. /package/dist/{src/config → config}/simplified-config.js +0 -0
  23. /package/dist/{src/core.js → core.js} +0 -0
  24. /package/dist/{src/examples → examples}/api-test.js +0 -0
  25. /package/dist/{src/examples → examples}/simple-api-test.js +0 -0
  26. /package/dist/{src/gundb → gundb}/api.js +0 -0
  27. /package/dist/{src/gundb → gundb}/crypto.js +0 -0
  28. /package/dist/{src/gundb → gundb}/derive.js +0 -0
  29. /package/dist/{src/gundb → gundb}/errors.js +0 -0
  30. /package/dist/{src/gundb → gundb}/index.js +0 -0
  31. /package/dist/{src/gundb → gundb}/rxjs.js +0 -0
  32. /package/dist/{src/gundb → gundb}/types.js +0 -0
  33. /package/dist/{src/interfaces → interfaces}/common.js +0 -0
  34. /package/dist/{src/interfaces → interfaces}/events.js +0 -0
  35. /package/dist/{src/interfaces → interfaces}/plugin.js +0 -0
  36. /package/dist/{src/interfaces → interfaces}/shogun.js +0 -0
  37. /package/dist/{src/managers → managers}/AuthManager.js +0 -0
  38. /package/dist/{src/managers → managers}/EventManager.js +0 -0
  39. /package/dist/{src/managers → managers}/PluginManager.js +0 -0
  40. /package/dist/{src/migration-test.js → migration-test.js} +0 -0
  41. /package/dist/{src/plugins → plugins}/base.js +0 -0
  42. /package/dist/{src/plugins → plugins}/index.js +0 -0
  43. /package/dist/{src/plugins → plugins}/nostr/index.js +0 -0
  44. /package/dist/{src/plugins → plugins}/nostr/nostrConnector.js +0 -0
  45. /package/dist/{src/plugins → plugins}/nostr/nostrConnectorPlugin.js +0 -0
  46. /package/dist/{src/plugins → plugins}/nostr/nostrSigner.js +0 -0
  47. /package/dist/{src/plugins → plugins}/nostr/types.js +0 -0
  48. /package/dist/{src/plugins → plugins}/oauth/index.js +0 -0
  49. /package/dist/{src/plugins → plugins}/oauth/oauthConnector.js +0 -0
  50. /package/dist/{src/plugins → plugins}/oauth/oauthPlugin.js +0 -0
  51. /package/dist/{src/plugins → plugins}/oauth/types.js +0 -0
  52. /package/dist/{src/plugins → plugins}/web3/index.js +0 -0
  53. /package/dist/{src/plugins → plugins}/web3/types.js +0 -0
  54. /package/dist/{src/plugins → plugins}/web3/web3Connector.js +0 -0
  55. /package/dist/{src/plugins → plugins}/web3/web3ConnectorPlugin.js +0 -0
  56. /package/dist/{src/plugins → plugins}/web3/web3Signer.js +0 -0
  57. /package/dist/{src/plugins → plugins}/webauthn/index.js +0 -0
  58. /package/dist/{src/plugins → plugins}/webauthn/types.js +0 -0
  59. /package/dist/{src/plugins → plugins}/webauthn/webauthn.js +0 -0
  60. /package/dist/{src/plugins → plugins}/webauthn/webauthnPlugin.js +0 -0
  61. /package/dist/{src/plugins → plugins}/webauthn/webauthnSigner.js +0 -0
  62. /package/dist/types/{src/config → config}/simplified-config.d.ts +0 -0
  63. /package/dist/types/{src/core.d.ts → core.d.ts} +0 -0
  64. /package/dist/{src/types → types}/events.js +0 -0
  65. /package/dist/types/{src/examples → examples}/api-test.d.ts +0 -0
  66. /package/dist/types/{src/examples → examples}/simple-api-test.d.ts +0 -0
  67. /package/dist/types/{src/gundb → gundb}/api.d.ts +0 -0
  68. /package/dist/types/{src/gundb → gundb}/crypto.d.ts +0 -0
  69. /package/dist/types/{src/gundb → gundb}/derive.d.ts +0 -0
  70. /package/dist/types/{src/gundb → gundb}/errors.d.ts +0 -0
  71. /package/dist/types/{src/gundb → gundb}/index.d.ts +0 -0
  72. /package/dist/types/{src/gundb → gundb}/rxjs.d.ts +0 -0
  73. /package/dist/types/{src/gundb → gundb}/types.d.ts +0 -0
  74. /package/dist/types/{src/interfaces → interfaces}/common.d.ts +0 -0
  75. /package/dist/types/{src/interfaces → interfaces}/events.d.ts +0 -0
  76. /package/dist/types/{src/interfaces → interfaces}/plugin.d.ts +0 -0
  77. /package/dist/types/{src/managers → managers}/AuthManager.d.ts +0 -0
  78. /package/dist/types/{src/managers → managers}/CoreInitializer.d.ts +0 -0
  79. /package/dist/types/{src/managers → managers}/EventManager.d.ts +0 -0
  80. /package/dist/types/{src/managers → managers}/PluginManager.d.ts +0 -0
  81. /package/dist/types/{src/migration-test.d.ts → migration-test.d.ts} +0 -0
  82. /package/dist/types/{src/plugins → plugins}/base.d.ts +0 -0
  83. /package/dist/types/{src/plugins → plugins}/index.d.ts +0 -0
  84. /package/dist/types/{src/plugins → plugins}/nostr/index.d.ts +0 -0
  85. /package/dist/types/{src/plugins → plugins}/nostr/nostrConnector.d.ts +0 -0
  86. /package/dist/types/{src/plugins → plugins}/nostr/nostrConnectorPlugin.d.ts +0 -0
  87. /package/dist/types/{src/plugins → plugins}/nostr/nostrSigner.d.ts +0 -0
  88. /package/dist/types/{src/plugins → plugins}/nostr/types.d.ts +0 -0
  89. /package/dist/types/{src/plugins → plugins}/oauth/index.d.ts +0 -0
  90. /package/dist/types/{src/plugins → plugins}/oauth/oauthConnector.d.ts +0 -0
  91. /package/dist/types/{src/plugins → plugins}/oauth/oauthPlugin.d.ts +0 -0
  92. /package/dist/types/{src/plugins → plugins}/oauth/types.d.ts +0 -0
  93. /package/dist/types/{src/plugins → plugins}/web3/index.d.ts +0 -0
  94. /package/dist/types/{src/plugins → plugins}/web3/types.d.ts +0 -0
  95. /package/dist/types/{src/plugins → plugins}/web3/web3Connector.d.ts +0 -0
  96. /package/dist/types/{src/plugins → plugins}/web3/web3ConnectorPlugin.d.ts +0 -0
  97. /package/dist/types/{src/plugins → plugins}/web3/web3Signer.d.ts +0 -0
  98. /package/dist/types/{src/plugins → plugins}/webauthn/index.d.ts +0 -0
  99. /package/dist/types/{src/plugins → plugins}/webauthn/types.d.ts +0 -0
  100. /package/dist/types/{src/plugins → plugins}/webauthn/webauthn.d.ts +0 -0
  101. /package/dist/types/{src/plugins → plugins}/webauthn/webauthnPlugin.d.ts +0 -0
  102. /package/dist/types/{src/plugins → plugins}/webauthn/webauthnSigner.d.ts +0 -0
  103. /package/dist/{src/types → types}/shogun.js +0 -0
  104. /package/dist/types/{src/types → types}/events.d.ts +0 -0
  105. /package/dist/types/{src/utils → utils}/errorHandler.d.ts +0 -0
  106. /package/dist/types/{src/utils → utils}/eventEmitter.d.ts +0 -0
  107. /package/dist/types/{src/utils → utils}/validation.d.ts +0 -0
  108. /package/dist/{src/utils → utils}/errorHandler.js +0 -0
  109. /package/dist/{src/utils → utils}/eventEmitter.js +0 -0
  110. /package/dist/{src/utils → utils}/validation.js +0 -0
@@ -1,650 +0,0 @@
1
- "use strict";
2
- /**
3
- * Esempio Pratico: Messaggistica Decentralizzata con Shogun Core
4
- *
5
- * Questo esempio mostra come creare un sistema di messaggistica sicuro usando:
6
- * - Shogun Core per autenticazione (username/password)
7
- * - GunDB per storage decentralizzato P2P
8
- * - SEA (Security, Encryption, Authorization) per crittografia
9
- *
10
- * Vantaggi:
11
- * ✅ Completamente decentralizzato (no server centrale)
12
- * ✅ Zero costi (no blockchain, no gas fees)
13
- * ✅ Real-time messaging
14
- * ✅ Offline-first
15
- * ✅ End-to-end encryption
16
- *
17
- * Note sull'ERC7627:
18
- * L'EIP era un template concettuale. Questo esempio implementa
19
- * solo la parte GunDB/Shogun Core senza interazione blockchain.
20
- * La funzione deriveEthereumAddress() rimane come utility per derivare
21
- * un address Ethereum dalla chiave GunDB se necessario in futuro.
22
- */
23
- var __importDefault = (this && this.__importDefault) || function (mod) {
24
- return (mod && mod.__esModule) ? mod : { "default": mod };
25
- };
26
- Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.SHIP_01 = void 0;
28
- const core_1 = require("../../src/core");
29
- const ethers_1 = require("ethers");
30
- const derive_1 = __importDefault(require("../../src/gundb/derive"));
31
- // ============================================================================
32
- // 1. SETUP: Inizializzazione del Sistema Completo
33
- // ============================================================================
34
- /**
35
- * Classe per messaggistica sicura con Shogun Core
36
- * Implementa l'interfaccia ISHIP_01
37
- * Usa solo GunDB per storage decentralizzato (no blockchain)
38
- */
39
- class SHIP_01 {
40
- constructor(shogunConfig) {
41
- // Inizializza Shogun Core
42
- this.shogun = new core_1.ShogunCore(shogunConfig);
43
- }
44
- // ========================================================================
45
- // 2. AUTENTICAZIONE: Username e Password
46
- // ========================================================================
47
- /**
48
- * Registra un nuovo utente
49
- */
50
- async signup(username, password) {
51
- try {
52
- // Registra con Shogun Core (crea SEA pair automaticamente)
53
- const signupResult = await this.shogun.signUp(username, password);
54
- if (!signupResult.success) {
55
- return {
56
- success: false,
57
- error: signupResult.error || "Signup failed",
58
- };
59
- }
60
- console.log("✅ Utente registrato");
61
- console.log(` Username: ${username}`);
62
- console.log(` GunDB Public Key: ${signupResult.pub}`);
63
- // Opzionale: deriva address Ethereum dalla chiave GunDB
64
- const derivedAddress = signupResult.pub
65
- ? await this.deriveEthereumAddress(signupResult.pub)
66
- : undefined;
67
- if (derivedAddress) {
68
- console.log(` Derived Address: ${derivedAddress}`);
69
- }
70
- return {
71
- success: true,
72
- userPub: signupResult.pub,
73
- derivedAddress,
74
- };
75
- }
76
- catch (error) {
77
- return {
78
- success: false,
79
- error: error.message,
80
- };
81
- }
82
- }
83
- /**
84
- * Login con username e password
85
- */
86
- async login(username, password) {
87
- try {
88
- // Login con Shogun Core
89
- const loginResult = await this.shogun.login(username, password);
90
- if (!loginResult.success) {
91
- return {
92
- success: false,
93
- error: loginResult.error || "Login failed",
94
- };
95
- }
96
- console.log("✅ Login effettuato");
97
- console.log(` Username: ${username}`);
98
- console.log(` GunDB Public Key: ${loginResult.userPub}`);
99
- // Opzionale: deriva address Ethereum dalla chiave GunDB
100
- const derivedAddress = loginResult.userPub
101
- ? await this.deriveEthereumAddress(loginResult.userPub)
102
- : undefined;
103
- if (derivedAddress) {
104
- console.log(` Derived Address: ${derivedAddress}`);
105
- }
106
- return {
107
- success: true,
108
- userPub: loginResult.userPub,
109
- derivedAddress,
110
- };
111
- }
112
- catch (error) {
113
- return {
114
- success: false,
115
- error: error.message,
116
- };
117
- }
118
- }
119
- /**
120
- * Login con SEA Key Pair
121
- *
122
- * Autenticazione diretta usando un key pair esportato.
123
- * Utile per:
124
- * - Recupero account senza password
125
- * - Portabilità tra dispositivi
126
- * - Backup dell'identità
127
- */
128
- async loginWithPair(seaPair) {
129
- try {
130
- console.log("🔐 Login con key pair...");
131
- // Autentica con GunDB usando il pair
132
- const authResult = await new Promise((resolve) => {
133
- this.shogun.db.gun.user().auth(seaPair, (ack) => {
134
- if (ack.err) {
135
- resolve({
136
- success: false,
137
- error: ack.err,
138
- });
139
- }
140
- else {
141
- resolve({
142
- success: true,
143
- userPub: seaPair.pub,
144
- });
145
- }
146
- });
147
- });
148
- if (!authResult.success) {
149
- console.log("❌ Login fallito:", authResult.error);
150
- return authResult;
151
- }
152
- // Opzionale: deriva address Ethereum dalla chiave GunDB
153
- const derivedAddress = await this.deriveEthereumAddress(seaPair.pub);
154
- console.log("✅ Login effettuato");
155
- console.log(` GunDB Public Key: ${seaPair.pub}`);
156
- console.log(` Derived Address: ${derivedAddress}`);
157
- return {
158
- success: true,
159
- userPub: authResult.userPub,
160
- derivedAddress,
161
- };
162
- }
163
- catch (error) {
164
- console.error("❌ Errore login con pair:", error);
165
- return {
166
- success: false,
167
- error: error instanceof Error ? error.message : "Unknown error",
168
- };
169
- }
170
- }
171
- /**
172
- * Logout
173
- */
174
- logout() {
175
- this.shogun.logout();
176
- console.log("👋 Logout effettuato");
177
- }
178
- /**
179
- * Verifica se l'utente è autenticato
180
- */
181
- isLoggedIn() {
182
- return this.shogun.isLoggedIn();
183
- }
184
- // ========================================================================
185
- // 3. GESTIONE CHIAVI PUBBLICHE: Salva su GunDB
186
- // ========================================================================
187
- /**
188
- * Salva la chiave pubblica dell'utente su GunDB
189
- * Questo permette ad altri di trovare la tua chiave per criptare messaggi
190
- */
191
- async publishPublicKey() {
192
- try {
193
- if (!this.isLoggedIn()) {
194
- return { success: false, error: "Not logged in" };
195
- }
196
- // Ottieni il SEA pair dell'utente corrente
197
- const currentUser = this.shogun.db.user;
198
- if (!currentUser || !currentUser.is) {
199
- return { success: false, error: "No user session" };
200
- }
201
- // Salva chiave pubblica sul nodo globale usando il userPub come chiave
202
- // Questo permette ad altri di trovarla facilmente
203
- const userPub = currentUser.is.pub;
204
- await this.shogun.db.gun
205
- .get(userPub)
206
- .put({
207
- pub: currentUser.is.pub,
208
- epub: currentUser.is.epub,
209
- algorithm: "ECDSA",
210
- timestamp: Date.now().toString(),
211
- })
212
- .then();
213
- console.log(`📝 Chiave pubblica pubblicata su GunDB`);
214
- return { success: true };
215
- }
216
- catch (error) {
217
- console.error("❌ Errore pubblicazione chiave:", error);
218
- return { success: false, error: error.message };
219
- }
220
- }
221
- // ========================================================================
222
- // 4. INVIO MESSAGGI: Solo GunDB
223
- // ========================================================================
224
- /**
225
- * Invia un messaggio crittografato a un altro utente
226
- */
227
- async sendMessage(recipientUsername, message) {
228
- try {
229
- if (!this.isLoggedIn()) {
230
- return { success: false, error: "Not logged in" };
231
- }
232
- const currentUser = this.shogun.db.user;
233
- if (!currentUser || !currentUser.is) {
234
- return { success: false, error: "No user session" };
235
- }
236
- // 1. Ottieni la chiave pubblica del destinatario
237
- const recipientKey = await this.getRecipientPublicKey(recipientUsername);
238
- if (!recipientKey) {
239
- return {
240
- success: false,
241
- error: `Recipient ${recipientUsername} has not published their public key`,
242
- };
243
- }
244
- // 2. Ottieni il SEA pair completo (include chiavi private)
245
- const senderPair = this.shogun.db.gun.user()?._?.sea;
246
- if (!senderPair) {
247
- return { success: false, error: "Cannot access SEA pair" };
248
- }
249
- // 3. Cripta il messaggio usando SEA.secret + SEA.encrypt (ECDH)
250
- const encryptedMessage = await this.shogun.db.crypto.encFor(message, senderPair, // sender pair completo
251
- { epub: recipientKey.epub } // recipient public encryption key
252
- );
253
- // 4. Genera ID messaggio
254
- const messageId = this.generateMessageId();
255
- const senderPub = currentUser.is.pub;
256
- // 5. Salva messaggio crittografato su GunDB
257
- const messageData = {
258
- from: senderPub,
259
- to: recipientUsername,
260
- content: encryptedMessage, // Contenuto crittografato!
261
- timestamp: Date.now().toString(),
262
- messageId: messageId,
263
- };
264
- // Salva sul nodo globale 'messages' per permettere il listener
265
- await this.shogun.db.gun
266
- .get(SHIP_01.NODES.MESSAGES)
267
- .get(messageId)
268
- .put(messageData)
269
- .then();
270
- console.log(`✅ Messaggio salvato: ${messageId}`);
271
- return {
272
- success: true,
273
- messageId: messageId,
274
- };
275
- }
276
- catch (error) {
277
- return {
278
- success: false,
279
- error: error.message,
280
- };
281
- }
282
- }
283
- /**
284
- * Ottiene la chiave pubblica di un utente da GunDB
285
- */
286
- async getRecipientPublicKey(username) {
287
- try {
288
- // Prima trova l'utente dal username
289
- const userData = await this.shogun.db.getUserByAlias(username);
290
- if (!userData || !userData.userPub) {
291
- console.error(`❌ User ${username} not found`);
292
- return null;
293
- }
294
- const userPub = userData.userPub;
295
- // Le chiavi sono salvate direttamente sul nodo userPub
296
- const publicKeyData = await this.shogun.db.gun.get(userPub).then();
297
- if (publicKeyData && publicKeyData.epub && publicKeyData.pub) {
298
- return {
299
- pub: publicKeyData.pub,
300
- epub: publicKeyData.epub,
301
- };
302
- }
303
- return null;
304
- }
305
- catch (error) {
306
- console.error("❌ Errore recupero chiave pubblica:", error);
307
- return null;
308
- }
309
- }
310
- // ========================================================================
311
- // 5. RICEZIONE MESSAGGI: Ascolta GunDB in real-time
312
- // ========================================================================
313
- /**
314
- * Ascolta messaggi crittografati in arrivo su GunDB
315
- */
316
- async listenForMessages(onMessage) {
317
- if (!this.isLoggedIn()) {
318
- console.error("❌ Non autenticato");
319
- return;
320
- }
321
- const currentUser = this.shogun.db.user;
322
- if (!currentUser || !currentUser.is) {
323
- console.error("❌ Nessuna sessione utente");
324
- return;
325
- }
326
- const userPub = currentUser.is.pub;
327
- // Ottieni username dell'utente corrente
328
- const username = currentUser.is.alias;
329
- // Set per tracciare messaggi già ricevuti (evita duplicati)
330
- const receivedMessages = new Set();
331
- // Ascolta messaggi in tempo reale su GunDB
332
- this.shogun.db.gun
333
- .get(SHIP_01.NODES.MESSAGES)
334
- .map()
335
- .on(async (data, key) => {
336
- // Filtra solo i messaggi destinati a questo utente (per username)
337
- if (data &&
338
- data.to === username &&
339
- data.from &&
340
- data.content &&
341
- data.messageId) {
342
- // Evita duplicati (GunDB può emettere più volte)
343
- if (receivedMessages.has(data.messageId)) {
344
- return;
345
- }
346
- receivedMessages.add(data.messageId);
347
- try {
348
- // Decripta il messaggio
349
- const decryptedContent = await this.decryptMessage(data.content, data.from);
350
- onMessage({
351
- from: data.from,
352
- content: decryptedContent,
353
- timestamp: parseInt(data.timestamp),
354
- });
355
- }
356
- catch (error) {
357
- console.error("❌ Errore decrittazione messaggio:", error);
358
- }
359
- }
360
- });
361
- console.log(`👂 In ascolto di messaggi per ${username} (${userPub.substring(0, 10)}...)`);
362
- }
363
- /**
364
- * Decripta un messaggio usando SEA.secret + SEA.decrypt (ECDH)
365
- */
366
- async decryptMessage(encryptedContent, senderPub) {
367
- // Ottieni il SEA pair completo del destinatario (noi)
368
- const receiverPair = this.shogun.db.gun.user()?._?.sea;
369
- if (!receiverPair) {
370
- throw new Error("Cannot access SEA pair");
371
- }
372
- // Ottieni epub del mittente
373
- const senderKey = await this.getPublicKeyByPub(senderPub);
374
- if (!senderKey) {
375
- throw new Error("Sender public key not found");
376
- }
377
- // Decripta usando SEA.secret + SEA.decrypt (ECDH)
378
- const decrypted = await this.shogun.db.crypto.decFrom(encryptedContent, { epub: senderKey.epub }, // sender's public encryption key
379
- receiverPair // receiver's pair completo
380
- );
381
- return decrypted;
382
- }
383
- /**
384
- * Ottiene la chiave pubblica di un utente dalla sua pub key
385
- */
386
- async getPublicKeyByPub(userPub) {
387
- try {
388
- // Le chiavi sono salvate direttamente sul nodo userPub
389
- const publicKeyData = await this.shogun.db.gun.get(userPub).then();
390
- if (publicKeyData && publicKeyData.epub && publicKeyData.pub) {
391
- return {
392
- pub: publicKeyData.pub,
393
- epub: publicKeyData.epub,
394
- };
395
- }
396
- return null;
397
- }
398
- catch (error) {
399
- console.error("❌ Errore recupero chiave:", error);
400
- return null;
401
- }
402
- }
403
- // ========================================================================
404
- // 6. RECUPERO STORICO: Query messaggi passati
405
- // ========================================================================
406
- /**
407
- * Recupera lo storico dei messaggi crittografati con un utente
408
- */
409
- async getMessageHistory(withUsername) {
410
- if (!this.isLoggedIn()) {
411
- console.error("❌ Non autenticato");
412
- return [];
413
- }
414
- const currentUser = this.shogun.db.user;
415
- if (!currentUser || !currentUser.is) {
416
- console.error("❌ Nessuna sessione utente");
417
- return [];
418
- }
419
- const userPub = currentUser.is.pub;
420
- const username = currentUser.is.alias;
421
- const allMessages = [];
422
- // Ottieni il userPub dell'altro utente
423
- const otherUserData = await this.shogun.db.getUserByAlias(withUsername);
424
- const otherUserPub = otherUserData?.userPub;
425
- // Use .map() instead of .then() to iterate all messages
426
- return new Promise((resolve) => {
427
- const messages = [];
428
- let messageCount = 0;
429
- this.shogun.db.gun
430
- .get(SHIP_01.NODES.MESSAGES)
431
- .map()
432
- .once(async (msgData, messageId) => {
433
- // Skip metadata fields
434
- if (!msgData || typeof msgData !== "object" || messageId === "_") {
435
- return;
436
- }
437
- messageCount++;
438
- try {
439
- // Check if message is part of this conversation
440
- // Fixed: Handle both username and userPub in matching
441
- const isSentToTarget = msgData.from === userPub &&
442
- (msgData.to === withUsername || msgData.to === otherUserPub);
443
- const isReceivedFromTarget = (msgData.to === username || msgData.to === userPub) &&
444
- msgData.from === otherUserPub;
445
- if (isSentToTarget || isReceivedFromTarget) {
446
- // Decrypt message
447
- const decryptedContent = await this.decryptMessage(msgData.content, msgData.from);
448
- messages.push({
449
- from: msgData.from,
450
- to: msgData.to,
451
- content: decryptedContent,
452
- timestamp: parseInt(msgData.timestamp),
453
- });
454
- }
455
- }
456
- catch (error) {
457
- // Silent error - message couldn't be decrypted
458
- }
459
- });
460
- // Wait a bit for GunDB to return all messages, then resolve
461
- setTimeout(() => {
462
- const sorted = messages.sort((a, b) => a.timestamp - b.timestamp);
463
- resolve(sorted);
464
- }, 2000);
465
- });
466
- }
467
- // ========================================================================
468
- // 7. UTILITY FUNCTIONS
469
- // ========================================================================
470
- /**
471
- * Converte la chiave pubblica di GunDB in address Ethereum
472
- * Usa la chiave privata SEA come seed per derivazione deterministica
473
- *
474
- * Questo garantisce che:
475
- * - Stesso SEA pair → stesso address Ethereum
476
- * - Derivazione cryptografica sicura
477
- * - Identità unificata tra GunDB e blockchain
478
- */
479
- async deriveEthereumAddress(publicKey) {
480
- try {
481
- // Ottieni il SEA pair completo
482
- const seaPair = this.shogun.db.gun.user()?._?.sea;
483
- if (!seaPair || !seaPair.priv) {
484
- throw new Error("Cannot access SEA pair");
485
- }
486
- // Usa la chiave privata SEA come seed per derive
487
- // Questo è MOLTO più sicuro e deterministico del username!
488
- const derived = await (0, derive_1.default)(seaPair.priv, null, {
489
- includeSecp256k1Ethereum: true,
490
- includeP256: false,
491
- includeSecp256k1Bitcoin: false,
492
- });
493
- return derived.secp256k1Ethereum.address;
494
- }
495
- catch (error) {
496
- console.error("❌ Errore derivazione address:", error);
497
- // Fallback: hash della chiave pubblica
498
- const fallbackKey = publicKey || "unknown";
499
- const hash = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(fallbackKey));
500
- return ethers_1.ethers.getAddress("0x" + hash.slice(-40));
501
- }
502
- }
503
- /**
504
- * Genera ID messaggio univoco
505
- */
506
- generateMessageId() {
507
- return ethers_1.ethers.hexlify(ethers_1.ethers.randomBytes(16));
508
- }
509
- }
510
- exports.SHIP_01 = SHIP_01;
511
- // GunDB Node Names - Constants for clarity
512
- SHIP_01.NODES = {
513
- MESSAGES: "messages",
514
- USERS: "users",
515
- PUBLIC_KEYS: "publicKeys",
516
- };
517
- async function testAliceAndBob() {
518
- console.log("🧪 TEST: Alice e Bob - Conversazione Crittografata E2E\n");
519
- console.log("=".repeat(60));
520
- // Setup Alice
521
- console.log("\n👩 ALICE - Setup");
522
- console.log("-".repeat(60));
523
- const alice = new SHIP_01({
524
- gunOptions: {
525
- peers: ["https://peer.wallie.io/gun"],
526
- radisk: true,
527
- },
528
- });
529
- // Alice signup/login
530
- await alice.signup("alice", "password123");
531
- const aliceLogin = await alice.login("alice", "password123");
532
- if (!aliceLogin.success) {
533
- console.error("❌ Alice login failed");
534
- return;
535
- }
536
- await alice.publishPublicKey();
537
- // Aspetta che la chiave sia sincronizzata
538
- await new Promise((resolve) => setTimeout(resolve, 1000));
539
- // Setup Bob
540
- console.log("\n👨 BOB - Setup");
541
- console.log("-".repeat(60));
542
- const bob = new SHIP_01({
543
- gunOptions: {
544
- peers: ["https://peer.wallie.io/gun"],
545
- radisk: true,
546
- },
547
- });
548
- // Bob signup/login
549
- await bob.signup("bob", "password456");
550
- const bobLogin = await bob.login("bob", "password456");
551
- if (!bobLogin.success) {
552
- console.error("❌ Bob login failed");
553
- return;
554
- }
555
- await bob.publishPublicKey();
556
- // Aspetta che la chiave sia sincronizzata
557
- await new Promise((resolve) => setTimeout(resolve, 1000));
558
- console.log("\n" + "=".repeat(60));
559
- console.log("💬 CONVERSAZIONE");
560
- console.log("=".repeat(60));
561
- // Alice e Bob ascoltano messaggi
562
- let aliceMessages = [];
563
- let bobMessages = [];
564
- await alice.listenForMessages((msg) => {
565
- aliceMessages.push(msg);
566
- console.log(`\n[Alice riceve] 📨`);
567
- console.log(` Da: ${msg.from.substring(0, 10)}...`);
568
- console.log(` Messaggio: "${msg.content}"`);
569
- console.log(` Timestamp: ${new Date(msg.timestamp).toLocaleTimeString()}`);
570
- });
571
- await bob.listenForMessages((msg) => {
572
- bobMessages.push(msg);
573
- console.log(`\n[Bob riceve] 📨`);
574
- console.log(` Da: ${msg.from.substring(0, 10)}...`);
575
- console.log(` Messaggio: "${msg.content}"`);
576
- console.log(` Timestamp: ${new Date(msg.timestamp).toLocaleTimeString()}`);
577
- });
578
- // Aspetta che i listener siano pronti
579
- await new Promise((resolve) => setTimeout(resolve, 2000));
580
- // Alice invia messaggio a Bob
581
- console.log("\n[Alice invia] 📤");
582
- const msg1 = await alice.sendMessage("bob", "Ciao Bob! Come stai? 👋");
583
- console.log(` ✅ Inviato: "${msg1.messageId}"`);
584
- // Aspetta che Bob riceva
585
- await new Promise((resolve) => setTimeout(resolve, 2000));
586
- // Bob risponde ad Alice
587
- console.log("\n[Bob invia] 📤");
588
- const msg2 = await bob.sendMessage("alice", "Ciao Alice! Tutto bene, grazie! Tu? 😊");
589
- console.log(` ✅ Inviato: "${msg2.messageId}"`);
590
- // Aspetta che Alice riceva
591
- await new Promise((resolve) => setTimeout(resolve, 2000));
592
- // Alice risponde
593
- console.log("\n[Alice invia] 📤");
594
- const msg3 = await alice.sendMessage("bob", "Anch'io benissimo! Questo sistema di messaggistica è fantastico! 🚀");
595
- console.log(` ✅ Inviato: "${msg3.messageId}"`);
596
- // Aspetta che Bob riceva
597
- await new Promise((resolve) => setTimeout(resolve, 2000));
598
- // Bob conclude
599
- console.log("\n[Bob invia] 📤");
600
- const msg4 = await bob.sendMessage("alice", "Vero! Zero costi, decentralizzato e veloce! 💪");
601
- console.log(` ✅ Inviato: "${msg4.messageId}"`);
602
- // Aspetta finale
603
- await new Promise((resolve) => setTimeout(resolve, 3000));
604
- // Mostra statistiche
605
- console.log("\n" + "=".repeat(60));
606
- console.log("📊 STATISTICHE FINALI");
607
- console.log("=".repeat(60));
608
- console.log(`\n👩 Alice:`);
609
- console.log(` - Messaggi inviati: 2`);
610
- console.log(` - Messaggi ricevuti: ${aliceMessages.length}`);
611
- console.log(` - Public Key: ${aliceLogin.userPub?.substring(0, 20)}...`);
612
- console.log(` - Derived Address: ${aliceLogin.derivedAddress}`);
613
- console.log(`\n👨 Bob:`);
614
- console.log(` - Messaggi inviati: 2`);
615
- console.log(` - Messaggi ricevuti: ${bobMessages.length}`);
616
- console.log(` - Public Key: ${bobLogin.userPub?.substring(0, 20)}...`);
617
- console.log(` - Derived Address: ${bobLogin.derivedAddress}`);
618
- // Recupera storico
619
- console.log("\n" + "=".repeat(60));
620
- console.log("📚 STORICO CONVERSAZIONE");
621
- console.log("=".repeat(60));
622
- const aliceHistory = await alice.getMessageHistory("bob");
623
- console.log(`\n👩 Storico di Alice con Bob (${aliceHistory.length} messaggi):`);
624
- aliceHistory.forEach((msg, i) => {
625
- const sender = msg.from === aliceLogin.userPub ? "Alice" : "Bob";
626
- console.log(` ${i + 1}. [${sender}]: ${msg.content}`);
627
- });
628
- const bobHistory = await bob.getMessageHistory("alice");
629
- console.log(`\n👨 Storico di Bob con Alice (${bobHistory.length} messaggi):`);
630
- bobHistory.forEach((msg, i) => {
631
- const sender = msg.from === bobLogin.userPub ? "Bob" : "Alice";
632
- console.log(` ${i + 1}. [${sender}]: ${msg.content}`);
633
- });
634
- // Riepilogo finale
635
- console.log("\n" + "=".repeat(60));
636
- console.log("✅ TEST COMPLETATO CON SUCCESSO!");
637
- console.log("=".repeat(60));
638
- console.log("\n📝 Riepilogo:");
639
- console.log(" ✅ 2 utenti registrati (Alice, Bob)");
640
- console.log(" ✅ 4 messaggi scambiati");
641
- console.log(" ✅ Messaggi ricevuti in real-time");
642
- console.log(" ✅ Storico recuperato correttamente");
643
- console.log(" ✅ Storage: GunDB P2P (gratis!)");
644
- console.log(" ✅ Costi: $0.00");
645
- console.log("\n🎉 Sistema di messaggistica decentralizzato funzionante!\n");
646
- }
647
- // Esegui esempio o test
648
- if (require.main === module) {
649
- testAliceAndBob().catch(console.error); // Test completo Alice & Bob
650
- }