# Privacy Framework: Wallet Developer Guide
This comprehensive guide is designed for wallet development teams to implement Privacy Framework compatibility. It provides technical specifications, implementation patterns, and best practices for building privacy-preserving wallet functionality.
## Table of Contents
- [Overview for Developers](#overview-for-developers)
- [Technical Requirements](#technical-requirements)
- [Implementation Guide](#implementation-guide)
- [Privacy Storage Implementation](#privacy-storage-implementation)
- [API Specifications](#api-specifications)
- [Security Implementation](#security-implementation)
- [Testing and Validation](#testing-and-validation)
- [Performance Optimization](#performance-optimization)
- [Integration Examples](#integration-examples)
- [Deployment Checklist](#deployment-checklist)
## Overview for Developers
Privacy Framework enables anonymous transactions on Starknet through zero-knowledge proofs and local data storage. This guide helps wallet developers implement privacy-preserving functionality.
### Key Concepts for Wallet Developers
**Privacy Model**: Commitment-nullifier scheme where:
- **On-chain**: Only cryptographic commitments and nullifiers are stored
- **Off-chain**: All sensitive data (secrets, amounts, recipients) stays in local wallet storage
- **Zero-Knowledge Proofs**: Validate operations without revealing private information
**Your Role as Wallet Developer**:
1. **Local Storage Management**: Securely store privacy operation data
2. **Encryption**: Encrypt all privacy-related data before storage
3. **Key Derivation**: Generate encryption keys from wallet account
4. **Proof Generation**: Support ZK proof creation and submission
5. **User Experience**: Provide intuitive privacy operation interfaces
### Why Local Storage is Critical
Privacy depends entirely on keeping sensitive data local. Your wallet must:
- Store operation secrets that generate commitments and nullifiers
- Maintain local Merkle tree state for efficient proof generation
- Keep transaction history encrypted and accessible only to the user
- Never transmit or store sensitive data on external servers
## Technical Requirements
### 1. Local Storage Infrastructure
**Essential Requirements:**
- **IndexedDB Support**: Primary storage for encrypted operation data
- **Persistent Storage**: Data must survive browser sessions and updates
- **Large Capacity**: Support for 50MB+ data (operations + Merkle tree + circuits)
- **Encryption at Rest**: All sensitive data encrypted with wallet-derived keys
**Storage Schema:**
```typescript
interface PrivacyDatabase {
operations: PrivacyOperation[];
merkleTree: MerkleTreeState;
metadata: WalletMetadata;
}
interface PrivacyOperation {
id: string;
secret: string; // 32-byte random value
nullifier: string; // poseidon_hash(secret, secret)
commitment: string; // poseidon_hash(secret, nullifier, amount, token)
amount: bigint;
tokenAddress: string;
status: 'pending' | 'confirmed' | 'nullified';
blockNumber?: number;
transactionHash?: string;
createdAt: Date;
nullifiedAt?: Date;
}
```
### 2. Starknet Integration Requirements
**Network Support:**
- **Mainnet**: Full production support
- **Sepolia Testnet**: Development and testing
- **Custom Networks**: Configurable RPC endpoints
**Transaction Capabilities:**
- **Multi-call Support**: Batch operations in single transaction
- **Large Proof Submission**: Support for 32KB+ ZK proofs
- **Gas Estimation**: Accurate estimates for privacy operations
- **Fee Management**: Handle STRK fee payments for privacy transactions
### 3. Cryptographic Requirements
**Encryption Standards:**
- **Algorithm**: AES-256-GCM for symmetric encryption
- **Key Derivation**: PBKDF2 with 100,000 iterations
- **Salt**: Fixed application-specific salt
- **IV**: Unique per encrypted record
**Zero-Knowledge Proof Support:**
- **Noir.js Integration**: For circuit execution
- **BB.js Integration**: For proof generation
- **WASM Support**: Browser-compatible proof generation
- **Worker Threads**: Background proof generation
## Implementation Guide
### Step 1: Initialize Privacy Storage
```typescript
class PrivacyWalletStorage {
private db: IDBDatabase;
private encryptionKey: CryptoKey;
async initialize(account: Account): Promise<void> {
// 1. Derive encryption key from wallet account
this.encryptionKey = await this.deriveEncryptionKey(account);
// 2. Initialize IndexedDB
this.db = await this.openDatabase();
// 3. Create object stores if needed
await this.setupSchema();
}
private async deriveEncryptionKey(account: Account): Promise<CryptoKey> {
// Sign deterministic message to get seed
const seed = await account.signMessage("Privacy Framework Encryption Key v1");
// Import seed as key material
const keyMaterial = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(seed),
"PBKDF2",
false,
["deriveKey"]
);
// Derive AES key
return crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: new TextEncoder().encode("privacy-framework-salt-v1"),
iterations: 100000,
hash: "SHA-256"
},
keyMaterial,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
}
}
```
### Step 2: Implement Data Encryption
```typescript
class EncryptionManager {
private key: CryptoKey;
constructor(key: CryptoKey) {
this.key = key;
}
async encrypt(data: any): Promise<ArrayBuffer> {
// 1. Serialize data
const plaintext = JSON.stringify(data);
// 2. Generate random IV
const iv = crypto.getRandomValues(new Uint8Array(12));
// 3. Encrypt data
const encrypted = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
this.key,
new TextEncoder().encode(plaintext)
);
// 4. Combine IV + encrypted data
const result = new Uint8Array(iv.length + encrypted.byteLength);
result.set(iv);
result.set(new Uint8Array(encrypted), iv.length);
return result.buffer;
}
async decrypt(encryptedData: ArrayBuffer): Promise<any> {
// 1. Extract IV and encrypted data
const iv = new Uint8Array(encryptedData.slice(0, 12));
const encrypted = encryptedData.slice(12);
// 2. Decrypt
const decrypted = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv },
this.key,
encrypted
);
// 3. Parse result
const plaintext = new TextDecoder().decode(decrypted);
return JSON.parse(plaintext);
}
}
```
## Privacy Storage Implementation
### Database Schema Design
```typescript
interface DatabaseSchema {
// Store individual privacy operations
operations: {
key: string; // operation ID
value: {
encrypted: ArrayBuffer; // encrypted operation data
timestamp: number; // creation timestamp
status: string; // operation status
};
};
// Store Merkle tree state
merkleTree: {
key: "current";
value: {
encrypted: ArrayBuffer; // encrypted tree data
lastUpdate: number; // last sync timestamp
blockNumber: number; // last synced block
};
};
// Store wallet metadata
metadata: {
key: string; // metadata type
value: {
encrypted: ArrayBuffer; // encrypted metadata
version: number; // schema version
};
};
}
```
### Operation Storage Methods
```typescript
class PrivacyOperationStorage {
private encryption: EncryptionManager;
private db: IDBDatabase;
async storeOperation(operation: PrivacyOperation): Promise<void> {
// 1. Encrypt operation data
const encrypted = await this.encryption.encrypt(operation);
// 2. Store in IndexedDB
const transaction = this.db.transaction(['operations'], 'readwrite');
const store = transaction.objectStore('operations');
await store.put({
encrypted,
timestamp: Date.now(),
status: operation.status
}, operation.id);
// 3. Wait for transaction completion
await new Promise((resolve, reject) => {
transaction.oncomplete = () => resolve(undefined);
transaction.onerror = () => reject(transaction.error);
});
}
async getOperation(operationId: string): Promise<PrivacyOperation | null> {
const transaction = this.db.transaction(['operations'], 'readonly');
const store = transaction.objectStore('operations');
const result = await store.get(operationId);
if (!result) return null;
// Decrypt and return operation
return await this.encryption.decrypt(result.encrypted);
}
async getAllOperations(): Promise<PrivacyOperation[]> {
const transaction = this.db.transaction(['operations'], 'readonly');
const store = transaction.objectStore('operations');
const cursor = await store.openCursor();
const operations: PrivacyOperation[] = [];
while (cursor) {
const decrypted = await this.encryption.decrypt(cursor.value.encrypted);
operations.push(decrypted);
cursor.continue();
}
return operations;
}
}
```
## API Specifications
### Core Privacy Wallet API
```typescript
interface PrivacyWalletAPI {
// Initialization
initializePrivacy(account: Account): Promise<void>;
isPrivacyInitialized(): boolean;
// Operation Management
createDeposit(amount: bigint, tokenAddress: string): Promise<PrivacyOperation>;
createWithdrawal(deposits: string[], recipient: string, amount: bigint): Promise<PrivacyTransaction>;
createTransfer(deposits: string[], recipientHash: string, amount: bigint): Promise<PrivacyTransaction>;
// Storage Management
exportOperations(): Promise<EncryptedBackup>;
importOperations(backup: EncryptedBackup): Promise<void>;
getOperationHistory(): Promise<PrivacyOperation[]>;
// Proof Generation
generateProof(operation: PrivacyOperation): Promise<ZKProof>;
verifyProof(proof: ZKProof): Promise<boolean>;
// Utility Methods
getReceivingHash(): Promise<string>;
estimatePrivacyGas(operation: PrivacyOperation): Promise<bigint>;
getPrivacyBalance(tokenAddress: string): Promise<bigint>;
}
```
### Event Interface
```typescript
interface PrivacyWalletEvents {
// Operation events
operationCreated: (operation: PrivacyOperation) => void;
operationConfirmed: (operationId: string, blockNumber: number) => void;
operationNullified: (operationId: string) => void;
// Proof generation events
proofGenerationStarted: (operationId: string) => void;
proofGenerationProgress: (operationId: string, progress: number) => void;
proofGenerationCompleted: (operationId: string, proof: ZKProof) => void;
proofGenerationFailed: (operationId: string, error: Error) => void;
// Storage events
storageQuotaWarning: (usedBytes: number, availableBytes: number) => void;
backupRequired: (operationCount: number) => void;
}
```
## Security Implementation
### Key Security Considerations
1. **Encryption Key Management**
- Keys derived from wallet account signatures
- Never store keys in plaintext
- Re-derive keys when needed
- Clear keys from memory after use
2. **Data Protection**
- Encrypt all privacy-related data
- Use authenticated encryption (AES-GCM)
- Unique IV for each encryption operation
- Secure deletion of sensitive data
3. **Memory Security**
- Clear sensitive data from variables after use
- Use TypedArrays for sensitive data when possible
- Avoid logging sensitive information
- Implement secure random number generation
### Security Implementation Example
```typescript
class SecurityManager {
private static readonly ENCRYPTION_MESSAGE = "Privacy Framework Encryption Key v1";
private static readonly SALT = "privacy-framework-salt-v1";
static async deriveKey(account: Account): Promise<CryptoKey> {
try {
// Get deterministic seed from wallet
const seed = await account.signMessage(this.ENCRYPTION_MESSAGE);
// Derive key using PBKDF2
const keyMaterial = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(seed),
"PBKDF2",
false,
["deriveKey"]
);
const key = await crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: new TextEncoder().encode(this.SALT),
iterations: 100000,
hash: "SHA-256"
},
keyMaterial,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
// Clear seed from memory
seed.fill?.(0);
return key;
} catch (error) {
throw new Error(`Key derivation failed: ${error.message}`);
}
}
static secureRandom(length: number): Uint8Array {
return crypto.getRandomValues(new Uint8Array(length));
}
static clearSensitiveData(data: any): void {
if (data && typeof data.fill === 'function') {
data.fill(0);
}
}
}
```
## Testing and Validation
### Unit Test Framework
```typescript
describe('Privacy Wallet Storage', () => {
let storage: PrivacyWalletStorage;
let mockAccount: Account;
beforeEach(async () => {
mockAccount = createMockAccount();
storage = new PrivacyWalletStorage();
await storage.initialize(mockAccount);
});
describe('Operation Storage', () => {
test('should store and retrieve operations', async () => {
const operation = createMockOperation();
await storage.storeOperation(operation);
const retrieved = await storage.getOperation(operation.id);
expect(retrieved).toEqual(operation);
});
test('should encrypt stored data', async () => {
const operation = createMockOperation();
await storage.storeOperation(operation);
// Verify data is encrypted in storage
const rawData = await getRawStorageData(operation.id);
expect(rawData).not.toContain(operation.secret);
});
});
describe('Key Derivation', () => {
test('should derive consistent keys', async () => {
const key1 = await SecurityManager.deriveKey(mockAccount);
const key2 = await SecurityManager.deriveKey(mockAccount);
// Keys should be functionally equivalent
const testData = new TextEncoder().encode("test");
const encrypted1 = await encrypt(testData, key1);
const decrypted = await decrypt(encrypted1, key2);
expect(decrypted).toEqual(testData);
});
});
});
```
### Integration Testing
```typescript
describe('Privacy Wallet Integration', () => {
test('full privacy operation flow', async () => {
const wallet = new PrivacyWallet();
const account = await createTestAccount();
// 1. Initialize privacy
await wallet.initializePrivacy(account);
expect(wallet.isPrivacyInitialized()).toBe(true);
// 2. Create deposit
const deposit = await wallet.createDeposit(
parseEther("1.0"),
ETH_TOKEN_ADDRESS
);
expect(deposit.status).toBe('pending');
// 3. Generate proof
const proof = await wallet.generateProof(deposit);
expect(await wallet.verifyProof(proof)).toBe(true);
// 4. Submit transaction
const txHash = await wallet.submitTransaction(proof);
expect(txHash).toBeDefined();
});
});
```
## Performance Optimization
### Storage Optimization
```typescript
class StorageOptimizer {
static async compressOperations(operations: PrivacyOperation[]): Promise<ArrayBuffer> {
// Use compression library (e.g., pako, lz-string)
const serialized = JSON.stringify(operations);
return compress(serialized);
}
static async cleanupOldOperations(storage: PrivacyOperationStorage, maxAge: number): Promise<void> {
const operations = await storage.getAllOperations();
const cutoff = Date.now() - maxAge;
const toDelete = operations.filter(op =>
op.status === 'nullified' &&
op.nullifiedAt &&
op.nullifiedAt.getTime() < cutoff
);
for (const operation of toDelete) {
await storage.deleteOperation(operation.id);
}
}
}
```
### Proof Generation Optimization
```typescript
class ProofOptimizer {
private static proofCache = new Map<string, CachedProof>();
static async generateProofWithCaching(operation: PrivacyOperation): Promise<ZKProof> {
const cacheKey = this.getOperationHash(operation);
const cached = this.proofCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < 3600000) { // 1 hour cache
return cached.proof;
}
// Generate proof in worker thread
const proof = await this.generateProofInWorker(operation);
// Cache result
this.proofCache.set(cacheKey, {
proof,
timestamp: Date.now()
});
return proof;
}
private static async generateProofInWorker(operation: PrivacyOperation): Promise<ZKProof> {
return new Promise((resolve, reject) => {
const worker = new Worker('./proof-worker.js');
worker.postMessage({ operation });
worker.onmessage = (event) => {
const { proof, error } = event.data;
worker.terminate();
if (error) reject(new Error(error));
else resolve(proof);
};
});
}
}
```
## Integration Examples
### Basic Wallet Integration
```typescript
class MyWallet extends BaseWallet implements PrivacyWalletAPI {
private privacyStorage: PrivacyWalletStorage;
private isPrivacyReady = false;
async initializePrivacy(account: Account): Promise<void> {
this.privacyStorage = new PrivacyWalletStorage();
await this.privacyStorage.initialize(account);
this.isPrivacyReady = true;
this.emit('privacyInitialized');
}
async createDeposit(amount: bigint, tokenAddress: string): Promise<PrivacyOperation> {
if (!this.isPrivacyReady) {
throw new Error('Privacy not initialized');
}
// Generate operation secrets
const secret = generateSecret();
const nullifier = poseidonHash([secret, secret]);
const commitment = poseidonHash([secret, nullifier, amount, tokenAddress]);
const operation: PrivacyOperation = {
id: generateOperationId(),
secret: secret.toString(),
nullifier: nullifier.toString(),
commitment: commitment.toString(),
amount,
tokenAddress,
status: 'pending',
createdAt: new Date()
};
await this.privacyStorage.storeOperation(operation);
this.emit('operationCreated', operation);
return operation;
}
async getPrivacyBalance(tokenAddress: string): Promise<bigint> {
const operations = await this.privacyStorage.getAllOperations();
return operations
.filter(op =>
op.tokenAddress === tokenAddress &&
op.status === 'confirmed'
)
.reduce((total, op) => total + op.amount, 0n);
}
}
```
## Deployment Checklist
### Pre-Release Validation
- [ ] **Storage Implementation**
- [ ] IndexedDB properly initialized
- [ ] Encryption/decryption working correctly
- [ ] Data persistence across sessions verified
- [ ] Storage quota management implemented
- [ ] **Security Validation**
- [ ] Key derivation tested with multiple accounts
- [ ] Encryption uses AES-256-GCM with unique IVs
- [ ] No sensitive data logged or exposed
- [ ] Memory cleanup implemented
- [ ] **Privacy Features**
- [ ] Operation creation and storage working
- [ ] Proof generation functional
- [ ] Backup/restore implemented
- [ ] Privacy balance calculation accurate
- [ ] **Performance Testing**
- [ ] Proof generation completes within acceptable time
- [ ] Storage operations are responsive
- [ ] Memory usage is reasonable
- [ ] No memory leaks detected
- [ ] **User Experience**
- [ ] Privacy features clearly indicated in UI
- [ ] Error handling provides helpful messages
- [ ] Loading states during proof generation
- [ ] Backup reminders implemented
### Production Considerations
1. **Monitoring and Analytics**
- Track proof generation success rates
- Monitor storage usage patterns
- Measure operation completion times
- Log privacy-related errors (without sensitive data)
2. **User Education**
- Provide clear documentation on privacy features
- Explain backup importance
- Warn users about privacy limitations
- Guide users through first privacy operation
3. **Support and Maintenance**
- Plan for schema migrations
- Implement debugging tools for developers
- Provide troubleshooting guides
- Monitor privacy framework updates
## Resources
- [Privacy Framework Architecture](./ARCHITECTURE.md)
- [User Guide](./USER_GUIDE.md)
- [Developer Guide](./DEVELOPER_GUIDE.md)
- [Security Best Practices](./SECURITY.md)
For technical support or questions about wallet compatibility, please contact our development team or join our community channels.
---
This guide provides comprehensive information for wallet development teams implementing Privacy Framework compatibility. Follow the implementation patterns and security guidelines to ensure robust privacy-preserving functionality.