gun-eth 1.3.6 → 1.4.0

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.
package/src/index.js DELETED
@@ -1,533 +0,0 @@
1
- (function (root, factory) {
2
- if (typeof define === "function" && define.amd) {
3
- define(["gun", "gun/sea", "ethers"], factory);
4
- } else if (typeof module === "object" && module.exports) {
5
- module.exports = factory(
6
- require("gun"),
7
- require("gun/sea"),
8
- require("ethers")
9
- );
10
- } else {
11
- factory(root.Gun, root.SEA, root.ethers);
12
- }
13
- })(typeof self !== "undefined" ? self : this, function (Gun, SEA, ethers) {
14
- console.log("Factory del plugin Gun-Eth chiamata");
15
-
16
- const MESSAGE_TO_SIGN = "Accesso a GunDB con Ethereum";
17
-
18
- // Funzione per verificare se ethers è disponibile
19
- function checkEthers() {
20
- if (typeof ethers === "undefined") {
21
- console.error(
22
- "Ethers.js non è disponibile. Assicurati che sia caricato prima di questo script."
23
- );
24
- return false;
25
- }
26
- console.log("Ethers version:", ethers.version);
27
- return true;
28
- }
29
-
30
- // Global variables
31
- let SHINE_ABI = [
32
- {
33
- anonymous: false,
34
- inputs: [
35
- {
36
- indexed: true,
37
- internalType: "bytes",
38
- name: "nodeId",
39
- type: "bytes",
40
- },
41
- {
42
- indexed: false,
43
- internalType: "bytes32",
44
- name: "contentHash",
45
- type: "bytes32",
46
- },
47
- {
48
- indexed: false,
49
- internalType: "address",
50
- name: "updater",
51
- type: "address",
52
- },
53
- ],
54
- name: "DataUpdated",
55
- type: "event",
56
- },
57
- {
58
- inputs: [
59
- {
60
- internalType: "bytes[]",
61
- name: "nodeIds",
62
- type: "bytes[]",
63
- },
64
- {
65
- internalType: "bytes32[]",
66
- name: "contentHashes",
67
- type: "bytes32[]",
68
- },
69
- ],
70
- name: "batchUpdateData",
71
- outputs: [],
72
- stateMutability: "nonpayable",
73
- type: "function",
74
- },
75
- {
76
- inputs: [
77
- {
78
- internalType: "bytes",
79
- name: "nodeId",
80
- type: "bytes",
81
- },
82
- ],
83
- name: "getLatestRecord",
84
- outputs: [
85
- {
86
- internalType: "bytes32",
87
- name: "",
88
- type: "bytes32",
89
- },
90
- {
91
- internalType: "uint256",
92
- name: "",
93
- type: "uint256",
94
- },
95
- {
96
- internalType: "address",
97
- name: "",
98
- type: "address",
99
- },
100
- ],
101
- stateMutability: "view",
102
- type: "function",
103
- },
104
- {
105
- inputs: [
106
- {
107
- internalType: "bytes",
108
- name: "",
109
- type: "bytes",
110
- },
111
- ],
112
- name: "nodeData",
113
- outputs: [
114
- {
115
- internalType: "bytes32",
116
- name: "contentHash",
117
- type: "bytes32",
118
- },
119
- {
120
- internalType: "uint256",
121
- name: "timestamp",
122
- type: "uint256",
123
- },
124
- {
125
- internalType: "address",
126
- name: "updater",
127
- type: "address",
128
- },
129
- ],
130
- stateMutability: "view",
131
- type: "function",
132
- },
133
- {
134
- inputs: [
135
- {
136
- internalType: "bytes",
137
- name: "nodeId",
138
- type: "bytes",
139
- },
140
- {
141
- internalType: "bytes32",
142
- name: "contentHash",
143
- type: "bytes32",
144
- },
145
- ],
146
- name: "updateData",
147
- outputs: [],
148
- stateMutability: "nonpayable",
149
- type: "function",
150
- },
151
- {
152
- inputs: [
153
- {
154
- internalType: "bytes",
155
- name: "nodeId",
156
- type: "bytes",
157
- },
158
- {
159
- internalType: "bytes32",
160
- name: "contentHash",
161
- type: "bytes32",
162
- },
163
- ],
164
- name: "verifyData",
165
- outputs: [
166
- {
167
- internalType: "bool",
168
- name: "",
169
- type: "bool",
170
- },
171
- {
172
- internalType: "uint256",
173
- name: "",
174
- type: "uint256",
175
- },
176
- {
177
- internalType: "address",
178
- name: "",
179
- type: "address",
180
- },
181
- ],
182
- stateMutability: "view",
183
- type: "function",
184
- },
185
- ];
186
-
187
- let SHINE_OPTIMISM_SEPOLIA = "0x43D838b683F772F08f321E5FA265ad3e333BE9C2";
188
- let SHINE_CONTRACT_ADDRESS;
189
- let rpcUrl = "";
190
- let privateKey = "";
191
-
192
- /**
193
- * Funzione per ottenere il signer
194
- * @returns {Promise<ethers.Signer>} Il signer.
195
- */
196
- const getSigner = async () => {
197
- if (rpcUrl && privateKey) {
198
- // Modalità standalone
199
- const provider = new ethers.JsonRpcProvider(rpcUrl);
200
- return new ethers.Wallet(privateKey, provider);
201
- } else if (
202
- typeof window !== "undefined" &&
203
- typeof window.ethereum !== "undefined"
204
- ) {
205
- // Modalità browser
206
- await window.ethereum.request({ method: "eth_requestAccounts" });
207
- const provider = new ethers.BrowserProvider(window.ethereum);
208
- return provider.getSigner();
209
- } else {
210
- throw new Error("No valid Ethereum provider found");
211
- }
212
- };
213
-
214
- /**
215
- * Sets standalone configuration for Gun.
216
- * @param {string} newRpcUrl - The new RPC URL.
217
- * @param {string} newPrivateKey - The new private key.
218
- * @returns {Gun} The Gun instance for chaining.
219
- */
220
- Gun.chain.setStandaloneConfig = function (newRpcUrl, newPrivateKey) {
221
- rpcUrl = newRpcUrl;
222
- privateKey = newPrivateKey;
223
- console.log("Standalone configuration set");
224
- return this;
225
- };
226
-
227
- /**
228
- * Verifies an Ethereum signature.
229
- * @param {string} message - The original message that was signed.
230
- * @param {string} signature - The signature to verify.
231
- * @returns {Promise<string|null>} The recovered address or null if verification fails.
232
- */
233
- Gun.chain.verifySignature = async function (message, signature) {
234
- try {
235
- const recoveredAddress = ethers.verifyMessage(message, signature);
236
- return recoveredAddress;
237
- } catch (error) {
238
- console.error("Error verifying signature:", error);
239
- return null;
240
- }
241
- };
242
-
243
- /**
244
- * Generates a password from a signature.
245
- * @param {string} signature - The signature to derive the password from.
246
- * @returns {string|null} The generated password or null if generation fails.
247
- */
248
- Gun.chain.generatePassword = function (signature) {
249
- try {
250
- const hexSignature = ethers.hexlify(signature);
251
- const hash = ethers.keccak256(hexSignature);
252
- console.log("Generated password:", hash);
253
- return hash;
254
- } catch (error) {
255
- console.error("Error generating password:", error);
256
- return null;
257
- }
258
- };
259
-
260
- /**
261
- * Creates an Ethereum signature for a given message.
262
- * @param {string} message - The message to sign.
263
- * @returns {Promise<string|null>} The signature or null if signing fails.
264
- */
265
- Gun.chain.createSignature = async function (message) {
266
- try {
267
- // Verifica se il messaggio è uguale a MESSAGE_TO_SIGN
268
- if (message !== MESSAGE_TO_SIGN) {
269
- throw new Error(
270
- "Invalid message, valid message is: " + MESSAGE_TO_SIGN
271
- );
272
- }
273
- const signer = await getSigner();
274
- const signature = await signer.signMessage(message);
275
- console.log("Signature created:", signature);
276
- return signature;
277
- } catch (error) {
278
- console.error("Error creating signature:", error);
279
- return null;
280
- }
281
- };
282
-
283
- /**
284
- * Creates and stores an encrypted key pair for a given address.
285
- * @param {string} address - The Ethereum address to associate with the key pair.
286
- * @param {string} signature - The signature to use for encryption.
287
- * @returns {Promise<void>}
288
- */
289
- Gun.chain.createAndStoreEncryptedPair = async function (address, signature) {
290
- try {
291
- const gun = this;
292
- const pair = await SEA.pair();
293
- const encryptedPair = await SEA.encrypt(JSON.stringify(pair), signature);
294
- await gun.get("gun-eth").get("users").get(address).put({ encryptedPair });
295
- console.log("Encrypted pair stored for:", address);
296
- } catch (error) {
297
- console.error("Error creating and storing encrypted pair:", error);
298
- }
299
- };
300
-
301
- /**
302
- * Retrieves and decrypts a stored key pair for a given address.
303
- * @param {string} address - The Ethereum address associated with the key pair.
304
- * @param {string} signature - The signature to use for decryption.
305
- * @returns {Promise<Object|null>} The decrypted key pair or null if retrieval fails.
306
- */
307
- Gun.chain.getAndDecryptPair = async function (address, signature) {
308
- try {
309
- const gun = this;
310
- const encryptedData = await gun
311
- .get("gun-eth")
312
- .get("users")
313
- .get(address)
314
- .get("encryptedPair")
315
- .then();
316
- if (!encryptedData) {
317
- throw new Error("No encrypted data found for this address");
318
- }
319
- const decryptedPair = await SEA.decrypt(encryptedData, signature);
320
- console.log(decryptedPair);
321
- return decryptedPair;
322
- } catch (error) {
323
- console.error("Error retrieving and decrypting pair:", error);
324
- return null;
325
- }
326
- };
327
-
328
- /**
329
- * SHINE (Secure Hybrid Information and Network Environment) functionality.
330
- * @param {string} chain - The blockchain to use (e.g., "optimismSepolia").
331
- * @param {string} nodeId - The ID of the node to verify or write.
332
- * @param {Object} data - The data to write (if writing).
333
- * @param {Function} callback - Callback function to handle the result.
334
- * @returns {Gun} The Gun instance for chaining.
335
- */
336
- Gun.chain.shine = function (chain, nodeId, data, callback) {
337
- console.log("SHINE plugin called with:", { chain, nodeId, data });
338
-
339
- if (!checkEthers()) {
340
- if (callback) callback({ err: "Ethers.js non è disponibile" });
341
- return this;
342
- }
343
-
344
- if (typeof callback !== "function") {
345
- console.error("Callback must be a function");
346
- return this;
347
- }
348
-
349
- const gun = this;
350
-
351
- // Seleziona l'indirizzo basato sulla catena
352
- if (chain === "optimismSepolia") {
353
- SHINE_CONTRACT_ADDRESS = SHINE_OPTIMISM_SEPOLIA;
354
- } else {
355
- throw new Error("Chain not supported");
356
- }
357
-
358
- // Funzione per verificare on-chain
359
- const verifyOnChain = async (nodeId, contentHash) => {
360
- console.log("Verifying on chain:", { nodeId, contentHash });
361
- const signer = await getSigner();
362
- const contract = new ethers.Contract(
363
- SHINE_CONTRACT_ADDRESS,
364
- SHINE_ABI,
365
- signer
366
- );
367
- const [isValid, timestamp, updater] = await contract.verifyData(
368
- ethers.toUtf8Bytes(nodeId),
369
- contentHash
370
- );
371
- console.log("Verification result:", { isValid, timestamp, updater });
372
- return { isValid, timestamp, updater };
373
- };
374
-
375
- // Funzione per scrivere on-chain
376
- const writeOnChain = async (nodeId, contentHash) => {
377
- console.log("Writing on chain:", { nodeId, contentHash });
378
- const signer = await getSigner();
379
- const contract = new ethers.Contract(
380
- SHINE_CONTRACT_ADDRESS,
381
- SHINE_ABI,
382
- signer
383
- );
384
- const tx = await contract.updateData(
385
- ethers.toUtf8Bytes(nodeId),
386
- contentHash
387
- );
388
- console.log("Transaction sent:", tx.hash);
389
- const receipt = await tx.wait();
390
- console.log("Transaction confirmed:", receipt);
391
- return tx;
392
- };
393
-
394
- // Nuova funzione per ottenere l'ultimo record dalla blockchain
395
- const getLatestRecord = async (nodeId) => {
396
- const signer = await getSigner();
397
- const contract = new ethers.Contract(
398
- SHINE_CONTRACT_ADDRESS,
399
- SHINE_ABI,
400
- signer
401
- );
402
- const [contentHash, timestamp, updater] = await contract.getLatestRecord(
403
- ethers.toUtf8Bytes(nodeId)
404
- );
405
- console.log("Latest record from blockchain:", {
406
- nodeId,
407
- contentHash,
408
- timestamp,
409
- updater,
410
- });
411
- return { contentHash, timestamp, updater };
412
- };
413
-
414
- // Processo SHINE
415
- if (nodeId && !data) {
416
- // Caso 1: Utente passa solo il nodo
417
- gun.get(nodeId).once(async (existingData) => {
418
- if (!existingData) {
419
- if (callback) callback({ err: "Node not found in GunDB" });
420
- return;
421
- }
422
-
423
- console.log("existingData", existingData);
424
-
425
- // Usa il contentHash memorizzato invece di ricalcolarlo
426
- const contentHash = existingData._contentHash;
427
- console.log("contentHash", contentHash);
428
-
429
- if (!contentHash) {
430
- if (callback)
431
- callback({ err: "No content hash found for this node" });
432
- return;
433
- }
434
-
435
- try {
436
- const { isValid, timestamp, updater } = await verifyOnChain(
437
- nodeId,
438
- contentHash
439
- );
440
- const latestRecord = await getLatestRecord(nodeId);
441
-
442
- if (isValid) {
443
- if (callback)
444
- callback({
445
- ok: true,
446
- message: "Data verified on blockchain",
447
- timestamp,
448
- updater,
449
- latestRecord,
450
- });
451
- } else {
452
- if (callback)
453
- callback({
454
- ok: false,
455
- message: "Data not verified on blockchain",
456
- latestRecord,
457
- });
458
- }
459
- } catch (error) {
460
- if (callback) callback({ err: error.message });
461
- }
462
- });
463
- } else if (data && !nodeId) {
464
- // Caso 2: Utente passa solo il testo (data)
465
- const newNodeId = Gun.text.random();
466
- const dataString = JSON.stringify(data);
467
- const contentHash = ethers.keccak256(ethers.toUtf8Bytes(dataString));
468
-
469
- gun
470
- .get(newNodeId)
471
- .put({ ...data, _contentHash: contentHash }, async (ack) => {
472
- console.log("ack", ack);
473
- if (ack.err) {
474
- if (callback) callback({ err: "Error saving data to GunDB" });
475
- return;
476
- }
477
-
478
- try {
479
- const tx = await writeOnChain(newNodeId, contentHash);
480
- if (callback)
481
- callback({
482
- ok: true,
483
- message: "Data written to GunDB and blockchain",
484
- nodeId: newNodeId,
485
- txHash: tx.hash,
486
- });
487
- } catch (error) {
488
- if (callback) callback({ err: error.message });
489
- }
490
- });
491
- } else {
492
- if (callback)
493
- callback({
494
- err: "Invalid input. Provide either nodeId or data, not both.",
495
- });
496
- }
497
-
498
- return gun;
499
- };
500
-
501
- /**
502
- * Converts a Gun private key to an Ethereum account.
503
- * @param {string} gunPrivateKey - The Gun private key in base64url format.
504
- * @returns {Object} An object containing the Ethereum account and public key.
505
- */
506
- Gun.chain.gunToEthAccount = function (gunPrivateKey) {
507
- // Function to convert base64url to hex
508
- const base64UrlToHex = (base64url) => {
509
- const padding = "=".repeat((4 - (base64url.length % 4)) % 4);
510
- const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/") + padding;
511
- const binary = atob(base64);
512
- return Array.from(binary, (char) =>
513
- char.charCodeAt(0).toString(16).padStart(2, "0")
514
- ).join("");
515
- };
516
-
517
- // Convert Gun private key to hex format
518
- const hexPrivateKey = "0x" + base64UrlToHex(gunPrivateKey);
519
-
520
- // Create an Ethereum wallet from the private key
521
- const wallet = new ethers.Wallet(hexPrivateKey);
522
-
523
- // Get the public address (public key)
524
- const publicKey = wallet.address;
525
-
526
- return {
527
- account: wallet,
528
- publicKey: publicKey,
529
- };
530
- };
531
-
532
- console.log("Plugin Gun-Eth successfully loaded");
533
- });