> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yattacorp.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Stealth Addresses

> One-time addresses for on-chain privacy on NEXUS

## What are Stealth Addresses?

A stealth address lets you receive funds or contract calls without linking transactions to your identity. Every sender generates a **unique one-time address** just for you — nobody watching the chain can tell which transactions belong to the same wallet.

NEXUS implements the ERC-5564 Dual-Key Stealth Address Protocol using secp256k1 ECDH.

<Info>
  Stealth addresses are **live in V1**. They are separate from Zcash shielded pools (z-addr), which are planned for V2.
</Info>

## How it Works (Plain English)

1. **You publish a stealth meta-address** — two public keys (scan key + spend key)
2. **Sender looks up your meta-address**, generates a random one-time key, and computes a unique address just for this transaction
3. **Transaction goes to that one-time address** — no link to your real identity on-chain
4. **You scan** new transactions using your private scan key to find yours
5. **You spend** using a derived private key only you can compute

```
You publish:  scan_pubkey + spend_pubkey  (66 bytes, your stealth meta-address)

Sender:
  1. Generate random ephemeral key R
  2. ECDH: shared_secret = HKDF(R × scan_pubkey)
  3. one_time_address = spend_pubkey + shared_secret × G
  4. Attach (R, view_tag) to transaction

You (scanning):
  1. For each tx: shared_secret = HKDF(scan_privkey × R)
  2. View tag matches? → Compute full address to confirm
  3. Match → Spend with: spend_privkey + shared_secret_scalar
```

## View Tags: Fast Scanning

Every transaction carries a 1-byte **view tag** (the first byte of the HKDF output). Before doing any expensive elliptic curve math, the scanner checks the view tag — this filters out **99.6% of non-matching transactions instantly**.

## Privacy Properties

| Property                               | Status |
| -------------------------------------- | ------ |
| Sender cannot be linked to recipient   | ✅      |
| Multiple receipts unlinkable           | ✅      |
| Works for transfers                    | ✅      |
| Works for contract calls               | ✅      |
| Scan key can be delegated (watch-only) | ✅      |
| Spend key never revealed during scan   | ✅      |

## Stealth Contract Calls

Stealth addresses work for **smart contract interactions** too, not just transfers. The NEXUS miner resolves the stealth address to your real address *before* execution, so contracts see your real `msg.sender` — approvals, ownership checks, and balances all work correctly. The public block record only shows the unlinkable one-time address.

## Using Stealth Addresses (TypeScript SDK)

```typescript theme={null}
import {
  deriveStealthKeyPair,
  encodeStealthMetaAddress,
  generateStealthAddress,
  getMyStealthTransactions,
  deriveStealthPrivkey,
} from '@yattacorp/nexus-sdk';

// ── Recipient: set up your stealth keypair ──────────────────────────────────
const stealthKeys = deriveStealthKeyPair(myMasterPrivkey);

// Publish this — it's your stealth meta-address (safe to share)
const metaAddress = encodeStealthMetaAddress(stealthKeys);
// e.g. "02abc...def02ghi...jkl" (66 bytes hex)

// ── Sender: generate a one-time address for the recipient ───────────────────
const { stealthAddress, ephemeralPubkey, viewTag } = generateStealthAddress(
  recipientScanPubkeyHex,
  recipientSpendPubkeyHex,
);
// Use stealthAddress as tx.from, attach ephemeralPubkey + viewTag to tx

// ── Recipient: scan for incoming transactions ───────────────────────────────
const myTxs = getMyStealthTransactions(
  allStealthTxsFromSnapshot,  // fetched from node
  stealthKeys.scanPrivkey,
  stealthKeys.spendPubkey,
);

// ── Recipient: derive private key to spend ──────────────────────────────────
for (const tx of myTxs) {
  const privkey = deriveStealthPrivkey(stealthKeys.spendPrivkey, tx.sharedSecretScalar);
  // sign transactions with privkey
}
```

## Key Derivation

Stealth scan and spend keys are derived from your master key using HKDF-SHA256 with domain separation:

```
scan_privkey  = HKDF(master, salt="nexus-stealth-scan",  info="scan-key-v2",  32 bytes)
spend_privkey = HKDF(master, salt="nexus-stealth-spend", info="spend-key-v2", 32 bytes)
```

This means a single master key controls your entire identity, while scan and spend keys are separate — you can share your scan key with a watchtower service without giving it spending ability.

## Scanning Privacy

Scanning is **fully client-side** — your scan private key never leaves your device. You fetch the global stealth transaction snapshot from a NEXUS node, then compute locally which transactions are yours. The node never learns which transactions belong to you.

## Cryptographic Details

| Component      | Specification                              |
| -------------- | ------------------------------------------ |
| Key agreement  | ECDH on secp256k1                          |
| Key derivation | HKDF-SHA256 (RFC 5869)                     |
| Domain         | `nexus-stealth-address-v2`                 |
| View tag       | 1 byte (first HKDF output byte)            |
| Address format | 32-byte x-only pubkey (Taproot-compatible) |
| Comparison     | Constant-time to prevent timing attacks    |
