Private payments
for your agents_
React hooks for zero-knowledge private payments via the ZAPP Protocol. Deposit → prove → withdraw. No on-chain link between sender and receiver. Fully on-chain — no server, no custody.
npm install use-zappread the docs →payment flow
Deposit
USDC enters the shielded pool. Your commitment hash joins the Merkle tree.
Prove
ZK proof of Merkle membership generated locally. No server sees your keys.
Withdraw
Funds land at recipient. Zero on-chain link between sender and receiver.
useZappPayment()
Full approve → deposit → prove → withdraw flow in one hook. Status, errors, and ZK proof — all typed and reactive. Abort on unmount included.
useX402Payment()
Drop-in fetch wrapper. Detects 402 responses, pays via the shielded pool privately, and retries with X-Payment-Proof. Agents pay APIs without revealing identity.
ZappProvider
Context-based config. Pass your contract addresses and wallet adapter once, use hooks anywhere in the tree. Works with wagmi, viem, and custom adapters.
On-chain only
No backend, no custody, no API keys. Every interaction goes directly to the ShieldedPool contract on Ethereum. Immutable and unstoppable by design.
PLONK verified
Every withdrawal is verified on-chain by the PlonkVerifier contract. Proofs are generated client-side via WASM — your nullifier and secret never leave the browser.
Fully typed
End-to-end TypeScript. ZKProof, CommitmentHash, Nullifier, and all request/result types exported. ZappConfig enforces your contract addresses at compile time.
002 · basic usage
One hook.
Fully private.
Wrap your app in ZappProvider with your deployed contract addresses, connect your wallet adapter, call pay(). Approve, deposit, prove, and withdraw happen under the hood — all on-chain.
import { useZappPayment } from "use-zapp"
export function PayButton() {
const {
pay, status, isLoading, result
} = useZappPayment()
const handlePay = async () => {
await pay({
amount: "10.00", // USDC
recipient: "0xFresh…", // any address
asset: "USDC",
})
}
return (
<button onClick={handlePay} disabled={isLoading}>
{isLoading ? status : "Pay 10 USDC privately"}
</button>
)
}003 · x402 endpoints
Pay APIs
privately.
fetchWithPayment() wraps fetch. On HTTP 402, pays via the shielded pool and retries with X-Payment-Proof. The API never learns which wallet paid.
import { useX402Payment } from "use-zapp"
export function AgentFetcher() {
const { fetchWithPayment, isPaying }
= useX402Payment()
const fetchData = async () => {
// 402 → auto-pay → retry
const res = await fetchWithPayment(
"https://api.example.com/premium"
)
const data = await res.json()
console.log(data)
}
return (
<button onClick={fetchData}>
{isPaying ? "paying…" : "fetch data"}
</button>
)
}004 · setup
One provider.
Your contracts.
Pass your deployed shieldedPoolAddress and verifierAddress once. The SDK talks directly to those contracts — no intermediary.
import { ZappProvider } from "use-zapp"
import { myWalletAdapter } from "@/lib/wallet"
export default function Layout({ children }) {
return (
<ZappProvider
config={{
shieldedPoolAddress: "0x…",
verifierAddress: "0x…",
walletAdapter: myWalletAdapter,
defaultChain: "ethereum",
defaultAsset: "USDC",
debug: true,
}}
>
{children}
</ZappProvider>
)
}ratio Pf/P0
100x
price at 50% supply
$0.100
max reserve
$2.1M
token cap
10M
current price
$0.0229
collateral ratio
68%
ZAPP
zero1.cash
Contracts not yet deployed · testnet coming soon
Connect your wallet
Try it now.
Connect a wallet with Base Sepolia testnet funds and send a private payment. Watch the three phases in real time — deposit, prove, withdraw.