Status: done

# 32 — Devnet custodial treasury: mock-USDT mint + deposit watcher

## What to build

The real Solana adapter behind the `packages/contracts` boundary, custodial model per ADR-0015. All on-chain surface is plain SPL transfers — no Anchor programs.

**Setup script** (`scripts/devnet_setup.py`): creates the mock-USDT SPL mint (6 decimals, matching real USDT) and the treasury token account on devnet, airdropping SOL for fees, and prints the `.env.devnet` values (mint address, RPC URL, treasury keypair path).

**Wallet binding**: `POST /v1/wallet/register` binds a client wallet pubkey to an API key.

**Deposit watcher**: polls the treasury token account for confirmed incoming USDT transfers and credits the sending wallet's bound API-key ledger balance. Transaction signatures are deduplicated so replayed/re-observed transfers credit exactly once.

Note: this supersedes the "testnet, never devnet" note in issue 06 (see ADR-0015) — devnet is the ecosystem standard for app development and real USDT exists on neither cluster.

## Acceptance criteria

- [ ] `scripts/devnet_setup.py` creates mint + treasury ATA and prints `.env.devnet` values
- [ ] `POST /v1/wallet/register` binds client wallet pubkey to API key
- [ ] Deposit watcher credits ledger within one poll interval of a confirmed transfer
- [ ] Duplicate/replayed transactions credit exactly once (signature dedupe)
- [ ] Local `solana-test-validator` integration test covers mint → deposit → credit
- [ ] Deterministic local adapter still works for CI without any validator

## Blocked by

- `31-billing-ledger.md`
