gun-eth 1.2.6 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. package/README.md +86 -21
  2. package/TUTORIAL.md +103 -0
  3. package/package.json +2 -2
  4. package/{index.js → src/index.js} +95 -45
  5. package/.yarn/cache/@adraffy-ens-normalize-npm-1.10.1-e60d7ca58d-0836f394ea.zip +0 -0
  6. package/.yarn/cache/@noble-curves-npm-1.2.0-9b40ee1239-bb798d7a66.zip +0 -0
  7. package/.yarn/cache/@noble-hashes-npm-1.3.2-1e619f9da0-fe23536b43.zip +0 -0
  8. package/.yarn/cache/@peculiar-asn1-schema-npm-2.3.13-7e52f15480-245cf39899.zip +0 -0
  9. package/.yarn/cache/@peculiar-json-schema-npm-1.1.12-f914d2ea65-b26ececdc2.zip +0 -0
  10. package/.yarn/cache/@peculiar-webcrypto-npm-1.5.0-4d84865c57-9022d7452d.zip +0 -0
  11. package/.yarn/cache/@types-node-npm-18.15.13-14d4d1b98f-79cc5a2b5f.zip +0 -0
  12. package/.yarn/cache/aes-js-npm-4.0.0-beta.5-c70da65547-cc2ea969d7.zip +0 -0
  13. package/.yarn/cache/asn1js-npm-3.0.5-cf5558af33-3b6af1bbad.zip +0 -0
  14. package/.yarn/cache/ethers-npm-6.13.2-177cd791bd-981860c736.zip +0 -0
  15. package/.yarn/cache/gun-npm-0.2020.1240-e808e9ee90-0effb70596.zip +0 -0
  16. package/.yarn/cache/pvtsutils-npm-1.3.5-b3122eabea-e734516b3c.zip +0 -0
  17. package/.yarn/cache/pvutils-npm-1.1.3-da8b07d6cf-2ee26a9e51.zip +0 -0
  18. package/.yarn/cache/tslib-npm-2.4.0-9cb6dc5030-8c4aa6a3c5.zip +0 -0
  19. package/.yarn/cache/tslib-npm-2.7.0-21668f5c21-1606d5c89f.zip +0 -0
  20. package/.yarn/cache/webcrypto-core-npm-1.8.0-b7c655d14a-4f128f5283.zip +0 -0
  21. package/.yarn/cache/ws-npm-7.5.10-878ccb886b-f9bb062abf.zip +0 -0
  22. package/.yarn/cache/ws-npm-8.17.1-f57fb24a2c-442badcce1.zip +0 -0
  23. package/.yarn/install-state.gz +0 -0
  24. /package/{SHINE.json → abis/SHINE.json} +0 -0
  25. /package/{SHINE.sol → contracts/SHINE.sol} +0 -0
package/README.md CHANGED
@@ -1,93 +1,147 @@
1
- # gun-eth
1
+ # GUN-ETH
2
2
 
3
- ## Description
3
+ <img src="https://imgs.search.brave.com/RM76D4wyToxCzGffJLw33O_L3glhpIVS3KLvXehpMt8/rs:fit:500:0:0:0/g:ce/aHR0cHM6Ly93d3cu/dXNlcmxvZ29zLm9y/Zy9maWxlcy9sb2dv/cy9mZXJuYW5kb3Nh/bnR1Y2NpLzI5NDY5/X2d1bmRiLWxvZ28u/cG5n" alt="gun" width="200"/>
4
+ <img src="https://imgs.search.brave.com/kQyriTMPqw42DEhIQj3eEKIcLZu_C4nNIVR8KtAn3lo/rs:fit:500:0:0:0/g:ce/aHR0cHM6Ly93d3cu/bG9nby53aW5lL2Ev/bG9nby9FdGhlcmV1/bS9FdGhlcmV1bS1E/aWFtb25kLUxvZ28u/d2luZS5zdmc" alt="eth" width="200"/>
4
5
 
5
- gun-eth is a plugin for GunDB that integrates Ethereum and Web3 functionality. This plugin extends GunDB's capabilities by allowing interaction with the Ethereum blockchain and providing cryptographic and signature management features.
6
+ ## Table of Contents
7
+
8
+ 1. [Description](#description)
9
+ 2. [Smart Contract](#smart-contract)
10
+ 3. [Key Features](#key-features)
11
+ 4. [How to Install](#how-to-install)
12
+ 5. [How to Use](#how-to-use)
13
+ 6. [Core Functions](#core-functions)
14
+ 7. [SHINE](#shine)
15
+ 8. [Standalone Mode](#standalone-mode)
16
+ 9. [Security Considerations](#security-considerations)
17
+ 10. [Contributing](#contributing)
18
+ 11. [License](#license)
19
+ 12. [Contact](#contact)
20
+
21
+ ## DESCRIPTION
22
+
23
+ Gun-eth is a plugin for GunDB that integrates Ethereum and Web3 functionality. This plugin extends GunDB's capabilities by allowing interaction with the Ethereum blockchain and providing cryptographic and signature management features.
24
+
25
+ ## SMART CONTRACT
6
26
 
7
27
  SHINE Smart Contract deployed on Optimism Sepolia: [0x43D838b683F772F08f321E5FA265ad3e333BE9C2](https://sepolia-optimism.etherscan.io/address/0x43D838b683F772F08f321E5FA265ad3e333BE9C2)
8
28
 
9
29
  Currently, the contract is deployed only on Optimism Sepolia. In the future, it will be deployed on multiple chains.
10
30
 
11
- ### Key Features
31
+ ## No time? Check the [TUTORIAL](./TUTORIAL.md)
32
+
33
+ ## KEY FEATURES
12
34
 
13
35
  - **Ethereum Signature Verification**: Verify Ethereum signatures for messages.
14
36
  - **Password Generation**: Generate secure passwords from Ethereum signatures.
15
37
  - **Signature Creation**: Create Ethereum signatures for messages.
16
38
  - **Encrypted Key Pair Management**: Create, store, and retrieve encrypted key pairs.
17
39
  - **SHINE Implementation**: Implement the SHINE for data verification on the blockchain.
40
+ - **Custom Token Management**: Set and retrieve custom tokens for Gun operations.
18
41
 
19
- ### How to install
42
+ ## HOW TO INSTALL
20
43
 
21
44
  ```bash
22
45
  npm install gun-eth
23
46
  ```
24
47
 
25
- ```bash
48
+ ```javascript
26
49
  import gun from "gun";
27
50
  import "gun-eth";
28
51
 
29
- const gun = gun();
52
+ const gun = Gun();
30
53
 
31
54
  await gun.generatePassword("YOUR_SIGNATURE");
32
55
  ```
33
56
 
34
- ### How to use
57
+ ## HOW TO USE
35
58
 
36
59
  Learn more about Gun.js [here](https://gun.eco/docs/Getting-Started).
37
60
 
38
61
  Learn more about plugin implementation [here](https://github.com/amark/gun/wiki/Adding-Methods-to-the-Gun-Chain#abstraction-layers).
39
62
 
40
- ### Core Functions
63
+ ## CORE FUNCTIONS
41
64
 
42
65
  - `verifySignature(message, signature)`: Verifies an Ethereum signature for a given message.
43
66
 
44
- ```js
67
+ ```javascript
45
68
  const recoveredAddress = await gun.verifySignature(message, signature);
46
69
  ```
47
70
 
48
71
  - `generatePassword(signature)`: Generates a password from an Ethereum signature.
49
72
 
50
- ```js
73
+ ```javascript
51
74
  const password = gun.generatePassword(signature);
52
75
  ```
53
76
 
54
77
  - `createSignature(message)`: Creates an Ethereum signature for a message.
55
78
 
56
- ```js
79
+ ```javascript
57
80
  const signature = await gun.createSignature(message);
58
81
  ```
59
82
 
60
83
  - `createAndStoreEncryptedPair(address, signature)`: Creates and stores an encrypted key pair.
61
84
 
62
- ```js
85
+ ```javascript
63
86
  await gun.createAndStoreEncryptedPair(address, signature);
64
87
  ```
65
88
 
66
89
  - `getAndDecryptPair(address, signature)`: Retrieves and decrypts a stored key pair.
67
90
 
68
- ```js
91
+ ```javascript
69
92
  const decryptedPair = await gun.getAndDecryptPair(address, signature);
70
93
  ```
71
94
 
72
95
  - `shine(chain, nodeId, data, callback)`: Implements SHINE for data verification and storage on the blockchain.
73
- ```js
96
+
97
+ ```javascript
74
98
  gun.shine("optimismSepolia", nodeId, data, callback);
75
99
  ```
76
100
 
77
- ### SHINE
101
+ - `setToken(token)`: Sets a custom token for Gun operations.
102
+
103
+ ```javascript
104
+ gun.setToken("yourCustomToken");
105
+ ```
106
+
107
+ - `getToken()`: Retrieves the current custom token.
108
+
109
+ ```javascript
110
+ const currentToken = gun.getToken();
111
+ ```
112
+
113
+ ## SHINE
78
114
 
79
115
  SHINE (Secure Hash Integrity Network Ethereum) provides a mechanism for verifying data integrity using Ethereum and Gun.js.
80
116
 
81
- 1. **Data Storage**: When saving data, a content hash is generated and stored in both Gun.js and on the Ethereum blockchain.
82
- 2. **Data Verification**: To verify data, the stored hash is compared with a hash generated from the data retrieved from Gun.js.
83
- 3. **Blockchain Interaction**: The plugin interacts with an Ethereum smart contract to store and verify data hashes.
117
+ #### SHINE Contract Configuration
118
+
119
+ Currently, SHINE supports only the Optimism Sepolia network. The contract address is managed internally:
120
+
121
+ ```javascript
122
+ const SHINE_OPTIMISM_SEPOLIA = "0x43D838b683F772F08f321E5FA265ad3e333BE9C2";
123
+ ```
124
+
125
+ To support other chains in the future, the plugin will select the appropriate address based on the `chain` parameter provided to the `shine` function.
126
+
127
+ #### SHINE Helper Functions
128
+
129
+ SHINE uses several internal helper functions to interact with the blockchain:
130
+
131
+ - `getSigner()`: Retrieves an Ethereum signer from the browser provider (e.g., MetaMask).
132
+ - `verifyOnChain(nodeId, contentHash)`: Verifies data integrity on the blockchain.
133
+ - `writeOnChain(nodeId, contentHash)`: Writes the content hash to the blockchain.
134
+ - `getLatestRecord(nodeId)`: Retrieves the latest record associated with a nodeId from the blockchain.
135
+
136
+ These functions are used internally by the `shine` method and are not directly exposed to the user.
84
137
 
85
138
  ### Usage Examples
86
139
 
87
140
  #### Verifying Data by NodeId
88
141
 
89
- ```js
142
+ ```javascript
90
143
  const nodeId = "your-node-id-here";
144
+
91
145
  gun.shine("optimismSepolia", nodeId, null, (ack) => {
92
146
  if (ack.ok) {
93
147
  console.log("Data verified on blockchain", ack);
@@ -102,8 +156,9 @@ gun.shine("optimismSepolia", nodeId, null, (ack) => {
102
156
 
103
157
  #### Storing New Data
104
158
 
105
- ```js
159
+ ```javascript
106
160
  const data = { message: "Hello, blockchain!" };
161
+
107
162
  gun.shine("optimismSepolia", null, data, (ack) => {
108
163
  if (ack.ok) {
109
164
  console.log("Data stored on Gun.js and blockchain", ack);
@@ -115,6 +170,16 @@ gun.shine("optimismSepolia", null, data, (ack) => {
115
170
  });
116
171
  ```
117
172
 
173
+ ## STANDALONE MODE
174
+
175
+ For users who want to run the plugin without a browser wallet, you can use the standalone mode. This requires setting up an RPC URL and a private key:
176
+
177
+ ```javascript
178
+ gun.setStandaloneConfig("https://your-rpc-url", "your-private-key");
179
+ ```
180
+
181
+ Make sure to keep your private key secure and never expose it in client-side code.
182
+
118
183
  ### Security Considerations
119
184
 
120
185
  - Use a secure Ethereum provider (e.g., MetaMask) when interacting with functions that require signatures.
package/TUTORIAL.md ADDED
@@ -0,0 +1,103 @@
1
+ # Tutorial: Illuminating Your Data with SHINE in GunDB 🌟
2
+
3
+ Hey there, GunDB aficionado! Ready to take your decentralized data game to the next level? Enter SHINE: your ticket to blockchain-verified data integrity. It's not just about storing data anymore; it's about making it cryptographically awesome!
4
+
5
+ ## Step 0: Wallet Integration - Your Blockchain Passport
6
+
7
+ Before we dive into the SHINE pool, remember: this plugin requires a browser-based wallet provider. Think of it as your blockchain passport. Here's how to check if you're ready to roll:
8
+
9
+ ```javascript
10
+ async function connectWallet() {
11
+ if (typeof window.ethereum !== "undefined") {
12
+ console.log("Ethereum object detected");
13
+ try {
14
+ await window.ethereum.request({ method: "eth_requestAccounts" });
15
+ console.log("Wallet connected successfully");
16
+ return true;
17
+ } catch (error) {
18
+ console.error("Wallet connection denied:", error);
19
+ return false;
20
+ }
21
+ } else {
22
+ console.log(
23
+ "Please install MetaMask or another Ethereum-compatible wallet"
24
+ );
25
+ return false;
26
+ }
27
+ }
28
+
29
+ // Make sure to call this before using SHINE
30
+ await connectWallet();
31
+ ```
32
+
33
+ Pro tip: Always ensure your wallet is connected before invoking SHINE functions. No wallet, no blockchain magic!
34
+
35
+ ## Step 1: Installation - Equipping Your Toolbelt
36
+
37
+ Let's add SHINE to your development arsenal:
38
+
39
+ ```bash
40
+ npm install gun-eth
41
+ ```
42
+
43
+ If your terminal responds without errors, you're locked and loaded!
44
+
45
+ ## Step 2: Import - Assembling the Pieces
46
+
47
+ Time to bring Gun and SHINE into your JavaScript playground:
48
+
49
+ ```javascript
50
+ import Gun from "gun";
51
+ import "gun-eth";
52
+ const gun = Gun();
53
+ ```
54
+
55
+ ## Step 3: SHINE in Action - Blockchain Meets Database
56
+
57
+ Let's say you've got some mission-critical data to store. Here's how you'd use SHINE to give it that blockchain-grade integrity:
58
+
59
+ ```javascript
60
+ const criticalData = {
61
+ key1: "Encrypted message",
62
+ key2: "Top secret algorithm",
63
+ key3: "42",
64
+ };
65
+
66
+ gun.shine("optimismSepolia", null, criticalData, (ack) => {
67
+ if (ack.ok) {
68
+ console.log("Data successfully anchored to the blockchain");
69
+ console.log("Node ID for future reference:", ack.nodeId);
70
+ } else {
71
+ console.error("Blockchain anchoring failed:", ack.err);
72
+ }
73
+ });
74
+ ```
75
+
76
+ Remember, your wallet needs to be ready to sign this transaction. It's like pushing code without commit access - it just won't fly!
77
+
78
+ ## Step 4: Verification - Trust the Crypto, Not the Hearsay
79
+
80
+ When it's time to verify your data's integrity:
81
+
82
+ ```javascript
83
+ const nodeId = "your-data-node-id";
84
+ gun.shine("optimismSepolia", nodeId, null, (ack) => {
85
+ if (ack.ok) {
86
+ console.log("Data integrity verified on the blockchain");
87
+ console.log("Timestamp:", ack.timestamp);
88
+ console.log("Last updater:", ack.updater);
89
+ } else {
90
+ console.error("Integrity check failed:", ack.err);
91
+ }
92
+ });
93
+ ```
94
+
95
+ Again, wallet connection is crucial. No blockchain access, no verification!
96
+
97
+ ## Step 5: Reap the Benefits
98
+
99
+ Congratulations! You've just leveled up your data management game. Your data is now cryptographically verifiable, tamper-evident, and blockchain-secured.
100
+
101
+ Remember: With SHINE, you're not just storing data; you're creating a cryptographic proof of its existence and integrity. Use this power wisely!
102
+
103
+ P.S. SHINE responsibly. With great cryptographic power comes great responsibility. Happy coding, and may your data always maintain its integrity! 🚀🔐
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "gun-eth",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "description": "A GunDB plugin for Ethereum, and Web3",
5
- "main": "index.js",
5
+ "main": "./src/index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
@@ -1,99 +1,136 @@
1
1
  const Gun = require("gun/gun");
2
2
  const SEA = require("gun/sea");
3
3
  const ethers = require("ethers");
4
- const SHINE = require("./SHINE.json");
5
-
6
- /* import Gun from "gun";
7
- import SEA from "gun/sea";
8
- import { ethers } from "ethers";
9
- import SHINE from "./SHINE.json"; */
4
+ const SHINE = require("../abis/SHINE.json");
10
5
 
11
6
  const SHINE_ABI = SHINE.abi;
12
7
  const SHINE_OPTIMISM_SEPOLIA = SHINE.address;
13
8
 
14
9
  let SHINE_CONTRACT_ADDRESS;
15
-
16
10
  let customToken = "";
17
11
 
12
+ let rpcUrl = "";
13
+ let privateKey = "";
14
+
15
+ /**
16
+ * Sets standalone configuration for Gun.
17
+ * @param {string} newRpcUrl - The new RPC URL.
18
+ * @param {string} newPrivateKey - The new private key.
19
+ * @returns {Gun} The Gun instance for chaining.
20
+ */
21
+ Gun.chain.setStandaloneConfig = function (newRpcUrl, newPrivateKey) {
22
+ rpcUrl = newRpcUrl;
23
+ privateKey = newPrivateKey;
24
+ console.log("Standalone configuration set");
25
+ return this;
26
+ };
27
+
28
+ /**
29
+ * Sets a custom token for Gun operations.
30
+ * @param {string} token - The token to be set.
31
+ * @returns {Gun} The Gun instance for chaining.
32
+ */
18
33
  Gun.chain.setToken = function (token) {
19
34
  if (typeof token === "string" && token.length > 0) {
20
35
  customToken = token;
21
- console.log("Token impostato con successo:", token);
36
+ console.log("Token set successfully:", token);
22
37
  } else {
23
- console.error("Token non valido. Deve essere una stringa non vuota.");
38
+ console.error("Invalid token. Must be a non-empty string.");
24
39
  }
25
40
  return this;
26
41
  };
27
42
 
28
- ctx.on("put", function (msg) {
43
+ /**
44
+ * Retrieves the current custom token.
45
+ * @returns {string} The current custom token.
46
+ */
47
+ Gun.chain.getToken = function () {
48
+ return customToken;
49
+ };
50
+
51
+ // Add custom token to all 'put' operations
52
+ Gun.on("put", function (msg) {
29
53
  const to = this.to;
30
- // Usa il token personalizzato
31
54
  msg.headers = {
32
55
  token: customToken,
33
56
  };
34
- to.next(msg); // passa al prossimo middleware
57
+ to.next(msg);
35
58
  });
36
59
 
37
- // Aggiungi il metodo alla catena di Gun
60
+ /**
61
+ * Verifies an Ethereum signature.
62
+ * @param {string} message - The original message that was signed.
63
+ * @param {string} signature - The signature to verify.
64
+ * @returns {Promise<string|null>} The recovered address or null if verification fails.
65
+ */
38
66
  Gun.chain.verifySignature = async function (message, signature) {
39
67
  try {
40
68
  const recoveredAddress = ethers.verifyMessage(message, signature);
41
69
  return recoveredAddress;
42
70
  } catch (error) {
43
- console.error("Errore durante la verifica della firma:", error);
71
+ console.error("Error verifying signature:", error);
44
72
  return null;
45
73
  }
46
74
  };
47
75
 
76
+ /**
77
+ * Generates a password from a signature.
78
+ * @param {string} signature - The signature to derive the password from.
79
+ * @returns {string|null} The generated password or null if generation fails.
80
+ */
48
81
  Gun.chain.generatePassword = function (signature) {
49
82
  try {
50
- // Usa SHA-256 per derivare una password dalla firma
51
83
  const hexSignature = ethers.hexlify(signature);
52
84
  const hash = ethers.keccak256(hexSignature);
53
-
54
- console.log("Password generata:", hash);
85
+ console.log("Generated password:", hash);
55
86
  return hash;
56
87
  } catch (error) {
57
- console.error("Errore nella generazione della password:", error);
88
+ console.error("Error generating password:", error);
58
89
  return null;
59
90
  }
60
91
  };
61
92
 
93
+ /**
94
+ * Creates an Ethereum signature for a given message.
95
+ * @param {string} message - The message to sign.
96
+ * @returns {Promise<string|null>} The signature or null if signing fails.
97
+ */
62
98
  Gun.chain.createSignature = async function (message) {
63
99
  try {
64
- // Controlla se window.ethereum è disponibile (metamask o altro provider)
65
- if (typeof window.ethereum !== "undefined") {
66
- await window.ethereum.request({ method: "eth_requestAccounts" });
67
- const provider = new ethers.BrowserProvider(window.ethereum);
68
- const signer = await provider.getSigner();
69
- const signature = await signer.signMessage(message);
70
- console.log("Firma creata:", signature);
71
- return signature;
72
- } else {
73
- throw new Error("Provider Ethereum non trovato");
74
- }
100
+ const signer = await getSigner();
101
+ const signature = await signer.signMessage(message);
102
+ console.log("Signature created:", signature);
103
+ return signature;
75
104
  } catch (error) {
76
- console.error("Errore durante la creazione della firma:", error);
105
+ console.error("Error creating signature:", error);
77
106
  return null;
78
107
  }
79
108
  };
80
109
 
110
+ /**
111
+ * Creates and stores an encrypted key pair for a given address.
112
+ * @param {string} address - The Ethereum address to associate with the key pair.
113
+ * @param {string} signature - The signature to use for encryption.
114
+ * @returns {Promise<void>}
115
+ */
81
116
  Gun.chain.createAndStoreEncryptedPair = async function (address, signature) {
82
117
  try {
83
118
  const gun = this;
84
119
  const pair = await SEA.pair();
85
120
  const encryptedPair = await SEA.encrypt(JSON.stringify(pair), signature);
86
-
87
121
  await gun.get("users").get(address).put({ encryptedPair });
88
- console.log("Pair crittografato e archiviato per:", address);
122
+ console.log("Encrypted pair stored for:", address);
89
123
  } catch (error) {
90
- console.error(
91
- "Errore durante la creazione e l'archiviazione del pair crittografato:",
92
- error
93
- );
124
+ console.error("Error creating and storing encrypted pair:", error);
94
125
  }
95
126
  };
96
127
 
128
+ /**
129
+ * Retrieves and decrypts a stored key pair for a given address.
130
+ * @param {string} address - The Ethereum address associated with the key pair.
131
+ * @param {string} signature - The signature to use for decryption.
132
+ * @returns {Promise<Object|null>} The decrypted key pair or null if retrieval fails.
133
+ */
97
134
  Gun.chain.getAndDecryptPair = async function (address, signature) {
98
135
  try {
99
136
  const gun = this;
@@ -103,22 +140,25 @@ Gun.chain.getAndDecryptPair = async function (address, signature) {
103
140
  .get("encryptedPair")
104
141
  .then();
105
142
  if (!encryptedData) {
106
- throw new Error("Nessun dato crittografato trovato per questo indirizzo");
143
+ throw new Error("No encrypted data found for this address");
107
144
  }
108
-
109
145
  const decryptedPair = await SEA.decrypt(encryptedData, signature);
110
-
111
146
  console.log(decryptedPair);
112
147
  return decryptedPair;
113
148
  } catch (error) {
114
- console.error(
115
- "Errore durante il recupero e la decrittazione del pair:",
116
- error
117
- );
149
+ console.error("Error retrieving and decrypting pair:", error);
118
150
  return null;
119
151
  }
120
152
  };
121
153
 
154
+ /**
155
+ * SHINE (Secure Hybrid Information and Network Environment) functionality.
156
+ * @param {string} chain - The blockchain to use (e.g., "optimismSepolia").
157
+ * @param {string} nodeId - The ID of the node to verify or write.
158
+ * @param {Object} data - The data to write (if writing).
159
+ * @param {Function} callback - Callback function to handle the result.
160
+ * @returns {Gun} The Gun instance for chaining.
161
+ */
122
162
  Gun.chain.shine = function (chain, nodeId, data, callback) {
123
163
  console.log("SHINE plugin called with:", { chain, nodeId, data });
124
164
 
@@ -138,12 +178,20 @@ Gun.chain.shine = function (chain, nodeId, data, callback) {
138
178
 
139
179
  // Funzione per ottenere il signer
140
180
  const getSigner = async () => {
141
- if (typeof window.ethereum !== "undefined") {
181
+ if (rpcUrl && privateKey) {
182
+ // Modalità standalone
183
+ const provider = new ethers.JsonRpcProvider(rpcUrl);
184
+ return new ethers.Wallet(privateKey, provider);
185
+ } else if (
186
+ typeof window !== "undefined" &&
187
+ typeof window.ethereum !== "undefined"
188
+ ) {
189
+ // Modalità browser
142
190
  await window.ethereum.request({ method: "eth_requestAccounts" });
143
191
  const provider = new ethers.BrowserProvider(window.ethereum);
144
192
  return provider.getSigner();
145
193
  } else {
146
- throw new Error("Ethereum provider not found");
194
+ throw new Error("No valid Ethereum provider found");
147
195
  }
148
196
  };
149
197
 
@@ -288,3 +336,5 @@ Gun.chain.shine = function (chain, nodeId, data, callback) {
288
336
 
289
337
  return gun;
290
338
  };
339
+
340
+ module.exports = Gun;
Binary file
File without changes
File without changes