# Share a single-note secret

> Disclose a single incoming note to a third party via the per-note ephemeral shared secret. Other notes stay private.

## What this lets you do

Reveal exactly one **incoming** note to a third party, like an auditor or accountant, without sharing your [viewing private key](/concepts/keys). The mechanism is the per-note ephemeral X25519 keypair that each `Note` event carries: ECDH between your `viewingPrivateKey` and the note's `ephemeralPubKey` produces a shared secret that decrypts only that one note's encrypted payload. When you hand that shared secret to a third party, they can decrypt that single note while every other incoming note stays private.

This complements the sender-side [payment receipt](generate-receipt) flow: a receipt proves "I sent X" from the sender's vantage, while the single-note secret proves "I received X" from the recipient's vantage. Both result in single-note disclosure without wholesale viewing-key disclosure.

## Constraints & limits

-   **[Discoverable-mode](/concepts/discoverable-vs-oob) notes only.** The decryption target is the encrypted payload in the on-chain `Note` event. Out-of-band notes don't have such a payload, so their [selective disclosure](/concepts/selective-disclosure) uses the noteSecret directly via the [receipt](generate-receipt) path.
-   **Per-note granularity.** Each Note event has its own ephemeralPubKey, which means the shared secret discloses exactly one note. Disclosing a batch means sharing one secret per note.
-   **You're sharing a 32-byte symmetric secret.** Treat it with the same caution as the noteSecret, because anyone who holds it can decrypt the corresponding payload.
-   **Doesn't disclose nullifier-derivation material.** The auditor sees the note's content (value, tokenId, label, plus the noteSecret) but cannot derive the nullifier without your `privateNullifyingKey`. That means they can't tell whether the note has been spent. Pair this with [verify-spent](../operations/verify-spent) if they need to know.

## What it unlocks next

-   Recipient-side compliance: a user can prove to their tax authority "I received this specific shielded payment from this org" without enabling them to inspect their broader receive history.
-   Selective audit trails for organizations that receive payments (donations, grants, vendor refunds) and need per-receipt disclosure rather than wallet-level.

## How to use it

```ts

// 1. Identify the specific incoming note by its commitment.
const target = (await session.exportAccount()).notes
    .find((n) => n.commitment === claimedCommitment);
if (!target) throw new Error("note not found: " + claimedCommitment);

// 2. Fetch the on-chain Note event to recover the ephemeralPubKey.
//    Note events are indexed by `hint`, not commitment, and the note's
//    createdAtBlock holds a timestamp, not a block number. Locate the
//    event through the note's creation transaction instead.
const receipt = await publicClient.getTransactionReceipt({ hash: target.txHash });
const noteEvents = parseEventLogs({ abi: [NOTE_EVENT_ABI], logs: receipt.logs });
const { ephemeralPubKey, encryptedPayload } = decodeNoteData(noteEvents[0].args.data);

// 3. Derive the shared secret with the recipient's viewing private key.
const crypto = new CryptoService();
const sharedSecret = crypto.ecdh(viewingPrivateKey, ephemeralPubKey);

// 4. Ship a disclosure bundle.
const disclosure = {
    type: "privacy-pools-v2-shared-secret-disclosure",
    pool: { chainId, poolAddress },
    note: { commitment: target.commitment, txHash: noteEvents[0].transactionHash },
    encryptedPayload,                               // already on-chain; included for convenience
    sharedSecret,                                   // the disclosure
};
// Auditor uses sharedSecret to decrypt encryptedPayload via the SDK's NotePayload codec.
```

## Behind the scenes

SDK utility [`CryptoService`](/sdk/crypto-services)`.ecdh(viewingPrivateKey, ephemeralPubKey)`, which performs X25519 ECDH
Decryption The auditor passes the shared secret and the on-chain encryptedPayload to the SDK's NotePayload codec to recover (noteSecret, value, tokenId, label).
What's not shared Your `viewingPrivateKey` stays on your device. Future incoming notes use different ephemeral pubkeys, so each one produces a different shared secret.
