Release history

Changelog

Every release of BTX PQ Wallet, newest first: what changed, and why. The post-quantum send core and key derivation are byte-pinned to the BTX node across all of them.

v1.5.0

Latest 2026-10-05

Includes everything prepared for 1.4.0 (below), which was never published, plus this round.

Your coins can move even if BTX switches off the everyday key. Every address this wallet has ever shown has two keys behind it: the everyday key (ML-DSA) and a recovery key (SLH-DSA). Until now the wallet could only use the first. BTX core can switch ML-DSA off if it is ever broken or doubted; it is not switched off today, but if it were, a wallet that cannot use its recovery key would hold coins it cannot move. Settings > Backup now has "Move coins with the recovery key": it moves every coin in the wallet to another wallet of yours, or to an address you type and confirm a second time.

What it costs, measured against a real BTX 0.34.12 node: the network charges each coin moved this way 10,000 vB, so 0.0001 BTX per coin at 1 sat/vB. Signing runs on up to four cores at once. Measured on an M5 with the window in the background: 5 coins in 7 seconds and 100 coins in about 7 minutes on 2026-10-03; on 2026-10-04, window hidden, 3 coins in 22 seconds, 5 in 42 seconds, 100 in 8 minutes 50 seconds (macOS slows background windows after about half a minute; the review screen's estimate assumes full speed, so with the window hidden it reads low). Coins worth no more than that are left where they are and listed, never dropped silently. One move signs at most 100 coins; the rest wait for a second move. Signing runs off the main window with a progress bar and a Cancel button, and nothing is sent until every coin is signed and checked. If a send does not land, the signed transaction is kept and sent again as is, never signed afresh.

Signing keeps going when you switch apps (macOS). WebKit pauses a background window's web page, and with it any signing in progress: measured on macOS, the second signature never finished. The wallet window now opts out of that (Tauri backgroundThrottling "disabled", macOS 14 and later), so a move signs at full speed whether or not the window is in front. While the window is minimized or fully covered the wallet skips its 30-second chain refresh and catches up the moment you return; a window merely behind other apps now keeps refreshing, which costs a little more network than 1.4.0. If no coin finishes for 45 seconds, the progress line says so plainly.

Newly mined coins wait until the network accepts them. A solo miner's block reward cannot be spent until it is 100 blocks old, and the network refuses a whole send that includes a younger one, so a miner who had just found a block could not send at all. Such coins are now left out of Send, the recovery-key move, the artifact forward and the node-wallet sweep, and the screen says how many blocks are left ("1 newly mined coin can be sent after about 99 more blocks"). Measured on a test node: a reward was held one block before the limit and sent at the limit.

The artifact check no longer trusts a shortened answer from the server. Before spending a coin the wallet now also checks that the output it reads is really that coin: this wallet's address, the coin's exact amount. A server that left an artifact's marker out of a transaction could otherwise make the artifact's coin look like plain BTX (a gap older than 1.5.0). Remembered checks are also forgotten when you switch servers.

Mining wallets can spend every coin. A wallet that receives mining payouts holds one coin per payout, often thousands. The wallet checks each coin's transaction before spending it (so an artifact's coin is never spent by accident), but it only ever checked about 600, and every coin past that was set aside with a note to "try again in a moment" that could never help. Measured on a test chain with 800 payouts: sending 10.5 of 11.2 BTX failed with "insufficient funds"; with this version the same wallet sends 9.5 BTX in one transaction. Every coin is now checked, eight at a time, and a transaction proven to carry no artifact is remembered until the wallet locks, so only the first send after opening the wallet takes a moment ("Checking your coins: N of M"). The Artifacts tab and Send share that work instead of each fetching every transaction.

Send knows when the everyday key is switched off. If every node that refuses a send says the everyday key is disabled, the wallet says so in plain words, remembers it, and shows a note on the Send tab with one click to the recovery-key move. The first normal send that goes through clears it. A new help topic explains the recovery key.

What it is not: both keys come from your master key, so this does not help if the master key itself is stolen.

Under the hood: the qID core is re-vendored (qid feat/recovery-spend-multi @ 4779eaf) and proven equivalent to the 1.4.0 core by the new tools/qid-equivalence.mjs (1,990 comparisons, 0 differences).

v1.4.0

never published; folded into 1.5.0

Includes everything prepared for 1.3.1, which was never published, plus the round below.

One confirmation is no longer treated as final. BTX blocks near the tip race constantly: btx-ops measured 39 fork races in about 21 hours on 2026-09-29, mostly 1 to 6 blocks deep and one 17 deep, and concluded that a BTX transaction under about 20 confirmations can still be reversed. Your history now counts each payment's confirmations ("3 of 20 confirmations") until it passes 20, about 30 minutes, and then shows its date as before. A payment pushed back out of its block by a competing one now shows as pending again instead of keeping the old block's count, and a count the wallet cannot make yet says "counting confirmations" rather than looking settled. The help text says the same, and the chime when a payment lands in a block no longer calls it final.

The fork check stops crying wolf on every tip race. It used to compare the newest block, where a routine race reads as a fork and draws "do not send". It now compares six blocks below the tip both sources share. Six is the engine's own bound on an ordinary automatic reorg (BTX 0.34.12, bounded reorg policy), so a disagreement that deep is a real split. A genuine fork is reported about nine minutes later than before; a witness that has fallen behind is still never compared below a fork point.

Servers the wallet stopped trusting for money can no longer be asked about money. Byron Bay and explorer.minebtx.com left the wallet's money list on 2026-08-19, but the network gate underneath still let both be asked about any address. minebtx is gone from the gate entirely. Byron Bay keeps exactly what the wallet uses it for, two block reads for the fork check and a copy of every send, and nothing else (audit 2026-07-25, F5).

An unencrypted wallet that holds money says so, under the balance. A wallet created without a passphrase stores its key unencrypted on this device. That was said once at creation and again in Settings. It is now said every time the wallet holds coins, with a button that goes straight to adding a passphrase (audit 2026-07-25, F2). Watch-only wallets have no key and never show it.

Forwarding an artifact shows the fee it actually pays. When the change from the fee coin is too small to keep, it is added to the fee; the preview used to show the fee before that, so it could understate the real fee by up to 0.00003818 BTX. The safety cap is now checked on the fee actually paid, and the coin that pays the fee is compared with the artifact's coin regardless of letter case. All three rules are in one tested function now.

A new passkey seal is proved to open before it is saved. On Windows and Linux, where a passkey protects the wallet instead of Touch ID, a seal is now decrypted and, where the platform could differ, reopened with a real passkey prompt before it is stored. If it does not open, nothing is written. The wallet also reads qID's newer passkey seal format, so a later version can adopt it safely.

A watch-only wallet for a test-network address explains itself. The post-quantum core refuses tbtx and btxrt addresses since August. A watch-only wallet saved before that would fail with a decoder error every time it opened. It now says what it is and that it can be forgotten.

The post-quantum core runs on the latest audited libraries. qID was rebuilt on @noble/post-quantum 0.7.1, @noble/hashes and @noble/curves 2.4.0 and @scure/base and @scure/bip32 2.4.0. None of the changes touch ML-DSA-44, SLH-DSA-SHAKE-128s or ML-KEM-768. Before the swap, 1,920 comparisons between the old and new core (30 seeds by 5 indices, every key type, both sign-in formats, 30 money-path builds, and signatures checked in both directions) found zero differences.

More of qID's audit work now guards the wallet itself. New wallet tests pin the signed messages of a sweep, a three-coin send and an artifact forward; hold the transaction size estimates to the exact numbers a real BTX node reported in the August regtest run (3,873, 7,691 and 11,509 vbytes); check that one satoshi of change moves every signed message; refuse a missing or non-bigint fee cap; refuse test network addresses; spend a coin listed twice in different case only once; and sign in end to end with the current challenge format while refusing an unknown one.

The block reading moved into the network notice (1.3.1, #100). The always-on header counter listed under 1.3.0 now lives inside the network notice, with a light-theme contrast fix. That notice is hidden while everything is healthy, so the counter is seen when it matters.

The wallet no longer blames the whole BTX network when the fault is its own server. Measured live on 2026-09-06: the wallet's data server sat on the same block for 9.5 hours while the network was 337 blocks ahead and producing normally. The wallet told everyone "BTX network is not producing blocks", which was false, and it pointed at the wrong remedy: waiting, when the answer was to use a different server. The wallet only names the network now when an independent source confirms it is stopped. When no second source can be reached it says so plainly, that either the chain or this server has stopped and it could not tell which, and it adds the other half of the news, that the balance on screen may be out of date. The send warning is unchanged: it still stops and asks either way.

The fork check has a witness that answers. The wallet compares its newest blocks against an independent source, and the only source it had has been down since early September, so every wallet has been showing the fork check as unavailable. easyNode's witness at witness-1.easybtx.com is now asked first. Measured on 2026-09-15, it was at the tip and held the reference block hash at every one of ten heights checked. It is allowed exactly two read-only questions about blocks and nothing else: it cannot be asked about anyone's balance, coins or history, and it is never handed a transaction, so the "delivered to N of M nodes" count on a receipt does not include it. The previous source stays as a fallback and comes back on its own.

v1.3.0

2026-09-06

The wallet says when its fork check could not run, instead of drawing the same screen as when it agreed. The second opinion the wallet asks about the chain can be too far behind to answer at all: measured 2026-09-06, that source was frozen 1,700 blocks back while the wallet was at the tip, so every comparison silently skipped. A check that did not run now says so rather than looking like a check that passed, and the wallet deliberately does not fall back to comparing at the stale source's own tip, because agreement below a fork point says nothing about which side of it you are on.

A server the wallet talks to can now be limited to exactly what it is for. A source used only to compare blocks gets two read-only block requests and nothing else, and a node used only to receive your signed transactions gets that and nothing else. Neither can be asked about anyone's balance, coins or history. This changes nothing today; it is what makes it safe to add more nodes to send through, which is the practical answer to transactions not spreading between nodes on their own.

Every send now goes to every node the wallet can reach, not just one. Measured on 2026-09-06 across two independent public BTX nodes: 21 of 22 peers had never sent our node a transaction, the two nodes' mempools shared none of their entries, and valid transactions paying twice the going rate had been waiting four days while blocks were mined empty. Transactions are not reaching miners reliably by peer relay, so a send handed to a single node was a bet on that node's own peers. The wallet now hands the same signed transaction to every node it may talk to, at once. One node accepting is a successful send, and a node replying that it already has the transaction counts as success rather than an error. The receipt says how many nodes took it. Sweeps and artifact forwards deliver the same way, because recovering funds is where landing the transaction matters most.

The wallet now works out its own transaction id instead of asking a server for it. It derives the id from the bytes it signed, so no server is trusted to name a transaction, and a node that answers with a different id is ignored and recorded rather than shown. This needed care on BTX: a measured post-quantum spend is 3,916 bytes of which 3,777 are the signature, and the signature is not part of the id, so the Bitcoin-shaped shortcut would have produced an id matching nothing.

A block counter in the header, always on. The newest block the wallet has read and how old it is, next to the wallet name, coloured by the same chain-health verdict as the banners so the two can never disagree. It costs no extra request; it rides the chain-health probe the wallet already runs about once a minute. Click it and the live node census opens (easybtx.com/nodes), every node's height beside the one you are reading from. It exists because a chain that stops looks exactly like a chain that is quiet, and because "is my data server on the latest tip?" was a question people had to leave the app to answer.

v1.2.0

2026-09-05

Sending works again on wallets with a lot of history. Wallets that had received many payments over time could show a correct balance and then refuse to send, with either "HTTP 400: Too many history entries" or "Could not check all your coins just now, so nothing was sent". Nothing was ever wrong with those wallets or their coins. The server that lists a wallet's spendable coins gives up once an address has held more than 500 coins at any point in its life, and it never recovers afterwards, so the wallet was being told there was nothing to spend. Measured on 2026-09-04: an address with a zero balance and no coins at all still failed, because the limit counts the busiest moment in its history rather than what it holds now. The limit has been raised on our server, and this release stops the wallet mistaking that answer for an empty wallet.

When the wallet cannot list your coins, it now says so in words you can act on. Those two messages were the server's own, printed verbatim. They named nothing a person could do and read like the wallet had lost the money. They now explain what happened, state plainly that your BTX is safe and untouched, and say whose problem it is to fix. When the cause is not one we recognise, the message keeps a short technical tail so a screenshot is enough for us to diagnose it, instead of the same sentence for every possible cause.

Reading the chain is around three times less data, and much faster on a slow connection. The wallet was downloading every chain read uncompressed even though the server had been offering compression all along: one history page measured 7,964,044 bytes where 2.7 MB would have done. It also opened a brand-new encrypted connection for every single request, and one Send can make hundreds of them. Both are fixed. On a fast link this is invisible. On a slow or unreliable one it is the difference between a Send that works and a Send that times out, which is what people on long-distance connections were hitting.

A history too large to read no longer means a wallet that can never send. The wallet refused any single chain response over 8 MiB, a limit set when the largest expected answer was thought to be under 1 MiB. Post-quantum transactions are far larger than that, and one live address (828 transactions, 597.89 BTX) was already over it, so on the version in the stores its owner cannot send at all. The limit is now set against measured sizes with room to grow, and a test keeps it there.

The fee guidance and the fee cap are now BTX numbers. The wallet judged "network busy" against a 1 MB block; BTX blocks are 24 MB, so a small backlog that would clear in the next block made it quote up to five times the needed fee. And the 0.02 BTX fee safety cap, a Bitcoin figure, quietly limited how many coins a post-quantum send could combine: at the highest fee rate it allowed ten. It is now derived from the network's own transaction size limit and the highest fee rate the screen accepts, so it can never bind before those do. The wallet also refuses, before signing, to build a transaction larger than the network will relay, instead of signing for minutes and then failing with a server error.

Artifacts are never silently dropped by a failed read. A network hiccup while checking your coins could make a relic vanish from the Artifacts list, hide the tab, and tell you in History that it "has since left this wallet". Now a failed check is counted and shown, the tab stays, and "has since left" is only ever said after a scan that read everything. The same fail-closed rule now covers forwarding an artifact (it no longer tells you to add BTX when the coin check simply failed) and the wallet list (a broken balance answer no longer shows as 0 BTX and triggers a false "received" chime).

Far less network use. The wallet capped its own burst at 8 requests in flight instead of hundreds, and stopped re-downloading your whole history page every 30 seconds when nothing had changed.

The wallet now notices when the BTX chain itself has stopped. A stalled chain can look perfectly normal on screen: every server answers, every balance is right, nothing moves. The wallet now measures the age of the newest block against the clock, shows a warning when the chain has not moved for a long time, and asks you to confirm before sending into a stalled chain. This is the first version that can tell a quiet chain from a stopped one.

v1.1.0

2026-08-17

Your wallets now have a second copy on this Mac. Until now, the wallet list — including every seed — lived in exactly one place: the app's local storage. If macOS ever evicted or corrupted that file, the wallet opened looking brand new. The wallet now keeps an automatic second copy in the Mac's Keychain (encrypted by macOS, never leaving this computer, never in iCloud), refreshes it on every change, and restores from it by itself if the original is ever missing or damaged — with a notice telling you it happened, and the damaged data kept aside rather than destroyed. Forgetting a wallet removes it from the Keychain copy too: forget still means forget. This was tested by corrupting and deleting a real wallet store and watching every wallet come back byte-for-byte.

Creating a wallet now asks you to prove you saved the master key. The old screen could be clicked past, which meant the only backup of a brand-new wallet was a screen you had already dismissed. Now the "open wallet" button unlocks only after one of: saving a recovery file, or typing the key's first and last 4 characters back — with the on-screen key hidden and pasting disabled, so the answer can only come from wherever you actually put it. That moment is what catches a half-copied key. Restoring an existing wallet skips this: you just proved you have the key by entering it.

A guided "save to password manager" step. The backup screen can now lay out a ready-made Login item for Bitwarden, 1Password or iCloud Passwords — the wallet's address in the item name and username so future-you can tell entries apart, the master key in the password field, one copy button per field.

The wallet now notices when its data server falls behind. A server can answer politely while being stuck blocks in the past — you saw confirmed transactions sit as "pending" forever during the August fork. The wallet now compares all of its servers' latest-block heights about once a minute and, if the one you're on is 3 or more blocks behind, says so plainly and offers a one-click switch to the server that is current. A failing server was already handled; a lying-by-lagging one now is too.

Every few months, the wallet asks you to prove your backup still works. Backups rot silently: files get cleaned up, the password-manager entry turns out to be for the other wallet, the paper note has 63 characters. Roughly every 3 months per wallet, a small banner asks for the same first-and-last-4 check, from your saved copy. Passing takes ten seconds. Failing tells you to fix your backup now — while the wallet is still open and the key is still one click away.

v1.0.0

2026-07-27

The macOS build, done right: universal, signed and notarized. The wallet's feature set is v0.30.0 unchanged; this release exists because the v0.30.0 macOS download could not open at all. Windows and Linux stay on v0.30.0.

Opens on a double-click. The app is signed by Bonuz Technology DMCC and notarized by Apple, and the ticket is stapled to both the app and the .dmg. Download, drag to Applications, open. No right-click Open, no Terminal, and macOS names Bonuz as the verified developer.

One download for every Mac. The binary is universal: Apple Silicon runs it natively, and Intel Macs (macOS 10.15 or later) run the very same .dmg natively too.

What went wrong in v0.30.0, honestly. The withdrawn macOS build declared a restricted entitlement (keychain sharing between apps) that macOS honours only with a provisioning profile a direct-download app does not have, so the system killed the app the instant it opened, while every signing check still passed. The wallet never needed that entitlement and it is gone. The release pipeline now launch-tests the exact signed bundle before anything ships, so a build that cannot open cannot be published.

Windows and Linux unchanged. Both stay on v0.30.0. They never had the fault.

v0.30.0

2026-07-23

A new shimmer theme, one-click qID sign-in, a livelier balance, and a batch of polish. The post-quantum send core, coin selection and artifact protection are byte-unchanged, and every change was adversarially re-verified before release.

Sign in to a site with one click. Clicking "Open in BTX PQ wallet" on a site like btc2btx.com now opens a focused sign-in card the moment a wallet is open: the site up top, one Sign button, and the exact request behind "Verify request" if you want to inspect it before signing. The proof is sent back automatically and success shows in green: you're signed in, return to your browser tab. You can switch which wallet signs right on the card; only that one address is disclosed. If the site cannot be reached you can retry or drop to the manual copy-paste flow, unchanged in Settings > qID Sign-In. A login proof can never move funds. Also fixed: on macOS, clicking a sign-in link while the wallet was closed opened the app but never showed the request; it now appears the moment you open a wallet.

A new "style of bonuz" appearance. Settings > Appearance > Color adds a fifth option. It keeps the clean green layout, but every brand-green accent (buttons, the balance frame, active tabs, links and the logo) comes alive as the bonuz orange-to-pink shimmer. Your money colours never change: received stays green, sent stays red. Reduced-motion users get the same palette without the animation.

The balance reload is dramatic again. Pressing refresh on your wallet list now spins the whole balance, the digits and the "BTX" unit together, and settles over about a second, so even a small or zero balance clearly reacts. The button also rests briefly after a few quick presses so it cannot be spammed.

Tap an incoming artifact to open it. In History, an artifact you received is now tappable and opens the same detail card as the Artifacts tab, with its artwork, type and identifiers.

Clearer message when a wallet holds only an artifact. If a wallet's only coin is the one an artifact rides on, Send now explains the balance is held inside an artifact and cannot be sent as ordinary BTX without destroying it, instead of a confusing "no confirmed funds". The coin was always kept safe; only the wording was misleading.

A tidier wallet-list footer. The long backup sentence is now a short line with an info button that opens the full master-key backup explanation.

v0.29.0

2026-07-19

Your relics finally show their real artwork, the qID sign-in proof is readable again, and adding a passphrase can no longer brick a wallet, after three independent adversarial security passes. No change to the post-quantum send core or key derivation (qid.bundle.js byte-identical).

Your relics show their real artwork. The Last Relic, the Vintage Seal and the attribute collections now display their actual picture in the wallet, both as a thumbnail in the Artifacts list and full-size when you open one, loaded from btxscan.io. A missing picture falls back to the on-chain sigil, never a broken image. You can turn artwork off in Settings > General > Artifact artwork.

The qID sign-in proof is readable again. After signing, the proof used to appear as black text on a black panel in dark themes. It is now clearly readable in every colour and light/dark combination, with a green frame that pulses when your proof arrives.

Forwarding stops honestly if the chain stops carrying artifacts. When a server refuses a forward because BTX has removed the transaction field artifacts ride on, the wallet says so plainly instead of offering a button that can only fail. Your artifacts stay yours, stay visible, and their coins stay protected.

"Set passphrase" can no longer brick a wallet. Adding or changing a passphrase now proves the new encrypted seal can be reopened before it replaces the old one. If anything is wrong, nothing is written and the wallet is left exactly as it was. A wallet with no passphrase is clearly flagged "Unencrypted".

v0.28.0

2026-07-17

The wallet now gets its chain data from our own server first, with automatic failover behind it — plus a cleaner artifact detail page, a fresh look, clickable fix guides, and a batch of self-custody hardening.

Our own chain server, with failover. Balance, history, and sends now talk to our own BTX Esplora node (api.btxscan.io) first, and fall back automatically to two independent community servers (Byron Bay, minebtx) when it cannot be reached:

  • If the current server stops answering, the wallet advances to the next one on its own and says so in a banner with a one-click "Try next server" — reads keep working even when a server (or your own DNS cache) has a bad day.
  • Sending is deliberately different: a broadcast is never quietly re-sent to a different server, and a failed send stays on screen for you to re-confirm yourself — a flaky network can never turn one payment into two.
  • The free-text server field is gone. Settings offers the three official servers only, and the app's network layer refuses everything else: only those three origins (or your own machine, for self-hosters) can ever be reached, and nothing inside the app can widen that at runtime.
  • Honest small print: the Byron Bay fallback does not index unconfirmed transactions yet, so while it is the active server a just-sent payment can show up ~90 seconds late, and very long histories show only the most recent pages. Your money is unaffected — the wallet only ever spends confirmed coins, and anything it cannot verify it sets aside instead of spending.

A cleaner artifact detail page. Opening a relic or NFT now leads with its artwork in a square frame and lays the rest out so it is obvious what everything is:

  • Artwork shows in a square frame that fits any picture without cropping or stretching it: a tall image gets bars on the sides, a wide image gets bars above and below, and a square one fills the frame. The quantum sigil holds the frame until you tap "Show artwork", which still fetches and verifies the image against the on-chain record before it appears, so nothing loads on its own.
  • The three identifiers are now clearly labelled and no longer look alike: the artifact's own fingerprint, the IPFS address where its artwork and traits live, and the on-chain transaction that carries it, each with a one line description so it is never a guess which hash is which.
  • The wall of explanatory text is gone; the facts (chest value, type, schema, minted or transferred) sit in a tidy grid.

Everything else in this release:

  • A fresh look: the PQ hexagon is now the default logo on new installs, and the logo picker shows the real logos instead of describing them in words. The window is titled "PQ wallet for BTX".
  • When a newer version exists, a blinking banner on the start screen points to pq-wallet.com/download. Updating stays manual and verifiable — there is still no auto-updater, on purpose.
  • Every network-flavored error now carries a clickable fix guide (pq-wallet.com/fixbugs), so a DNS hiccup gets a one-click way out instead of a screenshot of a scary red message.
  • Artifact protection is stricter: if the wallet cannot fully verify that a coin is not carrying a relic or NFT — say, the server's transaction data is incomplete — that coin is set aside rather than spent. A send can no longer burn an artifact because a server had a bad day.
  • .btxwallet files now import AND export in the official full-seed descriptor format, byte-identical to what btx.dev and the node tools produce — a bundle written here restores anywhere, and theirs restore here.

No change to the post-quantum send core or key derivation (qid.bundle.js byte-identical). Transparent funds only.

v0.27.0

2026-07-15

Sign in to a website straight from the desktop wallet, no copy-paste. When a site (btx.best) offers "Open in BTX PQ Wallet", it now launches the installed wallet with the sign-in request. The wallet shows you which site is asking, you pick which of your wallets signs, and on your click the login proof is sent back to that site automatically. You never copy or paste anything, and the site never sees a key.

  • The wallet registers the btxqid:// link scheme and opens a dedicated "Sign in to <site>" screen that reuses the exact qID Sign-In picker you already have: the proof discloses only the one address you choose, your other wallets stay private, and the seed is unlocked in place and wiped right after.
  • Nothing is ever signed automatically. A link only pre-fills the request and shows you the site, you still review the origin, choose a wallet, and click Sign. Every incoming link is treated as untrusted: a malformed request, or a proof URL whose origin does not match the site, is refused and nothing is signed. A qID proof is a login signature in a separate domain from transactions; it can never move funds.
  • One new, tightly-scoped network action returns the proof. It refuses to send anything that is not a well-formed login proof, will only post to an https address whose origin matches the origin named inside that proof, refuses redirects and embedded credentials and cleartext http, times out fast, and discards the response, the same hardening the chain and artwork fetches already use. Copy-and-paste still works everywhere as a fallback.

v0.26.1

2026-07-15

Two hardening fixes from a release audit. No change to the send core or the crypto.

  • The recovery and bundle sweep now protects your artifacts the same way ordinary Send already does. A sweep re-emits no artifact commitment, so a relic or NFT coin caught in a sweep would be burned. The sweep now spots artifact carrier coins from the address history and keeps them back (shown as "kept safe"), and fails closed on any coin it cannot verify, so a sweep can never burn an artifact. This closes the last path where a carrier could be spent as a plain input.
  • Recovery files and wallet bundles are now created owner-only (0600) from the first byte, instead of being written under the default file mode and tightened a moment later, so the plaintext master key is never briefly readable by another local user on a shared machine.

v0.26.0

2026-07-15

Move a wallet in and out as a portable file. You can now restore a .btxwallet.json bundle, the kind the website, a node, or btx-cli writes, straight into the wallet, and export the open wallet back out as the same kind of file. Both directions are fully offline: the file is read through the native open/save dialog and parsed on your own machine, with no new network calls anywhere.

  • Restore adopts the bundle's master key as an ordinary wallet and takes you straight to the one-time master-key backup screen, exactly like restoring any other key. The file is refused unless it is a mainnet bundle whose seed, fingerprint, and first address all agree, a corrupt or tampered file is turned away with a plain reason, and no key material is ever put on screen.
  • Because a bundle is HD but this wallet watches a single address, a quiet background check looks a few addresses ahead on both change branches after you restore. If any coins sit somewhere the adopted address wouldn't see, a banner offers to sweep them with the existing recovery wizard, nothing moves on its own, and the check never blocks or slows the backup step.
  • Export lives in Settings → Backup. A .btxwallet.json has no passphrase, that is the format, it stores your master key in plain text, so exporting takes a deliberate second click that spells out the risk, then writes the file to disk only (never the clipboard) with owner-only permissions.

No new cryptography and no new network endpoints: the same key derivation the wallet already uses both writes and checks the file, and the background address check reuses the balance lookup every screen already makes.

v0.25.1

2026-07-14

History now says when an artifact moved. A transaction carrying a BZA1 payload used to render as a bare "RECEIVED +0.001 BTX", no hint that a relic changed hands. Each such history row now carries a small marker naming what happened and to what: "Artifact minted to you: …", "Artifact received: …", "Artifact sent: …", a state update says "Artifact updated" (even when the same transaction also pays someone else) and a send-to-self "Artifact sent to yourself", so a row's caption can never contradict its own header (soulbound ones get a violet accent). The tag is decoded by the same parser the Artifacts tab already uses, only from transaction data the history view already fetched, no new network calls anywhere, and a pre-computed tag arriving in explorer JSON is ignored: fresh transactions always decode locally. One naming rule now covers every view: an artifact from a collection the wallet doesn't know by name (like RELICLAB) shows its raw collection tag in the Artifacts tab, the detail page, and the history line alike, so the same artifact never carries two different names. A malformed or oddly-shaped transaction from the explorer can never blank the history view, it simply renders without a tag. Cached history rows keep no script data, so the tag is computed when the cache is written and stored with the row; the cache key was bumped (v1 → v2), which forces one ordinary re-fetch of your recent history on first open.

v0.25.0

2026-07-14

Artwork, inside the wallet, without trusting anyone. An artifact's detail page now has a "Load artwork" button that fetches the off-chain record and image through the wallet's own hardened network path and shows the picture right in the page.

  • Nothing loads on its own: artwork is fetched only when you press the button, one artifact at a time, never while the list renders. Once loaded, it reappears instantly for the rest of the session.
  • The gateway is not trusted. Every byte fetched must hash to the exact record hash written on chain (and the image to the address inside that verified record), or nothing is shown. A tampered or wrong response cannot be displayed, only refused.
  • Only plain image formats (PNG, JPEG, GIF, WebP) are accepted, checked by their actual bytes, never by what the server claims. Anything that looks like a web page or SVG is refused outright, oversized responses are cut off rather than trimmed, and images that declare absurd dimensions are refused before your machine ever tries to draw them.
  • On any problem you keep the artifact's sigil and see one plain line: "Artwork could not be loaded and verified." Even a verified image that turns out to be undisplayable puts the button back so you can simply try again, nothing can wedge the page for the session. The existing "open the record in your browser" link is unchanged.

v0.24.3

2026-07-12

Hardening from an adversarial audit of the send path.

  • Closed a rare artifact-burn hole: on a wallet with a very large number of coins whose transactions sit beyond the history page, coins past the coverage limit are now set aside rather than treated as ordinary spendable, so a held relic can never slip through and be spent. A coin whose transaction cannot be read is never spendable, in every case.
  • "Send all" now says plainly when a coin could not be checked this round and is not included in the sweep, so a sweep is never silently short. Try again in a moment to include it.

v0.24.2

2026-07-12

Fixes the send that stayed stuck. Sending plain BTX from a wallet that holds an artifact was blocked with "could not check your coins", because the coin check tried a per-transaction lookup the wallet's own network guard does not permit, so every check failed and every coin was set aside.

  • The Send screen now spots artifact coins from your transaction history, the same data the Artifacts tab already reads, instead of a blocked per-coin lookup. A wallet with no artifacts does no artifact work at all: the Send screen is plain BTX, end to end. Your relics stay protected: their coins are never spent as an ordinary input, verified against every artifact this wallet holds.
  • Added the single-transaction lookup to the network guard as a well-formed, read-only route, so the Artifacts tab and the coin check can pull in an older artifact whose mint is beyond the recent history page.
  • The Artifacts tab now appears only in a wallet that actually holds an artifact. Switching wallets no longer carries the previous wallet's state over, and a fast switch always re-checks the wallet you landed on.

v0.24.1

2026-07-12

Sending plain BTX no longer stops when an artifact check hiccups. The Send screen protects your relics and NFTs by never spending an artifact's coin, but it used to verify every coin in one all-or-nothing pass, so a single flaky network read could pause an otherwise ordinary send with a scary "could not check your artifacts" message.

  • The check is now per coin. A coin is spendable only once its transaction is read and confirmed not to be an artifact carrier. A coin that cannot be verified right now is quietly set aside for this attempt, never spent, so an artifact can never be burned, while the rest of your balance stays fully spendable. One slow network read no longer blocks a send that has plenty of plain BTX behind it.
  • The Send and Receive screens stay plain BTX and never mention artifacts. All artifact handling lives in the Artifacts tab. In the rare case nothing can be verified at all, you see a plain "try again in a moment", not artifact wording.

v0.24.0

2026-07-12

Artifacts become tappable. Every relic or NFT in the Artifacts tab now opens a full detail page on top: the big quantum sigil, all its properties, the chest value it carries, its record hash, and a link to the off-chain record on IPFS (copy or open, behind a plain safety notice). Soulbound status is unmistakable, with a lock badge and a one-line explanation.

  • Forward an artifact to another wallet, straight from its detail page. The forward is carrier-preserving: the artifact's coin (and any chest value inside it) travels to the recipient untouched, and the network fee is paid from your ordinary balance, never skimmed from the chest. Soulbound artifacts are refused. Paste an address or pick a saved contact. This lives only in the Artifacts tab; the plain BTX Send screen is untouched and never mentions artifacts.
  • Fixed a scan bug: a forwarded artifact is no longer shown as still held by the sender (it was mis-reading the sender's change coin), which also stops that change coin from being needlessly held back from ordinary sends. The carrier is now anchored to its fixed position (the first non-OP_RETURN output), which also correctly handles a chest carrier larger than the change.
  • A forwarded artifact now keeps its collection and item number in the recipient's wallet (the TRANSFER record is decoded the same way as a mint).
  • The off-chain record's IPFS address is derived directly from the on-chain commitment, with no network call: the record is a single raw IPFS block, so its CID is the commitment itself.

No change to the post-quantum send core or key derivation (qid.bundle.js byte-identical). The forward reuses the same signing path as an ordinary send. Transparent funds only.

v0.23.0

2026-07-12

A big polish pass: an update-available pill, help built into the app, an AI onboarding guide, a balance that resolves like a number, a setting for the Artifacts tab, a clearer Settings menu, and a batch of UX, copy, and accessibility refinements across every screen. No change to the post-quantum send core or key derivation (qid.bundle.js byte-identical). Transparent funds only.

  • See when a new version is out. The header shows a small "Update available" pill when a newer build exists, and it opens pq-wallet.com to download it. The check runs once per launch through a pinned, hardened Rust request to pq-wallet.com/version.json (https only, size capped, no redirects, no input from the webview), so the webview still makes no network calls of its own. There is no auto-update: you always download and verify the build yourself. When the wallet is current, nothing is shown.
  • Windows and Linux no longer say "Touch ID." The passkey prompts and buttons now name your platform's method, so it reads "Windows Hello" on Windows, "your passkey" elsewhere, and "Touch ID" only on a Mac.
  • Unlock is keyboard friendly. The passphrase field is focused when you open a wallet and Enter submits, and the Settings dialog now closes with Escape and moves focus into itself.
  • Clearer messages. The pending line no longer doubles the word "confirming, " an empty Send amount asks you to enter one instead of showing "invalid amount, " cancelling a passkey during qID signing reads cleanly, and the broadcast-blocked help suggests toggling your VPN either way plus a phone hotspot test.
  • Signing-wallet unlock is fair. Unlocking a wallet to sign a qID proof no longer counts a paused wallet or a tamper refusal as a wrong passphrase, and it shows wait times as "5 min" like the rest of the app.
  • Artifacts you hold always show. The Artifacts tab now finds a held relic even when its mint is older than the recent history window, by reading it straight from your current coins.
  • Recovery files with punctuation in the wallet name parse correctly. A brace in the wallet name no longer truncates an EasyBTX recovery file.
  • The Artifacts "View" link now follows a custom explorer, the History open-transaction arrow is keyboard operable, and the in-app "Get the latest version" button points at pq-wallet.com.
  • Built-in help, on demand. Small info buttons open a clear explanation right where you are (how your wallet is protected, network fees, qID Sign-In, how updates work), so the screens stay uncluttered and the detail is one tap away.
  • Get guided by your own AI. A new "Guide me with your own AI" option gives you a ready-made prompt to paste into any AI you trust. It knows the whole wallet and walks you through anything, by text or voice. Nothing leaves the app: you copy, you paste.
  • Your balance resolves like a number. The decrypt animation on the balance now spins digits with the decimal point held steady, so it reads as a value locking in rather than random characters.
  • Choose when the Artifacts tab shows. A new setting in Appearance keeps the Artifacts tab always visible, shows it only when you hold one, or hides it.
  • A clearer Settings menu. Bigger and easier to read, with a clear marker for the section you are in, and clicking a category now jumps straight to it.
  • Consistent, more accessible controls. A visible keyboard focus ring on every control, hover feedback on the tabs and fee buttons, better empty states, and clearer labels throughout.
  • Quantum sigil for your artifacts. Each relic or NFT now shows a distinct, glowing "quantum sigil" drawn from its on-chain fingerprint, the same on every device. A held artifact keeps its sigil when it moves to another wallet. Fully on-chain glyphs still show their real pixels.
  • Artifacts are safe from an accidental send. Send and Send-All now never spend an artifact coin as a fee, so a relic or NFT can never be burned by an ordinary transaction. If the wallet cannot check your artifacts at that moment, the send pauses rather than risk one.

v0.22.0

2026-07-11

qID Sign-In gets a signing-wallet picker, and a new Artifacts tab shows the on-chain relics and NFTs this wallet holds. No change to the post-quantum send core or key derivation (qid.bundle.js byte-identical). Transparent funds only.

  • Choose which wallet signs a qID Sign-In. A qID proof discloses exactly one address, so the Settings, qID Sign-In screen now shows the signing wallet and lets you pick any of your wallets. Your other wallets stay private. Picking a locked wallet unlocks it in place; the choice is transient and never switches your active wallet.
  • Artifacts tab: see your relics and NFTs. A new tab lists the BZA1 artifacts (Genesis relics, NFTs, attestations) this wallet holds on chain, decoded straight from the transactions, with the item number, collection, soulbound flag, and a link to the carrier transaction on BTXScan. Read-only: the wallet never mints or moves an artifact, and keeping the artifact coin here means it is never spent as a fee.

v0.21.0

2026-07-09

Safer backups by default, BTXScan as the block explorer, smart fee presets, and hardened key handling. No change to the vendored post-quantum crypto core or the transaction signing path.

  • Encrypted backups are now the default: the recovery-file encrypt checkbox is pre-ticked (Argon2id + AES-GCM); saving an unencrypted key file takes a deliberate second click after a plain warning.
  • BTXScan (btxscan.io) is the wallet's block explorer for every transaction and address link; chain data still loads from the same source, so balances and sending are unchanged.
  • Smart fee presets: Normal (2 sat/vB) and Priority (4) buttons next to a compact custom rate field. When the mempool is busy the tiers come from the live fee histogram; on a clear network they stay low on purpose because a higher fee cannot confirm faster.
  • The master key stays hidden until you reveal it: the backup screens show dots plus a Reveal button, and Settings asks you to confirm nobody can see your screen first.
  • Wrong-passphrase throttling: repeated wrong unlock attempts pause unlocking with escalating delays (1 minute from the third try, 5 minutes from the eighth), resetting an hour after the last wrong try or on a successful unlock.
  • Sends survive hostile networks: if antivirus web protection, a VPN or a firewall drops the broadcast, the wallet retries automatically, reports the real cause, and correctly shows success when the network already accepted the transaction. Safe by design: a BTX PQ transaction is deterministic, so a retry can never double spend.
  • Hardening: explorer responses are size-capped in the Rust proxy; one read-only mempool route added to the network allowlist for the fee presets.

v0.20.2

2026-07-07

qID Sign-In polish. No change to the crypto core or the proof format (still v1).

  • The Sign-In screen now shows the request's canonical site origin, so a challenge cannot dress up its "Site" line with a misleading path or embedded credentials.
  • The pasted request and the generated proof are cleared when you close Settings or lock the wallet, so nothing lingers on screen.

v0.20.1

2026-07-07

Connectivity fix for networks that inspect HTTPS. No change to the send path or the crypto core.

  • Explorer connection now uses the operating system's certificate store. The wallet trusts the same certificates the system browser does, so it connects on networks behind a VPN, a corporate proxy, or antivirus that inspects HTTPS. Before this, the app trusted only a bundled root set, so on those networks the balance could not load (it showed "Explorer offline") even though the browser reached the same explorer fine. Under the hood: reqwest now uses rustls with native OS roots. This does not weaken anything: the wallet never sends keys over the network, and the transaction sighash commits to the amounts, so a proxied or lying explorer still cannot forge a wrong-amount spend.
  • Clearer connection error. When the explorer cannot be reached, the wallet now shows the real reason (for example a rejected certificate or a timeout) instead of a generic "offline", so a proxy or antivirus problem is identifiable at a glance.

v0.20.0

2026-07-07

The in-wallet qID Sign-In, plus release chores. No changes to the vendored PQ crypto core (qid.bundle.js) or the transaction signing path.

  • qID Sign-In (new). Prove you control a wallet to an app or service without exposing any key. An app gives you a one-time challenge, you paste it into Settings → qID Sign-In, check which site it is for, and sign. The wallet produces a standard ownership proof (a v1 ML-DSA-44 login signature) that you paste back. This is the wallet side of the Sign-In With BTX standard (qID), the BTX equivalent of Sign-In With Ethereum. A sign-in signature is domain-separated from spending (BTX-qID/login-v1 vs TapSighash), so it can never move funds. The screen shows the site and challenge before you sign, and read-only wallets cannot sign.
  • Under the hood: the challenge parsing and proof assembly are a new pure, unit-tested module (ui/signin.js), and the whole-frontend sha256 integrity gate pins it too, so everything ships byte-for-byte as reviewed. Signing reuses the existing signLogin primitive in the crypto core, unchanged. GitHub Actions Node bumped from 20 to 24.

v0.19.0

2026-07-05

Security hardening plus readability and multi-wallet UX. No changes to the vendored PQ crypto core (qid.bundle.js) or the signing path.

  • Auto-lock (new). The wallet now locks itself after a period of inactivity and returns to the wallet list, so an unlocked wallet, whose seed and spend keys live in memory while it is open, is not left exposed if you step away. You re-open it the same way as always (passphrase, Touch ID, or Windows Hello). Configurable in Settings → Security → Auto-lock after inactivity: Off / 1 min / 5 min / 15 min (default 5 min). It never locks a watch-only wallet (no key to protect) and never interrupts a send that is broadcasting. Following a full re-audit of the v0.18 hardening, this closes the last ranked open item: the previous lock was manual-only, leaving the in-memory keys exposed for the whole session.
  • Network proxy tightened. The chain proxy is now constrained to the exact Esplora routes the wallet uses (address lookups, UTXOs, history, broadcast), query strings, arbitrary paths and methods, and non-hex broadcast bodies are refused. Defense-in-depth on top of the existing egress pin.
  • Readable settings. Each Settings section header (General, Appearance, Security, …) now reads at full size and in full-strength text instead of the same faint grey as its fields, and every field label is white, so the panel is legible at a glance.
  • Never miss a deposit, even from the wallet list. When a wallet receives while you're on the wallets overview, it now chimes and marks that wallet with a small gold hexagon next to its balance (and a brief gold flash on the amount). The marker lingers ~30 minutes, so you can tell exactly which wallet changed even if you missed the sound.
  • Copy. Dropped the "test build" framing across the app while keeping the honest facts (not yet code-signed, on mainnet, verify the SHA-256); the at-rest KDF is correctly described as Argon2id.
  • Under the hood: the auto-lock timing decision is a new pure, unit-tested module (ui/autolock.js), and the whole-frontend sha256 integrity gate pins it too, so everything ships byte-for-byte as reviewed.

v0.18.0

2026-07-04

Security hardening + send/receive UX polish. No changes to the vendored PQ crypto core (qid.bundle.js) or the signing path.

  • Security: mainnet-only send guard, rejects tbtx/btxrt (testnet/regtest) addresses that decode to the same mainnet scriptPubKey; a CI "no DOM-sink" guardrail that fails the build if any HTML/JS-injection sink is introduced (locks in the "safe DOM only" property); the vendored-bundle integrity gate is now a fail-closed whole-frontend sha256 gate (every shipped ui/ file pinned) and CI runs it, plus the anti-XSS gate, by name.
  • Send: fixed the "send twice in a row" failure (bad-txns-inputs-missingorspent) by excluding a pending send's already-spent inputs from the next send, with a clear "previous send is still confirming" message instead of the raw node error; removed the confusing change and size rows from the send preview.
  • Receive: a continuous slow "coins arriving" animation now runs on the amount while a deposit confirms, plus a new double confirm chime when it becomes final; the incoming/confirming line is now white.
  • Receipt: bigger animated Sent badge + the sent amount shown big and white, with the saved contact name.
  • Wallets list: a force-refresh button.
  • Copy: removed the shielded (SMILE) line from the wallet screen. Version metadata reconciled to 0.18.0 (Cargo.toml was lagging at 0.16.0).

v0.17.0

2026-06-27

A polish release. The post-quantum send core and qid.bundle.js are byte-unchanged; all new logic is unit-tested (full suite now 117 green). Transparent-only.

Fixed

  • Sending no longer shows a phantom "+X BTX incoming." While a send was confirming, the balance card briefly showed your own change coming back as if it were an incoming deposit. The explorer under-reports the spent side of a mempool spend, so the old funded-minus-spent math only "saw" the change returning. The pending line now classifies the actual mempool transaction, it recognises the credit as your own change, and reads "Sending X BTX, confirming…" instead of a confusing +<change> BTX incoming.
  • The "Your wallets" list keeps its balances up to date. It used to freeze on the figures from when you first opened it and only refreshed after an app restart. It now re-checks every listed wallet on the same timer as the open wallet (default 30s), updates each row in place without disturbing an in-progress rename, and refreshes the sending wallet immediately after a send. The refresh is overlap-guarded and sequential, so a long list of large wallets can't stack explorer requests.

Added

  • A little 16-bit celebration when money moves. A short, quiet (~35%) blip plays when a transaction is sent, a rising two-note tone, with gold coins bursting outward from your balance, and a different, brighter chirp when a deposit arrives, with coins pulled inward onto the number. Toggle it in Settings → General → Sound effects (on by default). The sounds are synthesised in-app (no audio files are bundled), watch-only wallets stay silent, and all motion respects "reduce motion".

Changed

  • The Send "to" field now shows the whole address. It wraps onto two rows (in a slightly larger font) instead of truncating, and the first and last six characters are highlighted in white so a pasted address can be verified at a glance. The send preview shows the full destination address too.
  • A clearer address book. Picking a saved address now uses a custom dropdown that shows each name above its full address (no more cramped native list), and the Settings → Address book rows put Edit and a compact Delete on the right. Settings category labels are larger and white for readability.
  • The bonuz link in Settings → Links now points to the new BTX-in-bonuz page (bonuz.xyz/btx-wallet), which explains it and links the mobile downloads.

Under the hood

  • New unit-tested pure helper pendingFromTxs (change-aware mempool classification, reusing the existing classifyTx), and a balance-fetch overlap guard mirroring the history one. Sounds are generated with the WebAudio API (square-wave oscillators), so nothing new is bundled and the CSP is unchanged.

v0.16.0

2026-06-18

A recovery-and-usability release. The post-quantum send core and qid.bundle.js are byte-unchanged (same key derivation and P2MR sighash); all new logic is unit-tested (full suite now 109 green). Transparent-only.

Fixed

  • The node-recovery sweep no longer reports a completed transfer as "Nothing moved." A P2MR sweep is txid-deterministic (the post-quantum signature lives in the witness, so it doesn't change the txid), so re-broadcasting an already-confirmed sweep returns the node's RPC -27 ("transaction outputs already in utxo set"). The wallet now reads that as "already in your wallet, confirmed on-chain" with a link to verify, instead of a scary failure with a raw RPC dump; the contradictory "your funds are on the way" line no longer shows when nothing was sent. A real user hit this, and their funds had in fact moved and confirmed on-chain the whole time.
  • Recovering node funds before you have a wallet here no longer dead-ends. A first-time user who recovered a node wallet.dat used to be told to "create a wallet, then run Recover again", which forced a re-upload and a full re-scan. The wallet now guides you to set up (or restore) your wallet first and continues straight into the scan and sweep, with no second upload and no re-scan.
  • History no longer chokes on a wallet with thousands of transactions (e.g. a watched miner address). Auto-refresh now guards against overlapping fetches and keeps a small per-address cache of confirmed txs (display-only, never the spendable balance), fetching just the newest page each refresh instead of re-walking ~500.

Added

  • Read-only (watch-only) wallets. Add any btx1z address to follow its balance and history. It is clearly badged READ-ONLY (with a small "view only" chip in the wallet list); sending, the master-key backup, and the receive QR are hidden, and it can never be a recovery-sweep destination.
  • Copy a full explorer link wherever a transaction ID appears. The sweep result and the send receipt now show the txid with Copy link (a complete minebtx URL), Copy ID, and Open ↗, so a paste is a clickable link rather than a bare hash. History already behaved this way; it's now consistent across the app.
  • An easyBTX Telegram link (t.me/easybtx) in Settings.

Changed

  • Shielded (SMILE) is no longer on this wallet's roadmap. BTX is moving applications and shielding to an upcoming EVX layer-2 (EVM-style); this wallet stays transparent-only.

Under the hood

  • New unit-tested pure helpers: explorer-URL builders, a broadcast-error classifier, and the history cache merge (mergeTxs) in ui/txview.js; canReceiveSweep (ui/wallets.js); isValidBtxAddress (ui/recover.js). 13 new tests; full suite 109 green. qid.bundle.js unchanged (sha256 pin intact).

v0.15.0

2026-06-15

A usability and correctness release focused on transaction history, pending funds, and the send screen. The post-quantum send core and qid.bundle.js are unchanged (byte-identical key derivation and P2MR sighash). Transparent-only, and unaffected by the BTX block-125, 000 shielded sunset; verified against the BTX 0.32.x series through 0.32.11.

Fixed

  • History now shows your full transaction list, not just the most recent 25. The wallet used to fetch only the newest page from the explorer and stop at 25, so an active wallet looked like it was missing older transactions (the most common confusion users reported). It now follows the explorer's pagination, shows an honest count footer, and always offers an "Open full history in explorer" link. (Note: the minebtx explorer's own index may still omit a few transactions; that is server-side, not the wallet.)
  • Incoming and outgoing pending (mempool) funds are now visible. A deposit that is still confirming shows a "+X incoming, confirming…" line under the balance and a PENDING chip in History, so a payment you just received no longer looks like nothing arrived. The spendable/headline balance stays confirmed-only.
  • A just-sent transaction no longer briefly looks missing. After a broadcast, History and balance now re-check on a short escalating schedule instead of a single delayed refresh.
  • Send-screen errors are now plain language. An empty or mistyped address, an out-of-range fee rate, and the fee safety cap now show clear guidance instead of raw decoder or builder text.

Changed

  • More accurate transaction labels. Self-transfers and consolidations show the fee paid instead of a misleading "-0 BTX", and a transaction whose direction can't be confirmed (the explorer dropped an input) is flagged rather than silently mislabeled.
  • Correct live fee estimate. The one-input fee hint now uses the builder's real ~3916 vB instead of a hardcoded 4950 vB, which had overstated the network fee by about 26%.
  • Settings/header copy notes that shielded (SMILE) balances must be recovered with a shielded-capable BTX node, so holders of shielded funds aren't left wondering why this wallet doesn't show them.

Under the hood

  • New, fully unit-tested ui/txview.js module (explorer pagination, transaction classification, confirmed vs. pending balance split, and friendly send-error mapping), 26 new tests; full suite 96 tests green.

v0.14.3

2026-06-13

A security-hardening release from an independent round-3 super-audit plus an exhaustive follow-up sweep of the wallet and the qID library (every finding independently re-verified). No new features. The post-quantum send core and qid.bundle.js are unchanged, byte-identical key derivation and P2MR sighash, pinned by the offline vectors, and verified compatible with BTX v0.32.8.

Security

  • The node-recovery sweep destination is now authenticated. It derives the destination address from authenticated key material (the unlocked wallet's seal-reconciled address, a no-passphrase wallet's seed, or a protected wallet unlocked inline) instead of an unauthenticated stored address, a local-write attacker can no longer redirect recovered funds.
  • Removed an unauthenticated egress-allowlist persistence channel. A custom explorer is re-confirmed per session through the native dialog; the previously-persisted explorer-allow.txt, which a local attacker could forge to widen the network allow-list and exfiltrate the seed through a compromised webview, is gone.
  • CI now runs the vendored-bundle integrity gate (sha256 pins on qid.bundle.js / argon2.bundle.js) before building the signed installer, so a tampered seed-handling bundle can never ship.
  • Recovery files are written owner-only (0600); recovery / wallet.dat reads are capped at 64 MiB and the wallet.dat seed match is linear (no longer a quadratic freeze on a hostile file); a poisoned address-book entry can no longer block the wallet screen from rendering; the recovery scan now warns on an unverifiable balance instead of treating it as empty.

qID library (the future "Login with qID" SDK, not used by the released wallet)

  • Attestation capabilities are now enforced, not just signed; key supersession pins the winning login key per serial; the single-input transaction builders range-check inputs uniformly; buildRecoverySpend requires an external round-3 SPHINCS+ signature instead of a node-rejected fallback; relying-party nonce issuance is memory-bounded.

Note

  • The vendored qid.bundle.js (cf2d33…) is intentionally unchanged: its send/derivation crypto is byte-identical to qID main, and the qID changes above are to code the wallet does not run. A bundle re-vendor stays a deliberate, regtest-gated step.

v0.14.2

2026-06-12

Shows the app version in the header on the wallet-selector and create/unlock screens, and records a compatibility check against the current BTX node. No new crypto; qid.bundle.js and the send core are unchanged. (v0.14.1 was a local-only build; its header-version change ships here.)

Added

  • Version in the header on the selector + create/unlock screens (hidden on the wallet screen, where the action icons sit).

Verified

  • Compatible with BTX v0.32.6 / v0.32.7. The transparent P2MR consensus rules the wallet reproduces, key derivation, opcodes, the 0xc2 P2MR leaf + Merkle tags, the TapSighash path, the witness-v2 bech32m address, and the min-relay/dust policy, are byte-identical upstream. The 0.32.x changes are the shielded-pool sunset, mining, and P2P transport only, none of which the transparent-only wallet touches. No send-core or key-derivation change required.

v0.14.0

2026-06-11

Rebrand to BTX PQ wallet, a full theming system, and a batch of send/privacy UX fixes. The post-quantum send core and qid.bundle.js are unchanged, no new crypto, and the money-critical identifiers (the macOS Keychain service, the BTX-WALLET-RECOVERY file magic) are untouched, so existing wallets and recovery files keep working. (Supersedes the internal-only v0.13.0.)

Added

  • Theming (Settings → Appearance). Three independent controls: a logo (BTX PQ wallet pixel mark · pq hex mark, which also sets the app & Dock icon), a colour (Green · Ocean · Violet · Amber), and a mode (System · Dark · Light). System follows the OS appearance live; Dark/Light pin it. Every colour works in both light and dark.
  • Live macOS Dock icon matching the chosen logo+colour (new set_dock_icon command via AppKit; a no-op on other platforms, and it never touches the on-disk .app bundle icon).
  • Post-send receipt. After a broadcast the send form is replaced by a clear "Sent ✓" card with the full transaction hash, a Copy button, and a View-in-explorer link. Returning to Send shows a fresh form.
  • bonuz wallet promo (Settings → Links): "BTX is live in the bonuz wallet", in the bonuz brand (animated orange→pink gradient).

Changed

  • Name → BTX PQ wallet across the app, window title, About, and icons.
  • The privacy-eye now also masks transaction amounts in History, not just the balance.

Removed

  • The "You are on mainnet" warning, and the misleading Send all button (it errored and read as "send my whole balance"). The underlying sweep still powers node-fund recovery.

Fixed

  • Received is always green, Sent always red, in every theme. Direction colours had tracked the theme accent (so "received" turned cyan in the Ocean theme); they are now their own --pos/--neg tokens that a reskin can't change.

v0.12.1

2026-06-03

Recover node-era funds from an EasyBTX/btxd pqhd (post-quantum HD) descriptor wallet, from either the recovery .txt or the binary wallet.dat. The post-quantum send core and qid.bundle.js are unchanged; no new crypto.

Added

  • Recover node funds (EasyBTX/btxd file). A new wizard on the create/add screen parses a node EasyBTX Wallet Recovery File, derives every node address through the frozen qID bundle (byte-for-byte identical to btxd, guarded in CI by a node-verified address oracle), scans each address's real balance from the explorer, shows the total, and on explicit confirmation sweeps each funded address (one transaction each, signed with that address's own derived identity) into one single-address wallet you control. The same file also works via "Restore from a file" (auto-detected). Scanning is sequential with a live progress bar + Stop, since each address costs a ~6s SLH-DSA keygen (inherent, it must match the node); a "Scan deeper" option covers funds past the used range.
  • Import a binary wallet.dat directly. Users who only have the node's wallet.dat (no .txt) can recover too: a dependency-free SQLite reader extracts the pqhd seed(s) and feeds the same scan/move pipeline. Each extracted seed is trusted only if SHA256(seed)[:4] equals the descriptor's public stub, so a parse bug fails closed. Encrypted wallets are detected and refused with guidance.
  • Move-into-your-existing-wallet UX. Recovered funds move into the wallet you already use (shown by name, same master key, not a new wallet/key), explained in a plain-language banner, with an optional build → review → broadcast preview that shows the exact amount / fee / destination before anything sends.

Security / safety

  • Rejects any descriptor whose path isn't */0h/0h/{0, 1}/* (the frozen bundle pins coin=account=0h, so any other path would derive wrong addresses), plus public-form seeds, foreign files, and malformed input.
  • Shows the scanned on-chain balance before any sweep; never persists the node seeds (the recovery file is the durable backup, an interrupted sweep is replayable); keeps the per-tx 0.02 BTX max-fee + dust clamps.

v0.12.0

2026-06-02

Pre-release security-hardening update. Driven by an internal adversarial security audit (.gstack/security-reports/) and its fixes. The post-quantum send core and qid.bundle.js are unchanged. 40 node:test + 18 Rust tests green.

Security

  • F1 (HIGH): external-link opener. open_url no longer opens links through a Windows shell; it validates the URL (https-only, well-formed, no shell-unsafe characters) and opens with a shell-less opener. Closes a command-execution path that was reachable through a crafted explorer URL.
  • F5 (MEDIUM): explorer proxy. chain_request now validates the explorer base URL (a valid http/https URL with a host; cleartext http allowed only to a loopback host), closing an SSRF / cleartext-downgrade gap.
  • F2 (HIGH): recovery-file restore. Restoring from a recovery file now derives and shows the wallet's btx1z address, requires explicit confirmation, and hard-fails if the file's address line does not match its key (anti address-poisoning).
  • F4 (MEDIUM): passphrase policy. Minimum passphrase length raised from 6 to 12, enforced on create / set / change / recovery-file / restore. Never enforced on unlock, so existing wallets still open.
  • F6 (MEDIUM): build supply chain. All GitHub Actions pinned to full commit SHAs, the Rust toolchain pinned, and Dependabot added for review-gated bumps.
  • F10: local security reports (.gstack/) are now gitignored.
  • F7 (LOW): defense-in-depth. Transient seed buffers in the macOS keychain commands (mac_seal/mac_unseal) are wiped via zeroize on every exit path.
  • F9 (LOW): supply chain. The vendored crypto bundles (qid.bundle.js, argon2.bundle.js) are integrity-pinned by sha256 in a test, with provenance recorded. (F8, legacy PBKDF2 iterations, is intentionally left unchanged: the count must match existing v1 blobs to decrypt them, and those auto-upgrade to Argon2id on unlock.)

Changed

  • F3: create screen. Passphrase and Touch ID are presented as the recommended, most-secure tier. The no-passphrase option stays available (one click) but now carries a clear "stored unencrypted on this device" warning plus an info button that explains the tradeoff and reassures that the wallet is self-custodial either way. Both options are kept by design.

Security model (unchanged, for reference)

  • Keys are generated on-device and never leave it. At rest: a passphrase seal uses Argon2id (64 MiB, t=3) then AES-256-GCM; a biometric seal stores the seed in the OS keychain behind Touch ID (macOS) or Windows Hello.
  • Sends have a hard 0.02 BTX max-fee clamp, a dust guard, and a confirm step.
  • A full independent third-party audit is planned but not yet complete; keep your 64-character master key backed up offline.

v0.11.0

internal only, never publicly released
  • Re-vendored hardened qID crypto bundle. Native macOS Touch ID unlock (dormant until the app is signed). Opt-in code-signing wiring (macOS entitlements + gated Windows CI signing). Address book for public addresses. Argon2id replaced PBKDF2 for new seals; legacy PBKDF2 seals lazy-upgrade to Argon2id on unlock.

v0.10.0

2026-06-02
  • Multiple wallets (start-screen list, add / forget / rename, lossless migration of the legacy single wallet). Settings security: set / change / remove passphrase. Save / Restore checksummed recovery files via native dialogs. Argon2id KDF for new seals.

v0.9.1

2026-06-01

The first public release, the build you can actually download, on macOS and Windows, with passkey unlock and a full transaction history.

Highlights

  • Public macOS (.dmg) and Windows (.exe) downloads. The Windows installer (NSIS) is built reproducibly in GitHub Actions on windows-latest.
  • Passkey unlock via the WebAuthn PRF extension: the 32-byte seed is sealed with AES-256-GCM under a key minted inside the authenticator (Touch ID / Windows Hello / security key), and the design fails closed if PRF is unavailable rather than storing the seed unprotected.
  • Transaction history, per-transaction RECEIVED / SENT with a signed amount, date, counterparty address, and explorer link, computed locally from the transaction vin/vout deltas.

Trust

  • An "Is it safe?" section publishes the SHA-256 and VirusTotal lookup for every build, and explains plainly why a brand-new unsigned installer draws a SmartScreen reputation warning and a few machine-learning antivirus flags.

Notes

  • Test build: unsigned and on mainnet (sends move real BTX). Passkeys work on Windows (WebView2); on the unsigned macOS build they fall back to a passphrase until the app is code-signed.

v0.5.0

2026-05-31

The first build where the whole loop works: receive, hold, and send real BTX on mainnet.

Highlights

  • Real post-quantum sends confirmed on BTX mainnet (P2MR with ML-DSA signatures), including Send all (full sweep).
  • A Receive tab with an address QR code and a one-line, copyable btx1z address.
  • A Settings panel: configurable Esplora explorer URL, an auto-refresh interval, and the master-key backup.
  • Auto-refresh of balance and history on a timer, and explorer deep-links on every history row.

Safety

  • A dust guard and a hard 0.02 BTX maximum-fee clamp are enforced before any broadcast, with a preview of the fee, change, and input count and an explicit confirm step.

Notes

  • All network requests run in the Rust layer, the webview never reaches the internet directly, while the seed stays in the webview. Single address (v1).

v0.1.0

2026-05-31

The first build: a native desktop wallet on the node-verified post-quantum send core.

Highlights

  • Post-quantum keys derived on-device from a single 32-byte master seed: ML-DSA (the spending/login key) and SLH-DSA (the recovery key), combined into a btx1z P2MR address.
  • Receive, balance, and send on the node-verified qID core, multi-input P2MR construction (selectAndBuild, buildSweepAll) with every sighash commitment rebuilt per input.
  • Self-custodial: keys are generated on the device and never leave it; a one-time 64-character master-key backup is the only recovery.

Architecture

  • A Tauri 2 desktop shell with a Rust chain_request command proxying all chain traffic, a passphrase seal using PBKDF2 (210k iterations) + AES-256-GCM in local storage, and strict safe-DOM rendering (no innerHTML of any external string).

Notes

  • Test build on BTX mainnet, sends move real BTX. Transparent funds only.