gun-eth 1.3.6 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/gun-eth-protocol.cjs.js +11528 -0
- package/dist/gun-eth-protocol.esm.js +11503 -0
- package/dist/gun-eth-protocol.js +18 -0
- package/dist/gun-eth-protocol.react.js +11503 -0
- package/dist/gun-eth-protocol.umd.js +18 -0
- package/jsdoc.json +7 -0
- package/package.json +28 -25
- package/rollup.config.js +80 -0
- package/src/index.js +160 -512
- package/src/lib/authentication/index.js +13 -0
- package/src/lib/authentication/isAuthenticated.js +20 -0
- package/src/lib/authentication/login.js +25 -0
- package/src/lib/authentication/register.js +58 -0
- package/src/lib/blockchain/ethereum.js +74 -0
- package/src/lib/blockchain/shine.js +204 -0
- package/src/lib/certificates/friendsCertificates.js +92 -0
- package/src/lib/certificates/index.js +44 -0
- package/src/lib/certificates/messagingCertificates.js +94 -0
- package/src/lib/friends/acceptFriendRequest.js +69 -0
- package/src/lib/friends/addFriendRequest.js +49 -0
- package/src/lib/friends/friendRequests.js +51 -0
- package/src/lib/friends/friendsList.js +57 -0
- package/src/lib/friends/index.js +36 -0
- package/src/lib/friends/rejectFriendRequest.js +31 -0
- package/src/lib/messaging/chatsList.js +42 -0
- package/src/lib/messaging/createChat.js +132 -0
- package/src/lib/messaging/index.js +36 -0
- package/src/lib/messaging/messageList.js +106 -0
- package/src/lib/messaging/sendMessage.js +132 -0
- package/src/lib/messaging/sendVoiceMessage.js +119 -0
- package/src/lib/notes/createNote.js +41 -0
- package/src/lib/notes/deleteNote.js +12 -0
- package/src/lib/notes/getNote.js +25 -0
- package/src/lib/notes/getUserNote.js +59 -0
- package/src/lib/notes/index.js +8 -0
- package/src/lib/notes/updateNotes.js +35 -0
- package/src/lib/post/createPost.js +17 -0
- package/src/lib/post/decryptPost.js +14 -0
- package/src/lib/post/deletePost.js +13 -0
- package/src/lib/post/encryptPost,js +16 -0
- package/src/lib/post/getPost.js +36 -0
- package/src/lib/post/index.js +9 -0
- package/src/lib/post/updatePost.js +16 -0
- package/src/state/gun.js +33 -0
- package/types/types.d.ts +244 -0
- package/TUTORIAL.md +0 -103
- package/src/examples/eth2gun.html +0 -163
- package/src/examples/gun2eth.html +0 -164
- package/src/examples/shine.html +0 -256
- /package/src/{abis → lib/blockchain/abis}/SHINE.json +0 -0
- /package/src/{contracts → lib/blockchain/contracts}/SHINE.sol +0 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
/**
|
2
|
+
* Invia un messaggio vocale a un amico in una chat specifica.
|
3
|
+
*
|
4
|
+
* @param {string} roomId - L'ID della stanza di chat.
|
5
|
+
* @param {string} publicKey - La chiave pubblica dell'amico.
|
6
|
+
* @param {Object} voiceRecording - L'oggetto contenente i dati della registrazione vocale.
|
7
|
+
* @param {Function} [callback] - Funzione di callback opzionale per gestire il risultato dell'operazione.
|
8
|
+
*
|
9
|
+
* @returns {void}
|
10
|
+
*
|
11
|
+
* La funzione esegue le seguenti operazioni:
|
12
|
+
* 1. Verifica la presenza della chiave pubblica dell'utente corrente.
|
13
|
+
* 2. Controlla i certificati necessari per creare messaggi e aggiornare i metadati della chat.
|
14
|
+
* 3. Aggiorna il messaggio più recente nella chat per entrambi gli utenti.
|
15
|
+
* 4. Aggiunge il messaggio vocale alla lista dei messaggi per entrambi gli utenti.
|
16
|
+
*
|
17
|
+
* In caso di errore, la funzione di callback viene chiamata con un oggetto contenente
|
18
|
+
* informazioni sull'errore. In caso di successo, la callback viene chiamata con un
|
19
|
+
* messaggio di conferma.
|
20
|
+
*/
|
21
|
+
import { gun } from "../../state/gun";
|
22
|
+
|
23
|
+
let sendVoiceMessage = (
|
24
|
+
roomId,
|
25
|
+
publicKey,
|
26
|
+
voiceRecording,
|
27
|
+
callback = () => {}
|
28
|
+
) => {
|
29
|
+
(async (callback = () => {}) => {
|
30
|
+
let userPub = await gun.user().pair().pub;
|
31
|
+
let userPair = await gun.user()._.sea;
|
32
|
+
let friend = await gun.user(publicKey);
|
33
|
+
|
34
|
+
if (!userPub)
|
35
|
+
return callback({
|
36
|
+
errMessage: "Could not find pub.",
|
37
|
+
errCode: "failed-to-find-pub",
|
38
|
+
success: undefined,
|
39
|
+
});
|
40
|
+
|
41
|
+
let createMessagesCertificate = await gun
|
42
|
+
.user(publicKey)
|
43
|
+
.get("certificates")
|
44
|
+
.get(userPub)
|
45
|
+
.get("messages");
|
46
|
+
|
47
|
+
if (!createMessagesCertificate)
|
48
|
+
return callback({
|
49
|
+
errMessage: "Could not find friend certificate to create message",
|
50
|
+
errCode: "failed-to-find-friend-messages-certificate",
|
51
|
+
success: undefined,
|
52
|
+
});
|
53
|
+
|
54
|
+
let updateMetaCertificate = await gun
|
55
|
+
.user(publicKey)
|
56
|
+
.get("certificates")
|
57
|
+
.get(userPub)
|
58
|
+
.get("chats");
|
59
|
+
|
60
|
+
if (!updateMetaCertificate)
|
61
|
+
return callback({
|
62
|
+
errMessage: "Could not find friend certificate to add meta to chat",
|
63
|
+
errCode: "failed-to-find-friend-chats-certificate",
|
64
|
+
success: undefined,
|
65
|
+
});
|
66
|
+
|
67
|
+
gun
|
68
|
+
.user()
|
69
|
+
.get("chats")
|
70
|
+
.get(roomId)
|
71
|
+
.get("latestMessage")
|
72
|
+
.put(voiceRecording);
|
73
|
+
|
74
|
+
gun
|
75
|
+
.user(publicKey)
|
76
|
+
.get("chats")
|
77
|
+
.get(roomId)
|
78
|
+
.get("latestMessage")
|
79
|
+
.put(voiceRecording, null, { opt: { cert: updateMetaCertificate } });
|
80
|
+
|
81
|
+
gun
|
82
|
+
.user()
|
83
|
+
.get("messages")
|
84
|
+
.get(roomId)
|
85
|
+
.set(voiceRecording, ({ err }) => {
|
86
|
+
if (err)
|
87
|
+
return callback({
|
88
|
+
errMessage: err,
|
89
|
+
errCode: "message-creation-error",
|
90
|
+
success: undefined,
|
91
|
+
});
|
92
|
+
else
|
93
|
+
gun
|
94
|
+
.user(publicKey)
|
95
|
+
.get("messages")
|
96
|
+
.get(roomId)
|
97
|
+
.set(
|
98
|
+
voiceRecording,
|
99
|
+
({ err }) => {
|
100
|
+
if (err)
|
101
|
+
return callback({
|
102
|
+
errMessage: err,
|
103
|
+
errCode: "message-creation-error",
|
104
|
+
success: undefined,
|
105
|
+
});
|
106
|
+
else
|
107
|
+
return callback({
|
108
|
+
errMessage: undefined,
|
109
|
+
errCode: undefined,
|
110
|
+
success: "Created a voice message with friend.",
|
111
|
+
});
|
112
|
+
},
|
113
|
+
{ opt: { cert: createMessagesCertificate } }
|
114
|
+
);
|
115
|
+
});
|
116
|
+
})(callback);
|
117
|
+
};
|
118
|
+
|
119
|
+
export default sendVoiceMessage;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/**
|
2
|
+
* Creates a new note.
|
3
|
+
* @param {string} title - The title of the note.
|
4
|
+
* @param {string} author - The author of the note.
|
5
|
+
* @param {string} content - The content of the note.
|
6
|
+
* @param {boolean} isPublic - Whether the note is public or private.
|
7
|
+
* @param {string} [verification=''] - Verification data for public notes.
|
8
|
+
* @returns {Promise<string>} A promise that resolves to the note's hash.
|
9
|
+
*/
|
10
|
+
const createNote = async (title, author, content, isPublic, verification = '') => {
|
11
|
+
if (!isPublic && !user.is) {
|
12
|
+
console.log("L'utente deve essere autenticato per creare note private");
|
13
|
+
throw new Error("L'utente deve essere autenticato per creare note private");
|
14
|
+
}
|
15
|
+
|
16
|
+
const noteData = {
|
17
|
+
title: DOMPurify.sanitize(title),
|
18
|
+
author: DOMPurify.sanitize(author),
|
19
|
+
content: DOMPurify.sanitize(content),
|
20
|
+
verification: isPublic ? DOMPurify.sanitize(verification) : '',
|
21
|
+
lastUpdated: new Date().toISOString(),
|
22
|
+
isPublic: isPublic
|
23
|
+
};
|
24
|
+
|
25
|
+
const noteString = JSON.stringify(noteData);
|
26
|
+
const hash = await SEA.work(noteString, null, null, { name: "SHA-256" });
|
27
|
+
|
28
|
+
if (isPublic) {
|
29
|
+
await gun.get("gun-eth").get("public-notes").get(hash).put(noteString);
|
30
|
+
} else {
|
31
|
+
if (!user.is) {
|
32
|
+
throw new Error("L'utente deve essere autenticato per creare note private");
|
33
|
+
}
|
34
|
+
await user.get("gun-eth").get("private-notes").get(hash).put(noteData);
|
35
|
+
}
|
36
|
+
|
37
|
+
return hash;
|
38
|
+
};
|
39
|
+
|
40
|
+
export default createNote;
|
41
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/**
|
2
|
+
* Deletes a note by its hash.
|
3
|
+
* @param {string} hash - The hash of the note to delete.
|
4
|
+
* @returns {Promise<void>}
|
5
|
+
*/
|
6
|
+
export const deleteNote = async (hash, isPublic) => {
|
7
|
+
if (isPublic) {
|
8
|
+
await gun.get("gun-eth").get("public-notes").get(hash).put(null);
|
9
|
+
} else {
|
10
|
+
await user.get("gun-eth").get("private-notes").get(hash).put(null);
|
11
|
+
}
|
12
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/**
|
2
|
+
* Retrieves a note by its hash.
|
3
|
+
* @param {string} hash - The hash of the note to retrieve.
|
4
|
+
* @returns {Promise<Object|null>} A promise that resolves to the note object or null if not found.
|
5
|
+
*/
|
6
|
+
const getNote = async (hash) => {
|
7
|
+
const publicNote = await gun.get("gun-eth").get("public-notes").get(hash).then();
|
8
|
+
if (publicNote) {
|
9
|
+
return JSON.parse(publicNote);
|
10
|
+
}
|
11
|
+
|
12
|
+
if (!user.is) {
|
13
|
+
throw new Error("L'utente deve essere autenticato per accedere alle note private");
|
14
|
+
}
|
15
|
+
|
16
|
+
const privateNote = await user.get("gun-eth").get("private-notes").get(hash).then();
|
17
|
+
if (privateNote) {
|
18
|
+
const decryptedData = await SEA.decrypt(privateNote, user._.sea);
|
19
|
+
return JSON.parse(decryptedData);
|
20
|
+
}
|
21
|
+
|
22
|
+
return null;
|
23
|
+
};
|
24
|
+
|
25
|
+
export default getNote;
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Retrieves all notes for the current user.
|
4
|
+
* @returns {Promise<Array>} A promise that resolves to an array of user's notes.
|
5
|
+
*/
|
6
|
+
const getUserNotes = () => {
|
7
|
+
return new Promise((resolve) => {
|
8
|
+
const notes = [];
|
9
|
+
|
10
|
+
const loadPublicNotes = () => {
|
11
|
+
return new Promise((resolvePublic) => {
|
12
|
+
gun.get("gun-eth").get("public-notes").map().once((data, id) => {
|
13
|
+
if (data && id !== '_') {
|
14
|
+
try {
|
15
|
+
notes.push({ id, ...JSON.parse(data), isPublic: true });
|
16
|
+
} catch (error) {
|
17
|
+
console.error("Errore durante il parsing della nota pubblica:", error);
|
18
|
+
notes.push({ id, error: "Errore durante il parsing della nota", isPublic: true });
|
19
|
+
}
|
20
|
+
}
|
21
|
+
});
|
22
|
+
setTimeout(resolvePublic, 500);
|
23
|
+
});
|
24
|
+
};
|
25
|
+
|
26
|
+
const loadPrivateNotes = () => {
|
27
|
+
return new Promise((resolvePrivate) => {
|
28
|
+
if (user.is) {
|
29
|
+
user.get("gun-eth").get("private-notes").map().once(async (data, id) => {
|
30
|
+
if (data && id !== '_') {
|
31
|
+
try {
|
32
|
+
const decryptedData = await SEA.decrypt(data, user._.sea);
|
33
|
+
console.log("decryptedData:", decryptedData);
|
34
|
+
if (typeof decryptedData === 'string' ) {
|
35
|
+
notes.push({ id, ...JSON.parse(decryptedData), isPublic: false });
|
36
|
+
} else if (typeof decryptedData === 'object' && decryptedData !== null) {
|
37
|
+
notes.push({ id, ...decryptedData, isPublic: false });
|
38
|
+
} else {
|
39
|
+
console.error("Dati decriptati non validi:", decryptedData);
|
40
|
+
notes.push({ id, error: "Dati decriptati non validi", isPublic: false });
|
41
|
+
}
|
42
|
+
} catch (error) {
|
43
|
+
console.error("Errore durante la decrittazione della nota privata:", error);
|
44
|
+
notes.push({ id, error: "Errore durante la decrittazione della nota", isPublic: false });
|
45
|
+
}
|
46
|
+
}
|
47
|
+
});
|
48
|
+
}
|
49
|
+
setTimeout(resolvePrivate, 500);
|
50
|
+
});
|
51
|
+
};
|
52
|
+
|
53
|
+
Promise.all([loadPublicNotes(), loadPrivateNotes()]).then(() => {
|
54
|
+
resolve(notes);
|
55
|
+
});
|
56
|
+
});
|
57
|
+
};
|
58
|
+
|
59
|
+
export default getUserNotes;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import createNote from "./createNote";
|
2
|
+
import deleteNote from "./deleteNote";
|
3
|
+
import getNote from "./getNote";
|
4
|
+
import updateNote from "./updateNote";
|
5
|
+
import getUserNotes from "./getUserNote";
|
6
|
+
|
7
|
+
export { createNote, deleteNote, getNote, updateNote, getUserNotes };
|
8
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/**
|
2
|
+
* Updates an existing note.
|
3
|
+
* @param {string} hash - The hash of the note to update.
|
4
|
+
* @param {string} title - The updated title of the note.
|
5
|
+
* @param {string} author - The updated author of the note.
|
6
|
+
* @param {string} content - The updated content of the note.
|
7
|
+
* @param {boolean} isPublic - Whether the note is public or private.
|
8
|
+
* @param {string} [verification=''] - Updated verification data for public notes.
|
9
|
+
* @returns {Promise<void>}
|
10
|
+
*/
|
11
|
+
const updateNote = async (hash, title, author, content, isPublic, verification = '') => {
|
12
|
+
const noteData = {
|
13
|
+
title: DOMPurify.sanitize(title),
|
14
|
+
author: DOMPurify.sanitize(author),
|
15
|
+
content: DOMPurify.sanitize(content),
|
16
|
+
verification: isPublic ? DOMPurify.sanitize(verification) : '',
|
17
|
+
lastUpdated: new Date().toISOString(),
|
18
|
+
isPublic: isPublic
|
19
|
+
};
|
20
|
+
|
21
|
+
const noteString = JSON.stringify(noteData);
|
22
|
+
|
23
|
+
if (isPublic) {
|
24
|
+
await gun.get("gun-eth").get("public-notes").get(hash).put(noteString);
|
25
|
+
} else {
|
26
|
+
if (!user.is) {
|
27
|
+
throw new Error("L'utente deve essere autenticato per aggiornare note private");
|
28
|
+
}
|
29
|
+
const encryptedData = await SEA.encrypt(noteString, user._.sea);
|
30
|
+
await user.get("gun-eth").get("private-notes").get(hash).put(encryptedData);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
|
35
|
+
export default updateNote;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { gun } from "../../state/gun";
|
2
|
+
/**
|
3
|
+
* Creates a new encrypted post.
|
4
|
+
* @param {Object} post - The post object to create.
|
5
|
+
* @param {string} token - The encryption token.
|
6
|
+
* @returns {Promise<string>} A promise that resolves to the new post's key.
|
7
|
+
*/
|
8
|
+
const createPost = async (post, token) => {
|
9
|
+
const dbPosts = gun.get('gun-eth').get('posts');
|
10
|
+
|
11
|
+
const encrypted = await encryptPost(post, token);
|
12
|
+
const key = Date.now().toString();
|
13
|
+
await dbPosts.get(key).put(encrypted);
|
14
|
+
return key;
|
15
|
+
};
|
16
|
+
|
17
|
+
export default createPost;
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import SEA from "gun/sea";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Decrypts a post's text content.
|
5
|
+
* @param {Object} post - The encrypted post object to decrypt.
|
6
|
+
* @param {string} token - The decryption token.
|
7
|
+
* @returns {Promise<Object>} A promise that resolves to the decrypted post object.
|
8
|
+
*/
|
9
|
+
const decryptPost = async (post, token) => {
|
10
|
+
const text = await SEA.decrypt(post.text, token);
|
11
|
+
return { ...post, text };
|
12
|
+
};
|
13
|
+
|
14
|
+
export default decryptPost;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { gun } from "../../state/gun";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Deletes a post by its key.
|
5
|
+
* @param {string} key - The key of the post to delete.
|
6
|
+
* @returns {Promise<void>}
|
7
|
+
*/
|
8
|
+
const deletePost = async (key) => {
|
9
|
+
const dbPosts = gun.get('gun-eth').get('posts');
|
10
|
+
await dbPosts.get(key).put(null);
|
11
|
+
};
|
12
|
+
|
13
|
+
export default deletePost;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import SEA from "gun/sea";
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Encrypts a post's text content.
|
5
|
+
* @param {Object} post - The post object to encrypt.
|
6
|
+
* @param {string} token - The encryption token.
|
7
|
+
* @returns {Promise<Object>} A promise that resolves to the encrypted post object.
|
8
|
+
*/
|
9
|
+
const encryptPost = async (post, token) => {
|
10
|
+
const text = await SEA.encrypt(post.text, token);
|
11
|
+
return { ...post, text };
|
12
|
+
};
|
13
|
+
|
14
|
+
|
15
|
+
export default encryptPost;
|
16
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { gun } from "../../state/gun";
|
2
|
+
import decryptPost from "./decryptPost";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Retrieves and decrypts a post by its key.
|
6
|
+
* @param {string} key - The key of the post to retrieve.
|
7
|
+
* @param {string} token - The decryption token.
|
8
|
+
* @returns {Promise<Object|null>} A promise that resolves to the decrypted post object or null if not found.
|
9
|
+
*/
|
10
|
+
export const getPost = async (key, token) => {
|
11
|
+
const dbPosts = gun.get('gun-eth').get('posts');
|
12
|
+
|
13
|
+
const post = await dbPosts.get(key).then();
|
14
|
+
if (post) {
|
15
|
+
return await decryptPost(post, token);
|
16
|
+
}
|
17
|
+
return null;
|
18
|
+
};
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Retrieves and decrypts all posts.
|
22
|
+
* @param {string} token - The decryption token.
|
23
|
+
* @returns {Promise<Array>} A promise that resolves to an array of decrypted post objects.
|
24
|
+
*/
|
25
|
+
exportconst getAllPosts = async (token) => {
|
26
|
+
return new Promise((resolve) => {
|
27
|
+
const posts = [];
|
28
|
+
dbPosts.map().once(async (data, key) => {
|
29
|
+
if (data) {
|
30
|
+
const decrypted = await decryptPost(data, token);
|
31
|
+
posts.push({ ...decrypted, id: key });
|
32
|
+
}
|
33
|
+
resolve(posts);
|
34
|
+
});
|
35
|
+
});
|
36
|
+
};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import createPost from "./createPost";
|
2
|
+
import deletePost from "./deletePost";
|
3
|
+
import getPost from "./getPost";
|
4
|
+
import updatePost from "./updatePost";
|
5
|
+
import decryptPost from "./decryptPost";
|
6
|
+
import encryptPost from "./encryptPost";
|
7
|
+
import getAllPosts from "./getPost";
|
8
|
+
|
9
|
+
export { createPost, deletePost, getPost, updatePost, decryptPost, encryptPost, getAllPosts };
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { gun } from "../../state/gun";
|
2
|
+
import encryptPost from "./encryptPost";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Updates an existing post with new encrypted content.
|
6
|
+
* @param {string} key - The key of the post to update.
|
7
|
+
* @param {Object} post - The updated post object.
|
8
|
+
* @param {string} token - The encryption token.
|
9
|
+
* @returns {Promise<void>}
|
10
|
+
*/
|
11
|
+
const updatePost = async (key, post, token) => {
|
12
|
+
const encrypted = await encryptPost(post, token);
|
13
|
+
await dbPosts.get(key).put(encrypted);
|
14
|
+
};
|
15
|
+
|
16
|
+
export default updatePost;
|
package/src/state/gun.js
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
/**
|
2
|
+
* Modulo per l'inizializzazione e la configurazione di Gun.js
|
3
|
+
* @module gun
|
4
|
+
*/
|
5
|
+
|
6
|
+
// Importa il modulo principale di Gun
|
7
|
+
import Gun from "gun/gun";
|
8
|
+
// Importa i moduli aggiuntivi di Gun
|
9
|
+
import "gun/sea"; // Per la crittografia
|
10
|
+
import "gun/lib/radix"; // Per l'ottimizzazione delle prestazioni
|
11
|
+
import "gun/lib/radisk"; // Per la persistenza dei dati
|
12
|
+
import "gun/lib/store"; // Per il salvataggio dei dati
|
13
|
+
import "gun/lib/rindexed"; // Per l'indicizzazione dei dati
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Inizializza un'istanza di Gun con configurazioni specifiche
|
17
|
+
* @type {Gun}
|
18
|
+
*/
|
19
|
+
let gun = new Gun({
|
20
|
+
peers: ["https://gun-relay.scobrudot.dev/gun"], // Server peer per la sincronizzazione dei dati
|
21
|
+
axe: false, // Disabilita il protocollo AXE
|
22
|
+
localStorage: false, // Disabilita l'uso di localStorage
|
23
|
+
radisk: true, // Abilita Radisk per la persistenza dei dati
|
24
|
+
});
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Inizializza un utente Gun e richiama la sessione da sessionStorage
|
28
|
+
* @type {GunUser}
|
29
|
+
*/
|
30
|
+
let user = gun.user().recall({ sessionStorage: true });
|
31
|
+
|
32
|
+
// Esporta le istanze gun e user per l'uso in altri moduli
|
33
|
+
export { gun, user };
|