Welcome to the Universal FHEVM SDK! This guide will help you set up and start building confidential dApps in minutes.
Before you begin, ensure you have the following installed:
- Node.js v18 or higher (Download)
- npm or yarn package manager
- MetaMask or compatible Web3 wallet (Install)
- Basic knowledge of TypeScript/JavaScript
- Familiarity with Ethereum and smart contracts
- VS Code with TypeScript extension
- Hardhat for smart contract development
- Next.js for frontend (optional, but recommended)
npm install @fhevm/universal-sdk ethersor
yarn add @fhevm/universal-sdk ethersThe SDK requires ethers v6 as a peer dependency. If you haven't installed it yet:
npm install ethers@^6.0.0Create a file fhevm-demo.ts:
import { createFhevmInstance, NETWORKS } from '@fhevm/universal-sdk';
import { ethers } from 'ethers';
async function initFhevm() {
// Connect to MetaMask
const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []);
// Create FHEVM instance (< 10 lines!)
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider
});
console.log('FHEVM instance created!', fhevm);
return fhevm;
}
initFhevm();import { createFhevmInstance, NETWORKS } from '@fhevm/universal-sdk';
import { ethers } from 'ethers';
async function encryptValue() {
const provider = new ethers.BrowserProvider(window.ethereum);
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider
});
// Encrypt a number
const encrypted = await fhevm.encrypt32(12345);
console.log('Encrypted value:', encrypted);
return encrypted;
}
encryptValue();'use client';
import { useFhevm, useEncrypt, NETWORKS } from '@fhevm/universal-sdk/react';
import { useWalletClient } from 'wagmi';
import { ethers } from 'ethers';
export default function EncryptDemo() {
const { data: walletClient } = useWalletClient();
const provider = walletClient
? new ethers.BrowserProvider(walletClient)
: null;
// Initialize FHEVM
const { fhevm, isLoading, error } = useFhevm({
network: NETWORKS.sepolia,
provider
});
// Encrypt values
const { encrypt, encrypted, isLoading: encrypting } = useEncrypt(fhevm);
const handleEncrypt = async () => {
await encrypt({ type: 'euint32', value: 12345 });
};
if (isLoading) return <div>Initializing FHE...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<button onClick={handleEncrypt} disabled={encrypting}>
{encrypting ? 'Encrypting...' : 'Encrypt Value'}
</button>
{encrypted && <p>Encrypted: {encrypted}</p>}
</div>
);
}The SDK provides pre-configured network presets:
import { NETWORKS } from '@fhevm/universal-sdk';
// Available networks
NETWORKS.sepolia; // Ethereum Sepolia testnet
NETWORKS.zamaDevnet; // Zama development network
NETWORKS.zamaTestnet; // Zama test networkThe SDK supports all FHEVM encrypted types:
// Unsigned integers
await fhevm.encrypt8(255); // euint8 (0-255)
await fhevm.encrypt16(65535); // euint16 (0-65535)
await fhevm.encrypt32(4294967295); // euint32 (0-4294967295)
await fhevm.encrypt64(BigInt('18446744073709551615')); // euint64
// Boolean
await fhevm.encryptBool(true); // ebool
// Address
await fhevm.encryptAddress('0x1234...'); // eaddressFor complex contract calls with multiple encrypted parameters:
const contractAddress = '0x1234...';
const userAddress = '0x5678...';
const input = fhevm
.createEncryptedInput(contractAddress, userAddress)
.add32(1000) // Add euint32
.add8(50) // Add euint8
.addBool(true); // Add ebool
const { handles, inputProof } = await input.getEncrypted();
// Use in contract call
await contract.submitData(...handles, inputProof);Request decryption for encrypted results:
// Request decryption from Zama gateway
const requestId = await fhevm.requestDecryption(
encryptedValue,
contractAddress
);
// Wait for decryption result
const decrypted = await fhevm.awaitDecryption(requestId);
console.log('Decrypted value:', decrypted);Here's a complete example showing the full FHEVM flow:
import { createFhevmInstance, NETWORKS } from '@fhevm/universal-sdk';
import { ethers } from 'ethers';
async function completeFlow() {
// 1. Setup
const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []);
const signer = await provider.getSigner();
// 2. Initialize FHEVM
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider
});
// 3. Encrypt data
const encryptedAmount = await fhevm.encrypt32(1000);
console.log('Encrypted:', encryptedAmount);
// 4. Submit to contract
const contractAddress = '0x6Be5E20244cCAF9cBf47E6Af39933C5E7aC8c12c';
const contract = new ethers.Contract(
contractAddress,
['function submitValue(bytes calldata encryptedValue) external'],
signer
);
const tx = await contract.submitValue(encryptedAmount);
await tx.wait();
console.log('Transaction confirmed:', tx.hash);
// 5. Request decryption (for aggregates)
const requestId = await fhevm.requestDecryption(
encryptedAggregate,
contractAddress
);
// 6. Await result
const result = await fhevm.awaitDecryption(requestId);
console.log('Decrypted result:', result);
}
completeFlow();// app/providers.tsx
'use client';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { sepolia } from 'wagmi/chains';
import { RainbowKitProvider, getDefaultConfig } from '@rainbow-me/rainbowkit';
const config = getDefaultConfig({
appName: 'My FHEVM App',
projectId: 'YOUR_PROJECT_ID',
chains: [sepolia],
transports: {
[sepolia.id]: http()
}
});
export function Providers({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<RainbowKitProvider>
{children}
</RainbowKitProvider>
</WagmiProvider>
);
}// main.js
import { createFhevmInstance, NETWORKS } from '@fhevm/universal-sdk';
import { ethers } from 'ethers';
document.getElementById('encryptBtn').addEventListener('click', async () => {
const provider = new ethers.BrowserProvider(window.ethereum);
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider
});
const value = document.getElementById('valueInput').value;
const encrypted = await fhevm.encrypt32(parseInt(value));
document.getElementById('result').textContent = encrypted;
});// server.js
import { createFhevmInstance, NETWORKS } from '@fhevm/universal-sdk';
import { ethers } from 'ethers';
async function serverSideEncryption() {
// Use JsonRpcProvider for server-side
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider
});
// Encrypt on server
const encrypted = await fhevm.encrypt32(1000);
return encrypted;
}
serverSideEncryption();Create a .env.local file:
# Network Configuration
NEXT_PUBLIC_NETWORK=sepolia
# RPC URLs
NEXT_PUBLIC_SEPOLIA_RPC_URL=https://rpc.sepolia.org
NEXT_PUBLIC_ZAMA_DEVNET_RPC_URL=https://devnet.zama.ai
# Contract Addresses
NEXT_PUBLIC_CONTRACT_ADDRESS=0x6Be5E20244cCAF9cBf47E6Af39933C5E7aC8c12c
# Optional: WalletConnect Project ID (for RainbowKit)
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_idSolution: Ensure the SDK is installed:
npm install @fhevm/universal-sdk ethersSolution: Make sure MetaMask is installed and connected:
if (!window.ethereum) {
alert('Please install MetaMask');
}Solution: Switch to the correct network in MetaMask or programmatically:
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0xaa36a7' }] // Sepolia
});Solution: Increase timeout or check network connection:
const fhevm = await createFhevmInstance({
network: NETWORKS.sepolia,
provider,
timeout: 30000 // 30 seconds
});Now that you've set up the SDK, explore these topics:
- Core Concepts - Understand FHE and how it works
- API Reference - Complete API documentation
- React Guide - Build React apps with FHEVM hooks
- Next.js Guide - Next.js 14 App Router integration
- Security - Best practices for secure dApps
- Migration - Migrate from other FHEVM libraries
Check out our example projects:
- Next.js Showcase - Complete Next.js 14 app
- Transit Analytics - Real-world privacy-preserving analytics
- Vanilla JS - Simple HTML/JS example
- 📖 Documentation: View full docs
- 💬 Discord: Join community
- 🐛 Issues: Report bugs
- 📧 Email: support@fhevm-sdk.example
Ready to build confidential dApps? Let's dive deeper into the Core Concepts!