---
# System prepended metadata

title: 'Privacy Framework: Wallet Developer Guide'

---

# 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.
