Skip to main content

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.