gun-eth 1.3.2 → 1.3.5

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