Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UTXOrder — BSV Cold Vault + Cold-Signing

UTXOrder is a client-side, watch-only archive and unsigned-transaction builder for long-term Bitcoin SV (BSV) holdings. It is the hot half of a two-machine cold-storage system: it never holds a private key or a seed.

  • Track long-term UTXOs in buckets, with SPV BEEF proofs you can verify against a local header archive.
  • Build an unsigned transaction, hand it to an offline signer (e.g. ElectrumSVP) by QR, scan the signed transaction back, and broadcast — the keys never touch this machine.
  • Receive, export/import, and print a Cold Holdings Record for offline reference and inheritance.

Everything runs in your browser (IndexedDB / localStorage). No server account, no backend, no telemetry, no keys, no seeds.

Run it

  • Live: https://utxorder.sendbsv.com
  • For real funds, run a verified release locally (see Verifying UTXOrder) — don't trust a remote host with a funds tool. localhost is a secure context, so the camera (QR scanning) still works:
    # after verifying + unzipping a release bundle:
    python3 -m http.server 8000     # then open http://localhost:8000

Verifying UTXOrder

Every release is a self-contained static bundle with a GPG-signed SHA256SUMS, so you can confirm the code you run is exactly what was published — and match it to the open source in this repo.

1. Import the maintainer release key (the fingerprint published here is the trust anchor):

BSVanon (UTXOrder Release Signing) <support@sendbsv.com>
fingerprint:  1FF8 9BA3 647A C5B2 4BBB  7920 5D7A 63F8 5C14 3F8B

# import the copy shipped in this repo (recommended), or fetch from a keyserver:
gpg --import pubkeys/BSVanon.asc
gpg --recv-keys 1FF89BA3647AC5B24BBB79205D7A63F85C143F8B

2. Verify the manifest signature, then the bundle hash:

gpg --verify SHA256SUMS.asc SHA256SUMS      # must say: Good signature (BSVanon)
sha256sum -c SHA256SUMS                      # must say: <bundle>.zip: OK

3. Unzip and run locally (see Run it). The app footer shows the build commit — confirm it matches the release, which is published under a signed git tag:

git tag -v vX.Y.Z                            # must say: Good signature

If the signature, the hash, or the commit don't line up, do not use that copy.

Repository

  • web/ — Next.js app (App Router, output: 'export' static site). This is all you need to run UTXOrder.
  • web/scripts/build-release.sh — builds a verifiable release bundle + SHA256SUMS.
  • docs/ — local-only maintainer notes (ignored from the public repo).

Development

Node.js 20+, npm 10+.

cd web
npm ci
npm run dev          # dev server at http://localhost:3000
npm run build        # static export -> web/out/
npx vitest run       # tests

Security model

  • No keys, ever. UTXOrder is watch-only: it derives addresses from an account xpub (m/44'/0'/0', depth-checked) and refuses an xprv. Signing happens on a separate, offline machine.
  • A scanned signed transaction is cryptographically verified to match the built plan — same inputs, outputs, fee, and sighash 0x41 — before the Broadcast button unlocks. A mismatch is a hard stop.
  • Online access is limited to fetching proofs/headers, scanning an xpub's addresses, and broadcasting. A failed address query aborts the scan (fail-closed) rather than silently under-reporting a balance.
  • For real funds, run a verified release on a host you control.

Network privacy

Watch-only still leaks metadata. Scanning an xpub asks an indexer about every derived address, so an indexer could see your whole wallet by source IP, and any on-path network observer sees the same TLS connections. UTXOrder reduces — but cannot eliminate — this, with three in-app layers:

  • Jitter spaces out every request (address scans and proof/BEEF fetches alike).
  • Multi-indexer spread. Address lookups are sharded deterministically across two independent indexers (WhatsOnChain + BananaBlocks, with Bitails as a failover), so in normal operation no single indexer sees more than its fixed slice of your wallet per scan. If a provider fails or is rate-limited, UTXOrder fails over to a backup — which then sees a little more than its slice — rather than under-report a balance (correctness over privacy in that edge).
  • Address chaff. Each real address is queried alongside decoy addresses — a per-device, slowly-rotating crowd of other people's funded addresses (harvested from recent blocks, never via address lookups) plus random empties — so your real addresses don't stand out, and the crowd is stable across scans (so re-scanning can't subtract it). Each decoy is used at most once per scan; a very large scan can exhaust the crowd, after which its remaining addresses are queried with less (or no) decoy cover.

These are defense-in-depth. What actually protects you matters more:

  1. Run behind Tor or a dedicated VPN circuit, or point UTXOrder at your own node / local indexer. Source-IP correlation dominates every in-app trick; the network layer is where real privacy comes from.
  2. Scan less, cache more. Re-scanning the same xpub over and over is the biggest self-inflicted leak. UTXOrder keeps archived proofs locally (IndexedDB), so rescan deliberately — not on every visit.

Outbound hosts. If you place UTXOrder behind a Content-Security-Policy connect-src or an egress firewall, allow: api.whatsonchain.com, arc.gorillapool.io (fee rate), bananablocks.com, and api.bitails.io.

License

Open BSV

About

Recovery Wizard to validate wallet material, derive BSV addresses, verify TSC merkle proofs, and export encrypted archives.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages