Documentation Index
Fetch the complete documentation index at: https://docs.privora.xyz/llms.txt
Use this file to discover all available pages before exploring further.
The @privora/react package provides React hooks and components for building FHE-enabled applications with Privora.
Installation
npm install @privora/react @privora/sdk @solana/web3.js @solana/wallet-adapter-react
Quick Start
import { PrivoraProvider, usePrivoraContext, useEncrypt } from '@privora/react';
import { useWallet } from '@solana/wallet-adapter-react';
function App() {
const { signMessage } = useWallet();
return (
<PrivoraProvider
rpcUrl="http://localhost:8899"
autoInitialize
signMessage={signMessage}
>
<MyComponent />
</PrivoraProvider>
);
}
function MyComponent() {
const { privora, userCrypto, isInitialized } = usePrivoraContext();
const { encryptAndSubmit, isEncrypting } = useEncrypt(privora, userCrypto);
const handleSubmit = async (value: number) => {
const result = await encryptAndSubmit(value, 'u8');
if (result) {
console.log('Submitted hash:', result.hash);
}
};
if (!isInitialized) return <div>Initializing...</div>;
return <button onClick={() => handleSubmit(100)}>Submit</button>;
}
PrivoraProvider
The PrivoraProvider component wraps your application to provide Privora state to all child components.
Props
| Prop | Type | Required | Description |
|---|
rpcUrl | string | Yes | The Privora sequencer RPC URL |
signatureMessage | string | No | Custom message for deriving encryption keys |
autoInitialize | boolean | No | Auto-initialize when signMessage is available |
signMessage | SignMessageFn | null | No | Wallet adapter signMessage function |
children | ReactNode | Yes | Child components |
Basic Usage
// Manual initialization
function App() {
return (
<PrivoraProvider rpcUrl="http://localhost:8899">
<MyApp />
</PrivoraProvider>
);
}
Auto-initialization
// Auto-initialize with wallet adapter
function App() {
const { signMessage, connected } = useWallet();
return (
<PrivoraProvider
rpcUrl={process.env.NEXT_PUBLIC_RPC_URL!}
autoInitialize={connected}
signMessage={signMessage}
>
<MyApp />
</PrivoraProvider>
);
}
Hooks
usePrivora
Standalone hook for initializing and managing Privora state without using the context provider.
import { usePrivora } from '@privora/react';
function MyComponent() {
const { publicKey, signMessage } = useWallet();
const {
privora,
userCrypto,
userKeypair,
isInitialized,
isInitializing,
error,
initialize,
reset
} = usePrivora({
rpcUrl: 'http://localhost:8899',
});
useEffect(() => {
if (publicKey && signMessage && !isInitialized && !isInitializing) {
initialize(signMessage);
}
}, [publicKey, signMessage, isInitialized, isInitializing]);
// Use privora and userCrypto...
}
usePrivoraContext
Access the Privora context when using PrivoraProvider.
import { usePrivoraContext } from '@privora/react';
function MyComponent() {
const {
privora,
userCrypto,
isInitialized,
initialize,
reset
} = usePrivoraContext();
if (!isInitialized) {
return <button onClick={() => initialize(signMessage)}>Connect</button>;
}
return <div>Connected!</div>;
}
useEncrypt
Hook for encrypting values with FHE and user recovery.
import { useEncrypt } from '@privora/react';
function OrderForm({ privora, userCrypto }) {
const {
encrypt,
encryptAndSubmit,
submit,
isEncrypting,
isSubmitting,
error,
clearError
} = useEncrypt(privora, userCrypto);
const handleSubmit = async (price: number) => {
// Option 1: Encrypt and submit in one step
const result = await encryptAndSubmit(price, 'u8');
if (result) {
console.log('Hash:', result.hash);
// Store result.userCiphertext and result.userNonce for later decryption
}
// Option 2: Encrypt separately, then submit
const encrypted = await encrypt(price, 'u8');
if (encrypted) {
const hash = await submit(encrypted.encrypted);
}
};
return (
<div>
{error && <div className="error">{error}</div>}
<button onClick={() => handleSubmit(100)} disabled={isEncrypting || isSubmitting}>
{isEncrypting ? 'Encrypting...' : isSubmitting ? 'Submitting...' : 'Submit'}
</button>
</div>
);
}
useDecryptReveal
Hook for decrypting and revealing user-encrypted values with a show/hide toggle.
import { useDecryptReveal } from '@privora/react';
function OrderCard({ order, userCrypto }) {
const priceField = {
ciphertext: order.userPriceCiphertext,
nonce: order.userPriceNonce,
dataType: 'u8' as const,
};
const [priceState, { reveal, hide, toggle }] = useDecryptReveal(priceField, userCrypto);
return (
<div>
<span>
Price: {priceState.revealed ? priceState.value : '****'}
</span>
<button onClick={toggle} disabled={priceState.isDecrypting}>
{priceState.isDecrypting ? 'Decrypting...' : priceState.revealed ? 'Hide' : 'Reveal'}
</button>
{priceState.error && <span className="error">{priceState.error}</span>}
</div>
);
}
useDecryptRevealMultiple
Hook for managing multiple encrypted fields at once.
import { useDecryptRevealMultiple } from '@privora/react';
function OrderDetails({ order, userCrypto }) {
const fields = {
price: {
ciphertext: order.priceCiphertext,
nonce: order.priceNonce,
dataType: 'u8' as const
},
quantity: {
ciphertext: order.qtyCiphertext,
nonce: order.qtyNonce,
dataType: 'u8' as const
},
};
const { price, quantity, revealAll, hideAll } = useDecryptRevealMultiple(fields, userCrypto);
return (
<div>
<p>Price: {price.revealed ? price.value : '****'}</p>
<p>Quantity: {quantity.revealed ? quantity.value : '****'}</p>
<button onClick={revealAll}>Reveal All</button>
<button onClick={hideAll}>Hide All</button>
</div>
);
}
Context Utilities
Additional hooks for accessing specific parts of the context:
import {
usePrivoraInstance,
useUserCrypto,
useUserKeypair
} from '@privora/react';
function MyComponent() {
// Get just the Privora instance (or null if not initialized)
const privora = usePrivoraInstance();
// Get just the UserCrypto instance (or null if not initialized)
const userCrypto = useUserCrypto();
// Get the derived user keypair (or null if not initialized)
const userKeypair = useUserKeypair();
}
Complete Example
import {
PrivoraProvider,
usePrivoraContext,
useEncrypt,
useDecryptReveal
} from '@privora/react';
import {
ConnectionProvider,
WalletProvider,
useWallet
} from '@solana/wallet-adapter-react';
// Wallet setup wrapper
function AppWithWallet() {
const { signMessage, connected } = useWallet();
return (
<PrivoraProvider
rpcUrl={process.env.NEXT_PUBLIC_RPC_URL!}
autoInitialize={connected}
signMessage={signMessage}
>
<OrderBook />
</PrivoraProvider>
);
}
// Main orderbook component
function OrderBook() {
const { privora, userCrypto, isInitialized, isInitializing, error } = usePrivoraContext();
if (error) return <div>Error: {error}</div>;
if (isInitializing) return <div>Connecting to Privora...</div>;
if (!isInitialized) return <div>Please connect your wallet</div>;
return (
<div>
<SubmitOrderForm privora={privora} userCrypto={userCrypto} />
<OrderList userCrypto={userCrypto} />
</div>
);
}
// Order submission form
function SubmitOrderForm({ privora, userCrypto }) {
const [price, setPrice] = useState('');
const { encryptAndSubmit, isEncrypting, isSubmitting, error } = useEncrypt(privora, userCrypto);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
const result = await encryptAndSubmit(Number(price), 'u8');
if (result) {
// Save result for later display
saveOrder({
hash: result.hash,
userCiphertext: result.userCiphertext,
userNonce: result.userNonce,
});
setPrice('');
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={price}
onChange={e => setPrice(e.target.value)}
placeholder="Price (0-255)"
/>
<button disabled={isEncrypting || isSubmitting}>
{isEncrypting ? 'Encrypting...' : isSubmitting ? 'Submitting...' : 'Submit'}
</button>
{error && <p className="error">{error}</p>}
</form>
);
}
// Display order with reveal functionality
function OrderCard({ order, userCrypto }) {
const priceField = {
ciphertext: order.userCiphertext,
nonce: order.userNonce,
dataType: 'u8' as const,
};
const [state, { toggle }] = useDecryptReveal(priceField, userCrypto);
return (
<div className="order-card">
<span>Price: {state.revealed ? state.value : '****'}</span>
<button onClick={toggle}>
{state.revealed ? 'Hide' : 'Reveal'}
</button>
</div>
);
}
TypeScript Types
All types are exported from @privora/react:
import type {
// Hook options and results
UsePrivoraOptions,
UsePrivoraResult,
PrivoraState,
SignMessageFn,
// Encryption types
EncryptedWithRecovery,
SubmitResult,
UseEncryptState,
UseEncryptResult,
// Decryption types
EncryptedField,
RevealState,
UseDecryptRevealResult,
// Context types
PrivoraContextValue,
PrivoraProviderProps,
} from '@privora/react';
Notes
- The
@privora/react package requires @privora/sdk as a peer dependency
- For core types like
Privora, UserCrypto, Encrypted, and EncryptedType, import directly from @privora/sdk
- The package uses
'use client' directives for Next.js App Router compatibility