Skip to content

Migrate the Trezor adapter to Connect 10 - #232

Draft
droplister wants to merge 2 commits into
mainfrom
chore/trezor-connect-10
Draft

Migrate the Trezor adapter to Connect 10#232
droplister wants to merge 2 commits into
mainfrom
chore/trezor-connect-10

Conversation

@droplister

@droplister droplister commented Aug 4, 2026

Copy link
Copy Markdown
Member

Ready to merge as soon as a stable v10 ships. Everything compiles, lints, builds and passes unit tests — the one thing that can't be checked from a dev machine is a real device, so the emulator workflow is the gate.

Branched off chore/dependency-audit (#231), so it carries that PR's commits too.

Payoff

  • npm audit: 11 low → 0
  • bundle: 2.46 MB → 2.38 MB

Both because v10 drops @trezor/connect out of connect-webextension's deps, taking crypto-browserifyelliptic and utxo-libtiny-secp256k1elliptic with it. Worth being precise: elliptic never reached the shipped bundle under 9.x either (tree-shaken; signing is @noble/secp256k1 + @scure/btc-signer). This cleans the advisory list and the build graph, not a live exposure.

The emulator keeps working

v10 splits the API in two:

connect-webextension @trezor/connect
surface TrezorConnectPublicAPI TrezorConnectPrivilegedAPI
init() takes manifest/version/env/debug/enabledNetworks/requestedPermissions/coreMode full ConnectSettings — incl. transports: ['BridgeTransport']
events on, uiResponse, updateConnectSettings

That matches how the emulator was already driven: trezor-node-integration.test.ts uses @trezor/connect directly over the Bridge, and trezor-emulator-tests.yml already documents the browser operations tests as "Limited (expected)" because connect-webextension's popup architecture can't reach BridgeTransport — true under 9.x too.

So this un-quarantines that suite (skipped in 215f8c5 when the 10.x-alpha attempt dropped @trezor/connect). Re-added at 10.0.0-beta.1 as a devDep, and audit still reports 0 — v10's utxo-lib no longer carries tiny-secp256k1. e2e/trezor-emulator.ts needed no changes; it drives the bridge over plain HTTP.

Still test.fixme'd: trezor.spec.ts → "shows Trezor popup when connecting". Disabled because 10.x-alpha threw during connect in headless CI; whether beta.1 fixes it can only be settled by running the emulator workflow, so it's left rather than flipped blind.

What changed

All breakage was in trezorAdapter.ts. Deleting src/types/trezor-connect.d.ts is what exposed it — a hand-written stub of the v9 surface, so the compiler could never report that surface changing.

MechanicalErr moved from payload.error to error.message (29 sites); useEmptyPassphrase moved under device; pingDevicegetFeatures (it moved into the omitted management API); getAddress/getPublicKey split path and bundle into separate overloads.

Structural

  • Device events are gone with no replacement — connectionStatus/deviceInfo are now established by the first getDeviceInfo()/pingDevice() call rather than pushed from DEVICE.CONNECT/DISCONNECT.
  • getAccountInfo no longer starts discovery → selectAccount, which returns path/address/xpub directly and retires extractXpubFromDescriptor.
  • coin typing caught a real defect: two call sites passed the v9 long name 'Bitcoin', which isn't in v10's symbol union and would have failed on-device. This wallet only signs Bitcoin, so coin is dropped from HardwareMessageSignRequest and pinned to 'btc'.
  • events polyfill added — v10's @trezor/utils imports EventEmitter from Node's events, which vite resolves to __vite-browser-external and fails the background build.

Verification

  • tsc --noEmit clean
  • biome check src clean (678 files)
  • wxt build succeeds
  • vitest run src/utils/hardware src/utils/wallet — 139 passed, 11 skipped (emulator suite needs a local emulator on :9001)
  • playwright test e2e/pages/compose/broadcast/index.spec.ts — 10 passed
  • no elliptic/tiny-secp256k1/browserify-sign anywhere in .output/chrome-mv3

Not verified: nothing above touches a real device. trezor-emulator-tests.yml must pass before this merges.

https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj

@droplister droplister changed the title Spike: what @trezor/connect-webextension 10 would take @trezor/connect-webextension 10 Aug 4, 2026
@droplister droplister changed the title @trezor/connect-webextension 10 Migrate the Trezor adapter to Connect 10 Aug 4, 2026
Not mergeable - tsc fails by design. Recorded so the work is ready when v10
is stable; see TREZOR-CONNECT-10.md.

v10 drops @trezor/connect from the tree, and with it the crypto-browserify
and utxo-lib subtrees that carry elliptic. npm audit goes from 11 low to 0.
Those 11 are one advisory (GHSA-848j-6mx2-7j84) counted once per package in
the chain, and elliptic never reaches the shipped bundle - it is tree-shaken
out, and our signing runs on @noble/secp256k1 and @scure/btc-signer.

Deleting src/types/trezor-connect.d.ts is what makes the breakage visible.
It was a hand-written stub of the v9 surface, so the compiler could not tell
us when that surface went away. Removing it surfaces 68 errors, all in
trezorAdapter.ts. Most are mechanical - the Err branch moved from
payload.error to error.message, pingDevice moved to the omitted management
API, and the getAddress/getPublicKey/getAccountInfo params tightened.

Two are not. Device events (on/off/uiResponse) have no replacement, so
connection state has to be polled. And init() no longer accepts popup,
transports, pendingTransportEvent, transportReconnect or connectSrc, which
is how trezor-emulator-tests.yml drives the emulator - so migrating now
would rewrite the hardware signing path and delete its automated
verification in the same change.

Claude-Session: https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj
Completes the spike. Everything compiles, lints, builds and passes unit
tests; what it cannot do here is drive a real device, so the emulator
workflow is the gate before this merges.

npm audit goes from 11 low to 0 and the bundle drops 2.46 MB -> 2.38 MB.
Both come from v10 dropping @trezor/connect out of connect-webextension,
taking crypto-browserify -> elliptic and utxo-lib -> tiny-secp256k1 with it.

The emulator keeps working. v10 splits the API: connect-webextension gets
the public surface, whose init() takes no transports, while @trezor/connect
keeps the privileged one - full ConnectSettings, plus on/uiResponse and the
management methods. That is already how the emulator was driven, so
re-adding @trezor/connect at 10.0.0-beta.1 un-quarantines the Node suite
skipped in 215f8c5, and audit still reports zero. e2e/trezor-emulator.ts
needed nothing: it drives the bridge over plain HTTP.

Deleting src/types/trezor-connect.d.ts is what exposed the API breakage. It
was a hand-written stub of the v9 surface, so the compiler could never say
when that surface changed.

Mechanical: the Err branch moved from payload.error to error.message,
useEmptyPassphrase moved under device, pingDevice moved to the omitted
management API so getFeatures replaces it, and getAddress/getPublicKey split
path and bundle into separate overloads.

Structural: device events are gone with no replacement, so connection state
is established by the first getDeviceInfo/pingDevice call rather than pushed.
getAccountInfo no longer starts discovery, so selectAccount replaces it - it
returns path, address and xpub directly, retiring extractXpubFromDescriptor.

coin is now a typed union, which caught a real defect: two call sites passed
the v9 long name 'Bitcoin', which is not in the union and would have failed
on-device. This wallet only signs Bitcoin, so coin is dropped from
HardwareMessageSignRequest and pinned to 'btc'.

The events polyfill is needed because v10's @trezor/utils imports
EventEmitter from node's events, which vite resolves to
__vite-browser-external and fails the background build.

Claude-Session: https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj
@droplister
droplister force-pushed the chore/trezor-connect-10 branch from a3b7628 to 06d4316 Compare August 4, 2026 23:06
droplister added a commit that referenced this pull request Aug 10, 2026
`npm audit` reported a high against nanoid — not the Trezor `elliptic` chain the
release floor exempts, and with a fix available. It reaches us as
vite -> postcss -> nanoid, so `--omit=dev` hid it from the CI gate and it was
never in the shipped package. It is still worth closing: the advisory range is
<3.3.17 and postcss already allows ^3.3.16, so it was one patch away. nanoid is
now 3.3.18 and the full tree has no high or critical advisories at all, where
before it had one.

  biome                 2.5.6   -> 2.5.7
  @testing-library/jest-dom 7.0.0 -> 7.0.1
  happy-dom            20.11.1  -> 20.11.2
  tsx                   4.23.9  -> 4.23.11
  vite                   7.3.6  -> 8.2.1

vite is a major, and wxt 0.21.3 already declares `vite ^6.3.4 || ^7.0.0 ||
^8.0.0-0`, so it is a supported combination rather than a gamble. Build, tsc,
lint and 4406 tests pass on it; the built extension goes 2.52 MB -> 2.54 MB.

Nothing under `@trezor/` moved. Connect 10 is still beta-only on npm — `latest`
is 9.7.3 — so #232 stays parked until a stable release, as intended.

Both overrides stay, and both were checked rather than assumed:

- `protobufjs` is load-bearing. Without it the tree resolves 7.4.0/7.5.5 and
  audit reports a **critical** against protobufjs plus eight highs across the
  Trezor chain.
- `ws` is load-bearing too, but not where it looks. Production resolution is
  identical with or without it; what it prevents is `ws@7.5.9` landing under
  `@trezor/trezor-user-env-link`, the emulator test harness, which brings three
  highs into the dev tree. So it earns its place on dev hygiene, not on the
  shipped package — worth writing down, because a production-only audit makes it
  look redundant.

Every version is pinned exactly: `npm install` writes carets, and the
Check Pinned Dependencies job rejects them.

Claude-Session: https://claude.ai/code/session_01HUJSeVf1JXG1Rp3VXpb2Cr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant