Skip to content

Run a real host beside a dev server: createWebSocketProvider is documented but missing #435

Description

@peetzweg

The goal: a real host on your desk

A product developer types one command and gets a browser tab in which their product behaves exactly as it does inside the mobile host. Real signer, real product account for its own .dot name, real statement store, real permissions. No phone in the loop.

truapi-host signing-host --serve --frame-listen 127.0.0.1:9955 --product-id my-product.dot --auto-accept &
pnpm dev

That is what a dev server is for every other kind of app, with the host playing the role a database or an API mock plays elsewhere. Nothing about it is exotic, and the CLI is already 90% of the way there.

Why this matters more than it sounds

  • The paths that matter most are the least tested. Product-account signing, AutoSigning grants and authorized statement proofs can only be exercised on a phone running a nightly build today, which means they are the code we iterate on least.
  • The simulated host cannot catch drift. @parity/host-api-test-sdk is good and worth keeping, but it answers with dev accounts and its own wire implementation. It did not catch the RFC-0022 DerivationIndex change. A real host caught it in thirty seconds.
  • A phone in the loop taxes every cycle. Two devices per debugging round, and a clean identity, a reset, or two players at once are all genuinely painful.

The CLI fixes all three. Two small gaps stop it from being usable that way, one on each side:

gap issue state
a browser cannot dial the frame socket this issue PR #438
the host cannot run beside a dev server #436 PR #439

Both PRs are open and green. Together they turn the recipe above into something any web product can adopt in two lines.

Evidence that the rest already works

Verified against a live signing-host from a browser product (the DIM2 SPA, @parity/product-sdk-host in a plain tab), and re-verified across restarts over two weeks:

  • container detection, requestLogin answering AlreadyConnected, camera permission granted by the host
  • accountGet for dim2.dot/0 and /1, deterministic and stable across restarts, same username five days later
  • signRaw and createTransaction for our own product, refused for a foreign product id exactly as documented
  • resourceAllocation.request for AutoSigning returning Allocated, which is the promptless grant iOS gives and Android refuses, so this is the only place that code path can be exercised at all
  • statementStore.createProofAuthorized returning a real Sr25519 proof, submit accepted by the node, and a MatchAll subscription delivering the statement back
  • entropy.derive for the self-custody playing key

The gap this issue covers

The iOS and Android host READMEs both tell products to take the bridge URL and pass it to @parity/truapi's createWebSocketProvider(url). That function is not in the package. Grep for it and you find only the docs that promise it:

  • ios/truapi-host/README.md:80 and :274
  • ios/truapi-host/Sources/TrUAPIHost/TrUAPIHost.swift:936
  • android/truapi-host/README.md:58 and :256
  • android/truapi-host/src/main/kotlin/io/parity/truapi/TrUAPIHost.kt:25 and :533

Because it is missing, the same 30 lines are hand-written four times already:

where what
ios/.../TrUAPIHost.swift:192 createWebSocketMessagePort as a Swift string literal
android/.../TrUAPIHost.kt:421 the same snippet again, in Kotlin
rust/crates/truapi-host-cli/js/ws-provider.ts a real WireProvider, whose TCP branch uses nothing Node-specific
dim2-spa-fable apps/web/src/dev/cliHost.ts our copy, written because there was nothing to import

The practical effect: truapi-host signing-host --frame-listen says it is "required for browser clients", but a browser client cannot use it. The sandbox bootstrap builds only two transports, the iframe handover and a MessagePort already parked on window.__HOST_API_PORT__. There is no WebSocket path, so a product in a plain tab cannot reach the frame socket while it is listening.

Ask, two small parts, both in PR #438:

  1. Export createWebSocketProvider(url): WireProvider from @parity/truapi, so the docs become true and the four copies can collapse onto one.
  2. Add connectWebSocketHost(url) on the sandbox path, so isCorrectEnvironment() and getClientSync() also work in a plain tab. This is the half that lets a product built on @parity/product-sdk-host run against the CLI host with no product code changes at all.

Known limits, so the pitch is honest

  • The only network preset is paseo-next-v2, so a product whose descriptors target another network keeps its own chain reads while statements and host chain routes stay on nextv2.
  • Host-routed chain access was unavailable until recently, because feature_supported was hardcoded false. That is fixed on main and answers from the served chain set, so this is no longer a gap, just something to build on.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions