Monorepo for Reveal Protocol, built for the Arbitrum Open House buildathon.
Reveal is a receipt layer for crypto commerce on Arbitrum.
It turns a crypto payment into something merchants, APIs, dashboards, and agents can actually use:
payment → USDC settlement → on-chain receipt → merchant workflow
Buyer pays. Seller receives USDC. Reveal emits a verifiable on-chain receipt. The merchant backend can use that receipt to unlock content, top up credits, trigger fulfillment, or power agent workflows.
Mainnet: https://zkreveal.com
Dev: https://dev.zkreveal.com
Mainnet: https://api.studio.thegraph.com/query/1753681/reveal-protocol-arbitrum-one/version/latest
Dev: https://api.studio.thegraph.com/query/1753681/reveal-protocol/version/latest
Deployment manifests:
contracts/deployments/arbitrum-one.json
contracts/deployments/arbitrum-sepolia.json
contracts/deployments/robinhood-testnet.json
Reveal is deployed on:
Arbitrum One (chain 42161, native USDC settlement)
Arbitrum Sepolia (chain 421614, test USDC settlement)
Robinhood Chain test (chain 46630, USDG settlement)
The main demo flow runs on Arbitrum Sepolia for reproducibility, while the protocol is also deployed on Arbitrum One mainnet with native USDC settlement and on the Robinhood Chain testnet with USDG settlement.
Crypto payments are good at transferring value, but merchants need more than a wallet transfer.
They need to know:
what was purchased
who paid
which listing or quote was used
whether the payment is valid
when the payment happened
which backend workflow should run next
Reveal Protocol v1 creates a minimal settlement and receipt layer for this.
buyer pays USDC (settlement token)
↓
RevealReceiptStore settles funds
↓
ReceiptPurchased event is emitted
↓
merchant backend observes and verifies the receipt
↓
off-chain workflow unlocks
Reveal is intentionally not a marketplace, escrow system, refund manager, or delivery-verification protocol.
It focuses on one primitive:
A verifiable receipt for crypto commerce.
Reveal Protocol v1 introduces Receipt Mode.
Receipt Mode lets sellers create:
fixed-price listings
seller-authorized signed quotes
The protocol supports:
USDC settlement
EIP-712 signed quotes
on-chain purchase receipts
seller payouts
protocol fees
optional integrator fees
seller-scoped purchase references
receipt indexing
event-driven merchant workflows
The core receipt flow is:
create listing
↓
generate checkout quote
↓
buyer pays USDC (settlement token)
↓
contract emits ReceiptPurchased
↓
merchant backend observes receipt
↓
merchant unlocks the off-chain product or workflow
Reveal Protocol v1 has two main on-chain components.
Canonical replay-protection primitive.
It consumes each protocol-scoped purchaseRef exactly once, and only from authorized settlement modules.
This prevents the same purchase reference from being reused across receipt flows.
Seller-facing receipt and settlement contract.
It handles:
listing creation
listing activation
seller-authorized quote signers
fixed-price purchases
signed-quote purchases
USDC settlement
receipt creation
seller payout records
protocol fees
optional integrator fees
Important events include:
ReceiptPurchased
SellerPaid
ProtocolFeePaid
IntegratorFeePaid
ListingCreated
ListingStatusChanged
QuoteSignerAuthorizationChanged
Full contract documentation:
contracts/README.md
contracts/docs/receipt-mode-integration.md
The current Receipt Mode contracts do not implement zero-knowledge proofs.
The "zk" name reflects the longer-term direction of the project:
privacy-preserving receipts
selective disclosure
private verification
encrypted delivery
Today, privacy comes from design choices such as:
metadata commitments
opaque purchase references
off-chain fulfillment
private access tokens
Nothing in v1 should be read as a claim that the current contracts use ZK proofs.
The headline demo turns a normal API resource into a paid resource.
A client requests a protected asset and receives:
402 Payment Required
checkoutUrl
private access token
The buyer opens the Reveal checkout, pays in USDC, and the merchant backend unlocks the resource after observing the on-chain receipt.
GET /asset/market-signal
↓
402 Payment Required + Reveal checkout URL
↓
buyer pays 1 USDC through the Reveal checkout
↓
RevealReceiptStore emits ReceiptPurchased
↓
Alchemy webhook delivers the event to the merchant backend
↓
backend verifies the receipt and marks the session as PAID
↓
GET /asset/market-signal with Authorization: Bearer <token>
↓
protected content is unlocked
The first authenticated request consumes the access token and returns the paid content.
A replay returns an already-consumed response instead of serving the content again.
GET /asset/market-signal
-> 402 Payment Required
Pay on Reveal checkout
-> on-chain ReceiptPurchased
GET /asset/market-signal Authorization: Bearer <token>
-> 200 status: "consumed" + content
GET /asset/market-signal Authorization: Bearer <token>
-> 200 status: "already_consumed"
The public purchaseRef proves the payment flow, but it is not enough to claim the protected resource.
Access is gated by a private bearer token returned only in the original 402 response.
Reveal ships its own hosted checkout in the web app (apps/web, live at
zkreveal.com). A merchant never builds a payment screen: it
hands the buyer a checkoutUrl and Reveal hosts the rest — quote display, wallet
connect, USDC payment, and the on-chain purchaseSignedReceipt call that produces the
receipt.
The hosted checkout uses Privy for embedded and social-login wallet UX, so a buyer can sign in and get a wallet without leaving the page, then pay in USDC.
Privy login
↓
USDC payment
↓
RevealReceiptStore receipt
It also supports a gasless path: when a sponsored ZeroDev smart-account client is
configured (paymaster set in the Privy dashboard), the buyer pays the settlement token
through a gas-sponsored UserOperation and needs no native ETH. Otherwise payment falls back to the
embedded Privy wallet, which covers its own gas. The gasless path is wired in the demo
web app (apps/web); the production hosted checkout currently runs the standard
embedded-wallet flow.
The merchant backend can observe receipts through Alchemy webhooks.
In the demo, after a payment is confirmed on-chain:
Alchemy webhook triggers
↓
ReceiptPurchased is decoded
↓
backend verifies chain, contract, seller, buyer, listing, amount, and purchaseRef
↓
checkout status becomes PAID
↓
protected asset unlocks
The chain remains the source of truth.
Alchemy is used as the delivery layer that lets the merchant backend react to receipt events in real time.
Webhook setup guide:
docs/guides/alchemy-webhook-setup.md
The web app includes a seller dashboard for paid receipts.
Sellers can use it to:
create listings
save listing metadata
view paid receipts
open receipt transactions
track checkout activity
The dashboard can read receipt data from the subgraph and show purchases indexed from the protocol events.
openhouse/
├── contracts/ Reveal Protocol receipt contracts
├── apps/
│ ├── merchant-api/ Demo merchant backend: checkout sessions, payment links, receipt observation
│ └── web/ Buyer checkout, seller dashboard, listing metadata flow
├── packages/
│ ├── sdk/ Reveal Protocol integration helpers
│ ├── shared/ Shared constants and schemas
│ └── ui/ Shared UI components
├── subgraph/ Receipt and listing event indexing
├── docs/ Demo architecture, flows, and integration notes
└── .github/workflows CI workflows
This is a simple pnpm workspace.
apps/*
packages/*
are pnpm workspaces.
contracts/
subgraph/
docs/
live at the root.
Install workspace dependencies:
pnpm installRun workspace scripts:
pnpm dev
pnpm build
pnpm testThe contracts use Foundry.
Dependencies are not vendored. contracts/lib/ is gitignored and pinned through
contracts/foundry.lock.
cd contracts
forge install
forge testThe demo requires:
merchant API running on port 8080
web app running on port 3000
an Arbitrum Sepolia RPC URL
an on-chain listing owned by the configured seller
test USDC / supported demo token
See the full copy-paste setup guide:
docs/demo-run.md
cd apps/merchant-api
./gradlew runcd apps/web
pnpm devAPI=http://localhost:8080
ASSET=market-signal
curl -s "$API/asset/$ASSET" | jqThe first response returns:
payment_required
checkoutUrl
purchaseRef
private access token
Open the returned checkout URL, log in with Privy, and pay in USDC from the connected wallet.
After the receipt is observed, retry with the access token:
curl -s "$API/asset/$ASSET" \
-H "Authorization: Bearer <token>" \
| jqExpected result:
{
"status": "consumed",
"asset": {
"id": "market-signal",
"name": "Premium ETH/ARB Market Signal",
"content": "..."
}
}To manually confirm payment instead of waiting for the observer:
curl -s -X POST \
"$API/checkout/sessions/by-purchase-ref/<purchaseRef>/sync" \
| jqThe main Open House demo is an x402-style paid API resource.
asset: Premium ETH/ARB Market Signal
price: 1 USDC
network: Arbitrum Sepolia
flow: 402 → checkout → USDC payment → receipt → unlock
This shows how Reveal can be used by:
paid APIs
AI agents
merchant backends
digital content sellers
credit systems
automation workflows
docs/architecture.md
docs/architecture/merchant-api-direction.md
docs/guides/merchant-integration.md
docs/guides/alchemy-webhook-setup.md
docs/demo-run.md
docs/flows/merchant-payment-link.md
contracts/docs/receipt-mode-integration.md
Key guides:
- Architecture: docs/architecture.md
- Merchant API architecture: docs/architecture/merchant-api-direction.md
- Merchant integration guide: docs/guides/merchant-integration.md
- Alchemy webhook setup: docs/guides/alchemy-webhook-setup.md
- Demo runbook: docs/demo-run.md
- Merchant payment link flow: docs/flows/merchant-payment-link.md
- Contract integration guide: contracts/docs/receipt-mode-integration.md
CHANGELOG.md
contracts/deployments/arbitrum-one.json
contracts/deployments/arbitrum-sepolia.json
contracts/deployments/robinhood-testnet.json
Licensed under the Apache License, Version 2.0.
Copyright 2026 zkReveal.