@fhevm/shared
This package contains shared TypeScript definitions and ABIs (Application Binary Interfaces) generated from deployed smart contracts. It provides a unified way to access contract addresses and ABIs across all example applications.
Overview
The @fhevm/shared package automatically exports deployed contract information from the Hardhat sub-repo, making it easy to interact with FHE (Fully Homomorphic Encryption) contracts from any environment - Node.js, Next.js, or Vue.js.
Workflow
1. Write and Deploy Contracts
The project includes a Hardhat sub-repo in the packages/ directory for smart contract development.
# Navigate to the Hardhat sub-repo
cd packages/hardhat/
# Write your FHE contract in contracts/
# Example: contracts/FHECounter.sol
# Compile the contract
pnpm compile
# Deploy to your target network
pnpm deploy:localhost # For local development
# or
pnpm deploy:sepolia # For Sepolia testnet2. Generate Shared ABIs
After deploying your contracts, generate the ABIs from the root of the project:
# Navigate back to project root
cd ../../ # Now at fhevm-react-template/
# Generate shared ABIs
pnpm generate
# Build the shared package
pnpm shared:buildThe pnpm generate command will:
- Read deployed contract information from the Hardhat sub-repo
- Extract contract addresses and ABIs
- Generate TypeScript files in
@fhevm/shared - Make them available for import across all packages
Installation
This package is part of the monorepo and is automatically available to all demo applications after running:
# From project root (fhevm-react-template/)
pnpm install
pnpm generate # Generates the shared ABIs from Hardhat deployments
pnpm shared:buildUsage
Importing Contract Information
import { abis } from "@fhevm/shared";
// Access deployed contract on Sepolia (chain ID: 11155111)
const FHECounter = abis.deployedContracts["11155111"]["FHECounter"];
console.log(FHECounter.address); // Contract address
console.log(FHECounter.abi); // Contract ABIUsing with ethers.js
import { ethers } from "ethers";
import { abis } from "@fhevm/shared";
const FHECounter = abis.deployedContracts["11155111"]["FHECounter"];
// Create contract instance
const contract = new ethers.Contract(
FHECounter.address,
FHECounter.abi,
signer
);
// Call contract methods
const count = await contract.getCount();Chain-Specific Contracts
The package organizes contracts by chain ID:
// Sepolia testnet (chain ID: 11155111)
const sepoliaCounter = abis.deployedContracts["11155111"]["FHECounter"];
// Local development (chain ID: 31337)
const localCounter = abis.deployedContracts["31337"]["FHECounter"];
// Access different chains as neededContract Structure
FHECounter
The main example contract demonstrating FHE operations.
Address
FHECounter.address // "0x2F39E2bfb4d5c8d6e5503F5103C5411Ae583A032"ABI Methods
increment(inputEuint32, inputProof)
- Increments the encrypted counter
- Parameters:
inputEuint32(bytes32): Encrypted input valueinputProof(bytes): Zero-knowledge proof
- Returns: None (state-changing transaction)
decrement(inputEuint32, inputProof)
- Decrements the encrypted counter
- Parameters:
inputEuint32(bytes32): Encrypted input valueinputProof(bytes): Zero-knowledge proof
- Returns: None (state-changing transaction)
getCount()
- Returns the encrypted counter value
- Parameters: None
- Returns:
euint32(bytes32) - Encrypted counter value
protocolId()
- Returns the protocol identifier
- Parameters: None
- Returns:
uint256- Protocol ID
Type Safety
The package exports contracts with full TypeScript type safety:
import { abis } from "@fhevm/shared";
// TypeScript knows the structure
type DeployedContracts = typeof abis.deployedContracts;
type ChainId = keyof DeployedContracts;
type ContractName = keyof DeployedContracts["11155111"];
// Auto-completion works
const counter = abis.deployedContracts["11155111"]["FHECounter"];
// ^ ^
// | |
// Chain ID Contract NameExamples in Different Frameworks
Node.js
import { ethers } from "ethers";
import { abis } from "@fhevm/shared";
const FHECounter = abis.deployedContracts["11155111"]["FHECounter"];
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = ethers.Wallet.fromPhrase(process.env.SEED_PHRASE!, provider);
const contract = new ethers.Contract(FHECounter.address, FHECounter.abi, wallet);
// Use contract
const tx = await contract.increment(handles[0], inputProof);Next.js (React)
import { ethers } from "ethers";
import { useFhevm } from "@fhevm/react";
import { abis } from "@fhevm/shared";
const FHECounter = abis.deployedContracts["11155111"]["FHECounter"];
export default function Component() {
const { signer } = useFhevm();
const contract = signer
? new ethers.Contract(FHECounter.address, FHECounter.abi, signer)
: null;
// Use contract
}Vue.js
<script setup lang="ts">
import { ethers } from "ethers";
import { useFhevm } from "@fhevm/vue";
import { abis } from "@fhevm/shared";
const FHECounter = abis.deployedContracts["11155111"]["FHECounter"];
const { signer } = useFhevm();
let contract: ethers.Contract | null = null;
watchEffect(() => {
if (signer.value) {
contract = new ethers.Contract(FHECounter.address, FHECounter.abi, signer.value);
}
});
</script>Complete Development Flow
Step-by-Step Guide
- Write your smart contract
cd packages/hardhat/
# Edit contracts/YourContract.sol- Compile the contract
pnpm compile- Deploy to network
pnpm deploy:localhost # or deploy:sepolia- Generate shared ABIs
cd ../../ # Back to fhevm-react-template/
pnpm generate- Build shared package
pnpm shared:build- Use in your application
import { abis } from "@fhevm/shared";
const MyContract = abis.deployedContracts["CHAIN_ID"]["YourContract"];Package Structure
@fhevm/shared/
├── src/
│ ├── contracts/
│ │ └── deployedContracts.ts # Auto-generated from Hardhat deployments
│ └── index.ts # Package exports
├── package.json
└── tsconfig.jsonGenerated File Structure
The deployedContracts.ts file is auto-generated and follows this structure:
/**
* Auto-generated file.
* Contains deployed contracts with address and ABI.
*/
export const deployedContracts = {
"CHAIN_ID": {
ContractName: {
address: "0x...",
abi: [
// ABI array
],
},
},
} as const;Adding New Contracts
When you deploy new contracts:
- Write and deploy your contract in the Hardhat sub-repo
cd packages/hardhat/
pnpm compile
pnpm deploy:sepolia- Generate ABIs from project root
cd ../../ # fhevm-react-template/
pnpm generate- Build shared package
pnpm shared:build- Use the new contract
import { abis } from "@fhevm/shared";
const NewContract = abis.deployedContracts["CHAIN_ID"]["YourNewContract"];Important Notes
- Always run
pnpm generatefrom the project root (fhevm-react-template/), not from the Hardhat sub-repo - The Hardhat sub-repo must be properly initialized with
pnpm forkbefore generating ABIs - All contract data is exported as
constfor immutability - ABIs are automatically typed for TypeScript
- The package is designed to be tree-shakeable
- Contract addresses are network-specific (identified by chain ID)
- Always rebuild the shared package after generating new ABIs
- The generated files should not be manually edited as they will be overwritten
Troubleshooting
ABIs not updating after deployment
# Make sure you're at project root
cd fhevm-react-template/
pnpm generate
pnpm shared:buildContract not found after generation
- Verify the contract was successfully deployed in the Hardhat sub-repo
- Check the deployment output for the correct chain ID
- Ensure
pnpm generatecompleted without errors
TypeScript errors when importing
# Rebuild the shared package
pnpm shared:build