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

# Quickstart

> Install @opaquecash/opaque, derive stealth keys, and run a minimal send/receive flow.

This guide takes you from zero to a working integration: install the SDK, create an `OpaqueClient` from a connected wallet, register your meta-address, and run a stealth send.

## Prerequisites

* Node.js **20.17+**
* An Ethereum wallet (Sepolia testnet ETH for writes)
* Optional: a Solana (devnet) or Starknet (Sepolia) wallet for multichain flows
* For scan/sweep/prove: host or load the [cryptography WASM](/sdk/installation#wasm-module) module

## 1. Install

```bash theme={"dark"}
npm install @opaquecash/opaque viem
```

## 2. Create the client from a wallet

`OpaqueClient.fromWallet` does the whole session setup in one call: it prompts the
wallet once for a signature over the canonical `SETUP_MESSAGE`, derives the viewing and
spending keys from it (your private key is never touched), and wires the wallet as the
chain's transaction signer.

```ts theme={"dark"}
import { OpaqueClient } from "@opaquecash/opaque";

const client = await OpaqueClient.fromWallet({
  wallets: { chain: "ethereum", address: userAddress, provider: window.ethereum },
  chainId: 11155111,                              // Sepolia
  rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
  wasmModuleSpecifier: "/pkg/cryptography.js",    // required for scan/sweep/prove
});
```

Solana wallets use the same shape with wallet-adapter fields:

```ts theme={"dark"}
wallets: { chain: "solana", publicKey, signMessage, signTransaction }
```

<Note>
  The signature is HKDF entropy only and is never sent on-chain. Cache it (the
  `walletSignature` from `requestSetupSignature`) and pass it back to `fromWallet` to
  rebuild the client without prompting again. PSR schema/attestation admin does **not**
  require WASM; scanning, sweeping, and proof generation do.
</Note>

If you prefer to manage the signature yourself, sign `SETUP_MESSAGE` manually and use
[`OpaqueClient.create`](/sdk/opaque-client#opaqueclientcreateconfig-manual).

## 3. Share your meta-address

```ts theme={"dark"}
const metaAddress = client.getMetaAddressHex();
// Share this 98-byte hex so senders and issuers can pay or attest to you.
```

Register on-chain so others can resolve your normal address:

```ts theme={"dark"}
// High-level: submits the tx for you
const { txHash } = await client.registerMetaAddress("ethereum");

// Or build calldata and submit via your own wallet UI
const reg = client.buildRegisterMetaAddressTransaction();
await walletClient.sendTransaction({ to: reg.to, data: reg.data, chain: sepolia });
```

## 4. Send a stealth payment

`sendStealthPayment` resolves the recipient, derives a one-time stealth destination,
transfers the native asset, and publishes the discovery announcement:

```ts theme={"dark"}
import { parseEther } from "viem";

const result = await client.sendStealthPayment({
  chain: "ethereum",
  recipient: "0xRecipientEoaAddress...",
  amount: parseEther("0.01"),
});
```

The `recipient` can be an EVM address, a meta-address, a Solana pubkey, an
`ipfs://` DID document, or a `*.eth` name with a `com.opaque.meta` record. To resolve
without sending (for example to show a confirmation screen):

```ts theme={"dark"}
const { metaAddressHex, source } = await client.resolveRecipient(recipientInput);
```

For full control (custom gas, batching, your own wallet UI), use the low-level pair:

```ts theme={"dark"}
const send = client.prepareStealthSend(metaAddressHex);
const announce = client.buildAnnounceTransactionRequest(send);
await walletClient.sendTransaction({ to: send.stealthAddress, value: parseEther("0.01"), chain: sepolia });
await walletClient.sendTransaction({ to: announce.to, data: announce.data, chain: sepolia });
```

## 5. Receive: scan and sweep

```ts theme={"dark"}
const inbox = await client.scan({ chains: ["ethereum"] });
const balances = await client.getBalancesForOutputs(inbox);

if (inbox.length > 0) {
  const { tx } = await client.sweep({
    output: inbox[0],
    chain: inbox[0].chain,
    destination: freshAddress,
  });
}
```

<Note>
  `scan` and `getBalancesForOutputs` span every chain the client is configured for. To
  include **Starknet** (Sepolia, testnet preview), pass `starknet: {}` to `fromWallet`,
  then scan with `chains: ["ethereum", "solana", "starknet"]`. Sending and sweeping on
  Starknet use the dedicated `buildStarknetStealthSend` and `buildStarknetSweep`
  builders — see [Starknet](/concepts/starknet).
</Note>

Building a React app? `@opaquecash/react` packages the read side as hooks; see
[React hooks](/sdk/react).

## Runnable examples

The SDK repo ships a runnable example per flow in
[`sdk/examples/`](https://github.com/opaquecash/sdk/tree/main/examples): `from-wallet`,
`scan`, `send` (including a delayed announcement), `psr-prove`, and `uab-readonly`.

## Next steps

<CardGroup cols={2}>
  <Card title="Issue an attestation" icon="certificate" href="/guides/issue-attestation">
    Full issuer flow: schema, attest, announce.
  </Card>

  <Card title="Generate a reputation proof" icon="shield" href="/guides/generate-proof">
    Discover traits and submit a Groth16 proof on-chain.
  </Card>

  <Card title="Cross-chain inbox" icon="arrow-right-arrow-left" href="/concepts/cross-chain">
    UAB announcements over Wormhole.
  </Card>

  <Card title="API reference" icon="book" href="/sdk/opaque-client">
    Every `OpaqueClient` method documented with examples.
  </Card>
</CardGroup>
