gun-eth 1.4.22 → 1.4.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +0,0 @@
1
- {"version":3,"file":"gun-eth.min.js","sources":["../src/config/local.js","../src/abis/abis.js","../src/index.js"],"sourcesContent":["let contractAddresses = {\r\n PROOF_OF_INTEGRITY_ADDRESS: \"0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512\",\r\n STEALTH_ANNOUNCER_ADDRESS: \"0x5FbDB2315678afecb367f032d93F642f64180aa3\"\r\n};\r\n\r\nif (typeof window === 'undefined') {\r\n const { fileURLToPath } = require('url');\r\n const { dirname } = require('path');\r\n const { readFileSync } = require('fs');\r\n const { join } = require('path');\r\n\r\n try {\r\n const __filename = fileURLToPath(import.meta.url);\r\n const __dirname = dirname(__filename);\r\n const rawdata = readFileSync(join(__dirname, 'contract-address.json'), 'utf8');\r\n contractAddresses = JSON.parse(rawdata);\r\n console.log(\"Loaded contract addresses:\", contractAddresses);\r\n } catch (error) {\r\n console.warn(\"Warning: contract-address.json not found or invalid\");\r\n }\r\n}\r\n\r\nexport const LOCAL_CONFIG = {\r\n CHAIN_ID: 1337,\r\n PROOF_OF_INTEGRITY_ADDRESS: contractAddresses.PROOF_OF_INTEGRITY_ADDRESS,\r\n STEALTH_ANNOUNCER_ADDRESS: contractAddresses.STEALTH_ANNOUNCER_ADDRESS,\r\n RPC_URL: \"http://127.0.0.1:8545\",\r\n GUN_PEER: \"http://localhost:8765/gun\"\r\n}; ","import { LOCAL_CONFIG } from '../config/local.js';\r\n\r\n// Indirizzi di produzione per diverse chain\r\nexport const CHAIN_CONFIG = {\r\n optimismSepolia: {\r\n STEALTH_ANNOUNCER_ADDRESS: \"\",\r\n PROOF_OF_INTEGRITY_ADDRESS: \"\",\r\n RPC_URL: \"https://sepolia.optimism.io\",\r\n CHAIN_ID: 11155420\r\n },\r\n arbitrumSepolia: {\r\n STEALTH_ANNOUNCER_ADDRESS: \"\",\r\n PROOF_OF_INTEGRITY_ADDRESS: \"\",\r\n RPC_URL: \"https://sepolia-rollup.arbitrum.io/rpc\",\r\n CHAIN_ID: 421614\r\n },\r\n localhost: {\r\n RPC_URL: \"http://127.0.0.1:8545\",\r\n CHAIN_ID: 1337\r\n }\r\n};\r\n\r\n// Funzione per ottenere gli indirizzi corretti\r\nexport function getAddressesForChain(chainName) {\r\n let config;\r\n\r\n // Se è localhost, prova a caricare gli indirizzi locali\r\n if (chainName === 'localhost') {\r\n try {\r\n // Carica gli indirizzi dal file generato dal deploy locale\r\n const localAddresses = require('../config/contract-address.json');\r\n config = {\r\n ...CHAIN_CONFIG.localhost,\r\n ...localAddresses\r\n };\r\n console.log(\"Using local addresses:\", config);\r\n return config;\r\n } catch (err) {\r\n console.warn('No local addresses found');\r\n throw new Error('No local addresses found. Did you run local deployment?');\r\n }\r\n }\r\n\r\n // Altrimenti usa gli indirizzi di produzione\r\n config = CHAIN_CONFIG[chainName];\r\n if (!config) {\r\n throw new Error(`Chain ${chainName} not supported. Supported chains: ${Object.keys(CHAIN_CONFIG).join(', ')}`);\r\n }\r\n\r\n return config;\r\n}\r\n\r\n// Funzione helper per verificare se siamo in ambiente locale\r\nexport function isLocalEnvironment() {\r\n return process.env.NODE_ENV === 'development' && \r\n typeof window !== 'undefined' && \r\n window.location.hostname === 'localhost';\r\n}\r\n\r\nexport const STEALTH_ANNOUNCER_ABI = [\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"_devAddress\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"constructor\"\r\n },\r\n {\r\n \"anonymous\": false,\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"senderPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"spendingPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"stealthAddress\",\r\n \"type\": \"address\"\r\n },\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"timestamp\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"name\": \"StealthPaymentAnnounced\",\r\n \"type\": \"event\"\r\n },\r\n {\r\n \"anonymous\": false,\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"newAddress\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"name\": \"DevAddressUpdated\",\r\n \"type\": \"event\"\r\n },\r\n {\r\n \"anonymous\": false,\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"newFee\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"name\": \"DevFeeUpdated\",\r\n \"type\": \"event\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"senderPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"spendingPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"stealthAddress\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"name\": \"announcePayment\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"payable\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [],\r\n \"name\": \"devAddress\",\r\n \"outputs\": [\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [],\r\n \"name\": \"devFee\",\r\n \"outputs\": [\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [],\r\n \"name\": \"getAnnouncementsCount\",\r\n \"outputs\": [\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"fromIndex\",\r\n \"type\": \"uint256\"\r\n },\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"toIndex\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"name\": \"getAnnouncementsInRange\",\r\n \"outputs\": [\r\n {\r\n \"components\": [\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"senderPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"string\",\r\n \"name\": \"spendingPublicKey\",\r\n \"type\": \"string\"\r\n },\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"stealthAddress\",\r\n \"type\": \"address\"\r\n },\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"timestamp\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"internalType\": \"struct StealthAnnouncer.StealthAnnouncement[]\",\r\n \"name\": \"\",\r\n \"type\": \"tuple[]\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"_newFee\",\r\n \"type\": \"uint256\"\r\n }\r\n ],\r\n \"name\": \"updateDevFee\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"_newAddress\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"name\": \"updateDevAddress\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [],\r\n \"name\": \"withdrawStuckETH\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"function\"\r\n }\r\n];\r\n\r\nexport const PROOF_OF_INTEGRITY_ABI = [\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"bytes[]\",\r\n \"name\": \"nodeIds\",\r\n \"type\": \"bytes[]\"\r\n },\r\n {\r\n \"internalType\": \"bytes32[]\",\r\n \"name\": \"contentHashes\",\r\n \"type\": \"bytes32[]\"\r\n }\r\n ],\r\n \"name\": \"batchUpdateData\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"anonymous\": false,\r\n \"inputs\": [\r\n {\r\n \"indexed\": true,\r\n \"internalType\": \"bytes\",\r\n \"name\": \"nodeId\",\r\n \"type\": \"bytes\"\r\n },\r\n {\r\n \"indexed\": false,\r\n \"internalType\": \"bytes32\",\r\n \"name\": \"contentHash\",\r\n \"type\": \"bytes32\"\r\n },\r\n {\r\n \"indexed\": false,\r\n \"internalType\": \"address\",\r\n \"name\": \"updater\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"name\": \"DataUpdated\",\r\n \"type\": \"event\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"bytes\",\r\n \"name\": \"nodeId\",\r\n \"type\": \"bytes\"\r\n }\r\n ],\r\n \"name\": \"getLatestRecord\",\r\n \"outputs\": [\r\n {\r\n \"internalType\": \"bytes32\",\r\n \"name\": \"\",\r\n \"type\": \"bytes32\"\r\n },\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"\",\r\n \"type\": \"uint256\"\r\n },\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"bytes\",\r\n \"name\": \"nodeId\",\r\n \"type\": \"bytes\"\r\n },\r\n {\r\n \"internalType\": \"bytes32\",\r\n \"name\": \"contentHash\",\r\n \"type\": \"bytes32\"\r\n }\r\n ],\r\n \"name\": \"updateData\",\r\n \"outputs\": [],\r\n \"stateMutability\": \"nonpayable\",\r\n \"type\": \"function\"\r\n },\r\n {\r\n \"inputs\": [\r\n {\r\n \"internalType\": \"bytes\",\r\n \"name\": \"nodeId\",\r\n \"type\": \"bytes\"\r\n },\r\n {\r\n \"internalType\": \"bytes32\",\r\n \"name\": \"contentHash\",\r\n \"type\": \"bytes32\"\r\n }\r\n ],\r\n \"name\": \"verifyData\",\r\n \"outputs\": [\r\n {\r\n \"internalType\": \"bool\",\r\n \"name\": \"\",\r\n \"type\": \"bool\"\r\n },\r\n {\r\n \"internalType\": \"uint256\",\r\n \"name\": \"\",\r\n \"type\": \"uint256\"\r\n },\r\n {\r\n \"internalType\": \"address\",\r\n \"name\": \"\",\r\n \"type\": \"address\"\r\n }\r\n ],\r\n \"stateMutability\": \"view\",\r\n \"type\": \"function\"\r\n }\r\n];\r\n","// =============================================\r\n// IMPORTS AND GLOBAL VARIABLES\r\n// =============================================\r\nimport Gun from \"gun\";\r\nimport SEA from \"gun/sea.js\";\r\nimport { ethers } from \"ethers\";\r\nimport { PROOF_OF_INTEGRITY_ABI, STEALTH_ANNOUNCER_ABI, getAddressesForChain } from \"./abis/abis.js\";\r\nimport { LOCAL_CONFIG } from \"./config/local.js\";\r\n\r\n// Ottieni gli indirizzi corretti per la chain\r\nconst chainConfig = getAddressesForChain('optimismSepolia'); // o la chain desiderata\r\nconst STEALTH_ANNOUNCER_ADDRESS = chainConfig.STEALTH_ANNOUNCER_ADDRESS;\r\nconst PROOF_OF_INTEGRITY_ADDRESS = chainConfig.PROOF_OF_INTEGRITY_ADDRESS;\r\n\r\nlet PROOF_CONTRACT_ADDRESS;\r\nlet rpcUrl = \"\";\r\nlet privateKey = \"\";\r\n\r\nexport const MESSAGE_TO_SIGN = \"Access GunDB with Ethereum\";\r\n\r\nlet contractAddresses = {\r\n PROOF_OF_INTEGRITY_ADDRESS: null,\r\n STEALTH_ANNOUNCER_ADDRESS: STEALTH_ANNOUNCER_ADDRESS\r\n};\r\n\r\n// Solo per Node.js\r\nif (typeof window === 'undefined') {\r\n const { fileURLToPath } = require('url');\r\n const { dirname } = require('path');\r\n const { readFileSync } = require('fs');\r\n const path = require('path');\r\n \r\n const __filename = fileURLToPath(import.meta.url);\r\n const __dirname = dirname(__filename);\r\n\r\n try {\r\n const rawdata = readFileSync(path.join(__dirname, 'contract-address.json'), 'utf8');\r\n contractAddresses = JSON.parse(rawdata);\r\n console.log('Loaded contract addresses:', contractAddresses);\r\n } catch (err) {\r\n console.warn('Warning: contract-address.json not found or invalid');\r\n }\r\n}\r\n\r\n// =============================================\r\n// UTILITY FUNCTIONS\r\n// =============================================\r\n/**\r\n * Generates a random node ID for GunDB\r\n * @returns {string} A random hexadecimal string\r\n */\r\nexport function generateRandomId() {\r\n return ethers.hexlify(ethers.randomBytes(32)).slice(2);\r\n}\r\n\r\n/**\r\n * Generates a password from a signature.\r\n * @param {string} signature - The signature to derive the password from.\r\n * @returns {string|null} The generated password or null if generation fails.\r\n */\r\nexport function generatePassword(signature) {\r\n try {\r\n const hexSignature = ethers.hexlify(signature);\r\n const hash = ethers.keccak256(hexSignature);\r\n console.log(\"Generated password:\", hash);\r\n return hash;\r\n } catch (error) {\r\n console.error(\"Error generating password:\", error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Converts a Gun private key to an Ethereum account.\r\n * @param {string} gunPrivateKey - The Gun private key in base64url format.\r\n * @returns {Object} An object containing the Ethereum account and public key.\r\n */\r\nexport function gunToEthAccount(gunPrivateKey) {\r\n // Function to convert base64url to hex\r\n const base64UrlToHex = (base64url) => {\r\n const padding = \"=\".repeat((4 - (base64url.length % 4)) % 4);\r\n const base64 = base64url.replace(/-/g, \"+\").replace(/_/g, \"/\") + padding;\r\n const binary = atob(base64);\r\n return Array.from(binary, (char) =>\r\n char.charCodeAt(0).toString(16).padStart(2, \"0\")\r\n ).join(\"\");\r\n };\r\n\r\n // Convert Gun private key to hex format\r\n const hexPrivateKey = \"0x\" + base64UrlToHex(gunPrivateKey);\r\n\r\n // Create an Ethereum wallet from the private key\r\n const wallet = new ethers.Wallet(hexPrivateKey);\r\n\r\n // Get the public address (public key)\r\n const publicKey = wallet.address;\r\n\r\n return {\r\n account: wallet,\r\n publicKey: publicKey,\r\n privateKey: hexPrivateKey,\r\n };\r\n}\r\n\r\n/**\r\n * Gets an Ethereum signer based on current configuration\r\n * @returns {Promise<ethers.Signer>} The configured signer\r\n * @throws {Error} If no valid provider is found\r\n */\r\nexport const getSigner = async () => {\r\n if (rpcUrl && privateKey) {\r\n // Standalone mode with local provider\r\n const provider = new ethers.JsonRpcProvider(rpcUrl, {\r\n chainId: LOCAL_CONFIG.CHAIN_ID,\r\n name: \"localhost\"\r\n });\r\n return new ethers.Wallet(privateKey, provider);\r\n } else if (\r\n typeof window !== \"undefined\" &&\r\n typeof window.ethereum !== \"undefined\"\r\n ) {\r\n // Browser mode\r\n await window.ethereum.request({ method: \"eth_requestAccounts\" });\r\n const provider = new ethers.BrowserProvider(window.ethereum);\r\n return provider.getSigner();\r\n } else {\r\n throw new Error(\"No valid Ethereum provider found\");\r\n }\r\n};\r\n\r\n/**\r\n * Utility function to generate stealth address\r\n * @param {string} sharedSecret - The shared secret\r\n * @param {string} spendingPublicKey - The spending public key\r\n * @returns {Object} The stealth address and private key\r\n */\r\nexport function deriveStealthAddress(sharedSecret, spendingPublicKey) {\r\n try {\r\n // Convert shared secret to bytes\r\n const sharedSecretBytes = Buffer.from(sharedSecret, 'base64');\r\n \r\n // Generate stealth private key using shared secret and spending public key\r\n const stealthPrivateKey = ethers.keccak256(\r\n ethers.concat([\r\n sharedSecretBytes,\r\n ethers.getBytes(spendingPublicKey)\r\n ])\r\n );\r\n \r\n // Create stealth wallet\r\n const stealthWallet = new ethers.Wallet(stealthPrivateKey);\r\n\r\n console.log(\"Debug deriveStealthAddress:\", {\r\n sharedSecretHex: ethers.hexlify(sharedSecretBytes),\r\n spendingPublicKey,\r\n stealthPrivateKey,\r\n stealthAddress: stealthWallet.address\r\n });\r\n\r\n return {\r\n stealthPrivateKey,\r\n stealthAddress: stealthWallet.address,\r\n wallet: stealthWallet\r\n };\r\n } catch (error) {\r\n console.error(\"Error in deriveStealthAddress:\", error);\r\n throw error;\r\n }\r\n}\r\n\r\n// =============================================\r\n// BASIC GUN-ETH CHAIN METHODS\r\n// =============================================\r\n\r\n// Set the message to sign\r\nGun.chain.MESSAGE_TO_SIGN = MESSAGE_TO_SIGN;\r\n\r\n/**\r\n * Sets standalone configuration for Gun.\r\n * @param {string} newRpcUrl - The new RPC URL.\r\n * @param {string} newPrivateKey - The new private key.\r\n * @returns {Gun} The Gun instance for chaining.\r\n */\r\nGun.chain.setSigner = function (newRpcUrl, newPrivateKey) {\r\n rpcUrl = newRpcUrl;\r\n privateKey = newPrivateKey;\r\n console.log(\"Standalone configuration set\");\r\n return this;\r\n};\r\n\r\nGun.chain.getSigner = getSigner();\r\n\r\n/**\r\n * Verifies an Ethereum signature.\r\n * @param {string} message - The original message that was signed.\r\n * @param {string} signature - The signature to verify.\r\n * @returns {Promise<string|null>} The recovered address or null if verification fails.\r\n */\r\nGun.chain.verifySignature = async function (message, signature) {\r\n try {\r\n const recoveredAddress = ethers.verifyMessage(message, signature);\r\n return recoveredAddress;\r\n } catch (error) {\r\n console.error(\"Error verifying signature:\", error);\r\n return null;\r\n }\r\n};\r\n\r\n/**\r\n * Generates a password from a signature.\r\n * @param {string} signature - The signature to derive the password from.\r\n * @returns {string|null} The generated password or null if generation fails.\r\n */\r\nGun.chain.generatePassword = function (signature) {\r\n return generatePassword(signature);\r\n};\r\n\r\n/**\r\n * Creates an Ethereum signature for a given message.\r\n * @param {string} message - The message to sign.\r\n * @returns {Promise<string|null>} The signature or null if signing fails.\r\n */\r\nGun.chain.createSignature = async function (message) {\r\n try {\r\n // Check if message matches MESSAGE_TO_SIGN\r\n if (message !== MESSAGE_TO_SIGN) {\r\n throw new Error(\"Invalid message, valid message is: \" + MESSAGE_TO_SIGN);\r\n }\r\n const signer = await getSigner();\r\n const signature = await signer.signMessage(message);\r\n console.log(\"Signature created:\", signature);\r\n return signature;\r\n } catch (error) {\r\n console.error(\"Error creating signature:\", error);\r\n return null;\r\n }\r\n};\r\n\r\n// =============================================\r\n// KEY PAIR MANAGEMENT\r\n// =============================================\r\n/**\r\n * Creates and stores an encrypted key pair for a given address.\r\n * @param {string} address - The Ethereum address to associate with the key pair.\r\n * @param {string} signature - The signature to use for encryption.\r\n * @returns {Promise<void>}\r\n */\r\nGun.chain.createAndStoreEncryptedPair = async function (address, signature) {\r\n try {\r\n const gun = this;\r\n const pair = await SEA.pair();\r\n const v_pair = await SEA.pair();\r\n const s_pair = await SEA.pair();\r\n const password = generatePassword(signature);\r\n\r\n // Save original SEA pairs\r\n const encryptedPair = await SEA.encrypt(JSON.stringify(pair), password);\r\n const encryptedV_pair = await SEA.encrypt(JSON.stringify(v_pair), password);\r\n const encryptedS_pair = await SEA.encrypt(JSON.stringify(s_pair), password);\r\n\r\n // Convert only to get Ethereum addresses\r\n const viewingAccount = gunToEthAccount(v_pair.priv);\r\n const spendingAccount = gunToEthAccount(s_pair.priv);\r\n\r\n gun.get(\"gun-eth\").get(\"users\").get(address).put({\r\n pair: encryptedPair,\r\n v_pair: encryptedV_pair,\r\n s_pair: encryptedS_pair,\r\n publicKeys: {\r\n viewingPublicKey: v_pair.epub, // Use SEA encryption public key\r\n viewingPublicKey: v_pair.epub, // Use SEA encryption public key\r\n spendingPublicKey: spendingAccount.publicKey, // Use Ethereum address\r\n ethViewingAddress: viewingAccount.publicKey // Also save Ethereum address\r\n }\r\n });\r\n\r\n console.log(\"Encrypted pairs and public keys stored for:\", address);\r\n } catch (error) {\r\n console.error(\"Error creating and storing encrypted pair:\", error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Retrieves and decrypts a stored key pair for a given address.\r\n * @param {string} address - The Ethereum address associated with the key pair.\r\n * @param {string} signature - The signature to use for decryption.\r\n * @returns {Promise<Object|null>} The decrypted key pair or null if retrieval fails.\r\n */\r\nGun.chain.getAndDecryptPair = async function (address, signature) {\r\n try {\r\n const gun = this;\r\n const encryptedData = await gun\r\n .get(\"gun-eth\")\r\n .get(\"users\")\r\n .get(address)\r\n .get(\"pair\")\r\n .then();\r\n if (!encryptedData) {\r\n throw new Error(\"No encrypted data found for this address\");\r\n }\r\n const password = generatePassword(signature);\r\n const decryptedPair = await SEA.decrypt(encryptedData, password);\r\n console.log(decryptedPair);\r\n return decryptedPair;\r\n } catch (error) {\r\n console.error(\"Error retrieving and decrypting pair:\", error);\r\n return null;\r\n }\r\n};\r\n\r\n// =============================================\r\n// PROOF OF INTEGRITY\r\n// =============================================\r\n/**\r\n * Proof of Integrity\r\n * @param {string} chain - The blockchain to use (e.g., \"optimismSepolia\").\r\n * @param {string} nodeId - The ID of the node to verify or write.\r\n * @param {Object} data - The data to write (if writing).\r\n * @param {Function} callback - Callback function to handle the result.\r\n * @returns {Gun} The Gun instance for chaining.\r\n */\r\nGun.chain.proof = function (chain, nodeId, data, callback) {\r\n console.log(\"Proof plugin called with:\", { chain, nodeId, data });\r\n\r\n if (typeof callback !== \"function\") {\r\n console.error(\"Callback must be a function\");\r\n return this;\r\n }\r\n\r\n try {\r\n // Se siamo in localhost e in development, usa automaticamente la chain locale\r\n const targetChain = isLocalEnvironment() ? 'localhost' : chain;\r\n const chainConfig = getAddressesForChain(targetChain);\r\n \r\n console.log(`Using ${targetChain} configuration:`, chainConfig);\r\n\r\n // Usa gli indirizzi dalla configurazione\r\n const contract = new ethers.Contract(\r\n chainConfig.PROOF_OF_INTEGRITY_ADDRESS,\r\n PROOF_OF_INTEGRITY_ABI,\r\n signer\r\n );\r\n\r\n // Funzione per verificare on-chain\r\n const verifyOnChain = async (nodeId, contentHash) => {\r\n console.log(\"Verifying on chain:\", { nodeId, contentHash });\r\n const signer = await getSigner();\r\n const contract = new ethers.Contract(\r\n PROOF_CONTRACT_ADDRESS,\r\n PROOF_OF_INTEGRITY_ABI,\r\n signer\r\n );\r\n const [isValid, timestamp, updater] = await contract.verifyData(\r\n ethers.toUtf8Bytes(nodeId),\r\n contentHash\r\n );\r\n console.log(\"Verification result:\", { isValid, timestamp, updater });\r\n return { isValid, timestamp, updater };\r\n };\r\n\r\n // Funzione per scrivere on-chain\r\n const writeOnChain = async (nodeId, contentHash) => {\r\n console.log(\"Writing on chain:\", { nodeId, contentHash });\r\n const signer = await getSigner();\r\n const contract = new ethers.Contract(\r\n PROOF_CONTRACT_ADDRESS,\r\n PROOF_OF_INTEGRITY_ABI,\r\n signer\r\n );\r\n const tx = await contract.updateData(\r\n ethers.toUtf8Bytes(nodeId),\r\n contentHash\r\n );\r\n console.log(\"Transaction sent:\", tx.hash);\r\n const receipt = await tx.wait();\r\n console.log(\"Transaction confirmed:\", receipt);\r\n return tx;\r\n };\r\n\r\n // Funzione per ottenere l'ultimo record\r\n const getLatestRecord = async (nodeId) => {\r\n const signer = await getSigner();\r\n const contract = new ethers.Contract(\r\n PROOF_CONTRACT_ADDRESS,\r\n PROOF_OF_INTEGRITY_ABI,\r\n signer\r\n );\r\n const [contentHash, timestamp, updater] = await contract.getLatestRecord(\r\n ethers.toUtf8Bytes(nodeId)\r\n );\r\n console.log(\"Latest record from blockchain:\", {\r\n nodeId,\r\n contentHash,\r\n timestamp,\r\n updater,\r\n });\r\n return { contentHash, timestamp, updater };\r\n };\r\n\r\n \r\n if (nodeId && !data) {\r\n // Case 1: User passes only node\r\n gun.get(nodeId).once(async (existingData) => {\r\n if (!existingData) {\r\n if (callback) callback({ err: \"Node not found in GunDB\" });\r\n return;\r\n }\r\n\r\n console.log(\"existingData\", existingData);\r\n\r\n // Use stored contentHash instead of recalculating\r\n const contentHash = existingData._contentHash;\r\n console.log(\"contentHash\", contentHash);\r\n\r\n if (!contentHash) {\r\n if (callback) callback({ err: \"No content hash found for this node\" });\r\n return;\r\n }\r\n\r\n try {\r\n const { isValid, timestamp, updater } = await verifyOnChain(\r\n nodeId,\r\n contentHash\r\n );\r\n const latestRecord = await getLatestRecord(nodeId);\r\n\r\n if (isValid) {\r\n if (callback)\r\n callback({\r\n ok: true,\r\n message: \"Data verified on blockchain\",\r\n timestamp,\r\n updater,\r\n latestRecord,\r\n });\r\n } else {\r\n if (callback)\r\n callback({\r\n ok: false,\r\n message: \"Data not verified on blockchain\",\r\n latestRecord,\r\n });\r\n }\r\n } catch (error) {\r\n if (callback) callback({ err: error.message });\r\n }\r\n });\r\n } else if (data && !nodeId) {\r\n // Case 2: User passes only text (data)\r\n const newNodeId = generateRandomId();\r\n const dataString = JSON.stringify(data);\r\n const contentHash = ethers.keccak256(ethers.toUtf8Bytes(dataString));\r\n\r\n gun\r\n .get(newNodeId)\r\n .put({ ...data, _contentHash: contentHash }, async (ack) => {\r\n console.log(\"ack\", ack);\r\n if (ack.err) {\r\n if (callback) callback({ err: \"Error saving data to GunDB\" });\r\n return;\r\n }\r\n\r\n try {\r\n const tx = await writeOnChain(newNodeId, contentHash);\r\n if (callback)\r\n callback({\r\n ok: true,\r\n message: \"Data written to GunDB and blockchain\",\r\n nodeId: newNodeId,\r\n txHash: tx.hash,\r\n });\r\n } catch (error) {\r\n if (callback) callback({ err: error.message });\r\n }\r\n });\r\n } else {\r\n if (callback)\r\n callback({\r\n err: \"Invalid input. Provide either nodeId or data, not both.\",\r\n });\r\n }\r\n\r\n return gun;\r\n } catch (error) {\r\n callback({ err: error.message });\r\n return this;\r\n }\r\n};\r\n\r\n// =============================================\r\n// STEALTH ADDRESS CORE FUNCTIONS\r\n// =============================================\r\n/**\r\n * Converts a Gun private key to an Ethereum account.\r\n * @param {string} gunPrivateKey - The Gun private key in base64url format.\r\n * @returns {Object} An object containing the Ethereum account and public key.\r\n */\r\nGun.chain.gunToEthAccount = function (gunPrivateKey) {\r\n return gunToEthAccount(gunPrivateKey);\r\n};\r\n\r\n/**\r\n * Generate a stealth key and related key pairs\r\n * @param {string} recipientAddress - The recipient's Ethereum address\r\n * @param {string} signature - The sender's signature to access their keys\r\n * @returns {Promise<Object>} Object containing stealth addresses and keys\r\n */\r\nGun.chain.generateStealthAddress = async function (recipientAddress, signature) {\r\n try {\r\n const gun = this;\r\n \r\n // Get recipient's public keys\r\n const recipientData = await gun\r\n .get(\"gun-eth\")\r\n .get(\"users\")\r\n .get(recipientAddress)\r\n .get(\"publicKeys\")\r\n .then();\r\n\r\n if (!recipientData || !recipientData.viewingPublicKey || !recipientData.spendingPublicKey) {\r\n throw new Error(\"Recipient's public keys not found\");\r\n }\r\n\r\n // Get sender's keys\r\n const senderAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);\r\n const password = generatePassword(signature);\r\n \r\n const senderData = await gun\r\n .get(\"gun-eth\")\r\n .get(\"users\")\r\n .get(senderAddress)\r\n .then();\r\n\r\n if (!senderData || !senderData.s_pair) {\r\n throw new Error(\"Sender's keys not found\");\r\n }\r\n\r\n // Decrypt sender's spending pair\r\n let spendingKeyPair;\r\n try {\r\n const decryptedData = await SEA.decrypt(senderData.s_pair, password);\r\n spendingKeyPair = typeof decryptedData === 'string' ? \r\n JSON.parse(decryptedData) : \r\n decryptedData;\r\n } catch (error) {\r\n console.error(\"Error decrypting spending pair:\", error);\r\n throw new Error(\"Unable to decrypt spending pair\");\r\n }\r\n\r\n // Generate shared secret using SEA ECDH with encryption public key\r\n const sharedSecret = await SEA.secret(recipientData.viewingPublicKey, spendingKeyPair);\r\n\r\n if (!sharedSecret) {\r\n throw new Error(\"Unable to generate shared secret\");\r\n }\r\n\r\n console.log(\"Generate shared secret:\", sharedSecret);\r\n\r\n const { stealthAddress } = deriveStealthAddress(\r\n sharedSecret,\r\n recipientData.spendingPublicKey\r\n );\r\n\r\n return {\r\n stealthAddress,\r\n senderPublicKey: spendingKeyPair.epub, // Use encryption public key\r\n spendingPublicKey: recipientData.spendingPublicKey\r\n };\r\n\r\n } catch (error) {\r\n console.error(\"Error generating stealth address:\", error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Publish public keys needed to receive stealth payments\r\n * @param {string} signature - The signature to authenticate the user\r\n * @returns {Promise<void>}\r\n */\r\nGun.chain.publishStealthKeys = async function (signature) {\r\n try {\r\n const gun = this;\r\n const address = await this.verifySignature(MESSAGE_TO_SIGN, signature);\r\n const password = generatePassword(signature);\r\n\r\n // Get encrypted key pairs\r\n const encryptedData = await gun\r\n .get(\"gun-eth\")\r\n .get(\"users\")\r\n .get(address)\r\n .then();\r\n\r\n if (!encryptedData || !encryptedData.v_pair || !encryptedData.s_pair) {\r\n throw new Error(\"Keys not found\");\r\n }\r\n\r\n // Decrypt viewing and spending pairs\r\n const viewingKeyPair = JSON.parse(\r\n await SEA.decrypt(encryptedData.v_pair, password)\r\n );\r\n const spendingKeyPair = JSON.parse(\r\n await SEA.decrypt(encryptedData.s_pair, password)\r\n );\r\n\r\n const viewingAccount = gunToEthAccount(viewingKeyPair.priv);\r\n const spendingAccount = gunToEthAccount(spendingKeyPair.priv);\r\n\r\n // Publish only public keys\r\n gun.get(\"gun-eth\").get(\"users\").get(address).get(\"publicKeys\").put({\r\n viewingPublicKey: viewingAccount.publicKey,\r\n spendingPublicKey: spendingAccount.publicKey,\r\n });\r\n\r\n console.log(\"Stealth public keys published successfully\");\r\n } catch (error) {\r\n console.error(\"Error publishing stealth keys:\", error);\r\n throw error;\r\n }\r\n};\r\n\r\n// =============================================\r\n// STEALTH PAYMENT FUNCTIONS\r\n// =============================================\r\n/**\r\n * Recover funds from a stealth address\r\n * @param {string} stealthAddress - The stealth address to recover funds from\r\n * @param {string} senderPublicKey - The sender's public key used to generate the address\r\n * @param {string} signature - The signature to decrypt private keys\r\n * @returns {Promise<Object>} Object containing wallet to access funds\r\n */\r\nGun.chain.recoverStealthFunds = async function (\r\n stealthAddress,\r\n senderPublicKey,\r\n signature,\r\n spendingPublicKey\r\n) {\r\n try {\r\n const gun = this;\r\n const password = generatePassword(signature);\r\n\r\n // Get own key pairs\r\n const myAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);\r\n const encryptedData = await gun\r\n .get(\"gun-eth\")\r\n .get(\"users\")\r\n .get(myAddress)\r\n .then();\r\n\r\n if (!encryptedData || !encryptedData.v_pair || !encryptedData.s_pair) {\r\n throw new Error(\"Keys not found\");\r\n }\r\n\r\n // Decrypt viewing and spending pairs\r\n let viewingKeyPair;\r\n try {\r\n const decryptedViewingData = await SEA.decrypt(encryptedData.v_pair, password);\r\n viewingKeyPair = typeof decryptedViewingData === 'string' ? \r\n JSON.parse(decryptedViewingData) : \r\n decryptedViewingData;\r\n } catch (error) {\r\n console.error(\"Error decrypting keys:\", error);\r\n throw new Error(\"Unable to decrypt keys\");\r\n }\r\n\r\n // Generate shared secret using SEA ECDH\r\n const sharedSecret = await SEA.secret(senderPublicKey, viewingKeyPair);\r\n\r\n if (!sharedSecret) {\r\n throw new Error(\"Unable to generate shared secret\");\r\n }\r\n\r\n console.log(\"Recover shared secret:\", sharedSecret);\r\n\r\n const { wallet, stealthAddress: recoveredAddress } = deriveStealthAddress(\r\n sharedSecret,\r\n spendingPublicKey\r\n );\r\n\r\n // Verify address matches\r\n if (recoveredAddress.toLowerCase() !== stealthAddress.toLowerCase()) {\r\n console.error(\"Mismatch:\", {\r\n recovered: recoveredAddress,\r\n expected: stealthAddress,\r\n sharedSecret\r\n });\r\n throw new Error(\"Recovered stealth address does not match\");\r\n }\r\n\r\n return {\r\n wallet,\r\n address: recoveredAddress,\r\n };\r\n } catch (error) {\r\n console.error(\"Error recovering stealth funds:\", error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Announce a stealth payment\r\n * @param {string} stealthAddress - The generated stealth address\r\n * @param {string} senderPublicKey - The sender's public key\r\n * @param {string} spendingPublicKey - The spending public key\r\n * @param {string} signature - The sender's signature\r\n * @returns {Promise<void>}\r\n */\r\nGun.chain.announceStealthPayment = async function (\r\n stealthAddress,\r\n senderPublicKey,\r\n spendingPublicKey,\r\n signature,\r\n options = { onChain: false, chain: 'optimismSepolia' }\r\n) {\r\n try {\r\n const gun = this;\r\n const senderAddress = await this.verifySignature(MESSAGE_TO_SIGN, signature);\r\n\r\n if (options.onChain) {\r\n // On-chain announcement\r\n const signer = await getSigner();\r\n const chainAddresses = getAddressesForChain(options.chain);\r\n const contractAddress = chainAddresses.STEALTH_ANNOUNCER_ADDRESS;\r\n\r\n console.log(\"Using contract address:\", contractAddress);\r\n\r\n const contract = new ethers.Contract(\r\n contractAddress,\r\n STEALTH_ANNOUNCER_ABI,\r\n signer\r\n );\r\n\r\n // Get dev fee from contract\r\n const devFee = await contract.devFee();\r\n console.log(\"Dev fee:\", devFee.toString());\r\n\r\n // Call contract\r\n const tx = await contract.announcePayment(\r\n senderPublicKey,\r\n spendingPublicKey,\r\n stealthAddress,\r\n { value: devFee }\r\n );\r\n \r\n console.log(\"Transaction sent:\", tx.hash);\r\n const receipt = await tx.wait();\r\n console.log(\"Transaction confirmed:\", receipt.hash);\r\n \r\n console.log(\"Stealth payment announced on-chain (dev fee paid)\");\r\n } else {\r\n // Off-chain announcement (GunDB)\r\n gun\r\n .get(\"gun-eth\")\r\n .get(\"stealth-payments\")\r\n .set({\r\n stealthAddress,\r\n senderAddress,\r\n senderPublicKey,\r\n spendingPublicKey,\r\n timestamp: Date.now(),\r\n });\r\n console.log(\"Stealth payment announced off-chain\");\r\n }\r\n } catch (error) {\r\n console.error(\"Error announcing stealth payment:\", error);\r\n console.error(\"Error details:\", error.stack);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Get all stealth payments for an address\r\n * @param {string} signature - The signature to authenticate the user\r\n * @returns {Promise<Array>} List of stealth payments\r\n */\r\nGun.chain.getStealthPayments = async function (signature, options = { source: 'both' }) {\r\n try {\r\n const payments = [];\r\n\r\n if (options.source === 'onChain' || options.source === 'both') {\r\n // Get on-chain payments\r\n const signer = await getSigner();\r\n const contractAddress = process.env.NODE_ENV === 'development' \r\n ? LOCAL_CONFIG.STEALTH_ANNOUNCER_ADDRESS \r\n : STEALTH_ANNOUNCER_ADDRESS;\r\n\r\n const contract = new ethers.Contract(\r\n contractAddress,\r\n STEALTH_ANNOUNCER_ABI,\r\n signer\r\n );\r\n \r\n try {\r\n // Get total number of announcements\r\n const totalAnnouncements = await contract.getAnnouncementsCount();\r\n const totalCount = Number(totalAnnouncements.toString());\r\n console.log(\"Total on-chain announcements:\", totalCount);\r\n \r\n if (totalCount > 0) {\r\n // Get announcements in batches of 100\r\n const batchSize = 100;\r\n const lastIndex = totalCount - 1;\r\n \r\n for(let i = 0; i <= lastIndex; i += batchSize) {\r\n const toIndex = Math.min(i + batchSize - 1, lastIndex);\r\n const batch = await contract.getAnnouncementsInRange(i, toIndex);\r\n \r\n // For each announcement, try to decrypt\r\n for(const announcement of batch) {\r\n try {\r\n // Verify announcement is valid\r\n if (!announcement || !announcement.stealthAddress || \r\n !announcement.senderPublicKey || !announcement.spendingPublicKey) {\r\n console.log(\"Invalid announcement:\", announcement);\r\n continue;\r\n }\r\n\r\n // Try to recover funds to verify if announcement is for us\r\n const recoveredWallet = await this.recoverStealthFunds(\r\n announcement.stealthAddress,\r\n announcement.senderPublicKey,\r\n signature,\r\n announcement.spendingPublicKey\r\n );\r\n \r\n // If no errors thrown, announcement is for us\r\n payments.push({\r\n stealthAddress: announcement.stealthAddress,\r\n senderPublicKey: announcement.senderPublicKey,\r\n spendingPublicKey: announcement.spendingPublicKey,\r\n timestamp: Number(announcement.timestamp),\r\n source: 'onChain',\r\n wallet: recoveredWallet\r\n });\r\n\r\n } catch (e) {\r\n // Not for us, continue\r\n console.log(`Announcement not for us: ${announcement.stealthAddress}`);\r\n continue;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Error retrieving on-chain announcements:\", error);\r\n }\r\n }\r\n\r\n if (options.source === 'offChain' || options.source === 'both') {\r\n // Get off-chain payments\r\n const gun = this;\r\n const offChainPayments = await new Promise((resolve) => {\r\n const p = [];\r\n gun\r\n .get(\"gun-eth\")\r\n .get(\"stealth-payments\")\r\n .get(recipientAddress)\r\n .map()\r\n .once((payment, id) => {\r\n if (payment?.stealthAddress) {\r\n p.push({ ...payment, id, source: 'offChain' });\r\n }\r\n });\r\n setTimeout(() => resolve(p), 2000);\r\n });\r\n \r\n payments.push(...offChainPayments);\r\n }\r\n\r\n console.log(`Found ${payments.length} stealth payments`);\r\n return payments;\r\n } catch (error) {\r\n console.error(\"Error retrieving stealth payments:\", error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Clean up old stealth payments\r\n * @param {string} recipientAddress - The recipient's address\r\n * @returns {Promise<void>}\r\n */\r\nGun.chain.cleanStealthPayments = async function(recipientAddress) {\r\n try {\r\n const gun = this;\r\n const payments = await gun\r\n .get(\"gun-eth\")\r\n .get(\"stealth-payments\")\r\n .get(recipientAddress)\r\n .map()\r\n .once()\r\n .then();\r\n\r\n // Remove empty or invalid nodes\r\n if (payments) {\r\n Object.keys(payments).forEach(async (key) => {\r\n const payment = payments[key];\r\n if (!payment || !payment.stealthAddress || !payment.senderPublicKey || !payment.spendingPublicKey) {\r\n await gun\r\n .get(\"gun-eth\")\r\n .get(\"stealth-payments\")\r\n .get(recipientAddress)\r\n .get(key)\r\n .put(null);\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n console.error(\"Error cleaning stealth payments:\", error);\r\n }\r\n};\r\n\r\n// =============================================\r\n// EXPORTS\r\n// =============================================\r\n\r\n// Crea una classe GunEth che contiene tutti i metodi e le utility\r\nexport class GunEth {\r\n // Static utility methods\r\n static generateRandomId = generateRandomId;\r\n static generatePassword = generatePassword;\r\n static gunToEthAccount = gunToEthAccount;\r\n static getSigner = getSigner;\r\n static deriveStealthAddress = deriveStealthAddress;\r\n \r\n // Chain methods\r\n static chainMethods = {\r\n setSigner: Gun.chain.setSigner,\r\n getSigner: Gun.chain.getSigner,\r\n verifySignature: Gun.chain.verifySignature,\r\n generatePassword: Gun.chain.generatePassword,\r\n createSignature: Gun.chain.createSignature,\r\n createAndStoreEncryptedPair: Gun.chain.createAndStoreEncryptedPair,\r\n getAndDecryptPair: Gun.chain.getAndDecryptPair,\r\n proof: Gun.chain.proof,\r\n gunToEthAccount: Gun.chain.gunToEthAccount,\r\n generateStealthAddress: Gun.chain.generateStealthAddress,\r\n publishStealthKeys: Gun.chain.publishStealthKeys,\r\n recoverStealthFunds: Gun.chain.recoverStealthFunds,\r\n announceStealthPayment: Gun.chain.announceStealthPayment,\r\n getStealthPayments: Gun.chain.getStealthPayments,\r\n cleanStealthPayments: Gun.chain.cleanStealthPayments\r\n };\r\n\r\n // Constants\r\n static MESSAGE_TO_SIGN = MESSAGE_TO_SIGN;\r\n static PROOF_CONTRACT_ADDRESS = PROOF_CONTRACT_ADDRESS;\r\n static LOCAL_CONFIG = LOCAL_CONFIG;\r\n}\r\n\r\n// Esporta Gun come default\r\nexport default Gun;\r\n"],"names":["contractAddresses","PROOF_OF_INTEGRITY_ADDRESS","STEALTH_ANNOUNCER_ADDRESS","window","fileURLToPath","require","dirname","readFileSync","join","__filename","document","location","pathToFileURL","href","_documentCurrentScript","tagName","toUpperCase","src","URL","baseURI","rawdata","JSON","parse","console","log","error","warn","LOCAL_CONFIG","CHAIN_ID","RPC_URL","GUN_PEER","CHAIN_CONFIG","optimismSepolia","arbitrumSepolia","localhost","getAddressesForChain","chainName","config","require$$0","err","Error","Object","keys","STEALTH_ANNOUNCER_ABI","inputs","internalType","name","type","stateMutability","anonymous","outputs","components","PROOF_OF_INTEGRITY_ABI","indexed","chainConfig","PROOF_CONTRACT_ADDRESS","rpcUrl","privateKey","MESSAGE_TO_SIGN","path","__dirname","generateRandomId","ethers","hexlify","randomBytes","slice","generatePassword","signature","hexSignature","hash","keccak256","gunToEthAccount","gunPrivateKey","hexPrivateKey","base64url","padding","repeat","length","base64","replace","binary","atob","Array","from","char","charCodeAt","toString","padStart","base64UrlToHex","wallet","Wallet","account","publicKey","address","getSigner","async","provider","JsonRpcProvider","chainId","ethereum","request","method","BrowserProvider","deriveStealthAddress","sharedSecret","spendingPublicKey","sharedSecretBytes","Buffer","stealthPrivateKey","concat","getBytes","stealthWallet","sharedSecretHex","stealthAddress","Gun","chain","setSigner","newRpcUrl","newPrivateKey","this","verifySignature","message","verifyMessage","createSignature","signer","signMessage","createAndStoreEncryptedPair","gun","pair","SEA","v_pair","s_pair","password","encryptedPair","encrypt","stringify","encryptedV_pair","encryptedS_pair","viewingAccount","priv","spendingAccount","get","put","publicKeys","viewingPublicKey","epub","ethViewingAddress","getAndDecryptPair","encryptedData","then","decryptedPair","decrypt","proof","nodeId","data","callback","targetChain","isLocalEnvironment","Contract","verifyOnChain","contentHash","contract","isValid","timestamp","updater","verifyData","toUtf8Bytes","writeOnChain","tx","updateData","receipt","wait","getLatestRecord","once","existingData","_contentHash","latestRecord","ok","newNodeId","dataString","ack","txHash","generateStealthAddress","recipientAddress","recipientData","senderAddress","senderData","spendingKeyPair","decryptedData","secret","senderPublicKey","publishStealthKeys","viewingKeyPair","recoverStealthFunds","myAddress","decryptedViewingData","recoveredAddress","toLowerCase","recovered","expected","announceStealthPayment","options","onChain","contractAddress","devFee","announcePayment","value","set","Date","now","stack","getStealthPayments","source","payments","process","env","NODE_ENV","totalAnnouncements","getAnnouncementsCount","totalCount","Number","batchSize","lastIndex","i","toIndex","Math","min","batch","getAnnouncementsInRange","announcement","recoveredWallet","push","e","offChainPayments","Promise","resolve","p","map","payment","id","setTimeout","cleanStealthPayments","forEach","key","GunEth","static"],"mappings":"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"}