Skip to main content
The UTXO API is the current production path for SDK-based app integrations.

Core APIs

  • transact(params, options)
  • transfer(...)
  • partialWithdraw(...)
  • fullWithdraw(...)
  • swapUtxo(...)
  • swapWithChange(...)
All are exported from @cloak.dev/sdk.

Transaction semantics

externalAmount rules:
  • > 0: public deposit into the pool
  • < 0: public withdrawal from the pool
  • 0: fully shielded transfer
Under the hood, SDK builds proof + 264-byte public inputs and submits the resulting on-chain transaction.

Fees

  • SOL withdraw/swap:
    • gross = abs(externalAmount)
    • fee = 5_000_000 + floor(gross * 3 / 1000)
    • net = gross - fee
  • SPL (USDC/USDT) withdraw: fee = floor(gross * 3 / 1000) only — no fixed component
  • Deposits and shielded transfers have no protocol fee; SOL deposits must satisfy the min deposit (10_000_000 lamports — SOL pool only, no program minimum for SPL)
SDK helpers you can call directly:
  • SOL: calculateSolFeeLamports, calculateSolNetAmountLamports

Create UTXOs

Deposit example (transact)

Withdraw and transfer helpers

partialWithdraw/fullWithdraw use negative externalAmount semantics.

Swap example

swapWithChange sends a TransactSwap payload (proof + 264-byte public inputs + swap params).

Viewing-key registration requirements

  • Default behavior enforces viewing-key registration before protocol txs.
  • TransactOptions.enforceViewingKeyRegistration defaults to true.
  • Registration signs the fixed sign-in message and submits the registration record.
If viewing key is missing, history and decrypt flows cannot resolve your transaction data.

Risk-oracle deposits

When deposits require Range/Switchboard validation, include:
  • riskOracleQueue
  • riskQuoteUrl (or getRiskQuoteInstruction)
The SDK can fetch risk quotes for you; you can also provide your own quote backend or a direct instruction callback. If deposit account list is large, use v0 transactions with addressLookupTableAccounts.

Operational notes

  • Amounts use bigint in the UTXO API.
  • Proof retries are built in for stale roots (0x1001).
  • SDK-side Merkle reconstruction is preferred for older indices.
  • Optional cachedMerkleTree helps sequential txs avoid extra rebuild/fetch.
  • Optional useUniqueNullifiers helps repeated development runs avoid nullifier collisions.

Troubleshooting

  • Invalid public inputs size: the protocol expects 264 bytes, not 232.
  • RootNotFound / 0x1001: regenerate proof with fresh root (SDK retry usually handles this).
  • 0x1020 in local repeated runs: set CLOAK_UNIQUE_NULLIFIERS=1.
  • viewing key not found: re-run a transaction with registration enabled, then rescan history.

Next