← All apps
Lightning · Spark

Spark Signer

Spark wallet cold signer

Runs the Spark SDK in the browser with a custom signer that delegates every key op to Passport. No seed or FROST nonce ever in the browser.

View the code

Last updated Jul 2026

Passport Prime

Wallet · protected by Passport

Overview

A hardware signer for Spark (Lightning + on-chain) wallets. A browser GUI and a CLI companion run the stock @buildonspark/spark-sdk (pinned to 0.8.6) with a custom PrimeRemoteSigner that forwards every secret-touching operation (key derivation, FROST nonce, signing) to the device over newline-delimited JSON-RPC. No seed, private key, or FROST nonce ever exists in the companion.

FROST nonces are generated in device RAM, returned only as a commitment, and deleted before signing; a reboot wipes outstanding nonces and the wallet retries with a fresh commitment. Spend requests pass an on-device policy gate (per-tx, daily/weekly caps, optional allowlist) before a human slides to approve. Verified M0–M2 end-to-end on REGTEST against the KeyOS hosted simulator.

What it does

  • PrimeRemoteSigner delegates ~15 secret-touching SDK methods to the device; seed-export methods are disabled outright.
  • FROST nonces are RAM-only, single-use, commitment-only; reboot wipes them, so replay or reuse finds nothing.
  • On-device policy gate (per-tx, rolling daily/weekly caps, freeze switch, optional allowlist) with persist-before-sign.
  • L1 deposit claims and refunds are reconstructed and verified on-device, with the sighash bound to the checked amount and recipient.
  • Spark transfers and Lightning are policy-gated and human-approved, shown with an explicit "reported by companion" caveat.
  • Receiving re-keys an incoming leaf into the device’s sole control; it completes silently and never counts against the spend limits.
  • WebSocket on the simulator (ws://127.0.0.1:9911); USB CDC-ACM on hardware (M3). A Noise_XX session layer is designed for v1.5.
  • SDK is pinned exactly to 0.8.6: a re-audit is required on every SDK bump.

Technical breakdown

How the proof-of-concept is built, for developers evaluating the platform.

01

Keys never touch the browser

PrimeRemoteSigner (src/lib/prime-remote-signer.ts) implements the SDK’s SparkSigner interface and routes every key operation to the device: getIdentityPublicKey, getRandomSigningCommitment, signFrost, aggregateFrost, ECIES decrypt, secret splitting, and more. Seed-export methods (getStaticDepositSecretKey, generateMnemonic, mnemonicToSeed) throw. The SDK is handed an all-zero dummy seed; the device derives m/8797555’/account’/{0..4}’ from its own entropy.

02

Transport

The companion talks to the device over newline-delimited JSON-RPC ({id, method, params} → {id, result|error}), WebSocket on the simulator (ws://127.0.0.1:9911), USB CDC on hardware. Read-only methods time out at 10 s; approval-gated methods at 180 s, since a human may be deciding on the device screen. A single Lightning payment can burst 120+ sign calls.

03

Policy & intent verification

The policy engine (ported from the Nunchuk POC: per-tx, daily/weekly, freeze, allowlist) decides AutoSign / RequireApproval / Reject and flushes the ledger before any signature releases. L1 deposit claims and refunds are reconstructed on-device with the sighash bound to a verified amount and recipient; live unilateral-exit broadcast is not yet done. A Spark transfer splits into power-of-2 leaf denominations, so no single signature carries the operation total, which is why transfers and Lightning are policy-gated but companion-asserted in v1, with hardware bring-up and a Noise session layer on the roadmap.

Dig into the source

README, architecture notes, and the wire protocol live in the repo.

Foundation-Devices/passport-spark-signer

More on Passport Prime