JSPM

  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q36607F
  • License MIT

A GunDB plugin for Ethereum, and Web3

Package Exports

  • gun-eth

Readme

Gun-ETH 🔫

Gun-ETH Logo

A powerful Gun.js plugin that extends its capabilities by adding advanced blockchain and cryptographic features to create more secure and private decentralized applications.

✨ Why Gun-ETH?

  • 🎯 Powerful Extension: Adds advanced blockchain and cryptographic features to Gun.js
  • 🌐 Seamless Integration: Perfectly integrates with Gun.js while maintaining simplicity
  • 🔒 Advanced Privacy: Implements stealth transactions, proof chain, and encrypted data
  • 🚀 Modern Architecture: Intuitive APIs for easy Web3 functionality implementation

🚀 Quick Start

Installation

npm install gun-eth
# or
yarn add gun-eth

Basic Configuration

import Gun from 'gun';
import { GunEth } from 'gun-eth';
import { ethers } from 'ethers';

// Configure Gun with peers
const gun = Gun({
    peers: ['http://localhost:8765/gun']
});

// Initialize GunEth
const gunEth = await GunEth.init('localhost'); // or 'mainnet', 'sepolia', etc.

Signer Configuration

Gun-ETH provides two ways to configure the signer:

  1. Manual Configuration (Recommended for Production)
import { setSigner, getSigner } from 'gun-eth';

// Configure with explicit RPC URL and private key
await setSigner(
    "https://your-rpc-url", 
    "your-private-key"
);

// Get the configured signer
const signer = await getSigner();
  1. MetaMask Fallback (Development-Friendly)
import { getSigner } from 'gun-eth';

// Will automatically use MetaMask if available
try {
    const signer = await getSigner();
    console.log("Connected with address:", await signer.getAddress());
} catch (error) {
    console.error("No valid provider found");
}

The signer selection follows these priorities:

  1. Uses manually configured signer if set via setSigner()
  2. Falls back to MetaMask if available and no manual configuration
  3. Throws an error if no valid provider is found

Error Handling

try {
    const gunEth = await GunEth.init({
        gun,
        chain: 'localhost'
    });
} catch (error) {
    console.error('Initialization error:', error);
}

📚 Documentation

🔐 Gun-Ethereum Integration

ETH -> GUN Conversion

try {
    // Create signature with Ethereum wallet
    const signature = await GunEth.createSignature(GunEth.MESSAGE_TO_SIGN);
    
    // Convert to Gun SEA compatible keypair
    const gunKeyPair = await GunEth.ethToGunAccount(signature);
    
    console.log('Generated Gun SEA keypair:', gunKeyPair);
    // The keypair contains keys generated by Gun SEA:
    // {
    //     pub: "SEA-public-key",
    //     priv: "SEA-private-key",
    //     epub: "SEA-encryption-public-key",
    //     epriv: "SEA-encryption-private-key"
    // }
} catch (error) {
    console.error('Conversion error:', error);
}

GUN -> ETH Conversion

try {
    // Requires the SEA private key generated by Gun
    const ethAccount = await GunEth.gunToEthAccount(gunSEAPrivateKey);
    console.log('Ethereum account:', ethAccount);
} catch (error) {
    console.error('Conversion error:', error);
}

🔒 Stealth Chain

// Initialize Gun
const gun = Gun();
await GunEth.init({ gun, chain: 'localhost' });

try {
    // Publish stealth keys
    const signature = await GunEth.createSignature(GunEth.MESSAGE_TO_SIGN);
    await gun.publishStealthKeys(signature);

    // Generate stealth address
    const stealthInfo = await gun.generateStealthAddress(
        recipientAddress,
        signature,
        {} // Additional options if needed
    );

    console.log('Generated stealth address:', stealthInfo);
    // Returns:
    // {
    //     stealthAddress: "0x...",      // The generated stealth address
    //     senderPublicKey: "...",       // The sender's public key
    //     spendingPublicKey: "..."      // The recipient's spending public key
    // }

    // Announce the payment
    await gun.announceStealthPayment(
        stealthInfo.stealthAddress,
        stealthInfo.senderPublicKey,
        stealthInfo.spendingPublicKey,
        signature,
        { onChain: true } // Optional: announce on-chain
    );
} catch (error) {
    console.error('Stealth operation error:', error);
}

// Monitor stealth events
gun.monitorStealthEvents((event) => {
    console.log('New stealth event:', event);
});

⛓️ Proof Chain

try {
    // Write data with proof
    await gun.proof('users', null, {
        name: 'Alice',
        age: 25
    }, (ack) => {
        if (ack.err) {
            console.error('Write error:', ack.err);
            return;
        }
        console.log('Data written successfully:', {
            nodeId: ack.nodeId,
            txHash: ack.txHash
        });
    });

    // Verify data integrity
    await gun.proof('users', 'nodeId123', null, (ack) => {
        if (ack.err) {
            console.error('Verification error:', ack.err);
            return;
        }
        console.log('Verification completed:', ack.ok);
    });
} catch (error) {
    console.error('Proof operation error:', error);
}

🫧 Encrypted Bubbles

// Initialize Bubble Client
import { BubbleClient } from 'gun-eth';

const bubbleClient = new BubbleClient({
    providerUrl: "http://localhost:3000/api",
    signer: signer,  // Your Ethereum signer
    keypair: {       // Your encryption keypair
        epub: "your-encryption-public-key",
        epriv: "your-encryption-private-key"
    }
});

// Create and manage bubbles
const bubble = await bubbleClient.createBubble("My Bubble", {
    isPrivate: true
});

// Write encrypted content
await bubbleClient.writeBubble(
    bubble.id,
    "secret.txt",
    "My secret content"
);

// Read and decrypt content
const result = await bubbleClient.readBubble(
    bubble.id,
    "secret.txt"
);

// Share with another user
await bubbleClient.shareBubble(
    bubble.id,
    recipientAddress,
    { granteeEpub: recipientPublicKey }
);

🔄 Bubble Providers

Gun-ETH offers three types of providers for managing encrypted bubbles:

Base Provider

import { BaseBubbleProvider } from 'gun-eth';

class CustomProvider extends BaseBubbleProvider {
    async handleCreateBubble(options) { }
    async handleWriteBubble(bubbleId, fileName, content) { }
    async handleReadBubble(bubbleId, fileName) { }
    async handleGrantPermission(bubbleId, granteeAddress) { }
}

GUN Provider

import { GUNBubbleProvider } from 'gun-eth';

const gunProvider = new GUNBubbleProvider({
    gun: gunInstance,
    signer: signer,
    keypair: keypair
});

// Stores data directly in GUN's graph
await gunProvider.handleCreateBubble({
    name: "GUN Bubble",
    isPrivate: true
});

Hybrid Provider

import { HybridBubbleProvider } from 'gun-eth';

const hybridProvider = new HybridBubbleProvider({
    gun: gunInstance,
    signer: signer,
    keypair: keypair,
    storage: customStorageAdapter
});

// Supports both GUN and external storage
await hybridProvider.handleCreateBubble({
    name: "Hybrid Bubble",
    isPrivate: true,
    useExternal: true
});

📋 Templates

Gun-ETH provides ready-to-use templates for common implementations:

Client Template

// template-bubble-client.js
const CONFIG = {
    RPC_URL: process.env.RPC_URL,
    PRIVATE_KEY: process.env.PRIVATE_KEY,
    PROVIDER_URL: "http://localhost:3000/api",
    GUN_PEERS: ['http://localhost:8765/gun'],
    DECRYPTED_FILES_DIR: './decrypted-files'
};

// Initialize client with configuration
const client = await initializeClient();

// Example usage
const bubble = await client.createBubble("Test Bubble");
await client.writeBubble(bubble.id, "test.txt", "content");
const result = await client.readBubble(bubble.id, "test.txt");

Provider Template

// template-bubble-provider.js
const CONFIG = {
    RPC_URL: process.env.RPC_URL,
    PRIVATE_KEY: process.env.PRIVATE_KEY,
    GUN_PEERS: "http://localhost:8765/gun",
    GUN_DIR: "radata",
    BUBBLES_DIR: "bubbles"
};

// Initialize provider with configuration
const app = express();
const gun = Gun(gunOptions);
const provider = new HybridBubbleProvider(CONFIG);

// API endpoints
app.post('/bubble', handleCreateBubble);
app.post('/bubble/:id/write', handleWriteBubble);
app.get('/bubble/:id', handleReadBubble);

🏗️ Architecture

Gun-ETH is structured in independent modules:

  • Core: Base functionality and Gun.js integration
  • Stealth: Private transaction implementation
  • Proof: Verification and anchoring system
  • Crypto: Cryptographic utilities
  • Utils: Common support functions

🌟 Features

Secure Backup System

  • End-to-end encryption
  • Version control
  • Decentralized storage

Advanced Privacy

  • Stealth transactions
  • Private communications
  • On-chain announcements

Data Integrity

  • Cryptographic verification
  • Blockchain anchoring
  • Change monitoring

Web3 Integration

  • Seamless Gun/Ethereum account conversion
  • Signature and authentication support
  • Complete key management

🤝 Contributing

Contributions are welcome! Please:

  1. 🍴 Fork the repository
  2. 🌿 Create your feature branch (git checkout -b feature/AmazingFeature)
  3. 💾 Commit your changes (git commit -m 'Add: amazing feature')
  4. 📤 Push to the branch (git push origin feature/AmazingFeature)
  5. 🔄 Open a Pull Request

📄 License

MIT © 2024 Scobru