@blockfact/react-native-facti-pro
v5.0.0
Published
Complete SDK for BlockFact - On-device content registration with wallet management
Maintainers
Readme
@blockfact/react-native-facti-pro
BlockFact SDK v4.0 — On-device ZKP, FACT token registration, device attestation.
⚠️ v4.0 is a breaking change from v3.x. All v3.x SDKs are blocked. See Migration Guide.
⚠️ Camera Devices Only — Only accepts images captured directly from camera. No gallery uploads.
⚠️ Expo Go not supported — Requires native modules. Use
npx expo prebuildor EAS Build.
Features
- ✅ Native ZKP — Groth16 proofs via mopro-ffi (< 1s, replaces snarkjs)
- ✅ FACT Token — User-paid registration (0.01 FACT per content)
- ✅ Device Attestation — iOS App Attest / Android Play Integrity (mandatory)
- ✅ Offline Queue — Survives app kills, auto-resumes on connectivity
- ✅ Starknet Wallets — Generate, store (Keychain/Keystore), deploy on-chain
- ✅ IPFS Storage — .facti files pinned to Pinata
- ✅ Blockchain Verification — Verify content authenticity on-chain
- ✅ No API Keys — SDK loads config from backend automatically
Setup
# 1. Install
npm install @blockfact/react-native-facti-pro
# 2. Run setup CLI — verifies and installs all native dependencies
npx @blockfact/setupThe setup CLI checks: mopro-ffi, poseidon-lite, starknet.js v9+, zkey circuit assets (iOS + Android), DeviceCheckModule (iOS), Play Integrity (Android).
iOS (after setup CLI)
cd ios && pod installThen in Xcode:
- Add
DeviceCheckModule.swiftandDeviceCheckModule.mto your target - Add
DeviceCheck.frameworkto Linked Frameworks - Add
poseidon_check_final.zkeyto Copy Bundle Resources - For mopro-ffi:
-force_loadflag onlibblockfact_zkp.a, setDEAD_CODE_STRIPPING = NO
Android
Add to android/app/build.gradle:
dependencies {
implementation 'com.google.android.play:integrity:1.4.0'
}Metro Config
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const config = { resolver: { unstable_enablePackageExports: false } };
module.exports = mergeConfig(getDefaultConfig(__dirname), config);Usage
1. Wrap Your App
import { BlockFactProvider } from '@blockfact/react-native-facti-pro';
function App() {
return (
<BlockFactProvider apiBase="https://api.blockfact.io">
<YourApp />
</BlockFactProvider>
);
}2. Create Wallet + Register Content
import { useBlockFact } from '@blockfact/react-native-facti-pro';
function CameraScreen() {
const { wallet, createWallet, registerContent, hasWallet, loading } = useBlockFact();
const setup = async () => await createWallet();
const handleCapture = async (photo) => {
// SDK handles: FACT balance check → approval → ZKP → attestation → upload
const { jobId } = await registerContent({
filePath: photo.uri,
filename: 'photo.jpg',
latitude: location.latitude,
longitude: location.longitude,
});
console.log('Queued:', jobId);
};
}Web3Auth Mode
Pass your Account instance via the signer parameter:
import { Account } from 'starknet';
const account = new Account({
provider, address, signer: web3authPrivateKey, cairoVersion: '1'
});
await registerContent({
filePath: photo.uri,
latitude, longitude,
signer: account,
});3. Verify Content
import { verifyContent } from '@blockfact/react-native-facti-pro';
const result = await verifyContent(factiUrl);
if (result.valid) {
console.log('Verified:', result.blockNumber, result.timestamp);
}4. Check FACT Balance
import { getFactBalance } from '@blockfact/react-native-facti-pro';
const { balance, formatted } = await getFactBalance(wallet.address);
console.log(`${formatted} FACT`);API Reference
BlockFactProvider
| Prop | Type | Description |
|------|------|-------------|
| apiBase | string | API base URL (default: https://api.blockfact.io) |
| children | ReactNode | Your app |
useBlockFact()
{
wallet: Wallet | null;
loading: boolean;
error: string | null;
hasWallet: boolean;
createWallet: () => Promise<Wallet>;
registerContent: (params: RegisterParams) => Promise<{ jobId: string }>;
deleteWallet: () => Promise<void>;
}registerContent(params)
{
filePath: string; // Local file path
filename?: string; // Default: 'photo.jpg'
mime?: string; // Default: 'image/jpeg'
latitude?: number;
longitude?: number;
metadata?: object;
signer?: Account; // Optional: Web3Auth Account instance
}Throws:
INSUFFICIENT_FACT_BALANCE— balance < 0.01 FACTFACT_APPROVAL_REQUIRED— no private key or signer providedZKP_GENERATION_FAILED— mopro-ffi not installed
getFactBalance(address)
Returns { balance: bigint, formatted: string }
ensureFactApproval(wallet, signer?)
Returns { approved: boolean, txHash?: string }
verifyContent(factiUrl)
Returns { valid: boolean, metadata: object, blockNumber: number, timestamp: string }
Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| INSUFFICIENT_FACT_BALANCE | Wallet has < 0.01 FACT | New wallets get 50 FACT on creation |
| FACT_APPROVAL_REQUIRED | No signer for approve tx | Pass signer param or use standalone mode |
| ZKP_GENERATION_FAILED | mopro-ffi not installed | Run npx @blockfact/setup |
| SDK version blocked | SDK < v4.0.0 | npm install @blockfact/react-native-facti-pro@latest |
Security
- Private keys in iOS Keychain / Android Keystore — never leave device
- RPC calls proxied through
api.blockfact.io/api/rpc— no API keys in client - Device attestation prevents emulator/rooted device abuse
- ZKP proofs generated on-device — location data never sent to server
License
Proprietary — See LICENSE file. Free to use, not free to redistribute.
