Making a Deposit
Deposits move USDC from your wallet into the Lateo privacy pool. A Groth16 ZK proof is generated and verified on-chain atomically.
Via Dashboard (Freighter)
- Connect Freighter wallet on testnet
- Click Deposit and enter an amount
- Freighter prompts you to sign the
transact()call - The pool contract atomically:
- Verifies the Groth16 proof
- Transfers USDC from your wallet to the pool
- Inserts a commitment into the Merkle tree
- Your balance updates after on-chain confirmation
Via API (two-step)
Step 1: Prepare
curl -X POST http://localhost:3002/api/deposit/prepare \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <jwt>" \
-d '{"amount": "1.0000000", "publicKey": "GABC..."}'Response:
{
"prepareId": "uuid-...",
"transactionXDR": "AAAA..."
}The proxy generates a ZK proof, builds the unsigned transact() XDR, and simulates it.
Step 2: Sign and submit
Sign transactionXDR with Freighter or any Stellar wallet, then:
curl -X POST http://localhost:3002/api/deposit/submit \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <jwt>" \
-d '{"prepareId": "uuid-...", "signedTransactionXDR": "AAAA..."}'Response:
{
"status": "confirmed",
"txHash": "819901e4...",
"amount": "1.0000000",
"zkProof": { "generated": true, "onChain": true }
}Via MCP (localhost agents)
lateo_deposit(amount: "1")The proxy generates the ZK proof and the operator signs transact() on behalf of the agent. No Freighter needed.
What happens on-chain
The transact() function on the pool contract executes atomically:
- Calls the Groth16 Verifier contract to check the proof (BN254 pairing)
- Verifies the Merkle root matches one of the stored roots
- Verifies ASP membership (association set compliance)
- Transfers USDC from sender to pool via SAC
- Inserts two output commitments into the Merkle tree
- Marks input nullifiers as spent
If any step fails, the entire transaction reverts. No USDC moves.
Last updated on