title: Circom Guide
In this guide we'll talk about how to run Circom (Groth16) Circuits on your iOS/Android devices.
We won't go in details about how to [setup and build your Circom Circuits](/tutorials/circom) or how to [make an Expo App](https://docs.expo.dev/tutorials/create-your-first-app/).
Quickstart
Prepping the Project
Let's get started with a blank expo project, you can also use any existing expo app, adding zk-proofs requires only a couple of lines really.
```bash
bun create expo --template blank-typescript
```
and then add our expo module and relevant libs.
```bash
bunx expo install zk-expo expo-asset
```
We already have some sample files ready for you that you'll need to get your circuits running, create a directory /public in the project root and put these files in it.
[circuit\_wasm.wasm](/)
[circuit\_zkey.zkey](/)
[circuit\_graph.graph](/)
Next, create a file in the root called metro.config.js so that expo can pick up the wasm, zkey & graph extensions.
```js title="metro.config.js"
const { getDefaultConfig } = require("expo/metro-config");
const path = require("path");
const config = getDefaultConfig(__dirname);
config.resolver.assetExts = ["wasm", "zkey", "graph"];
module.exports = config;
```
Running the circuits
```tsx {2-3,7-9} title="App.tsx"
import { StyleSheet, Button, View } from 'react-native';
import { useAssets } from "expo-asset";
import * as ZkExpo from "zk-expo";
export default function App() {
const [assets, error] = useAssets([
require("./public/loginProof_wasm.wasm"),
require("./public/loginProof_zkey.zkey"),
]);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
```
Make the Proof
```tsx {11-31, 35} title="App.tsx"
import { useAssets } from "expo-asset";
import * as ZkExpo from "zk-expo";
export default function App() {
const [assets, error] = useAssets([
require("./public/circuit_wasm.wasm"),
require("./public/circuit_zkey.zkey")
]);
async function make() {
let inputs = {
secret: "1362766633228928585266883205500641602962979188179006392651332184307221268928",
message: "246923712567881323126559150739123310486883838966133236273155052809857112023",
scope: "187035976211163640032000461805755068405187575174480755232212391996596767257",
};
if (assets) {
let proof = await ZkExpo.groth16Prove(
assets[0].localUri as string,
assets[1].localUri as string,
JSON.stringify(inputs),
);
console.log({proof})
} else {
alert("Assets not loaded");
}
}
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
```
Voila 🥳 You just made a proof.
Make the Proof (Advanced)
```tsx title="App.tsx"
import { useAssets } from "expo-asset";
import * as ZkExpo from "zk-expo";
export default function App() {
const [assets, error] = useAssets([
require("./public/circuit_graph.graph"),
require("./public/circuit_zkey.zkey")
]);
async function make() {
let inputs = {
secret:
"1362766633228928585266883205500641602962979188179006392651332184307221268928",
message:
"246923712567881323126559150739123310486883838966133236273155052809857112023",
scope:
"187035976211163640032000461805755068405187575174480755232212391996596767257",
};
if (assets) {
let proof = await ZkExpo.groth16ProveV2(
assets[0].localUri as string,
assets[1].localUri as string,
JSON.stringify(inputs),
);
console.log({proof})
} else {
alert("Assets not loaded");
}
}
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
```
Voila 🥳 You just made a super-fast proof.
On-chain Verification
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
API Reference
ZkExpo.groth16Prove
```ts
async function groth16Prove(
wasm_path: string, // Local path to the wasm file.
zkey_path: string, // Local path to the zkey file.
inputs: string, // These are your JSON.stringified dictionary of inputs.
): Promise<{ proof: any; publicSignals: any }>
```
ZkExpo.groth16ProveV2
```ts
async function groth16Prove(
graph_path: string, // Local path to the graph file.
zkey_path: string, // Local path to the zkey file.
inputs: string, // These are your JSON.stringified dictionary of inputs.
): Promise<{ proof: any; publicSignals: any }>
```
Some Gotchas
Make sure to update your dependencies, also use npx expo install --fix.
Use Development Client Builds, this won't work on Expo Go as it requires native code.
If your app crashes while testing groth16Prove on a real iOS device, run the app using bun expo prebuild and XCode. iOS has some wierd quirks while running Wasm runtimes, this should be fine in the production versions of your app. You can also use groth16ProveV2 which doesn't need the wasm runtime and is faster.
iOS has memory restrictions of around 2-3GB imposed on each app. If your circuits are really large you might run into issues, consider splitting the circuits or using groth16ProveV2 to optimize your circuits.
If your iOS app runs into any linking issues on developement when using eas build, do an bun expo prebuild and open the ios folder in XCode. XCode GUI uses certain Apple internals that perform better than eas builds that use xcodebuild under the hood.
---
title: Halo2 Guide
In this guide we'll talk about how to run Halo2 (PLONK) Circuits on your iOS/Android devices.
We won't go in details about how to [setup and build your Halo2 Circuits](/tutorials/halo2) or how to [make an Expo App](https://docs.expo.dev/tutorials/create-your-first-app/).
Quickstart
Prepping the Project
Let's get started with a blank expo project, you can also use any existing expo app, adding zk-proofs requires only a couple of lines really.
```bash
bun create expo --template blank-typescript
```
and then add our expo module and relevant libs.
```bash
bunx expo install zk-expo expo-asset
```
We won't go in details about how to setup and build your Halo2 Circuits or how to make an Expo App. You can find a tutorial on that here and here.
We already have some sample files ready for you that you'll need to get your circuits running, create a directory /public in the project root and put these files in it.
[halo2circuit.wasm](/)
Next, create a file in the root called metro.config.js so that expo can pick up the wasm extension.
```js {6} title="metro.config.js"
const { getDefaultConfig } = require("expo/metro-config");
const path = require("path");
const config = getDefaultConfig(__dirname);
config.resolver.assetExts = ["wasm"];
module.exports = config;
```
Running the circuits
Load the Assets
```tsx {1-2,6-8} title="App.tsx"
import { useAssets } from "expo-asset";
import * as ZkExpo from "zk-expo";
export default function App() {
const [assets, error] = useAssets([
require("./public/halo2circuit.wasm"),
]);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
```
Make the Proof
```tsx {10-29, 33} title="App.tsx"
import { useAssets } from "expo-asset";
import * as ZkExpo from "zk-expo";
export default function App() {
const [assets, error] = useAssets([
require("./public/halo2circuit.wasm"),
]);
async function make() {
let inputs = {
secret: "1362766633228928585266883205500641602962979188179006392651332184307221268928",
message: "246923712567881323126559150739123310486883838966133236273155052809857112023",
scope: "187035976211163640032000461805755068405187575174480755232212391996596767257",
};
if (assets) {
let proof = await ZkExpo.halo2Prove(
assets[0].localUri as string,
[1, 1, 55],
);
console.log({proof})
} else {
alert("Assets not loaded");
}
}
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
```
Voila 🥳 You just made a Halo2 proof.
On-chain Verification
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
API Reference
ZkExpo.halo2Prove
```ts
async function halo2Prove(
wasmPath: string, // Local path to the wasm file.
publicInputs: number[], // An array of numerical inputs to the circuit.
): Promise // Returns the proof in hexadecimal.
```
Some Gotchas
Make sure to update your dependencies, also use npx expo install --fix.
Running Halo2 circuits in a WASM runtime using zk-expo requires some simple C glue, read about this in the Halo2 tutorial here.
We are following the [PSE's fork](https://github.com/privacy-scaling-explorations/halo2) of Halo2 v3 which has excellent support for on-chain proof verification.
Use Development Client Builds, this won't work on Expo Go as it requires native code.
iOS has memory restrictions of around 2-3GB imposed on each app. If your circuits are really large you might run into issues, consider splitting the circuits.
If your iOS app runs into any linking issues on developement when using eas build, do an bun expo prebuild and open the ios folder in XCode. XCode GUI uses certain Apple internals that perform better than eas builds that use xcodebuild under the hood.
---
title: Noir Guide
In this guide we'll talk about how to run Noir (PLONK & HONK, UltraHonk\[soon]) Circuits on your iOS/Android devices. We won't go in details about how to [setup and build your Noir Circuits](/tutorials/noir) or how to [make an Expo App](https://docs.expo.dev/tutorials/create-your-first-app/).
Quickstart
Prepping the Project
Let's get started with a blank expo project, you can also use any existing expo app, adding zk-proofs requires only a couple of lines really.
```bash
bun create expo --template blank-typescript
```
and then add our expo module and relevant libs.
```bash
bunx expo install zk-expo expo-file-system @react-native-async-storage/async-storage
```
We already have some sample files ready for you that you'll need to get your circuits running.
[srs.dat](https://cdn.omnid.io/share/Dc_OClY0)
Bytecode
```js
H4sIAAAAAAAA/7VUSQ7DIAyEhKa99ic2SzC3fqWo5P8vqBopUCHCLWYkZIQlMx4vUhxQ+7mJM+ZsX9kaWK1NXic0+AYdIjmwLq6EhI7cR5MxiSz5EIOHgNYk3FwwGxyoY8E1oGTkNfHxgqKj7OgpGz3hGpCTt2zqfuLPRXqUEPOAuIq5+UfkrfhrBGJg0yrB27Sq4Vnfe0P4f7xnu3R8BY/9TPn+ZRa4bNd685a/VOVfKi6SnwvW+fYm/9nR5wcPIDK6OgYAAA==
```
Next, create a file in the root called metro.config.js so that expo can pick up the dat extension.
```js title="metro.config.js"
const { getDefaultConfig } = require("expo/metro-config");
const path = require("path");
const config = getDefaultConfig(__dirname);
config.resolver.assetExts = ["dat"];
module.exports = config;
```
Running the circuits
Setup SRS
SRS (Structured Reference String) is a large file (~300MB). We need this for making our circuits work. This file can be downloaded once and stored locally for future use.
```tsx title="App.tsx"
import { useEffect, useState } from "react";
import { View, Button, Text } from "react-native";
import * as FileSystem from "expo-file-system";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as ZkExpo from "zk-expo";
const FILE_URL = "https://cdn.omnid.io/api/public/dl/Dc_OClY0";
const FILE_NAME = "srs.dat";
const STORAGE_KEY = "srsFileUri";
const BYTECODE =
"H4sIAAAAAAAA/7VUSQ7DIAyEhKa99ic2SzC3fqWo5P8vqBopUCHCLWYkZIQlMx4vUhxQ+7mJM+ZsX9kaWK1NXic0+AYdIjmwLq6EhI7cR5MxiSz5EIOHgNYk3FwwGxyoY8E1oGTkNfHxgqKj7OgpGz3hGpCTt2zqfuLPRXqUEPOAuIq5+UfkrfhrBGJg0yrB27Sq4Vnfe0P4f7xnu3R8BY/9TPn+ZRa4bNd685a/VOVfKi6SnwvW+fYm/9nR5wcPIDK6OgYAAA==";
export const NoirSection = () => {
const [fileUri, setFileUri] = useState(null);
const [isDownloading, setIsDownloading] = useState(false);
useEffect(() => {
const loadFileUri = async () => {
try {
const savedUri = await AsyncStorage.getItem(STORAGE_KEY);
if (savedUri) {
setFileUri(savedUri);
}
} catch (error) {
console.error("Failed to load the file URI from storage", error);
}
};
loadFileUri();
}, []);
const downloadFile = async () => {
setIsDownloading(true);
try {
// Check if the file is already downloaded
const savedUri = await AsyncStorage.getItem(STORAGE_KEY);
if (savedUri) {
console.log("File already downloaded:", savedUri);
setFileUri(savedUri);
return;
}
// Define the path to save the file
const fileUri = `${FileSystem.documentDirectory}${FILE_NAME}`;
// Start downloading the file
const downloadResumable = FileSystem.createDownloadResumable(
FILE_URL,
fileUri,
{},
(downloadProgress) => {},
);
let downloadSnapshot = await downloadResumable.downloadAsync();
if (downloadSnapshot) {
const { uri } = downloadSnapshot;
console.log("Finished downloading to:", uri);
// Save the file URI for future use
await AsyncStorage.setItem(STORAGE_KEY, uri);
setFileUri(uri);
} else {
alert("Download Failed.");
}
} catch (error) {
console.error("Error downloading file:", error);
} finally {
setIsDownloading(false);
}
};
async function setupSrs() {
if (fileUri) {
await ZkExpo.noirSetupSrs(fileUri, BYTECODE);
}
}
return (
{fileUri ? (
File is downloaded and saved at: {fileUri}
) : (
)}
);
};
```
You should now be able to download and cache the SRS file locally.
You should now be able to click "Setup Noir SRS" and setup the srs.
noirSetupSrs only needs to be called once throughout your app, you can do this in the background when you app opens.
Make the Proof
```tsx title="App.tsx"
export const NoirSection = () => {
const [fileUri, setFileUri] = useState(null);
const [isDownloading, setIsDownloading] = useState(false);
// useEffect, downloadFile, setupSrs functions
async function makeNoirProof(type: 'plonk'|'honk') {
let { success, proof, vk } = await ZkExpo.noirProve(
"17",
BYTECODE,
["0x2", "0x2"],
type,
);
}
return (
{fileUri ? (
File is downloaded and saved at: {fileUri}
) : (
)}
);
};
```
Voila 🥳 You just made a Noir proof.
On-chain Verification
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
API Reference
ZkExpo.noirSetupSrs
```ts
async function noirSetupSrs(
srsPath: string, // Local path of the SRS file.
bytecode: string, // Bytecode in base64.
): Promise<{ size: string }> // Returns the Size of the SRS file.
```
ZkExpo.noirProve
```ts
async function noirProve(
srsSize: string, // Size of the SRS file.
bytecode: string, // Bytecode in base64.
witness: string[], // Inputs in hex.
proofType: "plonk" | "honk" = "plonk",
): Promise<{ success: true; proof: string; vk: string } | { success: false }>
```
Some Gotchas
Make sure to update your dependencies, also use npx expo install --fix.
Use Development Client Builds, this won't work on Expo Go as it requires native code.
When using Development Client for testing, if you do bunx expo run ios and push an updated build of your app, AsyncStorage will remember your cached file but iOS would've removed it. In this case, clear your srs file from AsyncStorage and download it again. This is only for development versions of your app, updates on prod will be fine.
If your iOS app runs into any linking issues on developement when using eas build, do an bun expo prebuild and open the ios folder in XCode. XCode GUI uses certain Apple internals that perform better than eas builds that use xcodebuild under the hood.
More Reading
Noir Lang Documentation - https://noir-lang.org/docs
---
title: Get Started
Choose your Adventure
---
title: Console
icon: MonitorDot
https://console.omnid.io/
---
title: Deployments
icon: BookTextIcon
Contracts
Optimism Sepolia
Chain ID: 11155420
Explorer: https://sepolia-optimism.etherscan.io/
| Contract Name | Address |
|------------------------|--------------------------------------------|
| GroupManager | 0xe580A1006F0d80f9F824D64D800e000500000506 |
| OauthJwkRegistry | 0x803159FeC9d3F43c0aC9e2dE9AD1E50F6e107312 |
| MetadataExtension | 0xaD46E0966800A30e4240Df0A68BcA069990C9026 |
| AadhaarVerifier | 0x0eb62e169A48E4F31D6849a4FA5fD518794bdB7B |
| EddsaMimcVerifier | 0xC6901646Bd3223A84c01a4f0c176F95A61A0A0D4 |
| EddsaPoseidonVerifier | 0x75D173A389a58Af8AFa3294441279Aa55F296bF4 |
| InsidePolygon5Verifier | 0x1ad1B254D9D2f3FDA3B953cac0c6bD5e1F5Cc435 |
| Jwt512Verifier | 0x19d9d824aA245e6Ce807C60547aE3D56EcA3Fd0f |
| Jwt1024Verifier | 0xf4f66030F14B02944A415E0c685b4AD3F4d3c23B |
| MerkleVerifier | 0x3Ddfc7a84dEb0Ca8Bf3ddFf53e4B879a6eA90AF0 |
| Oauth512Verifier | 0x7470feDdFef0f9932eA51b67a30Faf56e2022bB9 |
| OwnershipVerifier | 0xd6A3754CEE259A58e50f6CED2c829d28F6a00Ac1 |
| RsaVerifier | 0x7646D9443B53a71E11DA34870f6945D079b4f73D |
| Sha256Verifier | 0xb66533021377aBF57C03FEc9ac0e162e4FcEBC0B |
| FCL\_ecdsaAddress | 0x84AB5FA40f99141092489E97334bA3aE95Ce0128 |
| VerifySignature10 | 0x146280EF117e342D32C6c411e749E096a74b7246 |
| LoginVerifier | 0x5F4779eA1364fBaa8d1f372aBf93890cdFcc0EE7 |
| LoginApp | 0x2685524fcB602beda731267B4A413Dcb5c79eC47 |
---
title: Explorer
icon: TelescopeIcon
https://explorer.omnid.io/
---
title: Subgraph - GraphQL API
icon: SearchIcon
Optimism Sepolia
Deployed to https://thegraph.com/studio/subgraph/omnid-testnet
Subgraph endpoints:
Queries (HTTP): https://api.studio.thegraph.com/query/1649/omnid-testnet/version/latest
Playground
---
title: Transaction Relay
icon: Forward
import Balance from '../../components/Balance'
Omnid's Transaction Relay, relays Login and Membership proofs on-chain for a gasless user experience.
It focuses on transction privacy by dropping any Privately Identifiable Information like origin IP etc, uses private Mempools and super-fast transaction inclusion.
Relay Details
Optimism Sepolia
Wallet : [0xBded25d1C7B2aD66127a428403B7a1d00Ec88c48](https://sepolia-optimism.etherscan.io/address/0xBded25d1C7B2aD66127a428403B7a1d00Ec88c48)
Balance :
Arbitrum Sepolia
Wallet : [0xBded25d1C7B2aD66127a428403B7a1d00Ec88c48](https://sepolia.arbiscan.io/address/0xBded25d1C7B2aD66127a428403B7a1d00Ec88c48)
Balance :
API Integration
Send a POST request to https://alchemy.omnid.io/relay/login
Example Body,
```json
{
"proof": [
"16542621509410053127180387595858590984069811549341034937997775421926834748020",
"20702256844640518841411526839603115720618751986459966057588068773690912905714",
"21811687962243789867810552422514798867905366303789368233601883705941622297142",
"7768624353157223849366228342281427754848881229957073051831197309450597677814",
"12180626064816181864527099324259146365047484523276645341551866903820338222938",
"19296035482436430695655967539447488884387331622027256005181332896174520709126",
"9270672781696211451602553041916807236621435485560976127236250211460439091332",
"13971011189193993844603405040627665795133383452032176546235959148967822825566"
],
"publicSignals": [
"20863566422097840723875850637863141710309762677874301494587303648930032009190",
"11988898704341589615651194483646701367638832472705883623925289677484196905814",
"21314750377587299243560398691338153649122129395319388938814883722875975462",
"187035976211163640032000461805755068405187575174480755232212391996596767257"
]
}
```
[SDK Integration](/nodejs#relayproof)
---
title: NodeJS
icon: Nodejs
Installation
\
sh
bun i @omnid/sdk
sh
pnpm i --save @omnid/sdk
sh
yarn add @omnid/sdk
sh
npm i --save @omnid/sdk
This SDK is compatible for the Web, Server & React-Native based environments.
Here is a tutorial on Intergating this on the [Web](/tutorials/web).
You can set it up using,
```ts
import { Omnid } from "@omnid/sdk";
let omnid = new Omnid();
```
Authentication
relayLoginProof
Example,
```tsx
let relayResponse = await omnid.auth.relayLoginProof(
[
proof.a[0],
proof.a[1],
proof.b[0][1],
proof.b[0][0],
proof.b[1][1],
proof.b[1][0],
proof.c[0],
proof.c[1],
],
publicSignals
);
```
Reference,
```tsx
relayLoginProof = async (
proof: Array,
publicSignals: Array,
relayEndpoint: string = "https://alchemy.omnid.io/relay/login",
): Promise
```
exchangeForJwt
Example,
```tsx
let body = await req.json() as Omit;
let omnid = new Omnid();
const respData = await omnid.auth.exchangeForJwt({
...body,
appSecretKey: process.env['OMNID_SIGNIN_SECRET_KEY'] as string
});
```
Reference,
```tsx
exchangeForJwt = async (
details: TokenExchangeRequest,
vaultEndpoint: string = "https://vault.omnid.io",
): Promise
```
Function Cloud
Function Cloud hosts large circuit assets and has a fast proof execution environment supporting multiple backends.
[Learn more about it](/protocol/function-cloud)
getCircuitFiles
Example,
```tsx
const sig = omnid.fc.getCircuitFiles('VerifySignature10');
const { downloaded, downloadProgress, makeProof } = useProof(sig);
```
Reference,
```tsx
getCircuitFiles = (
proofId: supportedProofIds,
cdn = ''
): circuitFileDetails
```
makeProof
Example,
```tsx
const { proof, publicSignals } = await makeProof('rsa', []);
```
Reference,
```tsx
makeProof = async (
proofId: supportedProofIds,
inputs: CircuitSignals,
node: string = `https://fc.omnid.io`
): Promise
```
relayProof
Example,
```tsx
const res = await relayProof('11', []);
```
Reference,
```tsx
relayProof = async (
groupId: number,
proofData: ProofData,
relayEndpoint: string = "https://alchemy.omnid.io/relay/login",
): Promise
```
portalProof
Excute proofs on one chain and have them portalled to another.
Group Templates
These let you quickly get the addresses holding any token, NFT, Attestation, DAO etc.
fromToken
Example,
```tsx
let data = await fromToken('0x00', 'eth', 'APIKEY');
```
Reference,
```tsx
fromToken = async (
token: string,
chainName: string,
COVALENT_APIKEY: string
): Promise>
```
fromSnapshot
Example,
```tsx
let data = await fromSnapshot(
'aave.eth',
'0xe03ecf69d92f04d39d1385ccc87d8782347471a7305897e85b3d5d04f26a522d',
);
```
Reference,
```tsx
fromSnapshot = async (
space: string,
proposal: string | null = null,
first: number = 1000,
skip: number = 0
): Promise
```
fromEas
Example,
```tsx
let data = await fromEas(
'0xe03ecf69d92f04d39d1385ccc87d8782347471a7305897e85b3d5d04f26a522d',
'0x385ccc87d8782347471a7305897e85b3d5d04f26a522'
1
);
```
Reference,
```tsx
fromEas = async (
schemaId: string,
attestor: string,
chainId: 1 | 10 | 8453 | 42161 | 59144 | 11155111 | 11155420 | 534351
): Promise
```
Query
getGroupIds
Example,
```tsx
let ids = await getGroupIds();
```
Reference,
```tsx
async getGroupIds(): Promise
```
getGroups
Example,
```tsx
let groups = await getGroups();
```
Reference,
```tsx
async getGroups(options: {
members?: boolean;
validatedProofs?: boolean;
filters?: {
admin?: string;
identityCommitment?: string;
timestamp?: Date;
timestampGte?: Date;
timestampLte?: Date;
};
}): Promise<{
id: string;
merkleTree: {
root: string;
depth: number;
size: number;
};
admin?: string;
members?: Array<{
id: number;
timestamp: number;
identityCommitment: number;
index: number;
}>;
validatedProofs?: {
message: string;
merkleTreeRoot: string;
merkleTreeDepth: number;
scope: string;
nullifier: string;
points: string[];
timestamp?: string;
}[];
}[]>
```
getGroup
Example,
```tsx
let group = await getGroup(1);
```
Reference,
```tsx
async getGroup(groupId: string, options: Omit = {}): Promise
```
isGroupMember
Example,
```tsx
let res = await isGroupMember(1, 'commitment');
```
Reference,
```tsx
async isGroupMember(groupId: string, member: string): Promise
```
SimpleMerkleTree
A utility class for you to quickly make merkle proofs.
makeTree
Reference,
```tsx
makeTree(hashedValues: Array) {}
```
getProof
Reference,
```tsx
getProof(leafHash: bigint): {
found: boolean;
path: bigint[];
pathInd: number[];
}: { found: true, path, pathInd }
```
getCalldata
Reference,
```tsx
getCalldata(proof: {
path: bigint[];
pathInd: number[];
}, leafHash: bigint) {
return JSON.stringify({
leaf: this.bigint2hex(leafHash),
path_elements: proof.path.map(this.bigint2hex),
path_indices: proof.pathInd
})
}
```
getRootHash
```tsx
let root = getRootHash()
```
Vault
Internals about [Vault](/protocol/vault)
Stealth Addresses
---
title: Alchemy AI
icon: Brain
Alchemy is a Model-Embedding pair with memory, fine-tuned on understanding and connecting humans. Optimized for subsecond response speeds.
Model: https://huggingface.co/anudit/finetuned-alchemy
Embedding: https://huggingface.co/anudit/finetuned-gte-base
https://alchemy.omnid.io
---
title: Authentication
icon: FingerprintIcon
Introduction
Online
Offline
Types of Authentication
Public Profile public
This allows you get the public profile of user like their Ethereum Address, Humaness Metrics etc. Compatible with [SIWE](https://login.xyz/) Standard.
ZK Attributes private
This allows you get the ZK Commitment of user to access the various attributes of their persona.
Additional Data data
You can request specific data items linked to the user from the vault only if the user permits.
---
title: Connections
icon: Handshake
What purpose do IRL connections serve
Social Recovery
Real World Trust Graphs
People Discovery
---
title: Cross Chain Messaging
icon: Send
Introduction
Manage Groups and Prove from any Chain.
Interface
Call the following functions on the forwarder contract to pass messages to the base chain GroupManager Contract.
```solidity filename="IForwarder.sol"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IForwarder {
// Directly verify proofs on the base chain.
function verifyProof(
uint256 groupId,
uint256 merkleTreeRoot,
uint256 signal,
uint256 nullifierHash,
uint256 externalNullifier,
uint256[8] calldata proof
) external;
// Directly send `abi.encodeWithSelector` messages to the GroupManager Contract.
function _sendInternal(
bytes memory __selectorEncodedPayload
) external;
}
```
Integration
```solidity filename="OmnidDemo.sol"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import './IForwarder.sol';
contract OmnidDemo {
IForwarder forwarder;
constructor (address _forwarderAddress) {
forwarder = IForwarder(_forwarderAddress);
}
function verifyProof(
uint256 groupId,
uint256 merkleTreeRoot,
uint256 signal,
uint256 nullifierHash,
uint256 externalNullifier,
uint256[8] calldata proof
) public {
forwarder.verifyProof(
groupId,
merkleTreeRoot,
signal,
nullifierHash,
externalNullifier,
proof
);
}
}
```
---
title: Encryption
icon: Lock
import Diagram from "./../../components/Diagram";
Introduction
Multi-hop Proxy Re-encryption, also known as Transform Encryption,
is a cryptographic technique that allows data encrypted with my public key, to be transformed in a way,
so that it can be decrypted using your private key, without revealing either of our private keys.
This transformation relies on a special key calculated from my private key and your public key.
More Reading
https://github.com/ironcorelabs/recrypt-rs
https://blog.nucypher.com/unveiling-umbral
https://github.com/yjjnls/recrypt-js
@omnid/pre
A proxy re-encryption implementation using the secp256k1 curve.
Installation
\
```````
```sh
bun i @omnid/pre
``````sh
pnpm i --save @omnid/pre
``````sh
yarn add @omnid/pre
``````sh
npm i --save @omnid/pre
```
```````
Post-Quantum Security
Imagine a lattice as a grid of dots, like a pattern of dots on graph paper. This grid is made up of points that are arranged in a repeating pattern. Now, this might seem pretty basic, but these simple grids are the foundation for solving really tough math problems aka [NP Hard Problems](/tutorials/glossary#np-hard-problems).
Why do we care about these grids? Well, in the world of cryptography, there's a big concern about the future.
You see, someday, powerful quantum computers will break many of the encryption methods we currently use.
That would be a problem because it could make our online communication less secure.
So, post-quantum cryptography is all about finding new ways to protect our data from quantum computer attacks.
And one of the most promising approaches involves these lattice-based grids.
Let's dive a bit deeper. A lattice is generated by two vectors (or arrows) that start from a central point (the origin). You can think of these vectors like directions or instructions. By stacking these vectors together, we can create paths that reach different points on the lattice. The lattice is basically all the points we can reach by following these "vector paths."
Now, here's the cool part: you can have different sets of vectors that generate the same lattice. Even though the instructions might look very different, they lead to the same destination. It's like having two different ways to get to the same place on a map.
One challenging problem related to these lattices is called the "shortest vector problem." It's all about finding the lattice point that's closest to the origin (0,0) without including the point at the origin itself. This problem is quite tricky, especially as you increase the number of dimensions in the lattice.
Speaking of dimensions, you can have lattices in more than just two dimensions. For example, you can have three-dimensional lattices, four-dimensional ones, and so on. As you add dimensions, the math becomes even more complicated.
Now, these lattice problems, including the shortest vector problem, are considered hard for regular computers to solve. And the good news is that they're also believed to be hard for quantum computers. That's why they're attractive for post-quantum cryptography.
One cryptographic idea involving lattices is called the GGH encryption scheme. In this scheme, you have a "good basis" and a "bad basis" for the same lattice. The good basis is kept secret, while the bad basis is public. When you want to send a secret message, you use the good basis to encrypt it, making it easy for the intended recipient to decrypt. But for someone trying to eavesdrop, only knowing the bad basis makes it incredibly difficult to crack the encryption.
However, GGH encryption has some flaws, so researchers are exploring other lattice-based cryptographic schemes. Some of these schemes use a problem called "learning with errors" to provide strong security against both classical and quantum attacks.
National Institute of Standards and Technology (NIST) has finalised CRYSTALS-Kyber, whose security is based on the hardness of solving the learning-with-errors (LWE) problem over lattices.
In Kyber, there are two main parts: one for creating keys and one for actually encrypting and decrypting messages. These keys are generated by both parties who want to communicate securely in a world with strong quantum computers.
More Reading
https://www.youtube.com/watch?v=QDdOoYdb748
https://www.nist.gov/news-events/news/2023/08/nist-standardize-encryption-algorithms-can-resist-attack-quantum-computers
---
title: Function Cloud
icon: Zap
full: true
\_openapi:
method: POST
route: /makeproof/loginProof
toc: \[]
structuredData:
headings: \[]
contents:
\- content: Submits encoded login proof details to validate user credentials.
Function Cloud is a fast proof execution environment supporting multiple backends. This is particularly useful for edge/IoT devices with limited computing capabilities and proof aggregation which requires large computing capabilities.
FC supports the following proving backends,
Circom
Halo2
Noir
Plonky3
Risc0
SP1
Binus
https://fc.omnid.io
groth16 Demo
\
noir Demo
\
---
title: Overview
import { EyeOff, Fingerprint, Send, Lock, Vault, Handshake, BrickWall, Brain, Zap } from 'lucide-react';
\
Learn how Omnid leverages ZK Proofs for anonymous coordination.
\
Learn how Omnid handles user authentication.
\
Learn how Omnid operates on & communicates using multiple chains.
\
Learn how Omnid securely shares encrypted data.
\
Learn how the Vault handles storage and sharing of Encrypted Information.
\
Learn how Omnid secures and preserves privacy at the transaction layer.
\
Learn how the we accelerate ZK Proofs for low power devices.
\
Learn how Omnid facilitates real world trust graphs using Connections.
\
Learn how Alchemy helps you to understand you and others.
---
title: Proxy RPC
icon: BrickWall
Introduction
Omnid's [RPC](/tutorials/glossary#rpc) is an [open-source](https://github.com/anudit/omnid-rpc-proxy), self-hostable RPC Proxy that scans the transactions before sending them to the chain for malicious/phishing activity using Omnid, static analysis, transaction simulation, various vulnerability detectors & anonymizing request using various RPCs, Light Clients & TOR Relays including DDoS protection. If malicious activity is detected, the transaction is rejected well before it ever sees the chain.
Supported Networks
Ethereum
| Network | RPC | ChainId |
|:---|:---|:---:|
| Mainnet | https://rpc.omnid.io/mainnet | 1 0x1 |
| Goerli Testnet | https://rpc.omnid.io/goerli | 5 0x5 |
| Sepolia Testnet | https://rpc.omnid.io/sepolia | 11155111 0xAA36A7 |
Flashbots
| Network | RPC | ChainId |
|:---|:---|:---:|
| Ethereum Mainnet | https://rpc.omnid.io/mainnet-flashbots | 1 0x1 |
| Ethereum Mainnet (Fast Mode) | https://rpc.omnid.io/mainnet-flashbots-fast | 1 0x1 |
| Ethereum Goerli | https://rpc.omnid.io/goerli-flashbots | 5 0x5 |
Polygon
| Network | RPC | ChainId |
|:---|:---|:---:|
| Mainnet | https://rpc.omnid.io/polygon | 137 0x89 |
| Mumbai Testnet | https://rpc.omnid.io/polygon-testnet | 80001 0x13881 |
| ZkEVM Mainnet | https://rpc.omnid.io/polygon-zkevm | 1101 0x44d |
| Mumbai Testnet | https://rpc.omnid.io/polygon-zkevm-testnet | 1442 0x5a2 |
Optimism
| Network | RPC | ChainId |
|:---|:---|:---:|
| Mainnet | https://rpc.omnid.io/optimism | 10 0xA |
| Goerli Testnet | https://rpc.omnid.io/optimism-testnet | 420 0x1A4 |
Arbitrum
| Network | RPC | ChainId |
|:---|:---|:---:|
| Mainnet (Arbitrum One) | https://rpc.omnid.io/arbitrum | 42161 0xA4B1 |
| Mainnet (Arbitrum Nova) | https://rpc.omnid.io/arbitrum-nova | 42170 0xA4BA |
| Goerli Testnet | https://rpc.omnid.io/arbitrum-testnet | 421613 0x66EED |
| Sepolia Testnet | https://rpc.omnid.io/arbitrum-sepolia-testnet | 421614 0x66eee |
BNBChain
Fantom
Base
Advanced
| Network | RPC | ChainId |
|:---|:---:|:---:|
| manual | https://rpc.omnid.io/manual?rpcUrl=https://polygon-rpc.com | auto |
🦺 LifeJackets
LifeJackets are customised security layers that can help setup additional layers of protection.
Query Params
| Param | Description | Example |
|:---:|:---:|:---:|
| blockUnverifiedContracts | Block Transactions to Un-Verified Contracts. Powered by [Sourcify.dev](https://sourcify.dev). Suported values: true, false. | https://rpc.omnid.io/ethereum?blockUnverifiedContracts=true |
| enableScanners | Run verified contracts through Slither for vulnerability analysis. Suported values: slither. | https://rpc.omnid.io/polygon-testnet?enableScanners=slither |
| blockRecentDnsUpdates | Checks the DNS records for a domain to see when it was last updated ([Only RFC 1912 Compliant Domains](https://www.ripe.net/publications/docs/ripe-203)). Blocks recently modified domains to prevent [DNS poisioning atttacks](https://cointelegraph.com/news/breaking-curve-finance-team-warns-users-to-avoid-using-site-until-further-notice). Supported Values: number set in Days. | https://rpc.omnid.io/ethereum?blockRecentDnsUpdates=2 |
| useTor | Broadcast Transactions over a Tor Proxy. Supported Values: true or false | https://rpc.omnid.io/mainnet?useTor=true |
| useGasHawk | Use GasHawk Beta. (Requires Setup). Only for mainnet. Supported Values: true or false | https://rpc.omnid.io/mainnet?useGasHawk=true |
Relevant links
Source Code : [GitHub](https://github.com/anudit/omnid-proxy-rpc)
[Website](https://rpc.omnid.io)
---
title: Vault
icon: Vault
https://vault.omnid.io
Introduction
The Vault is a [libp2p](https://docs.ipfs.tech/concepts/libp2p/) powered Node that securely handles longer term encrypted storage and communication for Omnid users.
Communication
Notification
Storage
---
title: ZK Proofs
icon: EyeOffIcon2
Semaphore Overview
Imagine you want to be part of a secret club, but you don't want anyone to know you're a member. Semaphore helps you do this. Here's how it works:
You create a secret code that only you know, kind of like a secret handshake.
You also have another secret code that only you know.
These two secret codes are combined to make a special ID for you, like a secret membership card.
Your secret ID is added to a special tree ([Merkle Tree](/tutorials/glossary#merkle-tree)) that keeps track of all the club members. This tree is like a list of all the members in the club.
Now, whenever you want to prove that you're a member of the club without revealing who you are, you use Semaphore's magic process.
You give Semaphore your two secret codes, and it does some math magic to prove that your secret ID is in the list of members.
You can then show this proof to the club to prove you're a member, without telling them your real identity.
So, Semaphore helps you be part of a secret group without showing your true identity.
Technical Details
GroupManager is an Implementation of the
More Reading & References
https://semaphore.pse.dev/docs/resources
https://blog.aayushg.com/posts/zk/
https://0xparc.org/blog
---
title: ReactJS
icon: React
Installation
\
```````
```sh
bun i @omnid/react
``````sh
pnpm i --save @omnid/react
``````sh
yarn add @omnid/react
``````sh
npm i --save @omnid/react
```
```````
This SDK is only for the Web, React-Native based users should use [zk-expo](/expo/circom) instead.
Here is a tutorial on Intergating this on the [Web](/tutorials/web).
Making Proofs
useProof Hook
Example,
```tsx
import { useProof } from '@omnid/react';
const rsa = {
wasmUrl: 'https://proxy.anudit.workers.dev/corsproxy?apiurl=https://cdn.omnid.io/api/public/dl/fKe9TQJo/rsa.wasm',
zkeyUrl: 'https://proxy.anudit.workers.dev/corsproxy?apiurl=https://cdn.omnid.io/api/public/dl/fKe9TQJo/rsa_gzip.zkey'
};
const { downloaded, downloadProgress, makeProof } = useProof(rsa, { gzippedZkey: true });
const { proof, publicSignals, calldata, timeTaken } = await makeProof(input);
```
Reference,
```tsx
const useProof = (
circuitFiles: { wasmUrl: string; zkeyUrl: string },
options?: {
differDownload?: boolean;
gzippedZkey?: boolean;
gzippedWasm?: boolean;
disableCache?: boolean;
}
): {
wasmBuffer: Uint8Array | null;
zkeyBuffer: Uint8Array | null;
downloaded: boolean;
downloadProgress: string | null;
download: () => Promise;
computeWitness: (wasm_buffer: Buffer, inputs: CircuitSignals) => Promise;
makeProof: (inputs: CircuitSignals) => Promise<{
proof: Groth16Proof;
publicSignals: PublicSignals;
timeTaken: number;
calldata: any;
}>;
clearCache: () => Promise;
}
```
Managing Localstorage
Usage,
```jsx
import { storeUint8Array, removeUint8Array, retrieveUint8Array } from "@omnid/react";
```
Reference,
storeUint8Array
```tsx
async function storeUint8Array(
key: string,
uint8ArrayData: Uint8Array,
storeName = 'circuit-cache'
): Promise
```
removeUint8Array
```tsx
async function removeUint8Array(
key: string,
storeName = 'circuit-cache'
): Promise
```
retrieveUint8Array
```tsx
async function retrieveUint8Array(
key: string,
storeName = 'circuit-cache'
): Promise
```
Tracking Events
useWebSocket hook
Instead of waiting for the chain to emit the event you can subscribe to the relay for incoming transaction hashes for your channel.
Example,
```tsx
import { useWebSocket, WebSocketMessageHandler } from "@omnid/react";
const handleMessage: WebSocketMessageHandler = (data) => {
alert(data.message, data.channel);
};
useWebSocket("YourZKHash", handleMessage, true, false);
```
Reference,
```tsx
export const useWebSocket = (
channelId: string,
onMessage: WebSocketMessageHandler,
active: boolean = false,
shouldReconnect: boolean = false,
): WebSocket | null
```
Managing Passkeys
```
import { Passkey } from '@omnid/react';
```
create
Reference,
```tsx
```
Usage,
```tsx
const { data: credential, error } = await Passkey.create({
appName: "Bio Demo",
username: "Omnid Devicekey"
});
console.log({ credential })
```
getPublicKeyFromAttestationResponse
Reference,
```tsx
```
Usage,
```
const { data: publicKey } = Passkey.getPublicKeyFromAttestationResponse({
response,
} as { response: AuthenticatorAttestationResponse });
```
importPublicKeyAsCryptoKey
Usage,
```tsx
const publicKeyAsCryptoKey = await Passkey.importPublicKeyAsCryptoKey(
publicKey as ArrayBuffer
);
const exported = await window.crypto.subtle.exportKey(
"jwk",
publicKeyAsCryptoKey as CryptoKey
);
```
importPublicKeyAsCryptoKey
Usage,
```tsx
const { data: assertion, response, error } = await Passkey.auth(Buffer.from(localId.id, 'base64'), challenge);
```
verifySignature
Usage,
```tsx
const verificationData = await Passkey.verifySignature({ publicKey, assertation });
```
---
title: Circom
Install Circom
Direct Binary
You can download the latest release from
https://github.com/iden3/circom/releases
From Source
```bash
git clone https://github.com/iden3/circom
cd circom
cargo install --path . --release
```
Use Playground
You can also build and try out circuits on zkREPL.
https://zkrepl.dev/?gist=168c24e72f4f492d998ab00dee82e21e
Understand your Circuit
Today we will build this simple circuit that creates a zero knowledge proof of knowing the factors of a number without revealing the number.
The circuit takes three inputs, a, b, ab.
a & b are private inputs, ab is a public input.
The circuit has one output, 1 if valid, 0 if invalid.
```c
// Example
a=10, b=11, ab=110 // Valid Inputs.
a=10, b=11, ab=100 // Invalid Inputs.
```
Full Circuit
```c title="CheckMult.circom"
pragma circom 2.1.6;
template IsZero() {
signal input in;
signal output out;
signal inv;
inv <-- in!=0 ? 1/in : 0;
out <== -in*inv +1;
in*out === 0;
}
template IsEqual() {
signal input in[2];
signal output out;
component isz = IsZero();
in[1] - in[0] ==> isz.in;
isz.out ==> out;
}
template CheckMult() {
signal input a;
signal input b;
signal input ab;
signal output out;
component eq = IsEqual();
eq.in[0] <== a * b;
eq.in[1] <== ab;
eq.out ==> out;
}
component main { public [ab] } = CheckMult();
/* INPUT = {
"a": "5",
"b": "77",
"ab": "265"
} */
```
Setup your Project
Fork the template, https://github.com/anudit/circom-template.
It simplifies the process of compiling Circom circuits in a highly customizable way.
Your project structure should look something like this.
You'll need to download the Powers of Tau file from https://storage.googleapis.com/zkevm/ptau/powersOfTau28\_hez\_final\_20.ptau and save it inside the build directory.
Install the dependencies,
```bash
bun install
```
Build & Test your Circuit
Now the fun part.
```bash
bun run build
```
Your circuit files should be present in build/CheckMult directory.
```bash
bun run test
```
Your logs should look like this.
```bash
➜ circom-template git:(main) bun run test
$ bun test ./tests/*.test.ts
bun test v1.1.30 (7996d06b)
tests/checkMult.test.ts:
✓ Test Mult > Mock generate data [53.45ms]
1 pass
0 fail
3 expect() calls
Ran 1 tests across 1 files. [269.00ms]
```
On-chain Verification
Your Solidity/Vyper/Fe Verifier should be present in build/CheckMult/CheckMultVerifier.(sol/vy/fe)
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
More Reading
Learn Circom: https://learn.0xparc.org/materials/circom/learning-group-1/circom-1
Build optimzed graphs of your circuits: https://github.com/iden3/circom-witnesscalc, Only for circom <2.2.0
---
title: Web3 Glossary
References
---
title: Halo2
Setup the Project
Fork the template, https://github.com/anudit/halo2-template.
It simplifies the process of compiling Halo2 circuits in a highly customizable way.
Your project structure should look something like this.
fib.rs contains a fibonacci circuit.
lib.rs contains the customizable C glue to run your circuit.
Understand the C Glue
```rust
pub extern "C" fn compute(
public_inputs: *const c_char
) -> *const c_char {}
```
This signature should remain constant otherwise zk-expo won't pickup the function.
The compute function contains the functions you need to parse inputs and return valid json.
Build and Test
Requires the WASM toolchain : rustup target add wasm32-unknown-unknown
```bash
cargo +nightly build --target wasm32-unknown-unknown --release
```
Optimize the wasm file,
```bash
brew install binaryen
wasm-opt -Oz -o optimized.wasm ./target/wasm32-unknown-unknown/release/hello_wasm.wasm
```
On-chain Verification
```rust
```
Your Solidity Verifier should be present in \`\`
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
More Reading
---
title: Noir
Install Noir and BB
```bash
curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash
curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash
```
Close the terminal, open another one, and run.
```bash
noirup
bbup --version 0.59.0
```
Setting up the Project
```bash
cargo init && nargo init
```
Your folder structure should look like this
Build and Test your Circuit
```bash
nargo check
```
This should create a Prover.toml file like such,
```bash
x = ""
y = ""
```
You can edit this file to pass inputs to your circuits.
You should play around with this file and try out different inputs. Example,
```bash
x = "1"
y = "2"
```
Now run your circuit,
```bash
nargo execute mywitness
```
Your witness should be available in ./target/mywitness.gz
```bash
nargo compile
```
Your circuit should be present in ./target/hello\_world.json directory.
Build and Verify your Proof
Prove
```bash
bb prove -b ./target/hello_world.json -w ./target/mywitness.gz -o ./target/proof
```
Verify
```bash
bb write_vk -b ./target/hello_world.json -o ./target/vk
bb verify -k ./target/vk -p ./target/proof
```
On-chain Verification
```bash
bb write_vk -b ./target/hello_world.json
bb contract
```
You should now have a contract.sol in your ./target/ directory.
Tutorial on [On-chain Verification](/tutorials/on-chain-verification)
Trimming your SRS
```rust title="trim.rs"
use noir_rs::srs::{get_srs, localsrs::LocalSrs, netsrs::NetSrs, Srs};
fn main() {
let srs: Srs = NetSrs::new(4194304).to_srs(); // 2^22
let local_srs = LocalSrs(srs);
let save_path = "./srs22.dat";
local_srs.save(Some(&save_path));
}
```
More Reading
https://noir-lang.org/docs/
---
title: On-Chain Verification
EVM
Groth16 Proof Verification costs a base ~220k gas.
Deploy the contract
You can use [Remix](https://remix.ethereum.org/) for simple deployments.
Install and setup Wagmi
```bash
bun i viem wagmi @tanstack/react-queryimport { http, createConfig } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
export const config = createConfig({
chains: [mainnet, sepolia],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
});
const queryClient = new QueryClient();
function App() {
return (
{/** ... */}
)
}
```
Verify the proof on-chain
```tsx
const { proof, calldata, publicSignals } = await makeProof(input);
const client = usePublicClient();
const data = await client.readContract({
address: contractAddress,
abi: contractAbi,
functionName: 'verifyProof',
args: calldata
});
```
Solana
EVM Extension: https://neonevm.org
NEAR
EVM Extension: https://aurora.dev
More Verifiers
https://github.com/SuccinctPaul/awesome-zk-verifier
---
title: Solidity
---
title: Web
In this tutorial we are going to talk about how to integrate ZK-Proofs in a React/NextJS project.