@blockfact/react-native-facti-pro
v2.5.1
Published
Complete SDK for BlockFact - Content registration with wallet management
Maintainers
Readme
@blockfact/react-native-facti-pro
Complete SDK for BlockFact - Content registration with Starknet wallet management.
🎉 100% Free & Open Source - No API keys, no usage limits, no fees
⚠️ Camera Devices Only - This SDK only accepts images captured directly from camera with EXIF data. This prevents misuse by image editing software and ensures authenticity at source.
Features
- ✅ Camera-Only Registration - Only accepts images from camera devices (prevents misuse)
- ✅ Starknet Wallet Management - Generate and securely store wallets
- ✅ Content Registration - Upload, watermark, and register on blockchain
- ✅ Device Attestation - iOS DeviceCheck / Android Play Integrity validation
- ✅ EXIF Validation - Requires fresh camera EXIF data
- ✅ Automatic ZKP Generation - Zero-knowledge proofs for privacy
- ✅ IPFS Storage - Permanent .facti file storage
- ✅ Blockchain Verification - Verify content authenticity
- ✅ Secure Key Storage - iOS Keychain / Android Keystore
- ✅ Completely Free - No API keys, no limits, no charges
Installation
npm install @blockfact/react-native-facti-pro
npm install react-native-get-random-values
# or
yarn add @blockfact/react-native-facti-pro react-native-get-random-valuesRequired Setup
1. Add crypto polyfill to index.js:
import 'react-native-get-random-values';
// ... rest of your index.js2. Update metro.config.js:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
const config = {
resolver: {
unstable_enablePackageExports: false,
},
};
module.exports = mergeConfig(defaultConfig, config);iOS Setup
cd ios && pod installAndroid Setup
Add Play Integrity API to android/app/build.gradle:
dependencies {
implementation 'com.google.android.play:integrity:1.3.0'
}Then create native module - see detailed setup instructions at the end of this README.
Usage
1. Wrap Your App
import { BlockFactProvider } from '@blockfact/react-native-facti-pro';
function App() {
return (
<BlockFactProvider>
<YourApp />
</BlockFactProvider>
);
}2. Create Wallet
import { useBlockFact } from '@blockfact/react-native-facti-pro';
function WalletScreen() {
const { wallet, createWallet, hasWallet, loading } = useBlockFact();
const handleCreateWallet = async () => {
try {
const newWallet = await createWallet();
console.log('Wallet created:', newWallet.address);
} catch (error) {
console.error('Failed to create wallet:', error);
}
};
if (loading) return <Text>Loading...</Text>;
if (!hasWallet) {
return (
<Button title="Create Wallet" onPress={handleCreateWallet} />
);
}
return (
<View>
<Text>Wallet Address:</Text>
<Text>{wallet.address}</Text>
</View>
);
}3. Register Content
import { useBlockFact } from '@blockfact/react-native-facti-pro';
import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location';
function CameraScreen() {
const { registerContent, loading } = useBlockFact();
const handleTakePhoto = async () => {
// Take photo
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (result.canceled) return;
// Get location
const location = await Location.getCurrentPositionAsync({});
// Register on blockchain
try {
const registration = await registerContent({
imageUri: result.assets[0].uri,
latitude: location.coords.latitude,
longitude: location.coords.longitude,
metadata: {
description: 'My photo',
tags: ['nature', 'landscape']
}
});
console.log('Registered!');
console.log('Transaction:', registration.txHash);
console.log('.facti URL:', registration.factiUrl);
// Share or save registration.factiUrl
} catch (error) {
console.error('Registration failed:', error);
}
};
return (
<Button
title={loading ? "Processing..." : "Take Photo"}
onPress={handleTakePhoto}
disabled={loading}
/>
);
}4. Verify Content
import { verifyContent } from '@blockfact/react-native-facti-pro';
async function verifyFactiFile(factiUrl) {
try {
const result = await verifyContent(factiUrl);
if (result.valid) {
console.log('✅ Content verified!');
console.log('Block:', result.blockNumber);
console.log('Timestamp:', result.timestamp);
console.log('Metadata:', result.metadata);
} else {
console.log('❌ Verification failed');
}
} catch (error) {
console.error('Verification error:', error);
}
}API Reference
BlockFactProvider
Wrap your app with this provider.
Props:
children(ReactNode) - Your app components
No API key required!
useBlockFact()
Hook to access BlockFact functionality.
Returns:
{
wallet: Wallet | null, // Current wallet
loading: boolean, // Loading state
error: string | null, // Error message
hasWallet: boolean, // Whether wallet exists
createWallet: () => Promise<Wallet>,
registerContent: (params) => Promise<RegistrationResult>,
deleteWallet: () => Promise<void>
}createWallet()
Generate a new Starknet wallet. Stored securely in device keychain.
Returns:
{
address: string, // Starknet address (0x...)
publicKey: string // Public key
}registerContent(params)
Register content on blockchain.
Parameters:
{
imageUri: string, // Local image URI
latitude: number, // GPS latitude
longitude: number, // GPS longitude
metadata?: object // Optional custom metadata
}Returns:
{
factiUrl: string, // IPFS URL to .facti file
factiCid: string, // IPFS CID
txHash: string, // Blockchain transaction hash
sessionId: string // Session identifier
}verifyContent(factiUrl)
Verify a .facti file on blockchain.
Parameters:
factiUrl(string) - URL to .facti file
Returns:
{
valid: boolean, // Whether content is valid
metadata: object, // Content metadata
blockNumber: number, // Block number
timestamp: string // Registration timestamp
}deleteWallet()
Delete wallet from device. Cannot be recovered!
Why Free?
BlockFact is building the trust layer for digital media. Our goal is to make .facti the standard file format for verified content.
Free SDK = Maximum adoption = Industry standard
We don't charge developers. Our revenue comes from:
- Camera manufacturer licensing
- Platform partnerships (iOS/Android)
- Enterprise verification services
Help us make .facti the standard - use it in your app!
Complete Example
import React, { useState } from 'react';
import { View, Button, Text, Image } from 'react-native';
import { BlockFactProvider, useBlockFact } from '@blockfact/react-native-facti-pro';
import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location';
function ContentRegistration() {
const { wallet, createWallet, registerContent, hasWallet, loading } = useBlockFact();
const [result, setResult] = useState(null);
const handleRegister = async () => {
// Create wallet if needed
if (!hasWallet) {
await createWallet();
}
// Pick image
const image = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (image.canceled) return;
// Get location
const location = await Location.getCurrentPositionAsync({});
// Register
const registration = await registerContent({
imageUri: image.assets[0].uri,
latitude: location.coords.latitude,
longitude: location.coords.longitude
});
setResult(registration);
};
return (
<View style={{ padding: 20 }}>
{wallet && (
<Text>Wallet: {wallet.address.slice(0, 10)}...</Text>
)}
<Button
title={loading ? "Processing..." : "Register Content"}
onPress={handleRegister}
disabled={loading}
/>
{result && (
<View style={{ marginTop: 20 }}>
<Text>✅ Registered!</Text>
<Text>TX: {result.txHash.slice(0, 20)}...</Text>
<Text>IPFS: {result.factiCid}</Text>
</View>
)}
</View>
);
}
export default function App() {
return (
<BlockFactProvider>
<ContentRegistration />
</BlockFactProvider>
);
}Security
- Private keys stored in iOS Keychain / Android Keystore
- Keys never leave the device
- All requests over HTTPS
- Open source - audit the code
Contributing
We welcome contributions! This is an open source project.
- Report bugs: GitHub Issues
- Submit PRs: GitHub
- Join community: Discord
License
Proprietary - See LICENSE file
Free to use, not free to copy.
This SDK is free to use for any purpose, but you may not redistribute, reverse engineer, or create derivative works. For commercial licensing or manufacturer integration, contact [email protected]
Support
- Email: [email protected]
- Docs: https://docs.blockfact.io
- Discord: https://discord.gg/blockfact
- GitHub: https://github.com/blockfact/react-native-facti-pro
Links
Built with ❤️ by BlockFact - Making digital media trustworthy
Features
- ✅ Starknet Wallet Management - Generate and securely store wallets
- ✅ Content Registration - Upload, watermark, and register on blockchain
- ✅ Automatic ZKP Generation - Zero-knowledge proofs for privacy
- ✅ IPFS Storage - Permanent .facti file storage
- ✅ Blockchain Verification - Verify content authenticity
- ✅ Secure Key Storage - iOS Keychain / Android Keystore
Installation
npm install @blockfact/react-native-facti-pro
# or
yarn add @blockfact/react-native-facti-proiOS Setup
cd ios && pod installAndroid Setup
No additional setup required.
Usage
1. Wrap Your App
import { BlockFactProvider } from '@blockfact/react-native-facti-pro';
function App() {
return (
<BlockFactProvider apiKey="YOUR_API_KEY">
<YourApp />
</BlockFactProvider>
);
}2. Create Wallet
import { useBlockFact } from '@blockfact/react-native-facti-pro';
function WalletScreen() {
const { wallet, createWallet, hasWallet, loading } = useBlockFact();
const handleCreateWallet = async () => {
try {
const newWallet = await createWallet();
console.log('Wallet created:', newWallet.address);
} catch (error) {
console.error('Failed to create wallet:', error);
}
};
if (loading) return <Text>Loading...</Text>;
if (!hasWallet) {
return (
<Button title="Create Wallet" onPress={handleCreateWallet} />
);
}
return (
<View>
<Text>Wallet Address:</Text>
<Text>{wallet.address}</Text>
</View>
);
}3. Register Content
import { useBlockFact } from '@blockfact/react-native-facti-pro';
import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location';
function CameraScreen() {
const { registerContent, loading } = useBlockFact();
const handleTakePhoto = async () => {
// Take photo
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (result.canceled) return;
// Get location
const location = await Location.getCurrentPositionAsync({});
// Register on blockchain
try {
const registration = await registerContent({
imageUri: result.assets[0].uri,
latitude: location.coords.latitude,
longitude: location.coords.longitude,
metadata: {
description: 'My photo',
tags: ['nature', 'landscape']
}
});
console.log('Registered!');
console.log('Transaction:', registration.txHash);
console.log('.facti URL:', registration.factiUrl);
// Share or save registration.factiUrl
} catch (error) {
console.error('Registration failed:', error);
}
};
return (
<Button
title={loading ? "Processing..." : "Take Photo"}
onPress={handleTakePhoto}
disabled={loading}
/>
);
}4. Verify Content
import { verifyContent } from '@blockfact/react-native-facti-pro';
async function verifyFactiFile(factiUrl) {
try {
const result = await verifyContent(factiUrl);
if (result.valid) {
console.log('✅ Content verified!');
console.log('Block:', result.blockNumber);
console.log('Timestamp:', result.timestamp);
console.log('Metadata:', result.metadata);
} else {
console.log('❌ Verification failed');
}
} catch (error) {
console.error('Verification error:', error);
}
}API Reference
BlockFactProvider
Wrap your app with this provider.
Props:
apiKey(string, required) - Your BlockFact Pro API keychildren(ReactNode) - Your app components
useBlockFact()
Hook to access BlockFact functionality.
Returns:
{
wallet: Wallet | null, // Current wallet
loading: boolean, // Loading state
error: string | null, // Error message
hasWallet: boolean, // Whether wallet exists
createWallet: () => Promise<Wallet>,
registerContent: (params) => Promise<RegistrationResult>,
deleteWallet: () => Promise<void>
}createWallet()
Generate a new Starknet wallet. Stored securely in device keychain.
Returns:
{
address: string, // Starknet address (0x...)
publicKey: string // Public key
}registerContent(params)
Register content on blockchain.
Parameters:
{
imageUri: string, // Local image URI
latitude: number, // GPS latitude
longitude: number, // GPS longitude
metadata?: object // Optional custom metadata
}Returns:
{
factiUrl: string, // IPFS URL to .facti file
factiCid: string, // IPFS CID
txHash: string, // Blockchain transaction hash
sessionId: string // Session identifier
}verifyContent(factiUrl)
Verify a .facti file on blockchain.
Parameters:
factiUrl(string) - URL to .facti file
Returns:
{
valid: boolean, // Whether content is valid
metadata: object, // Content metadata
blockNumber: number, // Block number
timestamp: string // Registration timestamp
}deleteWallet()
Delete wallet from device. Cannot be recovered!
Complete Example
import React, { useState } from 'react';
import { View, Button, Text, Image } from 'react-native';
import { BlockFactProvider, useBlockFact } from '@blockfact/react-native-facti-pro';
import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location';
function ContentRegistration() {
const { wallet, createWallet, registerContent, hasWallet, loading } = useBlockFact();
const [result, setResult] = useState(null);
const handleRegister = async () => {
// Create wallet if needed
if (!hasWallet) {
await createWallet();
}
// Pick image
const image = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
});
if (image.canceled) return;
// Get location
const location = await Location.getCurrentPositionAsync({});
// Register
const registration = await registerContent({
imageUri: image.assets[0].uri,
latitude: location.coords.latitude,
longitude: location.coords.longitude
});
setResult(registration);
};
return (
<View style={{ padding: 20 }}>
{wallet && (
<Text>Wallet: {wallet.address.slice(0, 10)}...</Text>
)}
<Button
title={loading ? "Processing..." : "Register Content"}
onPress={handleRegister}
disabled={loading}
/>
{result && (
<View style={{ marginTop: 20 }}>
<Text>✅ Registered!</Text>
<Text>TX: {result.txHash.slice(0, 20)}...</Text>
<Text>IPFS: {result.factiCid}</Text>
</View>
)}
</View>
);
}
export default function App() {
return (
<BlockFactProvider apiKey="YOUR_API_KEY">
<ContentRegistration />
</BlockFactProvider>
);
}Security
- Private keys stored in iOS Keychain / Android Keystore
- Keys never leave the device
- API key validated server-side
- All requests over HTTPS
License
Commercial license required. Contact [email protected]
Support
- Email: [email protected]
- Docs: https://docs.blockfact.io
- GitHub: https://github.com/blockfact/react-native-facti-pro
