NoirReactNative is a React Native package for generating and verifying Noir zero-knowledge proofs using the Barretenberg backend.
The Swift bindings are generated by the mopro CLI using the Noir adapter, which relies on a prebuilt Barretenberg backend.
To learn more about the original Rust implementation before generating bindings, please refer to noir-rs.
Use a Node.js package manager in your React Native app to install dependencies. For example:
# npm
npm install https://github.com/zkmopro/NoirReactNative # Or change to your own URL
# yarn / pnpm
yarn add https://github.com/zkmopro/NoirReactNative # Or change to your own URLOr add this in package.json
"dependencies": {
"noir-react-native": "github:zkmopro/NoirReactNative"
}Here is an example of how to integrate and use this package.
For the full test implementation, see example/App.tsx.
import {
getNoirVerificationKey,
generateNoirProof,
verifyNoirProof,
} from 'noir-react-native';Please checkout noir-rs to see how to generate the circuit and the srs.
To load the circuit and srs in a React Native app, please checkout loadAssets to get the path. Then define the file path, e.g.
const circuitPath = await loadAssets(circuitName);
const srsPath = await loadAssets(srsName);const onChain = true; // Use Keccak for Solidity compatibility
const lowMemoryMode = false;
const inputs = ['3', '5'];
const verificationKey = getNoirVerificationKey(
circuitPath.replace('file://', ''),
srsPath.replace('file://', ''),
onChain,
lowMemoryMode
);const proof: ArrayBuffer = generateNoirProof(
circuitPath.replace('file://', ''),
srsPath.replace('file://', ''),
circuitInputs,
onChain,
verificationKey,
lowMemoryMode
);const res: boolean = verifyNoirProof(
circuitPath.replace('file://', ''),
proof,
onChain,
vk,
lowMemoryMode
);- Use
mopro-cliand choosenoir
mopro initchoose noir
mopro buildchoose react-native and all architectures.
- Then, replace the entire bindings directory
MoproReactNativeBindingswith your generated files in the current folder:
├── android
├── babel.config.js
├── cpp
├── example # Optional: keep this folder
├── ios
├── lib
├── MoproFfiFramework.xcframework
├── node_modules
├── package-lock.json
├── package.json
├── README.md
├── src
├── tsconfig.build.json
├── tsconfig.json
├── turbo.json
└── ubrn.config.yamlor running, e.g.
cp -R \
MoproReactNativeBindings/android \
MoproReactNativeBindings/ios \
MoproReactNativeBindings/src \
MoproReactNativeBindings/lib \
MoproReactNativeBindings/MoproFfiFramework.xcframework \
MoproReactNativeBindings/package.json \
mopro-react-native-package/-
Zip the
MoproFfiFramework.xcframework -
Upload the
MoproFfiFramework.xcframeworkto some URL -
Update the check-mopro-download.sh script
Note
noir-rs v1.0.0-beta.19 build constraints. The ubrn:ios / ubrn:android
scripts intentionally omit --and-generate and reuse the committed bindings
in src/generated/ and cpp/generated/. Current uniffi-bindgen-react-native
(through 0.31.0-3) panics when regenerating bindings for this crate
(Module path should map to namespace: unresolved module path mopro_example_app_noir::error) because mopro-ffi's app!() macro exports
items from Rust submodules (error, circom_stub, halo2_stub, noir) that
ubrn's TypeScript generator can't map. The committed bindings already match
beta.19, so regeneration is not needed — only the Rust library is rebuilt.
ubrn:ios also pins targets to aarch64-apple-ios,aarch64-apple-ios-sim
because barretenberg-rs (beta.19) ships no x86_64-apple-ios prebuilt.
Use the example app folder:
- Install the dependencies
npm install- Start the server
npm run start- Run the app on iOS
npm run ios- Run the app on Android
export ANDROID_HOME=~/Library/Android/sdk/npm run androidWarning
If you are using Expo, run the app with:
"ios": "expo run:ios",
"android": "expo run:android"These commands build and run the native iOS and Android projects.
And make sure the Android minSdkVersion is set to 30 (required by the noir-rs v1.0.0-beta.19 barretenberg prebuilt).
This work was initially sponsored by a joint grant from PSE and 0xPARC. It is currently incubated by PSE.