## 1 Mnemonic

Your own existing seed phrase (12 or 24 BIP-39 words, space-separated) Or, generate a new seed for a brand-new wallet
Write these 24 words down now. They are your new wallet. Anyone who has them can spend the coins, and if you lose them the coins are gone for good. Copy them onto paper and keep them somewhere safe before you put any Bitcoin on this wallet. This page does not keep them for you.
Optional passphrase (BIP-39)
Account
Mainnet only. Mnemonic and passphrase are processed locally in this page — nothing is sent over the network. Your BIP-352 scan and spend keys are derived at m/352'/0'/{account}'/{1,0}'/0.

## 2 Wallet storage

Create encrypted local wallet
Silent Amulet can save your birthday height, found UTXOs, and spending keys in your browser so balance sync is fast on return. The blob is encrypted at rest with AES-GCM using a key derived from your password (PBKDF2-SHA-256, 250k iterations). Without this password the saved wallet can't be opened — not even on this same device. There is no recovery. You can always re-derive from your mnemonic.
Wallet birthday
The oldest block we need to scan. Setting this correctly is the single biggest way to make the first scan fast. Silent payments can't exist below block 840,000 (Taproot activation, April 2024), so that's the hard floor.
Brand new wallet Scan the last 50 blocks. Fastest first scan; sees payments from now on. Known date I set up this wallet around a certain date. Known block height I know the exact starting block.
Wallet creation date (a day or two off is fine): pick a date
Starting block height: block 840,000 or higher
Unlock saved wallet for these keys
A saved wallet was found for this mnemonic + passphrase + account. Enter its password to load the balance, UTXOs, and last-scanned height.
Wallet ready

## 3 Derived keys & address

Silent payment address
—
Scan pubkey Bscan
—
Spend pubkey Bspend
—
Show private keys (⚠ sensitive)
Scan priv bscan
—
Spend priv bspend
—
Your spend key controls every payment you ever receive via this silent-payment address. Treat it like any other Bitcoin private key.
Balance
0 sats
—

## 1 Your silent-payment address

Share this with senders. It never changes, and is never written on-chain.

sp1… address
Derive keys on the Setup tab first.
QR appears here after you derive
Click the QR to enlarge it for scanning — or copy the address text.

## 2 Labeled addresses (optional)

Label indices ≥ 1 produce distinct sp1… addresses that still resolve to the same spend key, so you can tag senders. Index 0 is reserved by spec for change.

Label index (m, ≥ 1)

## 3 Scan for received outputs (indexer)

Silent-payment receivers can't tell which taproot outputs are theirs without reading every transaction's inputs. A Blindbit-compatible indexer exposes per-block tweak data so a light client can do this work locally.

To keep scanning fast, Sync wallet checks only the last 50 blocks, which is enough to catch new incoming payments. To look further back (for example right after importing a wallet), use Advanced · scan a manual block range below and set your own range.
Indexer URL (Blindbit-compatible)
🔒 Local · no external exposure
Your keys never leave this page. The indexer only reads public chain data. Connecting to a remote indexer does expose your IP address and the block range you're asking about to that server's operator — that's the only leak, and it's unavoidable for any light-client scan.
Localhost CORS setup — required for Blindbit

Blindbit-oracle does not send Access-Control-Allow-Origin headers, so browsers block Silent Amulet from reading its responses. Put a tiny proxy in front:

Option A — Caddy (save as Caddyfile, run caddy run):

    :8000 {
      reverse_proxy 127.0.0.1:7000
      header {
        Access-Control-Allow-Origin *
        Access-Control-Allow-Methods "GET, OPTIONS"
        Access-Control-Allow-Headers *
      }
      @options method OPTIONS
      respond @options 204
    }

Option B — Python 3 (no dependencies, save as blindbit-cors.py, run python3 blindbit-cors.py):

    from http.server import BaseHTTPRequestHandler, HTTPServer
    from urllib.request import urlopen
    from urllib.error import HTTPError, URLError
    UPSTREAM = 'http://127.0.0.1:7000'
    class H(BaseHTTPRequestHandler):
        def _c(self, s=200, b=b''):
            self.send_response(s)
            self.send_header('Access-Control-Allow-Origin', '*')
            self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS')
            self.send_header('Access-Control-Allow-Headers', '*')
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            if b: self.wfile.write(b)
        def do_OPTIONS(self): self._c(204)
        def do_GET(self):
            try:
                with urlopen(UPSTREAM + self.path, timeout=30) as r: self._c(r.status, r.read())
            except HTTPError as e: self._c(e.code, e.read() if e.fp else b'')
            except URLError as e: self._c(502, str(e).encode())
    HTTPServer(('127.0.0.1', 8000), H).serve_forever()

Both listen on 127.0.0.1:8000 (Silent Amulet's Localhost preset) and forward to Blindbit on :7000 (Blindbit's example default). If your Blindbit runs on 8000 directly, change UPSTREAM / reverse_proxy to a different port and keep the proxy on 8000.

Advanced · scan a manual block range

Use Sync wallet (above) for the normal flow. This pane is for rescanning a specific window, e.g. after importing a wallet with an older birthday.

Start block height
End block height
Scan depth: Fast (k=1, typical) Thorough (k=5, multi-output per tx) Fast is right for almost everyone. Thorough matters only if a sender paid you multiple outputs in the same tx.
Crypto backend: loading…
Preparing… 0 matches
—
No matches yet — still scanning…
Error details

## Send Bitcoin to a silent payment

The quick way: paste the address, type an amount, fetch your funds, send. The numbered cards below do the very same thing step by step if you want to watch every detail.

Recipient silent-payment address Amount to send (sats)

Broadcasting from this browser shows your IP address and the transaction to the indexer you connect to. For maximum privacy, use the numbered cards below and push the signed transaction through your own node or Tor.

## 1 Recipient

Recipient silent-payment address (sp1…)
Amount to send (sats)
Fee priority
Fast — sat/vB next block · ~10 min Normal — sat/vB within ~3 blocks · ~30 min Economy — sat/vB ~1 hour+ Custom sat/vB
Live rates from mempool.space · fetching…
Fee (sats, total) · derived from priority + size
Add at least one UTXO to see the fee estimate.

## 2 Your UTXOs (inputs)

Add each UTXO you want to spend. For silent payments, only these types are eligible: P2TR-keypath (bc1p…), P2WPKH (bc1q…), P2SH-P2WPKH (3…), P2PKH (1…). Keys are used locally only.

No coins to spend yet. Open the panel below to scan this wallet for funds, or add a UTXO row by hand, then try again.
Find other Bitcoin in this wallet to spend into a silent payment

This checks the wallet you set up on the Setup tab for ordinary Bitcoin funds that are not silent payments yet, so you can send them onward to a silent-payment address. It looks at the wallet's native SegWit, Taproot and wrapped-SegWit addresses. It uses the seed already loaded on the Setup tab, so nothing is re-entered and nothing leaves this page.

Bitcoin indexer for the UTXO lookup

Privacy note: a public indexer sees every address of this wallet as one cluster. Point this at your own node for the best privacy. Also, spending UTXOs from several of these addresses in one payment links them together on-chain.

txid | vout | amount (sats) | scriptPubKey (hex) | privkey (hex) | elig. |
--- | --- | --- | --- | --- | --- | ---

## 3 Change address

Send change to (any sp1… / bc1p / bc1q / 1… / 3… address)

BIP-352 reserves label index 0 on your own SP address for self-pay (change). When you pick the sp1… option, Silent Amulet will run a dual-recipient sender derivation — same inputs, same tweak, two distinct P2TR outputs. The bc1p… option uses x-only(B_spend) directly as a raw P2TR output, spendable by signing with your spend key.

## 4 Construct transaction

Derived recipient P2TR output key (x-only)
—
Output scriptPubKey
—
SP change output · BIP-352 label m=0 derivation for self-pay
Derived change P2TR output key (x-only)
—
Change scriptPubKey
—
PSBTv2 (base64)
This PSBT carries your inputs and the silent-payment-derived P2TR output. Sign it with any PSBTv2-capable signer (Sparrow, Bitcoin Core 26+, etc.), then broadcast. Or use the in-wallet signer below.

## 5 Sign transaction

Build a fully signed raw transaction in the browser using the private keys already loaded in your UTXO editor. Covers all four input types — P2TR (Schnorr, BIP-341), P2WPKH / P2SH-P2WPKH (ECDSA, BIP-143), and P2PKH (legacy ECDSA). Requires the fast-crypto backend (@noble/secp256k1) to be loaded — check the crypto pill on the Receive tab. If it's not loaded, use the PSBT above with an external signer.

Computed txid
—
Signed raw transaction (hex)

## 6 Broadcast

Privacy note. Broadcasting from this browser to a public API reveals your IP address and the raw transaction bytes to the endpoint operator, who can link the two. For maximum privacy, copy the signed hex above and push it via Tor Browser, your own bitcoind, or any other trusted route. The quick buttons below are for convenience, not for privacy-sensitive sends.
Endpoint
mempool.space default · wide mempool view blockstream.info Esplora, same upstream shape api.blockcypher.com rate-limited, JSON-wrapped
Response
—
Dev · BIP-352 self-test

Runs the official BIP-352 test vector (Simple send: two inputs) end-to-end: input-hash, shared-secret, output pubkey, and address encoding.

Silent payment address
—