// one seed · many doors

A new door for
every payment.

Status: Ticker (placeholder, no token exists): Path: m/44'/501'/i'/0'
// the working app

Generate. Rotate. Check.

BIP39 mnemonic → PBKDF2-HMAC-SHA512 seed → SLIP-0010 Ed25519 derivation along m/44'/501'/i'/0' (the path Phantom and Solflare use for “Account i+1”). Every step runs in this tab.

1 Generate a fresh seed

A new random BIP39 mnemonic from crypto.getRandomValues. There is deliberately no “import” box — never type a seed phrase you already use into any website.

Write the words down on paper, in order. They are the only way to recover these addresses. They exist only in this tab's memory — no copy is saved, uploaded or put in browser storage. Anyone who sees them controls every address below.

2 Your receive address — rotate it for every payment

Give each payer a different index. All of them come from the same seed, but nothing on-chain links address #3 to address #4.

Address #0 · m/44'/501'/0'/0'
—
solana:<address>

3 Live balance scan (read-only, mainnet)

Looks up the first N addresses in one getMultipleAccounts call through this site's read-only RPC proxy and shows their lamports. Click a row to make it the current address.

The scan itself links your addresses. One request carries all N addresses together, so the RPC node (and this site's proxy) can see they belong to one person. Scan sparingly, or self-host with your own SOL_RPC.
Generate a seed to list addresses.
// how it works

From twelve words to unlimited addresses.

  1. Entropy → words. 128 or 256 random bits plus a SHA-256 checksum are split into 11-bit chunks and mapped onto the 2048-word BIP39 English list (via the pinned @scure/bip39).
  2. Words → seed. PBKDF2-HMAC-SHA512(mnemonic, "mnemonic", 2048) stretches the phrase into a 64-byte seed using the browser's native Web Crypto.
  3. Seed → master key. SLIP-0010 for Ed25519: HMAC-SHA512(key = "ed25519 seed", seed). The left half is the key, the right half the chain code.
  4. Hardened children. Each level computes HMAC-SHA512(chain, 0x00 ‖ key ‖ ser32(i + 2³¹)). Ed25519 only supports hardened derivation, so every level of 44'/501'/i'/0' is hardened.
  5. Key → address. The 32-byte child key is an Ed25519 private seed; @noble/curves computes its public key, and the base58 public key is the Solana address.
  6. Checked on load. Rotor re-derives the standard test mnemonic “abandon … about” and compares address #0 to the known value before you use it (see the self-test tile).
// privacy model

What rotating buys you — and what it doesn't.

Helps with

  • Payers no longer share one address, so payer A can't look up what payer B sent you
  • A public address on an invoice or profile doesn't expose your full history and balance
  • Derivation is fully local: the seed, keys and addresses are computed in this tab and never sent anywhere
  • Only the balance scan and history check touch the network — read-only, through /api/rpc

Does not help with

  • Spending re-links addresses. Paying fees for, or sweeping, several addresses from one wallet ties them together on-chain
  • Each fresh address needs SOL for fees before it can send — funding them from one place links them
  • Amounts, timing and payer addresses stay public
  • The balance scan reveals the set of addresses to the RPC operator

Rotating addresses reduces linkability for people looking at individual payments. It does not provide anonymity against chain analysis.

Known limitations — please read

  • This is a demo, not a wallet. Rotor can derive and show addresses but cannot sign or send anything. To move funds you would have to restore the words in a real wallet — so for real money, use a real wallet's account feature from the start.
  • The seed lives only in page memory. Reload, close the tab or press “Wipe” and it is gone. If you did not write the words down, any SOL sent to these addresses is lost forever.
  • Browsers are a hostile place for seeds. Extensions, screen recorders, clipboard managers and malware can read what's on this page. JavaScript strings can't be reliably zeroed, so “Wipe” clears references but cannot guarantee memory is overwritten.
  • No account ≠ never used. The scan shows current lamports. An address that received and then spent everything may show no account; “Check history” looks up past signatures for the current address.
  • Wallet compatibility. m/44'/501'/i'/0' is the default multi-account path in Phantom and Solflare; other wallets (or the CLI's bare m/44'/501') may use different paths and will show different addresses for the same words.
  • Unaudited, experimental code. Libraries are pinned (@scure/bip39, @noble/curves), and derivation is self-tested against a public vector, but the app has had no security review.