QSDM Web wallet
Create or import a self-custody CELL wallet in this browser. For the full desktop wallet, tasks, mining, and recovery, use QSDM Hive (recovery docs).
Your keys are generated, encrypted and used only inside this browser tab; qsdm.tech never receives your private key or passphrase.
Honest caveat: a web wallet is only as safe as the device it runs on. Malware, browser extensions, clipboard hijackers and phishing copies of this page can still steal funds. Use a clean, up-to-date device, check the address bar, and compare recipient addresses after pasting.
cryptography checklist rows pin ML-DSA-87 keygen,
AES-GCM vault encryption, and JWT/mTLS posture. This is a self-maintained checklist, not an independent audit.
See audit.html?category=cryptography.
Your QSDM Wallet
No wallet is installed in this browser yet. Pick one:
The vault is stored encrypted in this browser's
localStorage (AES-256-GCM with a PBKDF2-SHA-256
600 000-iteration key derived from your passphrase). It
never leaves this tab. Clearing site data or switching
browsers wipes it — export a backup
wallet.json from the Advanced → Open tab
any time.
Unlock Your Wallet
Address:
My Wallet
Receive CELL
Share only this address. The passphrase and keystore never leave this tab.
The QR code is drawn in this tab; the address is not sent to any QR service. After pasting an address anywhere, compare the first and last six characters: clipboard hijackers swap addresses.
Send CELL
Signed in this tab with ML-DSA-87 (wallet.wasm); only the signed envelope is sent. You will see a review before anything is signed.
Transaction History
All in ExplorerScanning recent blocks…
Recent activity in the last 1,000 blocks, scanned in your browser from the public API, plus sends from this browser. Full history is coming with the indexer.
Connect QSDM Hive Desktop
Sign CELL transfers with the QSDM Hive desktop app; your keys stay in Hive and this page only sees the address you approve.
Mining rewards
Enrolled nodes owned by this address and recent mining rewards paid to it.
Loading enrollments…
Create a new wallet
Pick a strong passphrase (12+ chars, mix of types). The
ML-DSA-87 keypair is generated by wallet.wasm
in this tab; the encrypted keystore is then stored in
localStorage — no server upload.
Import existing keystore
Pick a wallet.json file (produced here or by
qsdmcli wallet new). The passphrase is verified
in-page; if it checks out, the keystore is copied into
localStorage for future unlocks.
Backups: there is no reset
The keystore file and its passphrase are the only way to reach your
coins. Lose the JSON keystore or forget the passphrase and the
address is permanently unrecoverable: no support team, no reset email, no
validator override. Export wallet.json (gear icon → Export & backup) and keep it somewhere safe.
The same keystore format is produced by the offline CLI, qsdmcli
wallet new. If you would rather not trust a web page, use the CLI on a
machine you control; the keystore opens here either way.
Sky Fang players: link your game account through QSDM Hive, not this browser page. Open Sky Fang QSDM page
Advanced tools Optional: sign a message, inspect a keystore file, or use the legacy generate / balance / send tabs. Everyday create, unlock, and send live in the wallet panel above.
Generate a fresh wallet
Choose a strong passphrase (12+ characters, mix of types). The wallet
page never sees the passphrase in network traffic: it is fed to
PBKDF2-HMAC-SHA-256 (600 000 iterations) inside this browser
tab, the derived key encrypts the private key under AES-256-GCM,
and the resulting JSON keystore is yours to download.
Open an existing keystore
Drop in a wallet.json file (produced here, or by
qsdmcli wallet new). The browser will decrypt it locally to
confirm the passphrase is correct and the file isn't tampered with.
Nothing is uploaded.
Sign a message
Decrypt the keystore and produce a ML-DSA-87 signature over
an arbitrary message. The decrypted private key is held only inside the
WASM call; the browser zeros the JS reference as soon as the signature
is returned.
Check an address balance
Unlike the other three tabs, this one talks to the network.
It sends a single GET https://api.qsdm.tech/api/v1/wallet/balance?address=<addr>
and renders the response. An address is public information — it's already on
chain — so the request leaks no private material, but it does correlate
this browser with this address at the validator's HTTP log
layer. If you want to avoid that correlation, ask a friend's node, run your own
validator, or skip this tab entirely.
Send a transaction (self-custody)
This is the only tab that spends from your wallet.
Decrypt your keystore with the passphrase, fill in the recipient
and amount, click Send. The transaction is built and signed
inside this browser tab with your ML-DSA-87
private key — the private key never leaves the tab — and only
the already-signed envelope is POSTed to
api.qsdm.tech/api/v1/wallet/submit-signed. The
validator verifies the signature against the embedded public
key and enforces sender == hex(sha256(public_key)),
so the validator can never spend on your behalf.
v0.4.1 replay protection: every send carries a
per-account nonce that the validator atomically
bumps inside the same transaction as the balance debit. Replays
(same envelope, same nonce, twice) return HTTP 409
nonce_replay rather than double-spending. The
Nonce field below auto-resolves from the validator before
sign-time; you can override it manually for off-line ceremonies.
How this works & CLI
- Keypair generation: a
~3 MBGo WebAssembly module (wallet.wasm) runs the same cloudflare/circlML-DSA-87implementation that QSDM validators use to verify your transactions. It calls the browser'scrypto.getRandomValuesfor the keygen entropy. - Encryption: the browser's
WebCryptoAPI (crypto.subtle) derives the AES-256 key withPBKDF2-SHA256(600 000 iterations, 16-byte salt), then encrypts the private key underAES-256-GCMwith a fresh 12-byte nonce. The on-disk format is identical topkg/keystore(Go) so the CLI and browser can swap keystores freely. - Address derivation: the QSDM address is
hex(sha256(public_key)). Same shape as the validator-sidepkg/walletderivation. - Bounded network surface: the Generate / Open / Sign
tabs only fetch the three static files
(
wallet.wasm,wasm_exec.js,wallet.js). They never POST the passphrase, the private key, the public key, or even the address. The Check balance and Send transaction tabs are the two exceptions — Balance does a single read-onlyGETagainstapi.qsdm.techwith the address in the query string, and Send does a singlePOSTto/api/v1/wallet/submit-signedwith the already-signed transaction envelope (the body contains your public key + signature + amount + recipient; never the private key or passphrase). Both happen only after you click their button. Confirm in DevTools → Network. - WASM build version: loading…
Or do it from the CLI
Identical keystore format, offline. Import into QSDM Hive for normal use.
Advanced operators can use qsdmminer-console --protocol=v2
(see miner quickstart).
# Build once git clone https://github.com/blackbeardONE/QSDM cd QSDM/QSDM/source go build -o qsdmcli ./cmd/qsdmcli # Generate a keystore (passphrase prompted) ./qsdmcli wallet new --out ~/.qsdm/wallet.json ./qsdmcli wallet show
This wallet page runs entirely in your browser. Source: wallet WASM + wallet.js.