Generate a payment receipt
Selective disclosure receipts let a payer hand a third party, like an accountant or auditor, a JSON file that reveals a specific payment on-chain, without revealing anything else about the payer's shielded activity.
Generating a receipt
Every prepareTransfer call returns the data needed for a receipt:
const prepared = await session.prepareTransfer({
inputCommitments: [noteToSpend.commitment],
amount,
tokenId,
recipientDiscoveryData: { evmAddress: recipient },
});
const recipientPending = prepared.executeOptions.recipientPendingNotes[0];
const receipt = {
commitment: recipientPending.commitment,
value: recipientPending.value,
tokenId: recipientPending.tokenId,
label: recipientPending.label,
ownerAddress: recipientPending.ownerAddress ?? recipient,
noteSecret: recipientPending.noteSecret,
noteAddressHash: recipientPending.noteAddressHash,
};
const result = await session.relayTransfer(prepared.relayOptions[0]);
const savedReceipt = { receipt, txHash: result.txReceipt.txHash };
The SDK creates a fresh noteSecret for each recipient output while building the proof. Capture the recipient pending note before relay submission, then persist it with the landed transaction hash.
The receipt JSON format
For accountant-friendly output, wrap the raw note data with payment context:
{
"type": "privacy-pools-v2-payment-receipt",
"version": "1",
"pool": {
"chainId": 11155111,
"poolAddress": "0x323C28ce…",
"tokenId": "0xeeee…eeee"
},
"payment": {
"fromSenderWallet": "0xC9BC5421…",
"toRecipientWallet": "0x81d48…",
"amount": "0x7a120",
"amountFormatted": "0.5 USDC",
"txHash": "0x…",
"explorerUrl": "https://sepolia.etherscan.io/tx/0x…"
},
"note": { /* the captured receipt data above */ },
"verification": {
"commitmentFormula": [
"noteAddressHash = Poseidon(note.ownerAddress, note.noteSecret)",
"precommitment = Poseidon(noteAddressHash, note.tokenId, note.value, 0x0)",
"commitment = Poseidon(precommitment, note.label)"
],
"onChainCheck": "PoolVault.commitments(commitment) returns non-zero"
}
}
Verifying a receipt
The auditor runs four checks: parsing the JSON, recomputing the noteAddressHash, recomputing the commitment, and confirming the commitment exists on-chain. See the receipt export and audit guide for a complete browser-based verifier implementation.