Skip to content

Frontend

Next.js application for private trading.

Architecture

frontend/
├── app/                    # Pages
│   ├── swap/              # Token swap
│   └── liquidity/         # LP management
├── hooks/                  # React hooks
│   ├── useDepositAndSwap.ts
│   ├── useDepositAndMint.ts
│   ├── useBurn.ts
│   └── useCollectFees.ts
├── lib/
│   ├── zk/                # Proof generation
│   └── storage/           # Encrypted secrets
└── providers/
    └── ZylithProvider.tsx

Proof Generation

Browser-based using snarkjs WASM:

typescript
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
  {
    root,
    secret,
    nullifier,
    amount,
    pathElements,
    pathIndices,
    recipient,
    relayer,
    fee,
    minAmountOut,
  },
  'withdraw_v2.wasm',
  'withdraw_v2.zkey'
);

~20 seconds total on modern hardware.

Secret Storage

Encrypted localStorage with wallet-derived key:

typescript
// Derive key from wallet signature
const signature = await wallet.signMessage("Unlock Zylith secrets");
const key = await deriveKey(signature);

// Encrypt/decrypt commitments
const encrypted = await encrypt(key, commitments);
localStorage.setItem('zylith_secrets', encrypted);
  • AES-GCM encryption
  • Key never stored, derived on unlock
  • Secrets include: secret, nullifier, amount, leaf index

Bundled Flows

Seamless UX combining operations:

Deposit + Swap

  1. User has wallet balance, wants to swap privately
  2. Frontend deposits tokens (creates commitment)
  3. Immediately generates proof for swap
  4. Single user confirmation for both

Deposit + Mint

  1. User wants to add liquidity
  2. Frontend deposits both tokens
  3. Creates LP position with commitments
  4. Single flow, private position

State Management

typescript
interface ZylithContext {
  // Network
  network: 'mainnet' | 'sepolia';
  zylithAddress: string;
  relayUrl: string;

  // Pool
  poolState: PoolState;

  // Secrets
  commitments: StoredCommitment[];
  positions: StoredPosition[];
  isSecretsUnlocked: boolean;

  // Actions
  unlockSecrets: () => Promise<void>;
  getShieldedBalance: (token: string) => bigint;
}

Security

DataStorageProtection
Commitment secretslocalStorageAES-GCM
Encryption keyMemory onlyWallet signature derived
Private keysWalletNever exposed

Released under the MIT License.