gun-eth 1.4.21 → 1.4.23

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/dist/gun-eth.js DELETED
@@ -1,1382 +0,0 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('gun'), require('gun/sea.js'), require('ethers')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'gun', 'gun/sea.js', 'ethers'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GunEth = {}, global.Gun, global.SEA, global.ethers));
5
- })(this, (function (exports, Gun, SEA, ethers) { 'use strict';
6
-
7
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
- var STEALTH_ANNOUNCER_ADDRESS$1 = "";
9
- var PROOF_OF_INTEGRITY_ADDRESS = "";
10
- var require$$0 = {
11
- STEALTH_ANNOUNCER_ADDRESS: STEALTH_ANNOUNCER_ADDRESS$1,
12
- PROOF_OF_INTEGRITY_ADDRESS: PROOF_OF_INTEGRITY_ADDRESS
13
- };
14
-
15
- let contractAddresses$1 = {
16
- PROOF_OF_INTEGRITY_ADDRESS: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
17
- STEALTH_ANNOUNCER_ADDRESS: "0x5FbDB2315678afecb367f032d93F642f64180aa3"
18
- };
19
-
20
- if (typeof window === 'undefined') {
21
- const { fileURLToPath } = require('url');
22
- const { dirname } = require('path');
23
- const { readFileSync } = require('fs');
24
- const { join } = require('path');
25
-
26
- try {
27
- const __filename = fileURLToPath((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('gun-eth.js', document.baseURI).href)));
28
- const __dirname = dirname(__filename);
29
- const rawdata = readFileSync(join(__dirname, 'contract-address.json'), 'utf8');
30
- contractAddresses$1 = JSON.parse(rawdata);
31
- console.log("Loaded contract addresses:", contractAddresses$1);
32
- } catch (error) {
33
- console.warn("Warning: contract-address.json not found or invalid");
34
- }
35
- }
36
-
37
- const LOCAL_CONFIG = {
38
- CHAIN_ID: 1337,
39
- PROOF_OF_INTEGRITY_ADDRESS: contractAddresses$1.PROOF_OF_INTEGRITY_ADDRESS,
40
- STEALTH_ANNOUNCER_ADDRESS: contractAddresses$1.STEALTH_ANNOUNCER_ADDRESS,
41
- RPC_URL: "http://127.0.0.1:8545",
42
- GUN_PEER: "http://localhost:8765/gun"
43
- };
44
-
45
- // Indirizzi di produzione per diverse chain
46
- const CHAIN_CONFIG = {
47
- optimismSepolia: {
48
- STEALTH_ANNOUNCER_ADDRESS: "",
49
- PROOF_OF_INTEGRITY_ADDRESS: "",
50
- RPC_URL: "https://sepolia.optimism.io",
51
- CHAIN_ID: 11155420
52
- },
53
- arbitrumSepolia: {
54
- STEALTH_ANNOUNCER_ADDRESS: "",
55
- PROOF_OF_INTEGRITY_ADDRESS: "",
56
- RPC_URL: "https://sepolia-rollup.arbitrum.io/rpc",
57
- CHAIN_ID: 421614
58
- },
59
- localhost: {
60
- RPC_URL: "http://127.0.0.1:8545",
61
- CHAIN_ID: 1337
62
- }
63
- };
64
-
65
- // Funzione per ottenere gli indirizzi corretti
66
- function getAddressesForChain(chainName) {
67
- let config;
68
-
69
- // Se è localhost, prova a caricare gli indirizzi locali
70
- if (chainName === 'localhost') {
71
- try {
72
- // Carica gli indirizzi dal file generato dal deploy locale
73
- const localAddresses = require$$0;
74
- config = {
75
- ...CHAIN_CONFIG.localhost,
76
- ...localAddresses
77
- };
78
- console.log("Using local addresses:", config);
79
- return config;
80
- } catch (err) {
81
- console.warn('No local addresses found');
82
- throw new Error('No local addresses found. Did you run local deployment?');
83
- }
84
- }
85
-
86
- // Altrimenti usa gli indirizzi di produzione
87
- config = CHAIN_CONFIG[chainName];
88
- if (!config) {
89
- throw new Error(`Chain ${chainName} not supported. Supported chains: ${Object.keys(CHAIN_CONFIG).join(', ')}`);
90
- }
91
-
92
- return config;
93
- }
94
-
95
- const STEALTH_ANNOUNCER_ABI = [
96
- {
97
- "inputs": [
98
- {
99
- "internalType": "address",
100
- "name": "_devAddress",
101
- "type": "address"
102
- }
103
- ],
104
- "stateMutability": "nonpayable",
105
- "type": "constructor"
106
- },
107
- {
108
- "anonymous": false,
109
- "inputs": [
110
- {
111
- "internalType": "string",
112
- "name": "senderPublicKey",
113
- "type": "string"
114
- },
115
- {
116
- "internalType": "string",
117
- "name": "spendingPublicKey",
118
- "type": "string"
119
- },
120
- {
121
- "internalType": "address",
122
- "name": "stealthAddress",
123
- "type": "address"
124
- },
125
- {
126
- "internalType": "uint256",
127
- "name": "timestamp",
128
- "type": "uint256"
129
- }
130
- ],
131
- "name": "StealthPaymentAnnounced",
132
- "type": "event"
133
- },
134
- {
135
- "anonymous": false,
136
- "inputs": [
137
- {
138
- "internalType": "address",
139
- "name": "newAddress",
140
- "type": "address"
141
- }
142
- ],
143
- "name": "DevAddressUpdated",
144
- "type": "event"
145
- },
146
- {
147
- "anonymous": false,
148
- "inputs": [
149
- {
150
- "internalType": "uint256",
151
- "name": "newFee",
152
- "type": "uint256"
153
- }
154
- ],
155
- "name": "DevFeeUpdated",
156
- "type": "event"
157
- },
158
- {
159
- "inputs": [
160
- {
161
- "internalType": "string",
162
- "name": "senderPublicKey",
163
- "type": "string"
164
- },
165
- {
166
- "internalType": "string",
167
- "name": "spendingPublicKey",
168
- "type": "string"
169
- },
170
- {
171
- "internalType": "address",
172
- "name": "stealthAddress",
173
- "type": "address"
174
- }
175
- ],
176
- "name": "announcePayment",
177
- "outputs": [],
178
- "stateMutability": "payable",
179
- "type": "function"
180
- },
181
- {
182
- "inputs": [],
183
- "name": "devAddress",
184
- "outputs": [
185
- {
186
- "internalType": "address",
187
- "name": "",
188
- "type": "address"
189
- }
190
- ],
191
- "stateMutability": "view",
192
- "type": "function"
193
- },
194
- {
195
- "inputs": [],
196
- "name": "devFee",
197
- "outputs": [
198
- {
199
- "internalType": "uint256",
200
- "name": "",
201
- "type": "uint256"
202
- }
203
- ],
204
- "stateMutability": "view",
205
- "type": "function"
206
- },
207
- {
208
- "inputs": [],
209
- "name": "getAnnouncementsCount",
210
- "outputs": [
211
- {
212
- "internalType": "uint256",
213
- "name": "",
214
- "type": "uint256"
215
- }
216
- ],
217
- "stateMutability": "view",
218
- "type": "function"
219
- },
220
- {
221
- "inputs": [
222
- {
223
- "internalType": "uint256",
224
- "name": "fromIndex",
225
- "type": "uint256"
226
- },
227
- {
228
- "internalType": "uint256",
229
- "name": "toIndex",
230
- "type": "uint256"
231
- }
232
- ],
233
- "name": "getAnnouncementsInRange",
234
- "outputs": [
235
- {
236
- "components": [
237
- {
238
- "internalType": "string",
239
- "name": "senderPublicKey",
240
- "type": "string"
241
- },
242
- {
243
- "internalType": "string",
244
- "name": "spendingPublicKey",
245
- "type": "string"
246
- },
247
- {
248
- "internalType": "address",
249
- "name": "stealthAddress",
250
- "type": "address"
251
- },
252
- {
253
- "internalType": "uint256",
254
- "name": "timestamp",
255
- "type": "uint256"
256
- }
257
- ],
258
- "internalType": "struct StealthAnnouncer.StealthAnnouncement[]",
259
- "name": "",
260
- "type": "tuple[]"
261
- }
262
- ],
263
- "stateMutability": "view",
264
- "type": "function"
265
- },
266
- {
267
- "inputs": [
268
- {
269
- "internalType": "uint256",
270
- "name": "_newFee",
271
- "type": "uint256"
272
- }
273
- ],
274
- "name": "updateDevFee",
275
- "outputs": [],
276
- "stateMutability": "nonpayable",
277
- "type": "function"
278
- },
279
- {
280
- "inputs": [
281
- {
282
- "internalType": "address",
283
- "name": "_newAddress",
284
- "type": "address"
285
- }
286
- ],
287
- "name": "updateDevAddress",
288
- "outputs": [],
289
- "stateMutability": "nonpayable",
290
- "type": "function"
291
- },
292
- {
293
- "inputs": [],
294
- "name": "withdrawStuckETH",
295
- "outputs": [],
296
- "stateMutability": "nonpayable",
297
- "type": "function"
298
- }
299
- ];
300
-
301
- const PROOF_OF_INTEGRITY_ABI = [
302
- {
303
- "inputs": [
304
- {
305
- "internalType": "bytes[]",
306
- "name": "nodeIds",
307
- "type": "bytes[]"
308
- },
309
- {
310
- "internalType": "bytes32[]",
311
- "name": "contentHashes",
312
- "type": "bytes32[]"
313
- }
314
- ],
315
- "name": "batchUpdateData",
316
- "outputs": [],
317
- "stateMutability": "nonpayable",
318
- "type": "function"
319
- },
320
- {
321
- "anonymous": false,
322
- "inputs": [
323
- {
324
- "indexed": true,
325
- "internalType": "bytes",
326
- "name": "nodeId",
327
- "type": "bytes"
328
- },
329
- {
330
- "indexed": false,
331
- "internalType": "bytes32",
332
- "name": "contentHash",
333
- "type": "bytes32"
334
- },
335
- {
336
- "indexed": false,
337
- "internalType": "address",
338
- "name": "updater",
339
- "type": "address"
340
- }
341
- ],
342
- "name": "DataUpdated",
343
- "type": "event"
344
- },
345
- {
346
- "inputs": [
347
- {
348
- "internalType": "bytes",
349
- "name": "nodeId",
350
- "type": "bytes"
351
- }
352
- ],
353
- "name": "getLatestRecord",
354
- "outputs": [
355
- {
356
- "internalType": "bytes32",
357
- "name": "",
358
- "type": "bytes32"
359
- },
360
- {
361
- "internalType": "uint256",
362
- "name": "",
363
- "type": "uint256"
364
- },
365
- {
366
- "internalType": "address",
367
- "name": "",
368
- "type": "address"
369
- }
370
- ],
371
- "stateMutability": "view",
372
- "type": "function"
373
- },
374
- {
375
- "inputs": [
376
- {
377
- "internalType": "bytes",
378
- "name": "nodeId",
379
- "type": "bytes"
380
- },
381
- {
382
- "internalType": "bytes32",
383
- "name": "contentHash",
384
- "type": "bytes32"
385
- }
386
- ],
387
- "name": "updateData",
388
- "outputs": [],
389
- "stateMutability": "nonpayable",
390
- "type": "function"
391
- },
392
- {
393
- "inputs": [
394
- {
395
- "internalType": "bytes",
396
- "name": "nodeId",
397
- "type": "bytes"
398
- },
399
- {
400
- "internalType": "bytes32",
401
- "name": "contentHash",
402
- "type": "bytes32"
403
- }
404
- ],
405
- "name": "verifyData",
406
- "outputs": [
407
- {
408
- "internalType": "bool",
409
- "name": "",
410
- "type": "bool"
411
- },
412
- {
413
- "internalType": "uint256",
414
- "name": "",
415
- "type": "uint256"
416
- },
417
- {
418
- "internalType": "address",
419
- "name": "",
420
- "type": "address"
421
- }
422
- ],
423
- "stateMutability": "view",
424
- "type": "function"
425
- }
426
- ];
427
-
428
- // Ottieni gli indirizzi corretti per la chain
429
- const chainConfig = getAddressesForChain('optimismSepolia'); // o la chain desiderata
430
- const STEALTH_ANNOUNCER_ADDRESS = chainConfig.STEALTH_ANNOUNCER_ADDRESS;
431
- chainConfig.PROOF_OF_INTEGRITY_ADDRESS;
432
-
433
- let PROOF_CONTRACT_ADDRESS;
434
- let rpcUrl = "";
435
- let privateKey = "";
436
-
437
- const MESSAGE_TO_SIGN = "Access GunDB with Ethereum";
438
-
439
- let contractAddresses = {
440
- PROOF_OF_INTEGRITY_ADDRESS: null,
441
- STEALTH_ANNOUNCER_ADDRESS: STEALTH_ANNOUNCER_ADDRESS
442
- };
443
-
444
- // Solo per Node.js
445
- if (typeof window === 'undefined') {
446
- const { fileURLToPath } = require('url');
447
- const { dirname } = require('path');
448
- const { readFileSync } = require('fs');
449
- const path = require('path');
450
-
451
- const __filename = fileURLToPath((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('gun-eth.js', document.baseURI).href)));
452
- const __dirname = dirname(__filename);
453
-
454
- try {
455
- const rawdata = readFileSync(path.join(__dirname, 'contract-address.json'), 'utf8');
456
- contractAddresses = JSON.parse(rawdata);
457
- console.log('Loaded contract addresses:', contractAddresses);
458
- } catch (err) {
459
- console.warn('Warning: contract-address.json not found or invalid');
460
- }
461
- }
462
-
463
- // =============================================
464
- // UTILITY FUNCTIONS
465
- // =============================================
466
- /**
467
- * Generates a random node ID for GunDB
468
- * @returns {string} A random hexadecimal string
469
- */
470
- function generateRandomId() {
471
- return ethers.ethers.hexlify(ethers.ethers.randomBytes(32)).slice(2);
472
- }
473
-
474
- /**
475
- * Generates a password from a signature.
476
- * @param {string} signature - The signature to derive the password from.
477
- * @returns {string|null} The generated password or null if generation fails.
478
- */
479
- function generatePassword(signature) {
480
- try {
481
- const hexSignature = ethers.ethers.hexlify(signature);
482
- const hash = ethers.ethers.keccak256(hexSignature);
483
- console.log("Generated password:", hash);
484
- return hash;
485
- } catch (error) {
486
- console.error("Error generating password:", error);
487
- return null;
488
- }
489
- }
490
-
491
- /**
492
- * Converts a Gun private key to an Ethereum account.
493
- * @param {string} gunPrivateKey - The Gun private key in base64url format.
494
- * @returns {Object} An object containing the Ethereum account and public key.
495
- */
496
- function gunToEthAccount(gunPrivateKey) {
497
- // Function to convert base64url to hex
498
- const base64UrlToHex = (base64url) => {
499
- const padding = "=".repeat((4 - (base64url.length % 4)) % 4);
500
- const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/") + padding;
501
- const binary = atob(base64);
502
- return Array.from(binary, (char) =>
503
- char.charCodeAt(0).toString(16).padStart(2, "0")
504
- ).join("");
505
- };
506
-
507
- // Convert Gun private key to hex format
508
- const hexPrivateKey = "0x" + base64UrlToHex(gunPrivateKey);
509
-
510
- // Create an Ethereum wallet from the private key
511
- const wallet = new ethers.ethers.Wallet(hexPrivateKey);
512
-
513
- // Get the public address (public key)
514
- const publicKey = wallet.address;
515
-
516
- return {
517
- account: wallet,
518
- publicKey: publicKey,
519
- privateKey: hexPrivateKey,
520
- };
521
- }
522
-
523
- /**
524
- * Gets an Ethereum signer based on current configuration
525
- * @returns {Promise<ethers.Signer>} The configured signer
526
- * @throws {Error} If no valid provider is found
527
- */
528
- const getSigner = async () => {
529
- if (rpcUrl && privateKey) {
530
- // Standalone mode with local provider
531
- const provider = new ethers.ethers.JsonRpcProvider(rpcUrl, {
532
- chainId: LOCAL_CONFIG.CHAIN_ID,
533
- name: "localhost"
534
- });
535
- return new ethers.ethers.Wallet(privateKey, provider);
536
- } else if (
537
- typeof window !== "undefined" &&
538
- typeof window.ethereum !== "undefined"
539
- ) {
540
- // Browser mode
541
- await window.ethereum.request({ method: "eth_requestAccounts" });
542
- const provider = new ethers.ethers.BrowserProvider(window.ethereum);
543
- return provider.getSigner();
544
- } else {
545
- throw new Error("No valid Ethereum provider found");
546
- }
547
- };
548
-
549
- /**
550
- * Utility function to generate stealth address
551
- * @param {string} sharedSecret - The shared secret
552
- * @param {string} spendingPublicKey - The spending public key
553
- * @returns {Object} The stealth address and private key
554
- */
555
- function deriveStealthAddress(sharedSecret, spendingPublicKey) {
556
- try {
557
- // Convert shared secret to bytes
558
- const sharedSecretBytes = Buffer.from(sharedSecret, 'base64');
559
-
560
- // Generate stealth private key using shared secret and spending public key
561
- const stealthPrivateKey = ethers.ethers.keccak256(
562
- ethers.ethers.concat([
563
- sharedSecretBytes,
564
- ethers.ethers.getBytes(spendingPublicKey)
565
- ])
566
- );
567
-
568
- // Create stealth wallet
569
- const stealthWallet = new ethers.ethers.Wallet(stealthPrivateKey);
570
-
571
- console.log("Debug deriveStealthAddress:", {
572
- sharedSecretHex: ethers.ethers.hexlify(sharedSecretBytes),
573
- spendingPublicKey,
574
- stealthPrivateKey,
575
- stealthAddress: stealthWallet.address
576
- });
577
-
578
- return {
579
- stealthPrivateKey,
580
- stealthAddress: stealthWallet.address,
581
- wallet: stealthWallet
582
- };
583
- } catch (error) {
584
- console.error("Error in deriveStealthAddress:", error);
585
- throw error;
586
- }
587
- }
588
-
589
- // =============================================
590
- // BASIC GUN-ETH CHAIN METHODS
591
- // =============================================
592
-
593
- // Set the message to sign
594
- Gun.chain.MESSAGE_TO_SIGN = MESSAGE_TO_SIGN;
595
-
596
- /**
597
- * Sets standalone configuration for Gun.
598
- * @param {string} newRpcUrl - The new RPC URL.
599
- * @param {string} newPrivateKey - The new private key.
600
- * @returns {Gun} The Gun instance for chaining.
601
- */
602
- Gun.chain.setSigner = function (newRpcUrl, newPrivateKey) {
603
- rpcUrl = newRpcUrl;
604
- privateKey = newPrivateKey;
605
- console.log("Standalone configuration set");
606
- return this;
607
- };
608
-
609
- Gun.chain.getSigner = getSigner();
610
-
611
- /**
612
- * Verifies an Ethereum signature.
613
- * @param {string} message - The original message that was signed.
614
- * @param {string} signature - The signature to verify.
615
- * @returns {Promise<string|null>} The recovered address or null if verification fails.
616
- */
617
- Gun.chain.verifySignature = async function (message, signature) {
618
- try {
619
- const recoveredAddress = ethers.ethers.verifyMessage(message, signature);
620
- return recoveredAddress;
621
- } catch (error) {
622
- console.error("Error verifying signature:", error);
623
- return null;
624
- }
625
- };
626
-
627
- /**
628
- * Generates a password from a signature.
629
- * @param {string} signature - The signature to derive the password from.
630
- * @returns {string|null} The generated password or null if generation fails.
631
- */
632
- Gun.chain.generatePassword = function (signature) {
633
- return generatePassword(signature);
634
- };
635
-
636
- /**
637
- * Creates an Ethereum signature for a given message.
638
- * @param {string} message - The message to sign.
639
- * @returns {Promise<string|null>} The signature or null if signing fails.
640
- */
641
- Gun.chain.createSignature = async function (message) {
642
- try {
643
- // Check if message matches MESSAGE_TO_SIGN
644
- if (message !== MESSAGE_TO_SIGN) {
645
- throw new Error("Invalid message, valid message is: " + MESSAGE_TO_SIGN);
646
- }
647
- const signer = await getSigner();
648
- const signature = await signer.signMessage(message);
649
- console.log("Signature created:", signature);
650
- return signature;
651
- } catch (error) {
652
- console.error("Error creating signature:", error);
653
- return null;
654
- }
655
- };
656
-
657
- // =============================================
658
- // KEY PAIR MANAGEMENT
659
- // =============================================
660
- /**
661
- * Creates and stores an encrypted key pair for a given address.
662
- * @param {string} address - The Ethereum address to associate with the key pair.
663
- * @param {string} signature - The signature to use for encryption.
664
- * @returns {Promise<void>}
665
- */
666
- Gun.chain.createAndStoreEncryptedPair = async function (address, signature) {
667
- try {
668
- const gun = this;
669
- const pair = await SEA.pair();
670
- const v_pair = await SEA.pair();
671
- const s_pair = await SEA.pair();
672
- const password = generatePassword(signature);
673
-
674
- // Save original SEA pairs
675
- const encryptedPair = await SEA.encrypt(JSON.stringify(pair), password);
676
- const encryptedV_pair = await SEA.encrypt(JSON.stringify(v_pair), password);
677
- const encryptedS_pair = await SEA.encrypt(JSON.stringify(s_pair), password);
678
-
679
- // Convert only to get Ethereum addresses
680
- const viewingAccount = gunToEthAccount(v_pair.priv);
681
- const spendingAccount = gunToEthAccount(s_pair.priv);
682
-
683
- gun.get("gun-eth").get("users").get(address).put({
684
- pair: encryptedPair,
685
- v_pair: encryptedV_pair,
686
- s_pair: encryptedS_pair,
687
- publicKeys: {
688
- viewingPublicKey: v_pair.epub, // Use SEA encryption public key
689
- viewingPublicKey: v_pair.epub, // Use SEA encryption public key
690
- spendingPublicKey: spendingAccount.publicKey, // Use Ethereum address
691
- ethViewingAddress: viewingAccount.publicKey // Also save Ethereum address
692
- }
693
- });
694
-
695
- console.log("Encrypted pairs and public keys stored for:", address);
696
- } catch (error) {
697
- console.error("Error creating and storing encrypted pair:", error);
698
- throw error;
699
- }
700
- };
701
-
702
- /**
703
- * Retrieves and decrypts a stored key pair for a given address.
704
- * @param {string} address - The Ethereum address associated with the key pair.
705
- * @param {string} signature - The signature to use for decryption.
706
- * @returns {Promise<Object|null>} The decrypted key pair or null if retrieval fails.
707
- */
708
- Gun.chain.getAndDecryptPair = async function (address, signature) {
709
- try {
710
- const gun = this;
711
- const encryptedData = await gun
712
- .get("gun-eth")
713
- .get("users")
714
- .get(address)
715
- .get("pair")
716
- .then();
717
- if (!encryptedData) {
718
- throw new Error("No encrypted data found for this address");
719
- }
720
- const password = generatePassword(signature);
721
- const decryptedPair = await SEA.decrypt(encryptedData, password);
722
- console.log(decryptedPair);
723
- return decryptedPair;
724
- } catch (error) {
725
- console.error("Error retrieving and decrypting pair:", error);
726
- return null;
727
- }
728
- };
729
-
730
- // =============================================
731
- // PROOF OF INTEGRITY
732
- // =============================================
733
- /**
734
- * Proof of Integrity
735
- * @param {string} chain - The blockchain to use (e.g., "optimismSepolia").
736
- * @param {string} nodeId - The ID of the node to verify or write.
737
- * @param {Object} data - The data to write (if writing).
738
- * @param {Function} callback - Callback function to handle the result.
739
- * @returns {Gun} The Gun instance for chaining.
740
- */
741
- Gun.chain.proof = function (chain, nodeId, data, callback) {
742
- console.log("Proof plugin called with:", { chain, nodeId, data });
743
-
744
- if (typeof callback !== "function") {
745
- console.error("Callback must be a function");
746
- return this;
747
- }
748
-
749
- try {
750
- // Se siamo in localhost e in development, usa automaticamente la chain locale
751
- const targetChain = isLocalEnvironment() ? 'localhost' : chain;
752
- const chainConfig = getAddressesForChain(targetChain);
753
-
754
- console.log(`Using ${targetChain} configuration:`, chainConfig);
755
-
756
- // Usa gli indirizzi dalla configurazione
757
- const contract = new ethers.ethers.Contract(
758
- chainConfig.PROOF_OF_INTEGRITY_ADDRESS,
759
- PROOF_OF_INTEGRITY_ABI,
760
- signer
761
- );
762
-
763
- // Funzione per verificare on-chain
764
- const verifyOnChain = async (nodeId, contentHash) => {
765
- console.log("Verifying on chain:", { nodeId, contentHash });
766
- const signer = await getSigner();
767
- const contract = new ethers.ethers.Contract(
768
- PROOF_CONTRACT_ADDRESS,
769
- PROOF_OF_INTEGRITY_ABI,
770
- signer
771
- );
772
- const [isValid, timestamp, updater] = await contract.verifyData(
773
- ethers.ethers.toUtf8Bytes(nodeId),
774
- contentHash
775
- );
776
- console.log("Verification result:", { isValid, timestamp, updater });
777
- return { isValid, timestamp, updater };
778
- };
779
-
780
- // Funzione per scrivere on-chain
781
- const writeOnChain = async (nodeId, contentHash) => {
782
- console.log("Writing on chain:", { nodeId, contentHash });
783
- const signer = await getSigner();
784
- const contract = new ethers.ethers.Contract(
785
- PROOF_CONTRACT_ADDRESS,
786
- PROOF_OF_INTEGRITY_ABI,
787
- signer
788
- );
789
- const tx = await contract.updateData(
790
- ethers.ethers.toUtf8Bytes(nodeId),
791
- contentHash
792
- );
793
- console.log("Transaction sent:", tx.hash);
794
- const receipt = await tx.wait();
795
- console.log("Transaction confirmed:", receipt);
796
- return tx;
797
- };
798
-
799
- // Funzione per ottenere l'ultimo record
800
- const getLatestRecord = async (nodeId) => {
801
- const signer = await getSigner();
802
- const contract = new ethers.ethers.Contract(
803
- PROOF_CONTRACT_ADDRESS,
804
- PROOF_OF_INTEGRITY_ABI,
805
- signer
806
- );
807
- const [contentHash, timestamp, updater] = await contract.getLatestRecord(
808
- ethers.ethers.toUtf8Bytes(nodeId)
809
- );
810
- console.log("Latest record from blockchain:", {
811
- nodeId,
812
- contentHash,
813
- timestamp,
814
- updater,
815
- });
816
- return { contentHash, timestamp, updater };
817
- };
818
-
819
-
820
- if (nodeId && !data) {
821
- // Case 1: User passes only node
822
- gun.get(nodeId).once(async (existingData) => {
823
- if (!existingData) {
824
- if (callback) callback({ err: "Node not found in GunDB" });
825
- return;
826
- }
827
-
828
- console.log("existingData", existingData);
829
-
830
- // Use stored contentHash instead of recalculating
831
- const contentHash = existingData._contentHash;
832
- console.log("contentHash", contentHash);
833
-
834
- if (!contentHash) {
835
- if (callback) callback({ err: "No content hash found for this node" });
836
- return;
837
- }
838
-
839
- try {
840
- const { isValid, timestamp, updater } = await verifyOnChain(
841
- nodeId,
842
- contentHash
843
- );
844
- const latestRecord = await getLatestRecord(nodeId);
845
-
846
- if (isValid) {
847
- if (callback)
848
- callback({
849
- ok: true,
850
- message: "Data verified on blockchain",
851
- timestamp,
852
- updater,
853
- latestRecord,
854
- });
855
- } else {
856
- if (callback)
857
- callback({
858
- ok: false,
859
- message: "Data not verified on blockchain",
860
- latestRecord,
861
- });
862
- }
863
- } catch (error) {
864
- if (callback) callback({ err: error.message });
865
- }
866
- });
867
- } else if (data && !nodeId) {
868
- // Case 2: User passes only text (data)
869
- const newNodeId = generateRandomId();
870
- const dataString = JSON.stringify(data);
871
- const contentHash = ethers.ethers.keccak256(ethers.ethers.toUtf8Bytes(dataString));
872
-
873
- gun
874
- .get(newNodeId)
875
- .put({ ...data, _contentHash: contentHash }, async (ack) => {
876
- console.log("ack", ack);
877
- if (ack.err) {
878
- if (callback) callback({ err: "Error saving data to GunDB" });
879
- return;
880
- }
881
-
882
- try {
883
- const tx = await writeOnChain(newNodeId, contentHash);
884
- if (callback)
885
- callback({
886
- ok: true,
887
- message: "Data written to GunDB and blockchain",
888
- nodeId: newNodeId,
889
- txHash: tx.hash,
890
- });
891
- } catch (error) {
892
- if (callback) callback({ err: error.message });
893
- }
894
- });
895
- } else {
896
- if (callback)
897
- callback({
898
- err: "Invalid input. Provide either nodeId or data, not both.",
899
- });
900
- }
901
-
902
- return gun;
903
- } catch (error) {
904
- callback({ err: error.message });
905
- return this;
906
- }
907
- };
908
-
909
- // =============================================
910
- // STEALTH ADDRESS CORE FUNCTIONS
911
- // =============================================
912
- /**
913
- * Converts a Gun private key to an Ethereum account.
914
- * @param {string} gunPrivateKey - The Gun private key in base64url format.
915
- * @returns {Object} An object containing the Ethereum account and public key.
916
- */
917
- Gun.chain.gunToEthAccount = function (gunPrivateKey) {
918
- return gunToEthAccount(gunPrivateKey);
919
- };
920
-
921
- /**
922
- * Generate a stealth key and related key pairs
923
- * @param {string} recipientAddress - The recipient's Ethereum address
924
- * @param {string} signature - The sender's signature to access their keys
925
- * @returns {Promise<Object>} Object containing stealth addresses and keys
926
- */
927
- Gun.chain.generateStealthAddress = async function (recipientAddress, signature) {
928
- try {
929
- const gun = this;
930
-
931
- // Get recipient's public keys
932
- const recipientData = await gun
933
- .get("gun-eth")
934
- .get("users")
935
- .get(recipientAddress)
936
- .get("publicKeys")
937
- .then();
938
-
939
- if (!recipientData || !recipientData.viewingPublicKey || !recipientData.spendingPublicKey) {
940
- throw new Error("Recipient's public keys not found");
941
- }
942
-
943
- // Get sender's keys
944
- const senderAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);
945
- const password = generatePassword(signature);
946
-
947
- const senderData = await gun
948
- .get("gun-eth")
949
- .get("users")
950
- .get(senderAddress)
951
- .then();
952
-
953
- if (!senderData || !senderData.s_pair) {
954
- throw new Error("Sender's keys not found");
955
- }
956
-
957
- // Decrypt sender's spending pair
958
- let spendingKeyPair;
959
- try {
960
- const decryptedData = await SEA.decrypt(senderData.s_pair, password);
961
- spendingKeyPair = typeof decryptedData === 'string' ?
962
- JSON.parse(decryptedData) :
963
- decryptedData;
964
- } catch (error) {
965
- console.error("Error decrypting spending pair:", error);
966
- throw new Error("Unable to decrypt spending pair");
967
- }
968
-
969
- // Generate shared secret using SEA ECDH with encryption public key
970
- const sharedSecret = await SEA.secret(recipientData.viewingPublicKey, spendingKeyPair);
971
-
972
- if (!sharedSecret) {
973
- throw new Error("Unable to generate shared secret");
974
- }
975
-
976
- console.log("Generate shared secret:", sharedSecret);
977
-
978
- const { stealthAddress } = deriveStealthAddress(
979
- sharedSecret,
980
- recipientData.spendingPublicKey
981
- );
982
-
983
- return {
984
- stealthAddress,
985
- senderPublicKey: spendingKeyPair.epub, // Use encryption public key
986
- spendingPublicKey: recipientData.spendingPublicKey
987
- };
988
-
989
- } catch (error) {
990
- console.error("Error generating stealth address:", error);
991
- throw error;
992
- }
993
- };
994
-
995
- /**
996
- * Publish public keys needed to receive stealth payments
997
- * @param {string} signature - The signature to authenticate the user
998
- * @returns {Promise<void>}
999
- */
1000
- Gun.chain.publishStealthKeys = async function (signature) {
1001
- try {
1002
- const gun = this;
1003
- const address = await this.verifySignature(MESSAGE_TO_SIGN, signature);
1004
- const password = generatePassword(signature);
1005
-
1006
- // Get encrypted key pairs
1007
- const encryptedData = await gun
1008
- .get("gun-eth")
1009
- .get("users")
1010
- .get(address)
1011
- .then();
1012
-
1013
- if (!encryptedData || !encryptedData.v_pair || !encryptedData.s_pair) {
1014
- throw new Error("Keys not found");
1015
- }
1016
-
1017
- // Decrypt viewing and spending pairs
1018
- const viewingKeyPair = JSON.parse(
1019
- await SEA.decrypt(encryptedData.v_pair, password)
1020
- );
1021
- const spendingKeyPair = JSON.parse(
1022
- await SEA.decrypt(encryptedData.s_pair, password)
1023
- );
1024
-
1025
- const viewingAccount = gunToEthAccount(viewingKeyPair.priv);
1026
- const spendingAccount = gunToEthAccount(spendingKeyPair.priv);
1027
-
1028
- // Publish only public keys
1029
- gun.get("gun-eth").get("users").get(address).get("publicKeys").put({
1030
- viewingPublicKey: viewingAccount.publicKey,
1031
- spendingPublicKey: spendingAccount.publicKey,
1032
- });
1033
-
1034
- console.log("Stealth public keys published successfully");
1035
- } catch (error) {
1036
- console.error("Error publishing stealth keys:", error);
1037
- throw error;
1038
- }
1039
- };
1040
-
1041
- // =============================================
1042
- // STEALTH PAYMENT FUNCTIONS
1043
- // =============================================
1044
- /**
1045
- * Recover funds from a stealth address
1046
- * @param {string} stealthAddress - The stealth address to recover funds from
1047
- * @param {string} senderPublicKey - The sender's public key used to generate the address
1048
- * @param {string} signature - The signature to decrypt private keys
1049
- * @returns {Promise<Object>} Object containing wallet to access funds
1050
- */
1051
- Gun.chain.recoverStealthFunds = async function (
1052
- stealthAddress,
1053
- senderPublicKey,
1054
- signature,
1055
- spendingPublicKey
1056
- ) {
1057
- try {
1058
- const gun = this;
1059
- const password = generatePassword(signature);
1060
-
1061
- // Get own key pairs
1062
- const myAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);
1063
- const encryptedData = await gun
1064
- .get("gun-eth")
1065
- .get("users")
1066
- .get(myAddress)
1067
- .then();
1068
-
1069
- if (!encryptedData || !encryptedData.v_pair || !encryptedData.s_pair) {
1070
- throw new Error("Keys not found");
1071
- }
1072
-
1073
- // Decrypt viewing and spending pairs
1074
- let viewingKeyPair;
1075
- try {
1076
- const decryptedViewingData = await SEA.decrypt(encryptedData.v_pair, password);
1077
- viewingKeyPair = typeof decryptedViewingData === 'string' ?
1078
- JSON.parse(decryptedViewingData) :
1079
- decryptedViewingData;
1080
- } catch (error) {
1081
- console.error("Error decrypting keys:", error);
1082
- throw new Error("Unable to decrypt keys");
1083
- }
1084
-
1085
- // Generate shared secret using SEA ECDH
1086
- const sharedSecret = await SEA.secret(senderPublicKey, viewingKeyPair);
1087
-
1088
- if (!sharedSecret) {
1089
- throw new Error("Unable to generate shared secret");
1090
- }
1091
-
1092
- console.log("Recover shared secret:", sharedSecret);
1093
-
1094
- const { wallet, stealthAddress: recoveredAddress } = deriveStealthAddress(
1095
- sharedSecret,
1096
- spendingPublicKey
1097
- );
1098
-
1099
- // Verify address matches
1100
- if (recoveredAddress.toLowerCase() !== stealthAddress.toLowerCase()) {
1101
- console.error("Mismatch:", {
1102
- recovered: recoveredAddress,
1103
- expected: stealthAddress,
1104
- sharedSecret
1105
- });
1106
- throw new Error("Recovered stealth address does not match");
1107
- }
1108
-
1109
- return {
1110
- wallet,
1111
- address: recoveredAddress,
1112
- };
1113
- } catch (error) {
1114
- console.error("Error recovering stealth funds:", error);
1115
- throw error;
1116
- }
1117
- };
1118
-
1119
- /**
1120
- * Announce a stealth payment
1121
- * @param {string} stealthAddress - The generated stealth address
1122
- * @param {string} senderPublicKey - The sender's public key
1123
- * @param {string} spendingPublicKey - The spending public key
1124
- * @param {string} signature - The sender's signature
1125
- * @returns {Promise<void>}
1126
- */
1127
- Gun.chain.announceStealthPayment = async function (
1128
- stealthAddress,
1129
- senderPublicKey,
1130
- spendingPublicKey,
1131
- signature,
1132
- options = { onChain: false, chain: 'optimismSepolia' }
1133
- ) {
1134
- try {
1135
- const gun = this;
1136
- const senderAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);
1137
-
1138
- if (options.onChain) {
1139
- // On-chain announcement
1140
- const signer = await getSigner();
1141
- const chainAddresses = getAddressesForChain(options.chain);
1142
- const contractAddress = chainAddresses.STEALTH_ANNOUNCER_ADDRESS;
1143
-
1144
- console.log("Using contract address:", contractAddress);
1145
-
1146
- const contract = new ethers.ethers.Contract(
1147
- contractAddress,
1148
- STEALTH_ANNOUNCER_ABI,
1149
- signer
1150
- );
1151
-
1152
- // Get dev fee from contract
1153
- const devFee = await contract.devFee();
1154
- console.log("Dev fee:", devFee.toString());
1155
-
1156
- // Call contract
1157
- const tx = await contract.announcePayment(
1158
- senderPublicKey,
1159
- spendingPublicKey,
1160
- stealthAddress,
1161
- { value: devFee }
1162
- );
1163
-
1164
- console.log("Transaction sent:", tx.hash);
1165
- const receipt = await tx.wait();
1166
- console.log("Transaction confirmed:", receipt.hash);
1167
-
1168
- console.log("Stealth payment announced on-chain (dev fee paid)");
1169
- } else {
1170
- // Off-chain announcement (GunDB)
1171
- gun
1172
- .get("gun-eth")
1173
- .get("stealth-payments")
1174
- .set({
1175
- stealthAddress,
1176
- senderAddress,
1177
- senderPublicKey,
1178
- spendingPublicKey,
1179
- timestamp: Date.now(),
1180
- });
1181
- console.log("Stealth payment announced off-chain");
1182
- }
1183
- } catch (error) {
1184
- console.error("Error announcing stealth payment:", error);
1185
- console.error("Error details:", error.stack);
1186
- throw error;
1187
- }
1188
- };
1189
-
1190
- /**
1191
- * Get all stealth payments for an address
1192
- * @param {string} signature - The signature to authenticate the user
1193
- * @returns {Promise<Array>} List of stealth payments
1194
- */
1195
- Gun.chain.getStealthPayments = async function (signature, options = { source: 'both' }) {
1196
- try {
1197
- const payments = [];
1198
-
1199
- if (options.source === 'onChain' || options.source === 'both') {
1200
- // Get on-chain payments
1201
- const signer = await getSigner();
1202
- const contractAddress = process.env.NODE_ENV === 'development'
1203
- ? LOCAL_CONFIG.STEALTH_ANNOUNCER_ADDRESS
1204
- : STEALTH_ANNOUNCER_ADDRESS;
1205
-
1206
- const contract = new ethers.ethers.Contract(
1207
- contractAddress,
1208
- STEALTH_ANNOUNCER_ABI,
1209
- signer
1210
- );
1211
-
1212
- try {
1213
- // Get total number of announcements
1214
- const totalAnnouncements = await contract.getAnnouncementsCount();
1215
- const totalCount = Number(totalAnnouncements.toString());
1216
- console.log("Total on-chain announcements:", totalCount);
1217
-
1218
- if (totalCount > 0) {
1219
- // Get announcements in batches of 100
1220
- const batchSize = 100;
1221
- const lastIndex = totalCount - 1;
1222
-
1223
- for(let i = 0; i <= lastIndex; i += batchSize) {
1224
- const toIndex = Math.min(i + batchSize - 1, lastIndex);
1225
- const batch = await contract.getAnnouncementsInRange(i, toIndex);
1226
-
1227
- // For each announcement, try to decrypt
1228
- for(const announcement of batch) {
1229
- try {
1230
- // Verify announcement is valid
1231
- if (!announcement || !announcement.stealthAddress ||
1232
- !announcement.senderPublicKey || !announcement.spendingPublicKey) {
1233
- console.log("Invalid announcement:", announcement);
1234
- continue;
1235
- }
1236
-
1237
- // Try to recover funds to verify if announcement is for us
1238
- const recoveredWallet = await this.recoverStealthFunds(
1239
- announcement.stealthAddress,
1240
- announcement.senderPublicKey,
1241
- signature,
1242
- announcement.spendingPublicKey
1243
- );
1244
-
1245
- // If no errors thrown, announcement is for us
1246
- payments.push({
1247
- stealthAddress: announcement.stealthAddress,
1248
- senderPublicKey: announcement.senderPublicKey,
1249
- spendingPublicKey: announcement.spendingPublicKey,
1250
- timestamp: Number(announcement.timestamp),
1251
- source: 'onChain',
1252
- wallet: recoveredWallet
1253
- });
1254
-
1255
- } catch (e) {
1256
- // Not for us, continue
1257
- console.log(`Announcement not for us: ${announcement.stealthAddress}`);
1258
- continue;
1259
- }
1260
- }
1261
- }
1262
- }
1263
- } catch (error) {
1264
- console.error("Error retrieving on-chain announcements:", error);
1265
- }
1266
- }
1267
-
1268
- if (options.source === 'offChain' || options.source === 'both') {
1269
- // Get off-chain payments
1270
- const gun = this;
1271
- const offChainPayments = await new Promise((resolve) => {
1272
- const p = [];
1273
- gun
1274
- .get("gun-eth")
1275
- .get("stealth-payments")
1276
- .get(recipientAddress)
1277
- .map()
1278
- .once((payment, id) => {
1279
- if (payment?.stealthAddress) {
1280
- p.push({ ...payment, id, source: 'offChain' });
1281
- }
1282
- });
1283
- setTimeout(() => resolve(p), 2000);
1284
- });
1285
-
1286
- payments.push(...offChainPayments);
1287
- }
1288
-
1289
- console.log(`Found ${payments.length} stealth payments`);
1290
- return payments;
1291
- } catch (error) {
1292
- console.error("Error retrieving stealth payments:", error);
1293
- throw error;
1294
- }
1295
- };
1296
-
1297
- /**
1298
- * Clean up old stealth payments
1299
- * @param {string} recipientAddress - The recipient's address
1300
- * @returns {Promise<void>}
1301
- */
1302
- Gun.chain.cleanStealthPayments = async function(recipientAddress) {
1303
- try {
1304
- const gun = this;
1305
- const payments = await gun
1306
- .get("gun-eth")
1307
- .get("stealth-payments")
1308
- .get(recipientAddress)
1309
- .map()
1310
- .once()
1311
- .then();
1312
-
1313
- // Remove empty or invalid nodes
1314
- if (payments) {
1315
- Object.keys(payments).forEach(async (key) => {
1316
- const payment = payments[key];
1317
- if (!payment || !payment.stealthAddress || !payment.senderPublicKey || !payment.spendingPublicKey) {
1318
- await gun
1319
- .get("gun-eth")
1320
- .get("stealth-payments")
1321
- .get(recipientAddress)
1322
- .get(key)
1323
- .put(null);
1324
- }
1325
- });
1326
- }
1327
- } catch (error) {
1328
- console.error("Error cleaning stealth payments:", error);
1329
- }
1330
- };
1331
-
1332
- // =============================================
1333
- // EXPORTS
1334
- // =============================================
1335
-
1336
- // Crea una classe GunEth che contiene tutti i metodi e le utility
1337
- class GunEth {
1338
- // Static utility methods
1339
- static generateRandomId = generateRandomId;
1340
- static generatePassword = generatePassword;
1341
- static gunToEthAccount = gunToEthAccount;
1342
- static getSigner = getSigner;
1343
- static deriveStealthAddress = deriveStealthAddress;
1344
-
1345
- // Chain methods
1346
- static chainMethods = {
1347
- setSigner: Gun.chain.setSigner,
1348
- getSigner: Gun.chain.getSigner,
1349
- verifySignature: Gun.chain.verifySignature,
1350
- generatePassword: Gun.chain.generatePassword,
1351
- createSignature: Gun.chain.createSignature,
1352
- createAndStoreEncryptedPair: Gun.chain.createAndStoreEncryptedPair,
1353
- getAndDecryptPair: Gun.chain.getAndDecryptPair,
1354
- proof: Gun.chain.proof,
1355
- gunToEthAccount: Gun.chain.gunToEthAccount,
1356
- generateStealthAddress: Gun.chain.generateStealthAddress,
1357
- publishStealthKeys: Gun.chain.publishStealthKeys,
1358
- recoverStealthFunds: Gun.chain.recoverStealthFunds,
1359
- announceStealthPayment: Gun.chain.announceStealthPayment,
1360
- getStealthPayments: Gun.chain.getStealthPayments,
1361
- cleanStealthPayments: Gun.chain.cleanStealthPayments
1362
- };
1363
-
1364
- // Constants
1365
- static MESSAGE_TO_SIGN = MESSAGE_TO_SIGN;
1366
- static PROOF_CONTRACT_ADDRESS = PROOF_CONTRACT_ADDRESS;
1367
- static LOCAL_CONFIG = LOCAL_CONFIG;
1368
- }
1369
-
1370
- exports.default = Gun;
1371
- exports.GunEth = GunEth;
1372
- exports.MESSAGE_TO_SIGN = MESSAGE_TO_SIGN;
1373
- exports.deriveStealthAddress = deriveStealthAddress;
1374
- exports.generatePassword = generatePassword;
1375
- exports.generateRandomId = generateRandomId;
1376
- exports.getSigner = getSigner;
1377
- exports.gunToEthAccount = gunToEthAccount;
1378
-
1379
- Object.defineProperty(exports, '__esModule', { value: true });
1380
-
1381
- }));
1382
- //# sourceMappingURL=gun-eth.js.map