### Complete Cofhejs Initialization Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/error-handling.md
A comprehensive example of initializing Cofhejs, including provider setup and detailed error handling for initialization failures.
```typescript
async function initializeCoFHE() {
try {
// initialize your web3 provider
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = (await provider.getSigner()) as ethers.JsonRpcSigner
// initialize cofhejs Client with ethers (it also supports viem)
await cofhejs.initializeWithEthers({
provider: window.ethereum,
signer: wallet,
environment: 'TESTNET',
})
if (!result.success) {
// Handle specific error cases
if (result.error.includes('missing provider')) {
console.error('Provider not available. Please install a wallet extension.')
} else if (result.error.includes('failed to initialize cofhejs')) {
console.error('FHE initialization failed. The network may not be FHE-enabled.')
} else {
console.error('Initialization error:', result.error)
}
return null
}
console.log('`cofhejs` initialized successfully')
return result.data // The permit, if generated
} catch (unexpectedError) {
// Catch any unexpected errors not handled by the Result pattern
console.error('Unexpected error during initialization:', unexpectedError)
return null
}
}
// Example of creating and using a permit with error handling
async function createAndUsePermit(userAddress) {
const permitResult = await cofhejs.createPermit({
type: 'self',
issue: userAddress,
})
if (!permitResult.success) {
console.error('Permit creation failed:', permitResult.error)
return
}
const permit = permitResult.data
console.log('Permit created successfully:', permit)
// Continue with operations that require the permit
// ...
}
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Install all necessary project dependencies using pnpm, the recommended package manager.
```bash
pnpm install
```
--------------------------------
### Install Dependencies with Yarn
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/README.md
Run this command to install project dependencies using Yarn.
```bash
yarn
```
--------------------------------
### Start Local Development Server
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/README.md
Starts a local development server for live preview. Changes are reflected without a server restart. Note: pnpm may have issues with React hooks.
```bash
yarn start
```
--------------------------------
### Install Cofhejs with pnpm
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/architecture/user-facing-utilities/cofhejs.md
Install the Cofhejs library as a project dependency using pnpm.
```bash
pnpm add cofhejs
```
--------------------------------
### User Interface Example for Permit Signing
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/permits-management.md
A React component example for a modal that explains permits to users before they sign. It includes a button to trigger the permit signing process.
```jsx
const PermitModal = () => (
Sign a Permit
Permits grant secure access to your encrypted data on Fhenix by authenticating you with your signature. Each permit:
Is valid for 24 hours
Can only be used by you
Ensures your data remains private
)
```
--------------------------------
### Install Cofhejs with yarn
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/architecture/user-facing-utilities/cofhejs.md
Install the Cofhejs library as a project dependency using yarn.
```bash
yarn add cofhejs
```
--------------------------------
### Install Cofhejs
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/architecture/data-flows/encryption-request.md
Install the Cofhejs package using npm. This is the first step to include Cofhejs in your project.
```bash
npm install cofhejs
```
--------------------------------
### FHE Addition Example in Smart Contract
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/data-evaluation.md
Demonstrates creating two encrypted ciphertexts and performing an FHE addition, returning the encrypted result.
```solidity
function addNumbers() public view returns (euint32) {
euint32 a = FHE.asEuint32(10); // Creating two trivially-encrypted ciphertexts
euint32 b = FHE.asEuint32(20);
euint32 result = FHE.add(a, b); // Add them together
return result;
}
```
--------------------------------
### Initialize Cofhejs Client
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/encryption-operations.md
Initialize the Cofhejs client using either Ethers or Viem. Ensure the environment is set correctly, for example, to 'LOCAL'.
```typescript
await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: wallet,
environment: "LOCAL",
});
```
```typescript
// or
await cofhejs.initializeWithViem({
viemClient: provider,
viemWalletClient: wallet,
environment: "LOCAL",
});
```
--------------------------------
### FHE Counter Contract Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Example of an FHE-enabled Counter contract using encrypted data types and FHE operations. Ensure FHE library is imported.
```solidity
import "@fhenixprotocol/cofhe-contracts/FHE.sol";
contract Counter {
euint32 public count; // Encrypted uint32
function increment() public {
count = FHE.add(count, FHE.asEuint32(1));
FHE.allowThis(count);
FHE.allowSender(count);
}
// More functions...
}
```
--------------------------------
### Allow Other Contracts Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/acl-usage-examples.md
Demonstrates how to grant access to ciphertexts to other contracts, either persistently with `FHE.allow()` or temporarily for the current transaction with `FHE.allowTransient()`. This enables inter-contract collaboration.
```Solidity
contract A {
function doAdd(InEuint32 input1) {
handle1 = FHE.asEuint32(input1); // Contract A gets temporary ownership of handle1
FHE.allowTransient(handle1, addressB); // Contract B is allowed to use handle1 in this transaction alone
// or
FHE.allow(handle1, addressB); // Contract B is allowed to use handle1 forever
IContractB(addressB).doSomethingWithHandle1(handle1);
}
}
```
--------------------------------
### Import FHE Library Types
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/Your-First-FHE-Contract.md
Import necessary FHE library types like `euint64` and `InEuint64` for encrypted operations. Ensure the FHE library is correctly installed and accessible.
```solidity
import {FHE, euint64, InEuint64} from "@fhenixprotocol/cofhe-contracts/FHE.sol";
```
--------------------------------
### Allowance for Decryptions Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/acl-usage-examples.md
Illustrates how to allow specific addresses, including off-chain users via the decryption network, to decrypt a ciphertext using `FHE.allow(userAddress)`. This is crucial for sharing decryption rights.
```Solidity
contract A {
private mapping(address -> uint256) balances;
function transfer(InEuint32 _amount, address to) {
euint32 amount = FHE.asEuint32(_amount);
balances[msg.sender] = balances[msg.sender] - amount;
balances[to] = balances[to] + amount;
FHE.allow(balances[msg.sender], msg.sender); // now the sender can decrypt her balance
FHE.allow(balances[to], to); // now the receiver can decrypt his balance
// enable balance manipulation for future transactions
FHE.allowThis(balances[msg.sender]);
FHE.allowThis(balances[to]);
}
}
```
--------------------------------
### Full Cofhejs Flow Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Demonstrates the complete workflow of encrypting a value, interacting with a contract using the encrypted value, and unsealing the result. Uses helper functions like `expectResultSuccess` to validate operations.
```typescript
it('Full cofhejs flow', async function () {
const [bob] = await hre.ethers.getSigners()
const CounterFactory = await hre.ethers.getContractFactory('Counter')
const counter = await CounterFactory.connect(bob).deploy()
// `expectResultSuccess` is a helper function that ensures that the
// `Result` type returned by all `cofhejs` functions has succeeded.
// If the inner function (e.g. `cofhejs_initializeWithHardhatSigner`)
// fails, the test will fail.
expectResultSuccess(await cofhejs_initializeWithHardhatSigner(bob))
// Encrypt a value
const [encryptedInput] = expectResultSuccess(
await cofhejs.encrypt((step) =>
console.log(`Encrypt step - ${step}`), [Encryptable.uint32(5n)]))
// Use the encrypted input to reset the counter
await counter.connect(bob).reset(encryptedInput)
// Fetch the hash of the encrypted counter value
const encryptedValue = await counter.count()
// Unseal an encrypted value
const unsealedResult = expectResultSuccess(
await cofhejs.unseal(encryptedValue, FheTypes.Uint32))
// Check the unsealed result
expect(unsealedResult).equal(5n)
})
```
--------------------------------
### Initialize euint64 Vote Counts in createProposal
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/adding-FHE-to-existing-contract.md
Modify the `createProposal` function to initialize vote counts using `FHE.asEuint64(0)` for `euint64` types. This ensures that vote counts are stored in their encrypted form from the start.
```solidity
function createProposal(
string memory _name,
string[] memory _options,
uint256 _deadline
) external onlyOwner returns (uint256) {
if (_options.length < 2 || _options.length > 4)
revert InvalidOptionCount();
uint256 proposalId = proposalCount++;
Proposal storage proposal = proposals[proposalId];
proposal.name = _name;
proposal.deadline = _deadline;
proposal.exists = true;
for (uint i = 0; i < _options.length; i++) {
// diff-remove
proposal.options.push(Option({name: _options[i], votes: 0}));
// diff-add
proposal.options.push(
//diff-add
Option({name: _options[i], votes: FHE.asEuint64(0)})
//diff-add
);
}
emit ProposalCreated(proposalId, _name, _deadline);
return proposalId;
}
```
--------------------------------
### Original Fhenix L2 Contract Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/migrating-to-cofhe.md
This Solidity contract demonstrates FHE operations including wrapping, unwrapping, and encrypted transfers. It utilizes FHE library functions for encryption, decryption, and secure arithmetic operations on encrypted balances.
```solidity
pragma solidity ^0.8.20;
import "@fhenixprotocol/contracts/access/Permissioned.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@fhenixprotocol/contracts/FHE.sol";
contract WrappingERC20 is ERC20, Permissioned {
mapping(address => euint32) internal _encBalances;
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_mint(msg.sender, 100 * 10 ** uint(decimals()));
}
function wrap(uint32 amount) public {
// Make sure that the sender has enough of the public balance
require(balanceOf(msg.sender) >= amount);
// Burn public balance
_burn(msg.sender, amount);
// convert public amount to encrypted by encrypting it
euint32 encryptedAmount = FHE.asEuint32(amount);
// Add encrypted balance to his current balance
_encBalances[msg.sender] = _encBalances[msg.sender] + encryptedAmount;
// diff-add
// Allow the contract to operate on the encrypted balance for future operations
// diff-add
FHE.allowThis(_encBalances[msg.sender]);
// diff-add
// Allow the users to to use decrypt\sealoutput on their balances
// diff-add
FHE.allow(_encBalances[msg.sender], msg.sender);
}
function unwrap(InEuint32 memory amount) public {
euint32 _amount = FHE.asEuint32(amount);
// diff-remove
// verify that our encrypted balance is greater or equal than the requested amount
// diff-remove
FHE.req(_encBalances[msg.sender].gte(_amount));
// diff-add
// Using select to avoid leaking the result balance
// diff-add
_amount = FHE.select(_encBalances[msg.sender].gte(_amount), _amount, FHE.asEuint(0));
// subtract amount from encrypted balance
_encBalances[msg.sender] = _encBalances[msg.sender] - _amount;
// diff-add
// Allow the contract to operate on the encrypted balance for future operations
// diff-add
FHE.allowThis(_encBalances[msg.sender]);
// diff-add
// Allow the users to to use decrypt\sealoutput on their balances
// diff-add
FHE.allow(_encBalances[msg.sender], msg.sender);
// add amount to caller's public balance by calling the `mint` function
_mint(msg.sender, FHE.decrypt(_amount));
}
function transferEncrypted(address to, InEuint32 calldata encryptedAmount) public {
euint32 amount = FHE.asEuint32(encryptedAmount);
// diff-remove
// Make sure the sender has enough tokens.
// diff-remove
FHE.req(amount.lte(_encBalances[msg.sender]));
// diff-add
// Using select to avoid leaking the result balance
// diff-add
amount = FHE.select(_encBalances[msg.sender].gte(amount), amount, FHE.asEuint(0));
// Add to the balance of `to` and subract from the balance of `from`.
_encBalances[to] = _encBalances[to] + amount;
_encBalances[msg.sender] = _encBalances[msg.sender] - amount;
// diff-add
// Allow the contract to operate on the encrypted balance for future operations
// diff-add
FHE.allowThis(_encBalances[msg.sender]);
// diff-add
FHE.allowThis(_encBalances[to]);
// diff-add
// Allow the users to to use decrypt\sealoutput on their balances
// diff-add
FHE.allow(_encBalances[msg.sender], msg.sender);
// diff-add
FHE.allow(_encBalances[to], to);
}
// diff-remove
function getBalanceEncrypted(Permission calldata perm) public view onlySender(perm) returns (uint256) {
// diff-remove
return FHE.decrypt(_encBalances[msg.sender]);
// diff-remove
}
}
```
--------------------------------
### Full Auction Example Contract
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/decryption-operations.md
A complete Solidity contract demonstrating FHE encryption, decryption requests, and result retrieval in an auction scenario. It includes functions for bidding, closing the auction, and revealing the winner using both safe and unsafe decryption result queries.
```solidity
// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nimport "@fhenixprotocol/cofhe-contracts/FHE.sol";\n\ncontract AuctionExample {\n address private auctioneer;\n euint64 private highestBid;\n eaddress private highestBidder;\n uint64 public winningBid;\n address public winningBidder;\n bool public auctionClosed;\n\n event RevealedWinningBid(address winner, uint64 amount);\n\n modifier onlyAuctioneer() {\n require(\n msg.sender == auctioneer,\n "Only the auctioneer can call this function"\n );\n _ புகை \n }\n\n constructor() {\n auctioneer = msg.sender; // Set deployer as auctioneer\n auctionClosed = false;\n highestBid = FHE.asEuint64(0);\n highestBidder = FHE.asEaddress(address(0));\n\n // Preserve ownership for further access\n FHE.allowThis(highestBid);\n FHE.allowThis(highestBidder);\n }\n\n function bid(uint256 amount) external {\n require(!auctionClosed, "Auction is closed");\n\n euint64 emount = FHE.asEuint64(amount);\n ebool isHigher = FHE.gt(emount, highestBid);\n highestBid = FHE.max(emount, highestBid);\n highestBidder = FHE.select(\n isHigher,\n FHE.asEaddress(msg.sender), // Encrypt the sender's address\n highestBidder\n );\n\n // Preserve ownership for further access\n FHE.allowThis(highestBid);\n FHE.allowThis(highestBidder);\n }\n\n // ------------------------------------------------------\n // Step 1. Request on-chain decryption (in transaction)\n // ------------------------------------------------------\n function closeBidding() external onlyAuctioneer {\n require(!auctionClosed, "Auction is already closed");\n FHE.decrypt(highestBid);\n FHE.decrypt(highestBidder);\n auctionClosed = true;\n }\n\n // ------------------------------------------------------\n // Step 2. Process the decrypted result\n // ------------------------------------------------------\n function safelyRevealWinner() external onlyAuctioneer {\n require(auctionClosed, "Auction isn't closed");\n\n (uint64 bidValue, bool bidReady) = FHE.getDecryptResultSafe(highestBid);\n require(bidReady, "Bid not yet decrypted");\n\n (address bidderValue, bool bidderReady) = FHE.getDecryptResultSafe(highestBidder);\n require(bidderReady, "Bid not yet decrypted");\n\n winningBid = bidValue;\n winningBidder = bidderValue;\n emit RevealedWinningBid(bidderValue, bidValue);\n }\n\n function unsafeRevealWinner() external onlyAuctioneer {\n require(auctionClosed, "Auction isn't closed");\n\n uint64 bidValue = FHE.getDecryptResult(highestBid);\n address bidderValue = FHE.getDecryptResult(highestBidder);\n\n winningBid = bidValue;\n winningBidder = bidderValue;\n emit RevealedWinningBid(bidderValue, bidValue);\n }\n}
```
--------------------------------
### Persistent Allowance for This Contract Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/acl-usage-examples.md
Shows how to grant persistent ownership of a ciphertext to the current contract using `FHE.allowThis()`. This is necessary to use the ciphertext in future transactions.
```Solidity
contract A {
private euint32 result;
private euint32 handle1;
function doAdd(InEuint32 input1, InEuint32 input2) {
handle1 = FHE.asEuint32(input1); // Contract A gets temporary ownership of handle1
euint32 handle2 = FHE.asEuint32(input2); // Contract A gets temporary ownership of handle2
result = FHE.add(handle1, handle2); // Contract A gets temporary ownership of result
FHE.allowThis(result); // result is allowed for future transactions
}
function doSomethingWithResult() {
FHE.decrypt(result); // Allowed
FHE.add(handle1, result); // ACLNotAllowed (handle1 is not owned persistently)
}
}
```
--------------------------------
### Clone cofhe-hardhat-starter Repository
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Clone the starter repository and navigate into the project directory to begin development.
```bash
git clone https://github.com/fhenixprotocol/cofhe-hardhat-starter.git
cd cofhe-hardhat-starter
```
--------------------------------
### Build Static Website Content
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/README.md
Generates static website files into the 'build' directory, ready for hosting.
```bash
yarn build
```
--------------------------------
### FHE Counter Contract Test Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Example test case for incrementing a counter contract in the mock FHE environment. It checks the initial and updated values.
```typescript
it('Should increment the counter', async function () {
const { counter, bob } = await loadFixture(deployCounterFixture)
// Check initial value
const count = await counter.count()
await mock_expectPlaintext(bob.provider, count, 0n)
// Increment counter
await counter.connect(bob).increment()
// Check new value
const count2 = await counter.count()
await mock_expectPlaintext(bob.provider, count2, 1n)
})
```
--------------------------------
### Receive and Convert Encrypted Input
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/inputs.md
Demonstrates receiving an encrypted uint32 input and converting it to a usable encrypted type. Always convert input types using `FHE.asE...()` before use.
```solidity
function transfer(
address to,
InEuint32 memory inAmount // <------ encrypted input here
) public virtual returns (euint32 transferred) {
euint32 amount = FHE.asEuint32(inAmount);
}
```
```solidity
euint32 amount = FHE.asEuint32(inAmount);
```
--------------------------------
### Configure Testnet Deployment Environment
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Create a .env file to store private keys and RPC URLs required for deploying to testnets.
```dotenv
PRIVATE_KEY=your_private_key_here
SEPOLIA_RPC_URL=your_sepolia_rpc_url
ARBITRUM_SEPOLIA_RPC_URL=your_arbitrum_sepolia_rpc_url
```
--------------------------------
### Handle Permit Creation with Error Checking
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/permits-management.md
Demonstrates how to create a permit and handle potential success or failure responses, as well as unexpected errors.
```typescript
const handlePermitCreation = async () => {
try {
const result = await cofhejs.createPermit({
type: 'self',
issuer: userAddress,
})
if (!result.success) {
console.error('Permit creation failed:', result.error)
return
}
// Handle successful permit creation
} catch (error) {
console.error('Unexpected error:', error)
}
}
```
--------------------------------
### Get Encrypted Counter Value
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/Your-First-FHE-Contract.md
Returns the current encrypted value of the counter. This encrypted value can be read privately by authorized users.
```solidity
function get_encrypted_counter_value() external view returns(euint64) {
return counter;
}
```
--------------------------------
### Deploy Website using SSH
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/README.md
Deploys the website using SSH. Ensure SSH is configured for your deployment target.
```bash
USE_SSH=true yarn deploy
```
--------------------------------
### Cast Encrypted Vote
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/inputs.md
Example of casting an encrypted boolean vote in a poll. The `InEbool` input is converted to an `Ebool` using `FHE.asEbool()` before submission.
```solidity
function castEncryptedVote(address poll, InEbool calldata encryptedVote) public {
_submitVote(poll, FHE.asEbool(encryptedVote));
}
```
--------------------------------
### Initialize cofhejs with Ethers (Browser)
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Initializes the cofhejs SDK in a browser dApp using `window.ethereum`. It utilizes the EIP-1193 wallet provider for signing permits and requires manual control over permit prompts in production.
```APIDOC
## Initialize cofhejs with Ethers (Browser)
Initialize cofhejs in a browser dApp using `window.ethereum` as the provider, enabling MetaMask or any EIP-1193 wallet for signing permits. Control permit prompts manually in production.
### Method Signature
```typescript
await cofhejs.initializeWithEthers({
ethersProvider: ethers.BrowserProvider;
ethersSigner: ethers.JsonRpcSigner;
environment: "TESTNET" | "MOCK" | "MAINNET" | "LOCAL";
generatePermit?: boolean;
});
```
### Parameters
- **ethersProvider** (ethers.BrowserProvider) - The Ethers browser provider instance (e.g., from `window.ethereum`).
- **ethersSigner** (ethers.JsonRpcSigner) - The Ethers signer instance obtained from the provider.
- **environment** (string) - The operating environment ('TESTNET', 'MOCK', 'MAINNET', 'LOCAL').
- **generatePermit** (boolean, optional) - Controls permit prompts. Set to `false` to manage prompts manually.
### Request Example
```typescript
import { cofhejs } from "cofhejs/web";
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const result = await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: signer as ethers.JsonRpcSigner,
environment: "TESTNET",
generatePermit: false, // control permit prompts manually in production
});
if (!result.success) {
console.error("Browser init failed:", result.error);
}
```
### Response
- **success** (boolean) - Indicates if the initialization was successful.
- **error** (string) - An error message if initialization failed.
```
--------------------------------
### Initialize cofhejs with Viem
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Initializes the cofhejs SDK using Viem clients for both public and wallet operations. This method offers an alternative to the Ethers-based initialization for projects using Viem.
```APIDOC
## Initialize cofhejs with Viem
`cofhejs.initializeWithViem` offers the same functionality as the ethers variant but accepts a Viem `PublicClient` and `WalletClient`.
### Method Signature
```typescript
await cofhejs.initializeWithViem({
viemClient: PublicClient;
viemWalletClient: WalletClient;
environment: "TESTNET" | "MOCK" | "MAINNET" | "LOCAL";
});
```
### Parameters
- **viemClient** (PublicClient) - The Viem public client instance.
- **viemWalletClient** (WalletClient) - The Viem wallet client instance.
- **environment** (string) - The operating environment ('TESTNET', 'MOCK', 'MAINNET', 'LOCAL').
### Request Example
```typescript
import { cofhejs } from "cofhejs/node";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
const viemClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
});
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const viemWalletClient = createWalletClient({
account,
chain: arbitrumSepolia,
transport: http(),
});
await cofhejs.initializeWithViem({
viemClient,
viemWalletClient,
environment: "TESTNET",
});
```
```
--------------------------------
### Get Encrypted Counter Value
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/Your-First-FHE-Contract.md
Return the current encrypted value of the counter. This function allows reading the ciphertext handle without decrypting it.
```solidity
return counter;
```
--------------------------------
### Initialize Cofhe.js Client
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/migrating-to-cofhe.md
This snippet shows how to initialize the Cofhe.js client using ethers. It requires the provider, signer, and the desired network environment.
```javascript
// diff-remove
const fhenixClient = new fhenixjs.FhenixClient({ provider: provider })
// diff-add
await cofhejs.initializeWithEthers({
// diff-add
provider,
// diff-add
signer,
// diff-add
environment: 'TESTNET',
// diff-add
})
```
--------------------------------
### Initialize Cofhejs with Ethers
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/architecture/user-facing-utilities/cofhejs.md
Initialize the Cofhejs client using an Ethers provider and signer. Ensure your web3 provider is correctly set up.
```javascript
const { cofhejs } = require('cofhejs/node')
const { ethers } = require('ethers')
// initialize your web3 provider
const provider = new ethers.JsonRpcProvider('http://127.0.0.1:42069')
const wallet = new ethers.Wallet(PRIVATE_KEY, provider)
// initialize cofhejs Client with ethers (it also supports viem)
await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: wallet,
environment: 'TESTNET',
})
```
--------------------------------
### Automatic Transaction-Scoped Allowance Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/acl-usage-examples.md
Demonstrates how the contract creating a ciphertext automatically gains temporary ownership for the duration of the transaction. This is useful for immediate operations within the same transaction.
```Solidity
contract A {
function doAdd(InEuint32 input1, InEuint32 input2) {
euint32 handle1 = FHE.asEuint32(input1); // Contract A gets temporary ownership of handle1
euint32 handle2 = FHE.asEuint32(input2); // Contract A gets temporary ownership of handle2
euint32 result = FHE.add(handle1, handle2); // possible because Contract A has ownership of handle1 and handle2
}
}
```
--------------------------------
### FHE Operations with Bindings
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/solidity-api/FHE.md
Shows how to perform FHE operations using dot notation for a more concise syntax, including encrypted addition, multiplication, comparison, conditional logic, and decryption. Ensure inputs are initialized.
```solidity
// Use secure encrypted input
InEuint8 encryptedInputA; // This would be provided by the user's client-side encryption
InEuint8 encryptedInputB; // This would be provided by the user's client-side encryption
euint8 a = FHE.asEuint8(encryptedInputA);
euint8 b = FHE.asEuint8(encryptedInputB);
// Perform operations using dot notation
euint8 sum = a.add(b); // Encrypted addition
euint8 product = a.mul(b); // Encrypted multiplication
ebool isGreater = b.gt(a); // Encrypted comparison
// Conditional logic
euint8 result = isGreater.select(sum, product);
// Decrypt the result (allow the contract to access it)
result.allowThis();
uint8 decryptedResult = FHE.decrypt(result);
```
--------------------------------
### Safely Get Decrypted Counter Value
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/Your-First-FHE-Contract.md
Retrieve the decrypted counter value using `FHE.getDecryptResultSafe()`. This function returns the plaintext value and a boolean indicating if decryption is complete.
```solidity
(uint256 value, bool decrypted) = FHE.getDecryptResultSafe(lastDecryptedCounter);
if (!decrypted)
revert("Value is not ready");
return value;
```
--------------------------------
### Initialize cofhejs with Ethers (Browser)
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Initializes cofhejs in a browser dApp using window.ethereum for provider and signer. Allows MetaMask or other EIP-1193 wallets for signing permits. Set generatePermit to false to control permit prompts manually.
```typescript
import { cofhejs } from "cofhejs/web";
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const result = await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: signer as ethers.JsonRpcSigner,
environment: "TESTNET",
generatePermit: false, // control permit prompts manually in production
});
if (!result.success) {
console.error("Browser init failed:", result.error);
}
```
--------------------------------
### Deploy Counter Contract to Testnet
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Deploy the Counter contract to either Ethereum Sepolia or Arbitrum Sepolia testnets using pnpm scripts.
```bash
# For Ethereum Sepolia
pnpm eth-sepolia:deploy-counter
# For Arbitrum Sepolia
pnpm arb-sepolia:deploy-counter
```
--------------------------------
### CofheInItem Type Structure
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/encryption-operations.md
Defines the structure of encrypted items returned by Cofhejs, including `ctHash`, `securityZone`, `utype`, and `signature`. An example for `CoFheInUint8` is shown, extending the base `CoFheInItem`.
```typescript
export type CoFheInItem = {
ctHash: bigint;
securityZone: number;
utype: FheTypes;
signature: string;
};
export type CoFheInUint8 extends CoFheInItem {
utype: FheTypes.Uint8;
}
```
--------------------------------
### Initialize cofhejs with Viem
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Initializes cofhejs using a Viem PublicClient and WalletClient. This variant offers the same functionality as the Ethers version but integrates with Viem.
```typescript
import { cofhejs } from "cofhejs/node";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
const viemClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
});
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const viemWalletClient = createWalletClient({
account,
chain: arbitrumSepolia,
transport: http(),
});
await cofhejs.initializeWithViem({
viemClient,
viemWalletClient,
environment: "TESTNET",
});
```
--------------------------------
### Initialize cofhejs with Ethers (Node.js)
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Connects the SDK to an Ethers provider and signer, fetches the FHE public key, and optionally generates a default permit. Must be called before any encrypt, unseal, or permit operation.
```typescript
import { cofhejs, FheTypes, Encryptable } from "cofhejs/node";
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("http://127.0.0.1:42069");
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const result = await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: wallet,
environment: "TESTNET", // "MOCK" | "TESTNET" | "MAINNET" | "LOCAL"
});
if (!result.success) {
console.error("Initialization failed:", result.error);
process.exit(1);
}
console.log("cofhejs initialized");
```
--------------------------------
### FHE Bindings - Min/Max Functions
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/solidity-api/FHE.md
Demonstrates how to use min/max functions on encrypted types using the FHE binding libraries.
```APIDOC
## Min/Max Functions with Bindings
### Description
Find the minimum or maximum of two encrypted values using the FHE binding libraries.
### Example Usage
```solidity
// Assume a and b are already initialized euint8 types
// euint8 a = ...;
// euint8 b = ...;
euint8 minimum = a.min(b); // Minimum
euint8 maximum = a.max(b); // Maximum
```
```
--------------------------------
### Full Transfer Function with FHE Operations
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/inputs.md
A complete example of a transfer function that receives an encrypted amount, converts it, and performs FHE addition and subtraction operations on balances. Remember to manage ciphertext access in `_updateBalance`.
```solidity
function transfer(
address to,
InEuint32 memory inAmount
) public virtual returns (euint32 transferred) {
euint32 amount = FHE.asEuint32(inAmount);
toBalance = _balances[to];
fromBalance = _balances[msg.sender];
_updateBalance(to, FHE.add(toBalance, amount));
_updateBalance(from, FHE.sub(fromBalance, amount));
}
```
--------------------------------
### Basic FHE Operations
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/solidity-api/FHE.md
Demonstrates basic FHE operations like encrypted addition, multiplication, and comparison, followed by conditional logic and decryption. Ensure inputs are initialized before use.
```solidity
// Use secure encrypted input
InEuint8 encryptedInputA; // This would be provided by the user's client-side encryption
InEuint8 encryptedInputB; // This would be provided by the user's client-side encryption
euint8 a = FHE.asEuint8(encryptedInputA);
euint8 b = FHE.asEuint8(encryptedInputB);
// Perform operations
euint8 sum = FHE.add(a, b); // Encrypted addition
euint8 product = FHE.mul(a, b); // Encrypted multiplication
ebool isGreater = FHE.gt(b, a); // Encrypted comparison
// Conditional logic
euint8 result = FHE.select(isGreater, sum, product);
// Decrypt the result (allow the contract to access it)
result.allowThis();
uint8 decryptedResult = FHE.decrypt(result);
```
--------------------------------
### FHE Voting Contract Example
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/adding-FHE-to-existing-contract.md
This contract implements a secure voting system using FHE. It allows for creating proposals, casting encrypted votes, and finalizing results without revealing individual votes until the end. Ensure FHE library is imported.
```Solidity
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.25;
import {FHE, euint64, InEuint8} from "@fhenixprotocol/cofhe-contracts/FHE.sol";
contract FHEVotingExample {
struct Option {
string name;
euint64 votes;
}
struct Proposal {
string name;
uint256 deadline;
Option[] options;
mapping(address => bool) hasVoted;
bool exists;
uint8 winner;
}
address public owner;
uint256 public proposalCount;
mapping(uint256 => Proposal) public proposals;
euint64 private EUINT64_ZERO;
euint64 private EUINT64_ONE;
event ProposalCreated(
uint256 indexed proposalId,
string name,
uint256 deadline
);
event VoteCast(
uint256 indexed proposalId,
address indexed voter,
uint256 optionIndex
);
error NotOwner();
error InvalidOptionCount();
error ProposalNotFound();
error DeadlineExpired();
error AlreadyVoted();
error InvalidOptionIndex();
error DeadlineNotReached();
constructor() {
owner = msg.sender;
EUINT64_ZERO = FHE.asEuint64(0);
EUINT64_ONE = FHE.asEuint64(1);
}
modifier onlyOwner() {
if (msg.sender != owner) revert NotOwner();
_;
}
function createProposal(
string memory _name,
string[] memory _options,
uint256 _deadline
) external onlyOwner returns (uint256) {
if (_options.length < 2 || _options.length > 4)
revert InvalidOptionCount();
uint256 proposalId = proposalCount++;
Proposal storage proposal = proposals[proposalId];
proposal.name = _name;
proposal.deadline = _deadline;
proposal.exists = true;
for (uint i = 0; i < _options.length; i++) {
proposal.options.push(
Option({name: _options[i], votes: FHE.asEuint64(0)})
);
}
emit ProposalCreated(proposalId, _name, _deadline);
return proposalId;
}
function vote(uint256 _proposalId, InEuint8 memory _optionIndex) external {
euint8 optionIndex = FHE.asEuint8(_optionIndex);
Proposal storage proposal = proposals[_proposalId];
if (!proposal.exists) revert ProposalNotFound();
if (block.timestamp >= proposal.deadline) revert DeadlineExpired();
if (proposal.hasVoted[msg.sender]) revert AlreadyVoted();
for (uint8 i = 0; i < proposal.options.length; i++) {
proposal.options[i].votes = FHE.add(
proposal.options[i].votes,
FHE.select(
optionIndex.eq(FHE.asEuint8(i)),
EUINT64_ONE,
EUINT64_ZERO
)
);
FHE.allowThis(proposal.options[i].votes);
}
proposal.hasVoted[msg.sender] = true;
FHE.allowSender(optionIndex);
emit VoteCast(_proposalId, msg.sender, optionIndex);
}
function finalizeVote(uint256 _proposalId) external {
if (msg.sender != owner) revert NotOwner();
Proposal storage proposal = proposals[_proposalId];
if (!proposal.exists) revert ProposalNotFound();
if (block.timestamp < proposal.deadline) revert DeadlineNotReached();
for (uint8 i = 0; i < proposal.options.length; i++) {
FHE.decrypt(proposal.options[i].votes);
}
}
function getProposal(
uint256 _proposalId
)
external
view
returns (
string memory name,
uint256 deadline,
bool exists,
string[] memory options,
uint256[] memory votes,
bool finalized,
uint8 winner
)
{
Proposal storage proposal = proposals[_proposalId];
name = proposal.name;
deadline = proposal.deadline;
exists = proposal.exists;
options = new string[](proposal.options.length);
for (uint8 i = 0; i < proposal.options.length; i++) {
options[i] = proposal.options[i].name;
}
votes = new uint64[](proposal.options.length);
finalized = true;
for (uint8 i = 0; i < proposal.options.length; i++) {
(uint256 result, bool decrypted) = FHE.getDecryptResultSafe(
proposal.options[i].votes
);
votes[i] = decrypted ? result : 0;
if (!decrypted) finalized = false;
}
if (finalized) {
uint256 maxVotes = 0;
winner = 0;
for (uint8 i = 0; i < proposal.options.length; i++) {
if (proposal.options[i].votes > maxVotes) {
maxVotes = proposal.options[i].votes;
winner = i;
}
}
}
}
function hasVoted(
uint256 _proposalId,
```
--------------------------------
### Run Mock Environment Tests
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/quick-start/index.md
Execute tests using the mock FHE environment for rapid iteration without external dependencies.
```bash
pnpm test
```
--------------------------------
### Initialize Cofhejs Client in Browser
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/index.md
Initialize the cofhejs client for browser environments using ethers. This requires a browser-compatible web3 provider like MetaMask.
```javascript
const { cofhejs } = require("cofhejs/web");
const { ethers } = require("ethers");
// initialize your web3 provider
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = (await provider.getSigner()) as ethers.JsonRpcSigner;
// initialize cofhejs Client with ethers (it also supports viem)
await cofhejs.initializeWithEthers({
ethersProvider: provider,
ethersSigner: signer,
environment: "TESTNET"
});
```
--------------------------------
### Creating a Permit with Cofhe.js
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/index.md
Creates a permit for a user, which is used to verify identity and seal user data. This process uses EIP712 for signing structured data. Permits are stored locally and can be reused.
```javascript
const permit = await cofhejs.createPermit({
type: 'self',
issuer: wallet.address,
})
```
--------------------------------
### Initialize Encrypted Variables
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/tutorials/Your-First-FHE-Contract.md
Initialize encrypted state variables using `FHE.asEuint64()`. Encrypting `delta` once in the constructor optimizes repeated operations.
```solidity
counter = FHE.asEuint64(initial_value);
delta = FHE.asEuint64(1);
```
--------------------------------
### FHE Bindings - Comparison Operations
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/solidity-api/FHE.md
Demonstrates how to use comparison operations on encrypted types using the FHE binding libraries.
```APIDOC
## Comparison Operations with Bindings
### Description
Perform secure comparison operations on encrypted values using the FHE binding libraries, returning an encrypted boolean.
### Example Usage
```solidity
// Assume a and b are already initialized euint8 types
// euint8 a = ...;
// euint8 b = ...;
ebool isEqual = a.eq(b); // Equal
ebool isNotEqual = a.ne(b); // Not Equal
ebool isLessThan = a.lt(b); // Less Than
ebool isLessEqual = a.lte(b); // Less Than or Equal
ebool isGreaterThan = a.gt(b); // Greater Than
ebool isGreaterEqual = a.gte(b); // Greater Than or Equal
```
```
--------------------------------
### Initialize Cofhejs with Ethers (Production)
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/cofhejs/permits-management.md
Initializes the cofhejs client for production environments with automatic permit generation disabled. Manual permit creation is required.
```typescript
const provider = new ethers.JsonRpcProvider('http://127.0.0.1:42069')
const wallet = new ethers.Wallet(PRIVATE_KEY, provider)
// initialize cofhejs Client with ethers (it also supports viem)
await cofhejs.initializeWithEthers({
provider: provider,
signer: signer,
environment: 'MAINNET',
generatePermit: false,
})
```
--------------------------------
### FHE.sol: Trivial Encryption (asEuint)
Source: https://context7.com/fhenixprotocol/cofhe-docs/llms.txt
Demonstrates trivial encryption of plaintext constants into the ciphertext domain using `FHE.asEuint*`. Use this for mixed plaintext-ciphertext arithmetic, but note that these values are not confidential.
```solidity
import "@fhenixprotocol/cofhe-contracts/FHE.sol";
contract TrivialDemo {
euint32 public count;
constructor() {
// Trivial encryption of a public constant
count = FHE.asEuint32(0);
FHE.allowThis(count);
}
function addFive() external {
euint32 five = FHE.asEuint32(5); // public, trivially encrypted
count = FHE.add(count, five); // result stays encrypted
FHE.allowThis(count);
}
function resetTo(InEuint32 calldata secret) external {
// 'secret' IS confidential — encrypted off-chain by cofhejs
count = FHE.asEuint32(secret);
FHE.allowThis(count);
}
}
```
--------------------------------
### FHE Select vs. Traditional If-Else
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fhe-library/select-vs-ifelse.md
Demonstrates the correct way to handle conditional assignments using `FHE.select` with encrypted data, contrasting it with the non-functional traditional `if-else` approach.
```Solidity
euint32 a = FHE.asEuint32(10);
euint32 b = FHE.asEuint32(20);
euint32 max;
// Instead of this (won't work) :
// diff-remove
if (a.gt(b)) { // gt returns encrypted boolean (ebool), traditional if..else won't work as expected
// diff-remove
max = a;
// diff-remove
} else {
// diff-remove
max = b;
// diff-remove
}
// Do this:
// diff-add
ebool isHigher = a.gt(b);
// diff-add
max = FHE.select(isHigher, a, b);
```
--------------------------------
### FHERC20 Constructor
Source: https://github.com/fhenixprotocol/cofhe-docs/blob/master/docs/devdocs/fherc/fherc20.md
Initializes the FHERC20 token with name, symbol, and decimals, and sets up the EIP712 domain separator for secure permissioned transfers.
```Solidity
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) EIP712(name_, "1")
```