### Install the Relayer SDK CLI
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/cli.md
Globally install the `@zama-fhe/relayer-sdk` package using npm to enable the CLI tool. Ensure Node.js is installed first.
```bash
npm install -g @zama-fhe/relayer-sdk
```
--------------------------------
### Complete Delegate Decryption Example
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
This example shows the full workflow for delegated decryption, from contract setup to final decryption. It requires Alice to authorize Bob as a delegate before Bob can decrypt data encrypted by Alice. Ensure you have ALICE_PRIVATE_KEY and BOB_PRIVATE_KEY defined.
```typescript
import { ethers } from 'ethers';
import { createInstance, SepoliaConfig } from '@zama-fhe/relayer-sdk/node';
async function delegateDecryptExample() {
// Setup provider and signers
const provider = new ethers.JsonRpcProvider(
'https://ethereum-sepolia-rpc.publicnode.com',
);
const aliceSigner = new ethers.Wallet(ALICE_PRIVATE_KEY, provider);
const bobSigner = new ethers.Wallet(BOB_PRIVATE_KEY, provider);
const aliceAddr = await aliceSigner.getAddress();
const bobAddr = await bobSigner.getAddress();
// Initialize FHEVM instance with Sepolia config
const fhevmInstance = await createInstance({
...SepoliaConfig,
network: provider,
});
// Contract setup
const contractAddress = '0x...'; // Your deployed contract address
const contract = new ethers.Contract(
contractAddress,
[
'function initialize(uint32 value) external',
'function encryptedValue() public view returns (uint256)',
],
aliceSigner,
);
// Step 1: Alice initializes encrypted value
const tx1 = await contract.initialize(123456);
await tx1.wait();
// Step 2: Alice authorizes Bob as delegate
const aclAddress = SepoliaConfig.aclContractAddress;
const acl = new ethers.Contract(
aclAddress,
[
'function delegateForUserDecryption(address delegate, address contractAddress, uint64 expirationDate) external',
],
aliceSigner,
);
const expirationDate = Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60; // 1 year
const tx2 = await acl.delegateForUserDecryption(
bobAddr,
contractAddress,
expirationDate,
);
await tx2.wait();
// Step 3: Get encrypted handle and convert to hex
const handleRaw = await contract.encryptedValue();
const handleHex = ethers.toBeHex(handleRaw, 32);
// Step 4: Bob generates keypair
const bobKeypair = fhevmInstance.generateKeypair();
// Step 5: Create EIP-712 message
const extraData = '0x00';
const startTimestamp = Math.floor(Date.now() / 1000);
const durationDays = 10;
const eip712 = fhevmInstance.createDelegatedUserDecryptEIP712(
bobKeypair.publicKey,
[contractAddress],
aliceAddr,
startTimestamp,
durationDays,
extraData,
);
// Step 6: Bob signs the message
const signature = await bobSigner.signTypedData(
eip712.domain,
{
DelegatedUserDecryptRequestVerification:
eip712.types.DelegatedUserDecryptRequestVerification,
},
eip712.message,
);
// Step 7: Bob performs delegated decryption
const results = await fhevmInstance.delegatedUserDecrypt(
[{ handle: handleHex, contractAddress }],
bobKeypair.privateKey,
bobKeypair.publicKey,
signature.replace('0x', ''),
[contractAddress],
aliceAddr,
bobAddr,
startTimestamp,
durationDays,
extraData,
);
const decryptedValue = results[handleHex];
console.log('Decrypted value:', decryptedValue); // Output: 123457 (contract adds 1)
}
```
--------------------------------
### Encryption Usage Example with Async Options
Source: https://github.com/zama-ai/relayer-sdk/blob/main/API_MIGRATION.md
Demonstrates how to use the encrypt method with optional asynchronous parameters like timeout and an onProgress callback for real-time feedback.
```typescript
const builder = instance.createEncryptedInput(contractAddress, userAddress);
builder.add8(12);
builder.add32(34);
const result = await builder.encrypt({
timeout: 60000,
onProgress: (args: RelayerInputProofProgressArgs) => {
console.log(`${args.type}: ${args.elapsedMs}ms`);
},
});
```
--------------------------------
### Verify CLI Installation
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/cli.md
Access the CLI using the `relayer` command and verify the installation by exploring available commands.
```bash
relayer help
```
--------------------------------
### Install Relayer SDK with npm, Yarn, or pnpm
Source: https://github.com/zama-ai/relayer-sdk/blob/main/README.md
Use your preferred package manager to install the fhevm Relayer SDK and its dependencies.
```bash
# Using npm
npm install @zama-fhe/relayer-sdk
# Using Yarn
yarn add @zama-fhe/relayer-sdk
# Using pnpm
pnpm add @zama-fhe/relayer-sdk
```
--------------------------------
### Create FHEVM Instance with Sepolia Configuration
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/initialization.md
Initialize the FHEVM instance using the pre-defined `SepoliaConfig` object for simplified setup on the Sepolia testnet. Ensure the network RPC URL is correctly provided.
```typescript
import { createInstance, SepoliaConfig } from '@zama-fhe/relayer-sdk';
const instance = await createInstance({
...SepoliaConfig,
network: 'https://ethereum-sepolia-rpc.publicnode.com',
});
```
--------------------------------
### Create FHEVM Instance for Mainnet
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/initialization.md
Initialize the FHEVM instance for Mainnet using `MainnetConfig`. This requires a Zama API key for authentication, which should be provided in the `auth` object. Ensure your API key is securely stored and accessed, for example, via environment variables.
```typescript
import { createInstance, MainnetConfig } from '@zama-fhe/relayer-sdk';
const ZAMA_FHEVM_API_KEY = process.env.ZAMA_FHEVM_API_KEY; // Your Zama API key
const instance = await createInstance({
...MainnetConfig,
network: 'https://ethereum-rpc.publicnode.com', // or your preferred Ethereum mainnet RPC
auth: { __type: 'ApiKeyHeader', value: ZAMA_FHEVM_API_KEY },
});
```
--------------------------------
### Import SDK from Bundle
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
Import necessary functions from the relayer SDK bundle if you have installed the package.
```javascript
import {
initSDK,
createInstance,
SepoliaConfig,
} from '@zama-fhe/relayer-sdk/bundle';
```
--------------------------------
### Public Decryption Usage Example with Async Options
Source: https://github.com/zama-ai/relayer-sdk/blob/main/API_MIGRATION.md
Shows how to invoke the publicDecrypt method with optional asynchronous parameters including timeout, signal, onProgress callback, and authentication.
```typescript
const result = await instance.publicDecrypt(handles, {
timeout,
//signal: abortController.signal,
onProgress: (args: RelayerPublicDecryptProgressArgs) => {
console.log(`${args.type}: ${args.elapsedMs}ms`);
},
auth: { __type: 'ApiKeyHeader', value: zamaFhevmApiKey },
});
```
--------------------------------
### User Decryption Usage Example with Async Options
Source: https://github.com/zama-ai/relayer-sdk/blob/main/API_MIGRATION.md
Illustrates calling the userDecrypt method with various parameters including asynchronous options such as timeout, signal, onProgress callback, and authentication.
```typescript
const result = await instance.userDecrypt(
handleContractPairs,
keypair.privateKey,
keypair.publicKey,
signature,
contractAddresses,
signer.address,
startTimeStamp,
durationDays,
{
timeout,
//signal: abortController.signal,
onProgress: (args: RelayerUserDecryptProgressArgs) => {
console.log(`${args.type}: ${args.elapsedMs}ms`);
},
auth: { __type: 'ApiKeyHeader', value: zamaFhevmApiKey },
},
);
```
--------------------------------
### Initialize Relayer SDK with API Key
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/mainnet-api-key.md
Configure the Relayer SDK for mainnet usage by providing your API key during initialization. Ensure the API key is stored securely, for example, in environment variables.
```typescript
import { createInstance, MainnetConfig } from '@zama-fhe/relayer-sdk';
const ZAMA_FHEVM_API_KEY = process.env.ZAMA_FHEVM_API_KEY; // Your Zama API key
const instance = await createInstance({
...MainnetConfig,
network: 'https://ethereum-rpc.publicnode.com', // or your preferred Ethereum mainnet RPC
auth: { __type: 'ApiKeyHeader', value: ZAMA_FHEVM_API_KEY },
});
```
--------------------------------
### Calling FHE Addition from Ethers
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/input.md
Example of how to call the `add` function on a Solidity contract using the `ethers` library. It passes the ciphertext handles and the input proof obtained from the encryption process.
```js
my_contract.add(
ciphertexts.handles[0],
ciphertexts.handles[1],
ciphertexts.inputProof,
);
```
--------------------------------
### Initialize SDK and Generate Keys
Source: https://github.com/zama-ai/relayer-sdk/blob/main/e2e/servers/site/foo/browser.html
Initializes the SDK, sets up TFHE parameters, generates client and public keys, and serializes them. Also generates and serializes CompactPkeCrs with different parameters.
```javascript
async function initializeApp(protocolSDK) {
const startTime = Date.now();
// Use the library
await protocolSDK.initSDK();
const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
const tfhe = protocolSDK.tfhe;
const block_params = new tfhe.ShortintParameters(
tfhe.ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
const casting_params = new tfhe.ShortintCompactPublicKeyEncryptionParameters(
tfhe.ShortintCompactPublicKeyEncryptionParametersName.V1_0_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
const config = tfhe.TfheConfigBuilder.default()
.use_custom_parameters(block_params)
.use_dedicated_compact_public_key_parameters(casting_params)
.build();
const clientKey = tfhe.TfheClientKey.generate(config);
const publicKey = tfhe.TfheCompactPublicKey.new(clientKey);
const publicKeyBin = publicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK);
const privateKeyBin = clientKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK);
await trace(publicKeyBin instanceof Uint8Array, startTime);
await trace(publicKeyBin.length, startTime);
await trace(privateKeyBin instanceof Uint8Array, startTime);
await trace(privateKeyBin.length, startTime);
const crs0 = tfhe.CompactPkeCrs.from_config(config, 4 * 32);
const crs128 = crs0.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS);
await trace("crs128.length=" + crs128.length, startTime);
const crs1 = tfhe.CompactPkeCrs.from_config(config, 4 * 64);
const crs256 = crs1.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS);
await trace("crs256.length=" + crs256.length, startTime);
const crs2 = tfhe.CompactPkeCrs.from_config(config, 4 * 128);
const crs512 = crs2.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS);
await trace("crs512.length=" + crs512.length, startTime);
const crs3 = tfhe.CompactPkeCrs.from_config(config, 4 * 256);
const crs1024 = crs3.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS);
await trace("crs1024.length=" + crs1024.length, startTime);
const crs4 = tfhe.CompactPkeCrs.from_config(config, 4 * 512);
const crs2048 = crs4.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS);
await trace(`crs2048.length=${crs2048.length}`, startTime);
}
```
--------------------------------
### Initialize SDK using ESM CDN
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
Initialize the SDK and create an instance using the ESM CDN, configuring the network with window.ethereum.
```javascript
import {
initSDK,
createInstance,
SepoliaConfig,
} from 'https://cdn.zama.org/relayer-sdk-js/0.3.0-7/relayer-sdk-js.umd.cjs';
await initSDK();
const config = { ...SepoliaConfig, network: window.ethereum };
config.network = window.ethereum;
const instance = await createInstance(config);
```
--------------------------------
### Build Project
Source: https://github.com/zama-ai/relayer-sdk/blob/main/HOW-TO.md
Run the build command to compile the project after dependency updates.
```bash
npm run build
```
--------------------------------
### Initialize Relayer SDK with Bundled Version
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webpack.md
Use the prebundled version of the relayer SDK with a script tag and initialize it using window.fhevm.initSDK() and window.fhevm.createInstance().
```javascript
const start = async () => {
await window.fhevm.initSDK(); // load wasm needed
const config = { ...SepoliaConfig, network: window.ethereum };
config.network = window.ethereum;
const instance = window.fhevm.createInstance(config).then((instance) => {
console.log(instance);
});
};
```
--------------------------------
### Initialize Application with UMD Library
Source: https://github.com/zama-ai/relayer-sdk/blob/main/e2e/servers/site/foo/browser.html
Initializes the application by loading the UMD library and then calling an initialization function with the loaded library.
```javascript
// The protocol-sdk is served by localhost:5173
const umdUrl = 'http://localhost:5173/libs/relayer-sdk-js/relayer-sdk-js.umd.cjs';
const umdLibname = 'relayerSDK';
// The relayer-sdk is served by localhost:5174
// const umdUrl = 'http://localhost:5174/relayer-sdk-js/relayer-sdk-js.umd.cjs';
// const umdLibname = 'relayerSDK';
loadUMD(umdUrl, umdLibname)
.then(library => {
console.log("UMD loaded and ready!");
console.log("Library:", library);
// Initialize your app
initializeApp(library);
})
.catch(error => {
console.error("Error loading UMD:", error);
});
```
--------------------------------
### Load WASM with initSDK
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
Initialize the relayer SDK by loading the necessary WASM files before proceeding.
```javascript
import { initSDK } from '@zama-fhe/relayer-sdk/bundle';
const init = async () => {
await initSDK(); // Load needed WASM
};
```
--------------------------------
### Create Relayer SDK Instance
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
After loading the WASM, create an instance of the relayer SDK using the Sepolia configuration and the user's Ethereum network.
```javascript
import {
initSDK,
createInstance,
SepoliaConfig,
} from '@zama-fhe/relayer-sdk/bundle';
const init = async () => {
await initSDK(); // Load FHE
const config = { ...SepoliaConfig, network: window.ethereum };
return createInstance(config);
};
init().then((instance) => {
console.log(instance);
});
```
--------------------------------
### Run Tests
Source: https://github.com/zama-ai/relayer-sdk/blob/main/HOW-TO.md
Execute the test suite to verify the integrity of the project after dependency updates.
```bash
npm test
```
--------------------------------
### Import SDK from npm Package
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
Import the relayer SDK from the npm package. Ensure your package.json has '"type": "module"' or use '@zama-fhe/relayer-sdk/web' for CommonJS.
```javascript
import { initSDK, createInstance, SepoliaConfig } from '@zama-fhe/relayer-sdk';
```
--------------------------------
### Create FHEVM Instance with Full Configuration
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/initialization.md
Instantiate the FHEVM instance with all required contract addresses and chain configurations. This method provides explicit control over each parameter.
```typescript
import { createInstance } from '@zama-fhe/relayer-sdk';
const instance = await createInstance({
// ACL_CONTRACT_ADDRESS (FHEVM Host chain)
aclContractAddress: '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D',
// KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
kmsContractAddress: '0xbE0E383937d564D7FF0BC3b46c51f0bF8d5C311A',
// INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
inputVerifierContractAddress: '0xBBC1fFCdc7C316aAAd72E807D9b0272BE8F84DA0',
// DECRYPTION_ADDRESS (Gateway chain)
verifyingContractAddressDecryption:
'0x5D8BD78e2ea6bbE41f26dFe9fdaEAa349e077478',
// INPUT_VERIFICATION_ADDRESS (Gateway chain)
verifyingContractAddressInputVerification:
'0x483b9dE06E4E4C7D35CCf5837A1668487406D955',
// FHEVM Host chain id
chainId: 11155111,
// Gateway chain id
gatewayChainId: 10901,
// RPC provider to host chain (or Eip1193Provider)
network: 'https://ethereum-sepolia-rpc.publicnode.com',
// Relayer URL
relayerUrl: 'https://relayer.testnet.zama.org',
});
```
--------------------------------
### Configure Network with Eip1193Provider Instance
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/initialization.md
Integrate with browser wallets like MetaMask by providing an `Eip1193Provider` instance to the `network` property. This allows the SDK to use the wallet's connection to the blockchain.
```typescript
import { createInstance, SepoliaConfig } from '@zama-fhe/relayer-sdk';
// Using window.ethereum from MetaMask or other browser wallets
const instance = await createInstance({
...SepoliaConfig,
network: window.ethereum, // Eip1193Provider
});
```
--------------------------------
### Create and Encrypt Inputs for FHEVM
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/input.md
Use this to create a buffer for values, add them with their data types, and then encrypt them to generate ciphertext handles and a proof of knowledge. This process prepares inputs for on-chain FHE operations.
```ts
const buffer = instance.createEncryptedInput(
// The address of the contract allowed to interact with the "fresh" ciphertexts
contractAddress,
// The address of the entity allowed to import ciphertexts to the contract at `contractAddress`
userAddress,
);
// We add the values with associated data-type method
buffer.add64(BigInt(23393893233));
buffer.add64(BigInt(1));
// buffer.addBool(false);
// buffer.add8(BigInt(43));
// buffer.add16(BigInt(87));
// buffer.add32(BigInt(2339389323));
// buffer.add128(BigInt(233938932390));
// buffer.addAddress('0xa5e1defb98EFe38EBb2D958CEe052410247F4c80');
// buffer.add256(BigInt('2339389323922393930'));
// This will encrypt the values, generate a proof of knowledge for it, and then upload the ciphertexts using the relayer.
// This action will return the list of ciphertext handles.
const ciphertexts = await buffer.encrypt();
```
--------------------------------
### Include UMD CDN for Relayer SDK
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webapp.md
Include the UMD bundle from the Zama CDN at the top of your HTML to use the relayer SDK.
```html
```
--------------------------------
### Trace Execution and Display
Source: https://github.com/zama-ai/relayer-sdk/blob/main/e2e/servers/site/foo/browser.html
Logs messages to the DOM with execution timestamps and introduces a small delay for visual tracing.
```javascript
async function trace(str, startTime) {
const p = document.createElement('p');
p.textContent = `\[${Date.now() - startTime}ms\] ${str}`;
document.body.appendChild(p);
// repaint
p.offsetHeight;
await sleep(200);
}
```
--------------------------------
### Generate Keys
Source: https://github.com/zama-ai/relayer-sdk/blob/main/HOW-TO.md
Execute this script to update keys, which may be necessary for changes in crypto-parameters or serialization.
```bash
./generateKeys.js
```
--------------------------------
### Webpack Fallbacks for Node.js Core Modules
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webpack.md
Configure Webpack fallbacks for Node.js core modules like buffer, crypto, stream, and path to ensure browser compatibility.
```javascript
resolve: {
fallback: {
buffer: require.resolve('buffer/'),
crypto: require.resolve('crypto-browserify'),
stream: require.resolve('stream-browserify'),
path: require.resolve('path-browserify'),
},
}
```
--------------------------------
### Regenerate package-lock.json
Source: https://github.com/zama-ai/relayer-sdk/blob/main/HOW-TO.md
Run this command to update the package-lock.json file after modifying package.json.
```bash
npm install
```
--------------------------------
### Solidity Contract for FHE Addition
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/input.md
This Solidity contract snippet demonstrates how to implement an `add` function that utilizes FHE operations. It takes two external ciphertexts and a proof, then returns the encrypted sum.
```solidity
contract MyContract {
...
function add(
externalEuint64 a,
externalEuint64 b,
bytes calldata proof
) public virtual returns (euint64) {
return FHE.add(FHE.fromExternal(a, proof), FHE.fromExternal(b, proof))
}
}
```
--------------------------------
### Encrypt Integer and Boolean Data
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/cli.md
Encrypt a 64-bit integer and a boolean for a specific contract and user address. The data is appended with its type (e.g., `:64` for 64-bit integers, `:1` for booleans).
```bash
relayer encrypt 0x8Fdb26641d14a80FCCBE87BF455338Dd9C539a50 0xa5e1defb98EFe38EBb2D958CEe052410247F4c80 71721075:64 1:1
```
--------------------------------
### Load UMD Script Dynamically
Source: https://github.com/zama-ai/relayer-sdk/blob/main/e2e/servers/site/foo/browser.html
Loads a UMD script from a given URL and resolves with the global variable name specified. Handles cases where the script might already be loaded.
```javascript
function loadUMD(src, globalName) {
return new Promise((resolve, reject) => {
// Check if already loaded
if (window[globalName]) {
resolve(window[globalName]);
return;
}
const script = document.createElement('script');
script.src = src;
script.onload = () => {
if (window[globalName]) {
resolve(window[globalName]);
} else {
reject(new Error(`Global ${globalName} not found after loading`));
}
};
script.onerror = () => reject(new Error(`Failed to load ${src}`));
document.head.appendChild(script);
});
}
```
--------------------------------
### Async Options Types for Relayer SDK
Source: https://github.com/zama-ai/relayer-sdk/blob/main/API_MIGRATION.md
TypeScript type definitions for asynchronous operation options, including authentication, debugging, signals, timeouts, and progress callbacks for different relayer SDK methods.
```typescript
type RelayerInputProofOptionsType = {
auth?: Auth | undefined;
debug?: boolean | undefined;
signal?: AbortSignal | undefined;
timeout?: number | undefined;
onProgress?: ((args: RelayerInputProofProgressArgs) => void) | undefined;
};
type RelayerPublicDecryptOptionsType = {
auth?: Auth | undefined;
debug?: boolean | undefined;
signal?: AbortSignal | undefined;
timeout?: number | undefined;
onProgress?: ((args: RelayerPublicDecryptProgressArgs) => void) | undefined;
};
type RelayerUserDecryptOptionsType = {
auth?: Auth | undefined;
debug?: boolean | undefined;
signal?: AbortSignal | undefined;
timeout?: number | undefined;
onProgress?: ((args: RelayerUserDecryptProgressArgs) => void) | undefined;
};
```
--------------------------------
### Webpack Fallback for 'tfhe_bg.wasm'
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/webpack.md
Add a resolve fallback configuration in webpack.config.js to resolve 'tfhe_bg.wasm' when it cannot be found.
```javascript
resolve: {
fallback: {
'tfhe_bg.wasm': require.resolve('tfhe/tfhe_bg.wasm'),
},
}
```
--------------------------------
### Async API Signatures for Relayer SDK
Source: https://github.com/zama-ai/relayer-sdk/blob/main/API_MIGRATION.md
Defines the updated TypeScript signatures for the encrypt, publicDecrypt, and userDecrypt methods in the relayer-sdk, now supporting optional asynchronous options.
```typescript
encrypt: (options?: RelayerInputProofOptionsType) =>
Promise<{
handles: Uint8Array[];
inputProof: Uint8Array;
}>;
publicDecrypt: (
handles: (string | Uint8Array)[],
options?: RelayerPublicDecryptOptionsType,
) => Promise;
userDecrypt: (
handles: HandleContractPair[],
privateKey: string,
publicKey: string,
signature: string,
contractAddresses: string[],
userAddress: string,
startTimestamp: string | number,
durationDays: string | number,
options?: RelayerUserDecryptOptionsType,
) => Promise;
```
--------------------------------
### Decrypting Ciphertext Handles
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Use `delegatedUserDecrypt` to decrypt multiple ciphertext handles. Ensure handles are formatted as 32-byte hex strings. The total bit length of all ciphertexts must not exceed 2048 bits.
```typescript
// Convert handle to proper hex format (32 bytes = 0x + 64 hex chars)
const handleHex = ethers.toBeHex(ciphertextHandle, 32);
const handleContractPairs = [
{
handle: handleHex,
contractAddress: contractAddress,
},
];
const result = await instance.delegatedUserDecrypt(
handleContractPairs,
keypair.privateKey,
keypair.publicKey,
signature.replace('0x', ''),
contractAddresses,
delegatorAddress,
delegateAddress,
startTimestamp,
durationDays,
extraData,
);
// result maps each handle to its decrypted value
const decryptedBalance = result[handleHex];
```
--------------------------------
### Create EIP-712 Message for Delegate Decryption
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Generates the EIP-712 typed data structure required for delegate decryption. Ensure you have an initialized FhevmInstance and the necessary contract and delegator addresses. The `extraData` parameter is mandatory; use '0x00' as a default.
```typescript
import { createInstance } from '@zama-fhe/relayer-sdk/node';
// instance: FhevmInstance (see initialization guide)
// delegatorAddress: the data owner's address
// contractAddress: the contract holding the encrypted value
const keypair = instance.generateKeypair();
// For production/testnet: use '0x00' as default extraData
// Future SDK versions may include getExtraData() for context-aware decryption
const extraData = '0x00';
const contractAddresses = [contractAddress];
const startTimestamp = Math.floor(Date.now() / 1000);
const durationDays = 10;
const eip712 = instance.createDelegatedUserDecryptEIP712(
keypair.publicKey,
contractAddresses,
delegatorAddress,
startTimestamp,
durationDays,
extraData,
);
```
--------------------------------
### Retrieve Encrypted Balance Handle
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/user-decryption.md
Implement a view function in your Solidity smart contract to retrieve a user's encrypted balance handle. This handle is an identifier for the underlying ciphertext stored on the blockchain.
```solidity
import "@fhevm/solidity/lib/FHE.sol";
contract ConfidentialERC20 {
...
function balanceOf(account address) public view returns (euint64) {
return balances[msg.sender];
}
...
}
```
--------------------------------
### createDelegatedUserDecryptEIP712
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Creates the EIP-712 typed data structure required for delegate decryption. This structure is used to generate the signature needed for the `delegatedUserDecrypt` call.
```APIDOC
## createDelegatedUserDecryptEIP712
### Description
Creates the EIP-712 typed data structure for delegate decryption.
### Method
(Not specified, likely a SDK method call)
### Parameters
#### Path Parameters
(None specified)
#### Query Parameters
(None specified)
#### Request Body
- **publicKey** (string) - Required - The delegate's NaCl public key from `generateKeypair()`
- **contractAddresses** (string[]) - Required - Contract addresses holding the encrypted values (max 10)
- **delegatorAddress** (string) - Required - The data owner's address (must have ACL permission)
- **startTimestamp** (number) - Required - Unix timestamp for when the permit becomes valid
- **durationDays** (number) - Required - How many days the permit remains valid (1–365)
- **extraData** (BytesHex) - Required - KMS context from `getExtraData()`
### Request Example
(No example provided in source)
### Response
#### Success Response
- **(Implicit)** `KmsDelegatedUserDecryptEIP712Type` — the complete EIP-712 object with `domain`, `types`, and `message` fields.
#### Response Example
(No example provided in source)
```
--------------------------------
### Granting ACL Permissions in Solidity
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Use FHE.allow() and FHE.allowThis() in your Solidity contract to grant ACL permissions to the delegator and the contract itself, which is necessary for decryption.
```solidity
import {FHE, euint64} from "@fhevm/solidity/lib/FHE.sol";
contract ConfidentialERC20 {
mapping(address => euint64) internal balances;
function transfer(address to, euint64 amount) public {
// ... transfer logic ...
FHE.allowThis(balances[to]); // required for decryption to work
FHE.allow(balances[to], to); // grants ACL to the data owner (delegator)
}
}
```
--------------------------------
### Registering Delegation with ACL Contract (JavaScript)
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Authorize a delegate for user decryption by calling delegateForUserDecryption on the ACL contract. This registers the delegation on-chain with an expiration date. Ensure you use the correct ACL contract address for your chain.
```javascript
import { ethers } from 'ethers';
// The ACL contract address (check your chain's ZamaConfig for the correct address)
const ACL_ADDRESS = '0x...'; // chain-specific ACL address
const ACL_ABI = [
'function delegateForUserDecryption(address delegate, address contractAddress, uint64 expirationDate) external',
];
// delegatorSigner: the delegator's (data owner's) ethers Signer
const acl = new ethers.Contract(ACL_ADDRESS, ACL_ABI, delegatorSigner);
// Authorize the delegate for 1 year
const expirationDate = Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60;
const tx = await acl.delegateForUserDecryption(
delegateAddress,
contractAddress,
expirationDate,
);
await tx.wait();
```
--------------------------------
### Perform Client-Side User Decryption
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/user-decryption.md
Use the `@zama-fhe/relayer-sdk` to perform user decryption client-side. This function takes a list of ciphertext handles and re-encrypts them with the user's public key, requiring a signature for verification.
```typescript
// instance: [`FhevmInstance`] from `zama-fhe/relayer-sdk`
// signer: [`Signer`] from ethers (could a [`Wallet`])
// ciphertextHandle: [`string`]
// contractAddress: [`string`]
const keypair = instance.generateKeypair();
// userDecrypt can take a batch of handles (with their corresponding contract addresses).
// In this example we only pass one handle.
const handleContractPairs = [
{
handle: ciphertextHandle,
contractAddress: contractAddress,
},
];
const startTimeStamp = Math.floor(Date.now() / 1000).toString();
const durationDays = '10'; // String for consistency
const contractAddresses = [contractAddress];
const eip712 = instance.createEIP712(
keypair.publicKey,
contractAddresses,
startTimeStamp,
durationDays,
);
const signature = await signer.signTypedData(
eip712.domain,
{
UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification,
},
eip712.message,
);
const result = await instance.userDecrypt(
handleContractPairs,
keypair.privateKey,
keypair.publicKey,
signature.replace('0x', ''),
contractAddresses,
signer.address,
startTimeStamp,
durationDays,
);
// result maps each handle to its decrypted value
const decryptedValue = result[ciphertextHandle];
```
--------------------------------
### Sign EIP-712 Message as Delegate
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Signs the EIP-712 message generated for delegate decryption using the delegate's ethers Signer. This action authenticates the delegate's authorization for the decryption request.
```typescript
// delegateSigner: the delegate's ethers Signer
const signature = await delegateSigner.signTypedData(
eip712.domain,
{
DelegatedUserDecryptRequestVerification:
eip712.types.DelegatedUserDecryptRequestVerification,
},
eip712.message,
);
```
--------------------------------
### Sleep Utility Function
Source: https://github.com/zama-ai/relayer-sdk/blob/main/e2e/servers/site/foo/browser.html
A simple utility function to pause execution for a specified duration.
```javascript
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
```
--------------------------------
### delegatedUserDecrypt
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/delegate-decrypt.md
Performs the delegate decryption request through the Relayer. It takes handle-contract pairs, cryptographic keys, signature, and other relevant details to decrypt values.
```APIDOC
## delegatedUserDecrypt
### Description
Performs the delegate decryption request through the Relayer.
### Method
(Not specified, likely a SDK method call)
### Parameters
#### Path Parameters
(None specified)
#### Query Parameters
(None specified)
#### Request Body
- **handleContractPairs** (HandleContractPair[]) - Required - Array of `{ handle, contractAddress }` pairs to decrypt
- **privateKey** (string) - Required - The delegate's NaCl private key from `generateKeypair()`
- **publicKey** (string) - Required - The delegate's NaCl public key from `generateKeypair()`
- **signature** (string) - Required - EIP-712 signature from the delegate (without `0x` prefix)
- **contractAddresses** (string[]) - Required - Same contract addresses used in the EIP-712 message
- **delegatorAddress** (string) - Required - The data owner's address
- **delegateAddress** (string) - Required - The delegate's address (the signer)
- **startTimestamp** (number) - Required - Same timestamp used in the EIP-712 message
- **durationDays** (number) - Required - Same duration used in the EIP-712 message
- **extraData** (BytesHex) - Required - Same `extraData` used in the EIP-712 message
- **options** (RelayerUserDecryptOptionsType) - Optional - Request options (e.g., timeout)
### Request Example
(No example provided in source)
### Response
#### Success Response
- **(Implicit)** A record mapping each handle (`0x${string}`) to its decrypted value (`bigint`, `boolean`, or `0x${string}`).
#### Response Example
(No example provided in source)
```
--------------------------------
### Perform Public Decryption via HTTP
Source: https://github.com/zama-ai/relayer-sdk/blob/main/docs/public-decryption.md
Use this snippet to decrypt a list of ciphertext handles using the Relayer's public decrypt endpoint. Ensure the total bit length of ciphertexts does not exceed 2048 bits. The results object contains decrypted clear values and other related data.
```typescript
// A list of ciphertexts handles to decrypt
const handles = [
'0x830a61b343d2f3de67ec59cb18961fd086085c1c73ff0000000000aa36a70000',
'0x98ee526413903d4613feedb9c8fa44fe3f4ed0dd00ff0000000000aa36a70400',
'0xb837a645c9672e7588d49c5c43f4759a63447ea581ff0000000000aa36a70700',
];
// The list of decrypted values
// results = {
// clearValues: {
// '0x830a61b343d2f3de67ec59cb18961fd086085c1c73ff0000000000aa36a70000': true,
// '0x98ee526413903d4613feedb9c8fa44fe3f4ed0dd00ff0000000000aa36a70400': 242n,
// '0xb837a645c9672e7588d49c5c43f4759a63447ea581ff0000000000aa36a70700': '0xfC4382C084fCA3f4fB07c3BCDA906C01797595a8'
// }
// abiEncodedClearValues: '0x.....'
// decryptionProof: '0x.....'
// }
const results: PublicDecryptResults = instance.publicDecrypt(handles);
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.