gun-eth 1.3.1 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
package/src/index.js CHANGED
@@ -1,379 +1,5 @@
1
- const Gun = require("gun/gun");
2
- const SEA = require("gun/sea");
3
- const ethers = require("ethers");
4
- const SHINE = require("../abis/SHINE.json");
5
-
6
- const SHINE_ABI = SHINE.abi;
7
- const SHINE_OPTIMISM_SEPOLIA = SHINE.address;
8
-
9
- let SHINE_CONTRACT_ADDRESS;
10
- let customToken = "";
11
-
12
- let rpcUrl = "";
13
- let privateKey = "";
14
-
15
- const MESSAGE_TO_SIGN = "Accesso a GunDB con Ethereum";
16
-
17
- /**
18
- * Funzione per ottenere il signer
19
- * @returns {Promise<ethers.Signer>} Il signer.
20
- */
21
- const getSigner = async () => {
22
- if (rpcUrl && privateKey) {
23
- // Modalità standalone
24
- const provider = new ethers.JsonRpcProvider(rpcUrl);
25
- return new ethers.Wallet(privateKey, provider);
26
- } else if (
27
- typeof window !== "undefined" &&
28
- typeof window.ethereum !== "undefined"
29
- ) {
30
- // Modalità browser
31
- await window.ethereum.request({ method: "eth_requestAccounts" });
32
- const provider = new ethers.BrowserProvider(window.ethereum);
33
- return provider.getSigner();
34
- } else {
35
- throw new Error("No valid Ethereum provider found");
36
- }
37
- };
38
-
39
- /**
40
- * Sets standalone configuration for Gun.
41
- * @param {string} newRpcUrl - The new RPC URL.
42
- * @param {string} newPrivateKey - The new private key.
43
- * @returns {Gun} The Gun instance for chaining.
44
- */
45
- Gun.chain.setStandaloneConfig = function (newRpcUrl, newPrivateKey) {
46
- rpcUrl = newRpcUrl;
47
- privateKey = newPrivateKey;
48
- console.log("Standalone configuration set");
49
- return this;
50
- };
51
-
52
- /**
53
- * Sets a custom token for Gun operations.
54
- * @param {string} token - The token to be set.
55
- * @returns {Gun} The Gun instance for chaining.
56
- */
57
- Gun.chain.setToken = function (token) {
58
- if (typeof token === "string" && token.length > 0) {
59
- customToken = token;
60
- console.log("Token set successfully:", token);
61
- } else {
62
- console.error("Invalid token. Must be a non-empty string.");
63
- }
64
- return this;
65
- };
66
-
67
- /**
68
- * Retrieves the current custom token.
69
- * @returns {string} The current custom token.
70
- */
71
- Gun.chain.getToken = function () {
72
- return customToken;
73
- };
74
-
75
- // Add custom token to all 'put' operations
76
- Gun.on("put", function (msg) {
77
- const to = this.to;
78
- msg.headers = {
79
- token: customToken,
80
- };
81
- to.next(msg);
82
- });
83
-
84
- /**
85
- * Verifies an Ethereum signature.
86
- * @param {string} message - The original message that was signed.
87
- * @param {string} signature - The signature to verify.
88
- * @returns {Promise<string|null>} The recovered address or null if verification fails.
89
- */
90
- Gun.chain.verifySignature = async function (message, signature) {
91
- try {
92
- const recoveredAddress = ethers.verifyMessage(message, signature);
93
- return recoveredAddress;
94
- } catch (error) {
95
- console.error("Error verifying signature:", error);
96
- return null;
97
- }
98
- };
99
-
100
- /**
101
- * Generates a password from a signature.
102
- * @param {string} signature - The signature to derive the password from.
103
- * @returns {string|null} The generated password or null if generation fails.
104
- */
105
- Gun.chain.generatePassword = function (signature) {
106
- try {
107
- const hexSignature = ethers.hexlify(signature);
108
- const hash = ethers.keccak256(hexSignature);
109
- console.log("Generated password:", hash);
110
- return hash;
111
- } catch (error) {
112
- console.error("Error generating password:", error);
113
- return null;
114
- }
115
- };
116
-
117
- /**
118
- * Creates an Ethereum signature for a given message.
119
- * @param {string} message - The message to sign.
120
- * @returns {Promise<string|null>} The signature or null if signing fails.
121
- */
122
- Gun.chain.createSignature = async function (message) {
123
- try {
124
- // Verifica se il messaggio è uguale a MESSAGE_TO_SIGN
125
- if (message !== MESSAGE_TO_SIGN) {
126
- throw new Error("Invalid message, valid message is: " + MESSAGE_TO_SIGN);
127
- }
128
- const signer = await getSigner();
129
- const signature = await signer.signMessage(message);
130
- console.log("Signature created:", signature);
131
- return signature;
132
- } catch (error) {
133
- console.error("Error creating signature:", error);
134
- return null;
135
- }
136
- };
137
-
138
- /**
139
- * Creates and stores an encrypted key pair for a given address.
140
- * @param {string} address - The Ethereum address to associate with the key pair.
141
- * @param {string} signature - The signature to use for encryption.
142
- * @returns {Promise<void>}
143
- */
144
- Gun.chain.createAndStoreEncryptedPair = async function (address, signature) {
145
- try {
146
- const gun = this;
147
- const pair = await SEA.pair();
148
- const encryptedPair = await SEA.encrypt(JSON.stringify(pair), signature);
149
- await gun.get("gun-eth").get("users").get(address).put({ encryptedPair });
150
- console.log("Encrypted pair stored for:", address);
151
- } catch (error) {
152
- console.error("Error creating and storing encrypted pair:", error);
153
- }
154
- };
155
-
156
- /**
157
- * Retrieves and decrypts a stored key pair for a given address.
158
- * @param {string} address - The Ethereum address associated with the key pair.
159
- * @param {string} signature - The signature to use for decryption.
160
- * @returns {Promise<Object|null>} The decrypted key pair or null if retrieval fails.
161
- */
162
- Gun.chain.getAndDecryptPair = async function (address, signature) {
163
- try {
164
- const gun = this;
165
- const encryptedData = await gun
166
- .get("gun-eth")
167
- .get("users")
168
- .get(address)
169
- .get("encryptedPair")
170
- .then();
171
- if (!encryptedData) {
172
- throw new Error("No encrypted data found for this address");
173
- }
174
- const decryptedPair = await SEA.decrypt(encryptedData, signature);
175
- console.log(decryptedPair);
176
- return decryptedPair;
177
- } catch (error) {
178
- console.error("Error retrieving and decrypting pair:", error);
179
- return null;
180
- }
181
- };
182
-
183
- /**
184
- * SHINE (Secure Hybrid Information and Network Environment) functionality.
185
- * @param {string} chain - The blockchain to use (e.g., "optimismSepolia").
186
- * @param {string} nodeId - The ID of the node to verify or write.
187
- * @param {Object} data - The data to write (if writing).
188
- * @param {Function} callback - Callback function to handle the result.
189
- * @returns {Gun} The Gun instance for chaining.
190
- */
191
- Gun.chain.shine = function (chain, nodeId, data, callback) {
192
- console.log("SHINE plugin called with:", { chain, nodeId, data });
193
-
194
- if (typeof callback !== "function") {
195
- console.error("Callback must be a function");
196
- return this;
197
- }
198
-
199
- const gun = this;
200
-
201
- // Seleziona l'indirizzo basato sulla catena
202
- if (chain === "optimismSepolia") {
203
- SHINE_CONTRACT_ADDRESS = SHINE_OPTIMISM_SEPOLIA;
204
- } else {
205
- throw new Error("Chain not supported");
206
- }
207
- // Funzione per verificare on-chain
208
- const verifyOnChain = async (nodeId, contentHash) => {
209
- console.log("Verifying on chain:", { nodeId, contentHash });
210
- const signer = await getSigner();
211
- const contract = new ethers.Contract(
212
- SHINE_CONTRACT_ADDRESS,
213
- SHINE_ABI,
214
- signer
215
- );
216
- const [isValid, timestamp, updater] = await contract.verifyData(
217
- ethers.toUtf8Bytes(nodeId),
218
- contentHash
219
- );
220
- console.log("Verification result:", { isValid, timestamp, updater });
221
- return { isValid, timestamp, updater };
222
- };
223
-
224
- // Funzione per scrivere on-chain
225
- const writeOnChain = async (nodeId, contentHash) => {
226
- console.log("Writing on chain:", { nodeId, contentHash });
227
- const signer = await getSigner();
228
- const contract = new ethers.Contract(
229
- SHINE_CONTRACT_ADDRESS,
230
- SHINE_ABI,
231
- signer
232
- );
233
- const tx = await contract.updateData(
234
- ethers.toUtf8Bytes(nodeId),
235
- contentHash
236
- );
237
- console.log("Transaction sent:", tx.hash);
238
- const receipt = await tx.wait();
239
- console.log("Transaction confirmed:", receipt);
240
- return tx;
241
- };
242
-
243
- // Nuova funzione per ottenere l'ultimo record dalla blockchain
244
- const getLatestRecord = async (nodeId) => {
245
- const signer = await getSigner();
246
- const contract = new ethers.Contract(
247
- SHINE_CONTRACT_ADDRESS,
248
- SHINE_ABI,
249
- signer
250
- );
251
- const [contentHash, timestamp, updater] = await contract.getLatestRecord(
252
- ethers.toUtf8Bytes(nodeId)
253
- );
254
- console.log("Latest record from blockchain:", {
255
- nodeId,
256
- contentHash,
257
- timestamp,
258
- updater,
259
- });
260
- return { contentHash, timestamp, updater };
261
- };
262
-
263
- // Processo SHINE
264
- if (nodeId && !data) {
265
- // Caso 1: Utente passa solo il nodo
266
- gun.get(nodeId).once(async (existingData) => {
267
- if (!existingData) {
268
- if (callback) callback({ err: "Node not found in GunDB" });
269
- return;
270
- }
271
-
272
- console.log("existingData", existingData);
273
-
274
- // Usa il contentHash memorizzato invece di ricalcolarlo
275
- const contentHash = existingData._contentHash;
276
- console.log("contentHash", contentHash);
277
-
278
- if (!contentHash) {
279
- if (callback) callback({ err: "No content hash found for this node" });
280
- return;
281
- }
282
-
283
- try {
284
- const { isValid, timestamp, updater } = await verifyOnChain(
285
- nodeId,
286
- contentHash
287
- );
288
- const latestRecord = await getLatestRecord(nodeId);
289
-
290
- if (isValid) {
291
- if (callback)
292
- callback({
293
- ok: true,
294
- message: "Data verified on blockchain",
295
- timestamp,
296
- updater,
297
- latestRecord,
298
- });
299
- } else {
300
- if (callback)
301
- callback({
302
- ok: false,
303
- message: "Data not verified on blockchain",
304
- latestRecord,
305
- });
306
- }
307
- } catch (error) {
308
- if (callback) callback({ err: error.message });
309
- }
310
- });
311
- } else if (data && !nodeId) {
312
- // Caso 2: Utente passa solo il testo (data)
313
- const newNodeId = Gun.text.random();
314
- const dataString = JSON.stringify(data);
315
- const contentHash = ethers.keccak256(ethers.toUtf8Bytes(dataString));
316
-
317
- gun
318
- .get(newNodeId)
319
- .put({ ...data, _contentHash: contentHash }, async (ack) => {
320
- console.log("ack", ack);
321
- if (ack.err) {
322
- if (callback) callback({ err: "Error saving data to GunDB" });
323
- return;
324
- }
325
-
326
- try {
327
- const tx = await writeOnChain(newNodeId, contentHash);
328
- if (callback)
329
- callback({
330
- ok: true,
331
- message: "Data written to GunDB and blockchain",
332
- nodeId: newNodeId,
333
- txHash: tx.hash,
334
- });
335
- } catch (error) {
336
- if (callback) callback({ err: error.message });
337
- }
338
- });
339
- } else {
340
- if (callback)
341
- callback({
342
- err: "Invalid input. Provide either nodeId or data, not both.",
343
- });
344
- }
345
-
346
- return gun;
347
- };
348
-
349
-
350
- /**
351
- * Converts a Gun private key to an Ethereum account.
352
- * @param {string} gunPrivateKey - The Gun private key in base64url format.
353
- * @returns {Object} An object containing the Ethereum account and public key.
354
- */
355
- Gun.chain.gunToEthAccount = function(gunPrivateKey) {
356
- // Function to convert base64url to hex
357
- const base64UrlToHex = (base64url) => {
358
- const padding = "=".repeat((4 - (base64url.length % 4)) % 4);
359
- const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/") + padding;
360
- const binary = atob(base64);
361
- return Array.from(binary, (char) => char.charCodeAt(0).toString(16).padStart(2, "0")).join("");
362
- };
363
-
364
- // Convert Gun private key to hex format
365
- const hexPrivateKey = "0x" + base64UrlToHex(gunPrivateKey);
366
-
367
- // Create an Ethereum wallet from the private key
368
- const wallet = new ethers.Wallet(hexPrivateKey);
369
-
370
- // Get the public address (public key)
371
- const publicKey = wallet.address;
372
-
373
- return {
374
- account: wallet,
375
- publicKey: publicKey
376
- };
377
- };
378
-
379
- module.exports = Gun;
1
+ if (typeof window === 'undefined') {
2
+ module.exports = require('./node/gun-eth-node.js');
3
+ } else {
4
+ module.exports = require('./browser/gun-eth-browser.js');
5
+ }