Mint POAPs to stealth addresses. Prove attendance without doxxing your physical location.
Standard POAPs create a public, on-chain link between an identity (e.g., "name.eth"`) and a physical location. This is a privacy risk. Anyone can track your attendance at events, which can compromise personal security.
This project severs that link. It mints a POAP to a new, single-use stealth address. On-chain, the transaction appears to go to a random, unlinked account. Only the intended recipient can find and control this address.
A user performs a one-time setup.
The process for a POAP issuer is direct. The user scans a QR code to claim an NFT. The link opens in their browser. They can choose a stealth address or their ENS to receive the POAP to. If they choose their ENS, the POAP is automatically sent to one of the stealth addresses that the user owns.
The recipient finds their POAP by opening the website.
Announcement
events on the ERC-5564 contract.PPOAP (Privacy-Preserving Proof of Attendance Protocol) solves a privacy issue in POAPs. Public on-chain data can reveal a person's location. We mint POAPs to single-use, anonymous stealth addresses. This breaks the link between a user's public identity and their event attendance.
The project is a Next.js application built with TypeScript.
Frontend: The UI uses Next.js and React. Styling is done with Tailwind CSS. Asynchronous state, like fetching POAP data, is managed by TanStack Query.
Authentication (Privy): Privy is the authentication layer. It handles user login and wallet connections. This provides a known public identity (e.g., name.eth
) for registry lookups while enabling the private stealth flow.
Privacy Engine (Stealth Addresses):
app/utils/stealth-address.js
implements the cryptographic flow. A sender uses the recipient's stealth meta-address
to compute a new stealth address that only the recipient can control.Stealth Meta-Address Registry
, an on-chain directory. A user can link their public address to their stealth meta-address. The application includes ABIs and functions (getMetaAddress.js
, setMetaAddress.js
) to use this registry.POAP API Integration: The application uses the official POAP APIs. It uses the Collectors API to validate claims and fetch metadata. It uses the Minting API to execute the mint to the generated stealth address.
Handling raw private keys is a poor user experience and a security risk. Our solution uses Passkeys (WebAuthn) to generate these keys deterministically, without direct user interaction with the keys. The app/utils/pass-keys.js
module contains this logic.
The flow is:
PublicKeyCredential
secured by biometrics."cannes-love-poap"
).EIP-5564-spending-key
, EIP-5564-viewing-key
) to derive the 32-byte spending and viewing private keys.@noble/secp256k1
library to compute compressed public keys and construct the final stealth meta-address
.This method provides cryptographic privacy through a biometric login. The same Passkey generates the same stealth keys. The keys are not stored; they are derived on-the-fly.
/claim/ethcannes
).initializeStealthAddress
) and derives the stealth meta-address
.generateStealthAddress
function computes the final, single-use stealthAddress
.stealthAddress
.