From bc6dbeb6ac724f6e6f9fad888fcb9f1e978651b9 Mon Sep 17 00:00:00 2001 From: Jinhao Xu Date: Wed, 4 Nov 2026 20:04:37 +0800 Subject: [PATCH 1/2] docs: record the work 0.8.1 shipped and the 0.9.0 changes The 0.8.1 tag included everything merged since 0.8.0, but its notes listed only the native host fix; the phishing list, transaction simulation and remaining browser methods move into its section, and 0.9.0 carries the audit fixes. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- CHANGELOG.md | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1837a7c2..d70a8237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ A `vX.Y.Z` tag runs `publish-npm.yml` (publishing `packages/wallet`, `packages/w ## [Unreleased] +## [0.9.0] - 2026-11-05 + +Hardening from the 0.9 audit: contract-reported token text is shown only when it is safe, pending +connection requests are bounded and expire, and the engine's timeouts and jitter run on the +injected timer and random source. Closes #99, #100, #101 and #102. + ### Added - `@qntx/wallet-engine`: untrusted contract text is checked before it is shown: a watched token's symbol must be printable (no control, bidi or zero-width characters, at most 32 code points) and its decimals an integer in 0..36 or the request fails with `-32602`; a non-ASCII symbol adds a `token-symbol-unicode` warning; simulated asset changes keep an unverified token's `symbol` and `decimals` only when they pass the same checks. @@ -20,15 +26,19 @@ A `vX.Y.Z` tag runs `publish-npm.yml` (publishing `packages/wallet`, `packages/w - `@qntx/wallet-chains`: BIP-322 script pushes longer than 252 bytes are rejected instead of mis-encoded. - `@qntx/wallet-engine`: the Solana and EIP-1193 handlers share one session-event helper and the Solana sign path one request method. -- `@qntx/wallet-engine/connect`: the injected Solana Wallet Standard wallet now conforms to `@wallet-standard/base` and `@solana/wallet-standard-features` (typed, no cast): every feature is versioned `1.0.0`, `solana:signTransaction` and `solana:signAndSendTransaction` declare `supportedTransactionVersions: ["legacy", 0]` and are variadic (N inputs become one host request, one approval), `signMessage` returns `[{ signedMessage, signature, signatureType }]`, `standard:events` `on` returns an unsubscribe function, and each input's `account` and `chain` are forwarded. The handler rejects an account other than the session's (`4100`), an unknown or mixed chain (`-32602`) and a chain the session is not authorized for (`4100`); sign-and-send needs a chain and returns raw signature bytes. +## [0.8.1] - 2026-11-05 + +A native wallet can unlock again after it locks, without restarting the app. This release also +shipped the work merged since 0.8.0 — the local phishing list, transaction simulation and the +remaining in-app browser methods — including the breaking engine changes listed below; they were +missing from these notes when the release was cut. + +### Added - `@qntx/wallet-engine/connect`: the remaining browser methods. - `wallet_addEthereumChain` answers `4902` for a chain the wallet does not enable, otherwise `null`; a chain outside the session goes through the `network` connection approval without becoming current. The page's `rpcUrls` are validated for shape only and never used. - `wallet_watchAsset` (ERC-20) reads `symbol` and `decimals` on-chain in a new factor-free `watch-asset` request, shows them with a `token-impersonation` danger when another built-in token of the chain reports the same symbol, and adds the token on approval. `AssetsController` gains `isTracked` and `tokenMetadata`; `RequestControllerOptions` takes a required `tokens` and `Eip1193HandlerOptions` a required `isTracked`. - `solana:signIn` (Sign In With Solana) is registered in the injected Wallet Standard wallet; the message text from `connect/siws.ts` is byte-identical to `@solana/wallet-standard-util` 1.2.0 and bound to the page's host. -- `@qntx/wallet-engine/connect`: Solana `signMessage` now refuses non-UTF-8 bytes with `4200` like `personal_sign`, and a Solana message request's display carries `message.text` (and `signIn`). -- Sessions must be reconnected to use `wallet_watchAsset` and `solana:signIn`: they are new session methods. - - `@qntx/wallet-engine`: transaction simulation for display. Internal EVM and Solana sends, dApp `evm.transaction` requests and single-transaction `solana-sign` requests carry a `simulation: SimulationOutcome` (`success` with signed `AssetChange`s, `reverted` or @@ -57,20 +67,6 @@ A `vX.Y.Z` tag runs `publish-npm.yml` (publishing `packages/wallet`, `packages/w from `@qntx/wallet-engine/idb`). - `@qntx/gateway` (staging): a `scheduled` handler and a `RISK` KV namespace for the list; the build is not scheduled until its hosting is decided. -### Changed - -- **Breaking:** `RequestControllerOptions` takes a required `simulateSolana`, and - `@qntx/wallet-chains` `parseCompiledMessage` returns `lookups` (table address with writable and - readonly indexes) in place of `lookupCount`/`lookupAddresses`. -- **Breaking:** `EngineOptions.publicStore` is required, and `ConnectionController` and - `RequestController` take a required `phishing` option. -- `@qntx/wallet-engine`: `engine.unsubscribe()` also stops the phishing list refresh. -- The install-id `fetch` for the gateway moved from `NetworkController` to `gateway/client.ts`. - -## [0.8.1] - 2026-11-05 - -A native wallet can unlock again after it locks, without restarting the app. - ### Fixed - `packages/wallet-native`: after a lock (manual or background auto-lock), a wallet deletion or a @@ -83,6 +79,16 @@ A native wallet can unlock again after it locks, without restarting the app. - `packages/wallet-native`: `NativeWalletOptions.host` is replaced by `createHost`, a factory called once per kernel runtime. Hosts that passed `host: fake` pass `createHost: () => fake`, creating a new fake per call when the test must survive a lock. +- `@qntx/wallet-engine/connect`: the injected Solana Wallet Standard wallet now conforms to `@wallet-standard/base` and `@solana/wallet-standard-features` (typed, no cast): every feature is versioned `1.0.0`, `solana:signTransaction` and `solana:signAndSendTransaction` declare `supportedTransactionVersions: ["legacy", 0]` and are variadic (N inputs become one host request, one approval), `signMessage` returns `[{ signedMessage, signature, signatureType }]`, `standard:events` `on` returns an unsubscribe function, and each input's `account` and `chain` are forwarded. The handler rejects an account other than the session's (`4100`), an unknown or mixed chain (`-32602`) and a chain the session is not authorized for (`4100`); sign-and-send needs a chain and returns raw signature bytes. +- `@qntx/wallet-engine/connect`: Solana `signMessage` now refuses non-UTF-8 bytes with `4200` like `personal_sign`, and a Solana message request's display carries `message.text` (and `signIn`). +- Sessions must be reconnected to use `wallet_watchAsset` and `solana:signIn`: they are new session methods. +- **Breaking:** `RequestControllerOptions` takes a required `simulateSolana`, and + `@qntx/wallet-chains` `parseCompiledMessage` returns `lookups` (table address with writable and + readonly indexes) in place of `lookupCount`/`lookupAddresses`. +- **Breaking:** `EngineOptions.publicStore` is required, and `ConnectionController` and + `RequestController` take a required `phishing` option. +- `@qntx/wallet-engine`: `engine.unsubscribe()` also stops the phishing list refresh. +- The install-id `fetch` for the gateway moved from `NetworkController` to `gateway/client.ts`. ## [0.8.0] - 2026-11-04 From 5a69ed0e0017eeba58c7f8faf4f73d315ed0917a Mon Sep 17 00:00:00 2001 From: Jinhao Xu Date: Wed, 4 Nov 2026 20:04:44 +0800 Subject: [PATCH 2/2] chore: release v0.9.0 --- bun.lock | 38 ++++++++++++++--------------- packages/wallet-chains/package.json | 2 +- packages/wallet-engine/package.json | 12 ++++----- packages/wallet-kernel/package.json | 6 ++--- packages/wallet-native/package.json | 4 +-- packages/wallet-worker/package.json | 8 +++--- packages/wallet/package.json | 6 ++--- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/bun.lock b/bun.lock index 89d76549..85754920 100644 --- a/bun.lock +++ b/bun.lock @@ -58,7 +58,7 @@ }, "packages/wallet": { "name": "@qntx/wallet", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "@scure/base": "2.4.0", }, @@ -67,7 +67,7 @@ "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", "@qntx/tsconfig": "1.0.1", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet-chains": "0.9.0", "@scure/bip32": "2.4.0", "@scure/bip39": "2.4.0", "@scure/btc-signer": "2.4.1", @@ -79,7 +79,7 @@ "peerDependencies": { "@qntx/nostr": "~0.15.3", "@qntx/spark": "~0.5.2", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet-chains": "0.9.0", }, "optionalPeers": [ "@qntx/nostr", @@ -89,7 +89,7 @@ }, "packages/wallet-chains": { "name": "@qntx/wallet-chains", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "@noble/curves": "2.4.0", "@noble/hashes": "2.4.0", @@ -124,7 +124,7 @@ }, "packages/wallet-engine": { "name": "@qntx/wallet-engine", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "@noble/ciphers": "2.4.0", "@noble/hashes": "2.4.0", @@ -144,9 +144,9 @@ "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", "@qntx/spark-wasm": "0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1", - "@qntx/wallet-worker": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0", + "@qntx/wallet-worker": "0.9.0", "@solana-program/token-2022": "0.20.0", "@solana/wallet-standard-features": "1.5.0", "@solana/wallet-standard-util": "1.2.0", @@ -160,21 +160,21 @@ "peerDependencies": { "@qntx/nostr": "~0.15.3", "@qntx/spark": "~0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0", }, }, "packages/wallet-kernel": { "name": "@qntx/wallet-kernel", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "@noble/ciphers": "2.4.0", "@noble/curves": "2.4.0", "@noble/hashes": "2.4.0", "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0", "@scure/base": "2.4.0", "@scure/bip32": "2.4.0", "@scure/bip39": "2.4.0", @@ -190,7 +190,7 @@ }, "packages/wallet-native": { "name": "@qntx/wallet-native", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "cborg": "6.1.5", }, @@ -209,14 +209,14 @@ "peerDependencies": { "@qntx/nostr-native": "0.15.3", "@qntx/spark-native": "0.5.2", - "@qntx/wallet": "0.8.1", + "@qntx/wallet": "0.9.0", "react-native": "~0.88.0", "react-native-nitro-modules": "~0.37.1", }, }, "packages/wallet-worker": { "name": "@qntx/wallet-worker", - "version": "0.8.1", + "version": "0.9.0", "dependencies": { "@noble/hashes": "2.4.0", "@scure/base": "2.4.0", @@ -229,8 +229,8 @@ "@qntx/spark": "0.5.2", "@qntx/spark-wasm": "0.5.2", "@qntx/tsconfig": "1.0.1", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-kernel": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-kernel": "0.9.0", "@scure/base": "2.4.0", "@scure/btc-signer": "2.4.1", "@types/node": "26.6.5", @@ -239,7 +239,7 @@ "vite-plus": "1.4.0", }, "peerDependencies": { - "@qntx/wallet": "0.8.1", + "@qntx/wallet": "0.9.0", }, }, }, diff --git a/packages/wallet-chains/package.json b/packages/wallet-chains/package.json index 2946b579..7355a796 100644 --- a/packages/wallet-chains/package.json +++ b/packages/wallet-chains/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet-chains", - "version": "0.8.1", + "version": "0.9.0", "description": "qntx/wallet chain semantics: SignRequest codecs, display decoding, verifiability and signing for EVM, Solana and Bitcoin", "license": "MIT OR Apache-2.0", "author": "QuantX ", diff --git a/packages/wallet-engine/package.json b/packages/wallet-engine/package.json index 69957118..22c6c7fd 100644 --- a/packages/wallet-engine/package.json +++ b/packages/wallet-engine/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet-engine", - "version": "0.8.1", + "version": "0.9.0", "description": "qntx/wallet engine primitives: controllers, events and encrypted engine storage", "license": "MIT OR Apache-2.0", "author": "QuantX ", @@ -69,9 +69,9 @@ "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", "@qntx/spark-wasm": "0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1", - "@qntx/wallet-worker": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0", + "@qntx/wallet-worker": "0.9.0", "@solana-program/token-2022": "0.20.0", "@solana/wallet-standard-features": "1.5.0", "@solana/wallet-standard-util": "1.2.0", @@ -85,8 +85,8 @@ "peerDependencies": { "@qntx/nostr": "~0.15.3", "@qntx/spark": "~0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1" + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0" }, "devEngines": { "packageManager": { diff --git a/packages/wallet-kernel/package.json b/packages/wallet-kernel/package.json index 64f22821..9a5f7527 100644 --- a/packages/wallet-kernel/package.json +++ b/packages/wallet-kernel/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet-kernel", - "version": "0.8.1", + "version": "0.9.0", "private": true, "description": "qntx/wallet secret enclave kernel (private, bundled by the host packages)", "license": "MIT OR Apache-2.0", @@ -26,8 +26,8 @@ "@noble/hashes": "2.4.0", "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-chains": "0.9.0", "@scure/base": "2.4.0", "@scure/bip32": "2.4.0", "@scure/bip39": "2.4.0", diff --git a/packages/wallet-native/package.json b/packages/wallet-native/package.json index 0912180b..e0c3fb00 100644 --- a/packages/wallet-native/package.json +++ b/packages/wallet-native/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet-native", - "version": "0.8.1", + "version": "0.9.0", "description": "Native kernel runtime host for the qntx wallet — CBOR transport, KernelHost adapter and createNativeWallet", "license": "MIT OR Apache-2.0", "author": "QuantX ", @@ -60,7 +60,7 @@ "peerDependencies": { "@qntx/nostr-native": "0.15.3", "@qntx/spark-native": "0.5.2", - "@qntx/wallet": "0.8.1", + "@qntx/wallet": "0.9.0", "react-native": "~0.88.0", "react-native-nitro-modules": "~0.37.1" } diff --git a/packages/wallet-worker/package.json b/packages/wallet-worker/package.json index 11c4f9d0..714b0ec1 100644 --- a/packages/wallet-worker/package.json +++ b/packages/wallet-worker/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet-worker", - "version": "0.8.1", + "version": "0.9.0", "description": "Web Worker and worker_threads hosts for @qntx/wallet", "keywords": [ "nostr", @@ -67,8 +67,8 @@ "@qntx/spark": "0.5.2", "@qntx/spark-wasm": "0.5.2", "@qntx/tsconfig": "1.0.1", - "@qntx/wallet": "0.8.1", - "@qntx/wallet-kernel": "0.8.1", + "@qntx/wallet": "0.9.0", + "@qntx/wallet-kernel": "0.9.0", "@scure/base": "2.4.0", "@scure/btc-signer": "2.4.1", "@types/node": "26.6.5", @@ -77,7 +77,7 @@ "vite-plus": "1.4.0" }, "peerDependencies": { - "@qntx/wallet": "0.8.1" + "@qntx/wallet": "0.9.0" }, "devEngines": { "packageManager": { diff --git a/packages/wallet/package.json b/packages/wallet/package.json index c7c99918..30b6939d 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -1,6 +1,6 @@ { "name": "@qntx/wallet", - "version": "0.8.1", + "version": "0.9.0", "description": "Self-custodial wallet SDK: Wallet host entry, protocol and types", "keywords": [ "sdk", @@ -84,7 +84,7 @@ "@qntx/nostr": "0.15.3", "@qntx/spark": "0.5.2", "@qntx/tsconfig": "1.0.1", - "@qntx/wallet-chains": "0.8.1", + "@qntx/wallet-chains": "0.9.0", "@scure/bip32": "2.4.0", "@scure/bip39": "2.4.0", "@scure/btc-signer": "2.4.1", @@ -96,7 +96,7 @@ "peerDependencies": { "@qntx/nostr": "~0.15.3", "@qntx/spark": "~0.5.2", - "@qntx/wallet-chains": "0.8.1" + "@qntx/wallet-chains": "0.9.0" }, "peerDependenciesMeta": { "@qntx/nostr": {