Skip to content

Releases: paritytech/host-api-test-sdk

v0.13.1

Choose a tag to compare

@johnthecat johnthecat released this 20 Sep 12:41
ddceacd

Three parts of the host were declared to the core as absent and could not be configured otherwise, so three product-facing features were dead on arrival in 0.13.0. Each is now wired, and each has a test that fails without it.

All three surfaced when a real product suite migrated to 0.13.0. They shipped because account.getUserId() and preimage.submit() had no coverage here.

Fixed

account.getUserId() failed for every product with Unknown: No primary username for this session. The session was minted with both username fields empty, on the assumption that the core resolves them itself. It does — but only from the dotNS contracts on Asset Hub, and it gives up at once when the host declares no Asset Hub, which this one did. Sessions now carry "<name>.01" for the active account (alice.01, bob.01), following switchAccount.

A chain: 'Bulletin' network never reached the core, so preimage.submit() could not work at all — the core asked to connect to the all-zero genesis and got bulletin chain unavailable: … no chain configured for genesis 0x0000…. The core routes its own Bulletin and Asset Hub traffic by the genesis hashes handed to it at boot, not by anything supportedChains() reports, and both were hard-coded to all-zero. They now come from whichever configured network declares that chain role. Preimage lookup was unaffected.

The product's dotNS identifier was fixed at test-product.dot. The core refuses any call acting as a product account whose dotNsIdentifier is not the id the host declared the product under — signRaw, signPayload and createTransaction with PermissionDenied, statementStore.createProofAuthorized with UnknownAccount. A product signing under its own name got a blanket PermissionDenied with nothing in any log to explain it, and no option existed to change the id.

Added

productId on createTestHostServer and the Playwright fixture (default 'test-product.dot') — the dotNS identifier the host declares the product under, and the namespace the core scopes product storage and permissions to.

createTestHostFixture({
  productUrl: "http://localhost:3000",
  productId: "myapp.dot",
});

It is not what productAccounts is keyed by — that is the dotNsIdentifier in the request, which the gate normally forces to the same value. Note that 'localhost' and 'localhost:<port>' are development wildcards the core admits for any dotNsIdentifier, so setting one turns the gate off entirely.

accounts[].username, overriding the derived "<name>.01":

accounts: [{ name: "Alice", uri: "//Alice", username: "zaphod.07" }]

Changed

A network with chain: 'AssetHub' now has an effect on the core, where before it was declared absent. The core reads dotNS from it — product manifests, and the trustedProducts grants carrying cross-product access — so a grant that was refused instantly now costs a real round trip to that network's rpcUrl. Unchanged for a network with no chain role. Signing is untouched: still the in-page People loopback, still no network.

Upgrading

Nothing to change. Set productId if your product signs under its own dotNS name, and add a chain: 'Bulletin' network if you test preimage submission.

Full notes: CHANGELOG.md · README

v0.13.0

Choose a tag to compare

@johnthecat johnthecat released this 20 Sep 07:08
561a954

A rewrite of everything below the public API. The host no longer speaks the @novasamatech/host-container protocol — it runs the TrUAPI core itself, truapi-server compiled to WebAssembly in a Web Worker. Both sides of the wire move together, so a product must be on @parity/truapi 0.17 and boot through @parity/truapi/sandbox. A product on the old protocol will not connect at all.

Still no network, no node, no Docker: the People chain is an in-page loopback statement store, and the host mints both halves of the SSO session at boot.

Upgrading

Grep your tests for these — most are silent if you miss them.

  • productAccounts is keyed by the bare product id. { 'myapp.dot/0': 'bob' }{ 'myapp.dot': 'bob' }. A per-index key is now rejected with an error naming the replacement, and one entry moves every indexed account of that product together.
  • Any test pinning a product-account address must re-read it. The core derives index n as a soft child of the product subtree, not the hard junction //Selected//dotnsId/n. Root dev accounts are unchanged — //Alice is still 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY.
  • Signing is an SSO round trip, not a synchronous callback. Tests that await a signature already work; tests that read getSigningLog() immediately after triggering an action must now await the product's own promise first.
  • Chat requires executionKind: 'Worker'. The core denies every Chat entry point for App and Widget.
  • accounts[].uri accepts only hard junctions, and the roster's first entry is the one active signing identity. switchAccount now resolves names against the roster instead of synthesising //Name.
  • Removed controls: the statement-store, login and payment groups, plus setEnforcePermissions. Removed types: LoginBehavior, PaymentLogEntry, PaymentTopUpBehavior, StatementSubmissionLogEntry.
  • Renamed: clearChatState()clearChat().
  • injectChatAction is async and takes ChatActionInput.

Overriding host conditions

The headline addition: a test can now set what the host reports and how it decides, live or before the product's first frame.

Two families, named consistently — get<Thing> / set<Thing> / seed<Thing> / clear<Thing> for ambient data, and set<Thing>Behavior plus get<Thing>Log / clear<Thing>Log for decisions. Ambient data covers theme, locale, feature support, the supported chain set, product storage, chat rooms and bots, and device-permission status; decisions cover permissions, user confirmation, navigation and notifications. Passing undefined to a per-key setter restores what the host would otherwise report.

initialState and behaviors on createTestHostServer and the Playwright fixture apply the same overrides before the product loads, so a product that reads theme or locale during startup can be tested on that path. An unknown status or behaviour mode throws at boot, naming the value.

Two limitations, both documented: product-storage keys must be replayed exactly as getProductStorage() reports them (the core namespaces them per product), and the function form of a behavior works in-page only — the Playwright fixture's setters take 'approve-all' | 'reject-all', because a function cannot cross page.evaluate.

See Overriding host conditions for the full table.

Also added

  • executionKind ('App' | 'Widget' | 'Worker', default 'App') on the server and the fixture.
  • getChainStatus() alongside getConnectionStatus() — the host's own session, as distinct from the product's connection. Signing travels over the session, so a switch that leaves it 'disconnected' means no signature is coming.
  • NetworkConfig.chain — a network's protocol role, reported through supportedChains(). A network that omits it is left out rather than labelled by guesswork.

Fixed

Four of these blocked signing outright, and each was invisible from the test suite that passed over it:

  • statement_submit was rejected by the core, which blocked ALL signing. The loopback store replied with the bare string "new"; the core reads a field, so every SSO request died before a signing request ever reached the responder.
  • An indexed product account was reported under one key and signed for under another — a product's own signature did not verify against its own address. Now verified against schnorrkel's own pinned vector, not just against itself.
  • The AutoSigning capability was refused as an invalid subtree secret. @scure/sr25519 hands out the cofactor-multiplied encoding; schnorrkel's SecretKey::from_bytes takes only the canonical one.
  • Topic filters were parsed under the wrong key spelling, so a real filter matched every statement and matchAny was silently narrowed to matchAll.
  • featureSupported denied the one chain the host always serves — the in-page People loopback, which every signature travels over.
  • Switching to a custom account signed with the wrong key, silently ignoring the configured URI.

v0.12.1

Choose a tag to compare

@Imod7 Imod7 released this 14 Aug 12:06
17a28f9

host-api-test-sdk 0.12.1

One fix. Drop-in upgrade from 0.12.0.

Fixed

  • All three built-in network genesis hashes refreshed after chain resets. PASEO_ASSET_HUB, PREVIEWNET, and PREVIEWNET_ASSET_HUB were all pinned to genesis values from earlier deployments of those chains, verified dead against live RPC:

    Constant Was Now
    PASEO_ASSET_HUB 0xbf0488…ef19f 0x23e730eb1c6fecae09c917439a5038cb6122d0d48980e8b9bbf0ff56f94a2ca6
    PREVIEWNET 0x477dd8…12525 0x8c27ddf678c2ae9bef0efebfc485a9309f3d735c6d3fbb8d947afc3ace0e80f4
    PREVIEWNET_ASSET_HUB 0x860d75…c7867c 0x4d11c803cc6921429e3876638977ad006ea1bba8cd3976a0bca2f164e7026210

The host routes each connection request to a network by genesis hash, so a stale pin means the host does not recognise the chain your product is asking for. The symptom is the product stuck at connection-status: "connecting" until the test times out, with a reachable RPC endpoint and nothing obviously wrong in the logs.

One thing worth calling out: before this release the pins were wrong but consistent. A test host and a set of descriptors both generated against the same dead chain agree with each other perfectly, so a suite can be green while connected to a chain that no longer exists. If your e2e went green across one of these resets without you touching anything, that is what happened.

What you need to do

  • Upgrade to 0.12.1. If you use the built-in network configs, that is the whole change — the correct hashes come with the upgrade.
  • If you hard-coded any of the three old hashes in your own NetworkConfig or in test assertions, update them. Better still, read them off the exported config (PASEO_ASSET_HUB.genesisHash) so the next reset costs you nothing.
  • These chains reset periodically. Treat a genesis literal in your own repo as something that will go stale, not as a constant.

v0.12.0

Choose a tag to compare

@mordamax mordamax released this 03 Aug 13:31
a20c7d6

host-api-test-sdk 0.12.0

Tracks upstream @novasamatech/*@^0.9.1 (triangle-js-sdks#239) and serves products on @parity/truapi@^0.6.0. v0.9 is wire-incompatible with v0.8: RFC-0022 changes DerivationIndex from a bare u32 to Enum{Index(u32), Raw([u8; 32])}, so your product side has to move in the same commit.

Against 0.11.0 a truapi-0.6 product fails quietly: the wrong account for any index other than 0, signRaw over a different payload than the one requested, and createTransaction dropped without a reply. product-sdk's E2E suite goes from 2 failed to 54 passed on this release.

What changed on our side

Product accounts take a selector, not a number (breaking)

Index(n) resolves exactly as the plain n did, so productAccounts keys and derived addresses are unchanged. Raw 32-byte selectors are new, keyed by hex ("myapp.dot/0x1234…"). The wrapper takes number | Uint8Array and normalises for you; hand-built requests wrap the index:

-hostApi.signRaw(enumValue("v1", { account: [dotnsId, 0], payload }));
+hostApi.signRaw(enumValue("v1", { account: [dotnsId, derivationIndexOf(0)], payload }));

accountCreateProof returns a struct (breaking)

-const proofHex = u8aToHex(result.value);
+const proofHex = u8aToHex(result.value.proof);

Plus contextualAlias, ringIndex, ringRevision.

accountGetAlias rejects with GetAliasErr (breaking)

Alias errors moved out of RequestCredentialsErr into their own enum (RingNotFound / NotMember / Rejected / Unknown).

SmartContractAllowance carries a selector (breaking)

-{ tag: "SmartContractAllowance", value: 0 }
+{ tag: "SmartContractAllowance", value: { tag: "Index", value: 0 } }

handleAccountSignVrf (RFC-0023, new upstream) is not implemented — the container answers SignVrfErr.Unknown.

What you need to do

  1. Upgrade to 0.12.0 and move your product side to @parity/truapi@^0.6.0 or @novasamatech/host-api-wrapper@^0.9.1 in the same commit.
  2. Through the wrapper, nothing else. Hand-built requests: wrap indices in derivationIndexOf() and adjust the three shapes above.
  3. If your fixtures still pass chain:, see 0.10.0 — it is silently ignored, so any rpcUrl override you set is being dropped.

v0.11.0

Choose a tag to compare

@valentinfernandez1 valentinfernandez1 released this 20 Jul 12:48
3aba914

@parity/truapi 0.4 products connect out of the box

Products that upgraded to @parity/truapi 0.4 (including everything built on recent @parity/product-sdk) change how the iframe channel is opened: instead of exchanging frames directly over window postMessage, the product posts { type: "truapi-ready" } and expects the host to answer with { type: "truapi-init" } carrying a transferred MessagePort. Against older test-sdk releases, that handshake went unanswered, the product waited 20 seconds for a port that never arrived and waitForConnection() timed out.

The test host now answers the handshake and serves all traffic over the transferred port. No test changes are needed:

const bobFixture = createTestHostFixture({
  productUrl: "http://localhost:5260",
  accounts: ["bob"],
  networks: [PASEO_ASSET_HUB],
});
// waitForConnection() now resolves for truapi-0.4 products too

Products on the 0.3 bootstrap (@novasamatech/host-api-wrapper) are unaffected, the direct window postMessage channel is still served, and both kinds of product talk to the same container with the same handlers, logs, and permission model.

v0.10.0

Choose a tag to compare

@BigTava BigTava released this 25 Jun 22:56
3990c24

Replaces the single chain host option with a networks array (routed by genesis hash) and renames ChainConfig to NetworkConfig. See CHANGELOG.md for the full entry and migration notes.

v0.9.2

Choose a tag to compare

@mordamax mordamax released this 15 Jun 15:12
0a4223a

Changed

  • Upstream @novasamatech/*^0.8.8. Tracks 0.8.7 (triangle-js-sdks release/0.8.7) and 0.8.8 (release/0.8.8). The diff against 0.8.6 in host-api, host-container, and host-api-wrapper is LICENSE files and version bumps only — no source changes. The 0.8.7 statement-store rework (priority epoch, expiry retries, AccountFull handling) and the 0.8.8 legacy sign requests both live in host-papp (the SSO peer / authorising-device path), which this SDK does not simulate. No handler surface changes; no test changes beyond re-running the suite.

v0.9.1

Choose a tag to compare

@mordamax mordamax released this 08 Jun 09:56
f88d92a

Changed

  • Upstream @novasamatech/*^0.8.6. Pulls in RFC-0021 coin top-ups (triangle-js-sdks#194), the PaymentTopUpSource codec fix (#198PrivateKey/Coins keys are now 64-byte sr25519 secrets, not 32-byte ed25519), the deriveProductEntropyFromSource export for RFC-0007 Option 1 hosts (#205), and host-chat / host-papp internals. All existing handlers (theme, payments, signing, statement-store) continue to work without code changes.

Added

  • PaymentTopUpSource.Coins(Vector<Sr25519SecretKey>) flows through to paymentLog.source. handlePaymentTopUp already forwarded params.source as-is, so the new variant lands in the log entry as { tag: 'Coins', value: Uint8Array[] }. Each key in the vector is 64 bytes after the upstream codec fix.
  • setPaymentTopUpBehavior(behavior) test control for driving products through the RFC-0021 PartialPayment error path. Behavior is 'ok' (default), { type: 'partial', credited } (credit credited and reject with PaymentTopUpErr.PartialPayment({ credited }), mirroring how a real host reports that only some coins could be claimed), or { type: 'reject', reason: 'InvalidSource' | 'InsufficientFunds' }. The paymentLog entry always records the attempted amount and source regardless of outcome.
  • PaymentTopUpBehavior type exported from the package root so tests can type the argument.

Internal

  • Integration tests for the coins round-trip and the partial-payment behavior. The partial-payment test asserts both the rejected promise's payload.credited and that the balance was bumped by exactly that amount.
  • Test product gained paymentTopUpCoins(amount, keysHex[]) helper.

v0.9.0

Choose a tag to compare

@mordamax mordamax released this 01 Jun 14:07
9578409

Changed

  • Upstream @novasamatech/*^0.8.0 (triangle-js-sdks#179). v0.8 is wire-incompatible with v0.7 — a test host built on this release will only talk to products on @novasamatech/host-api@^0.8.0. Upgrade your product side in lockstep. Most products don't need code changes if they use createPapiProvider for chain access and @novasamatech/product-react-renderer for custom chat. See the v0.8 migration guide for the product-side breaking points.

Breaking changes

  • Theme subscription delivers the new { name, variant } struct instead of a flat 'light' | 'dark'. setTheme('light' | 'dark') keeps working as a shorthand (mapped to { name: { tag: 'Default', value: undefined }, variant: 'Light' | 'Dark' }) and now also accepts the full struct so tests can drive custom-named themes. getTheme() returns the struct — read theme.variant for the previous light/dark value.
  • AllocatableResource variant rename: BulletInAllowanceBulletinAllowance. Affects tests that hand-build resource-allocation requests.

Added

  • PaymentLogEntry.purse records the optional purse selector from RFC-0017 — into on top-ups, from on payment requests. Undefined means the product targeted the main purse.
  • Theme and ThemeInput types exported from the package root.
  • .github/CODEOWNERS added with * @mordamax.

v0.8.6

Choose a tag to compare

@decrypto21 decrypto21 released this 01 Jun 12:38
f2d53a5

One fix. Drop-in upgrade from 0.8.5.

Fixed

  • PASEO_ASSET_HUB.genesisHash refreshed after the Paseo Asset Hub chain reset (#32). The paseo-asset-hub-next chain was reset, changing its genesis from 0x173cea… to 0xbf0488dbe9daa1de1c08c5f743e26fdc2a4ecd74cf87dd1b4b1eeb99ae4ef19f. The built-in PASEO_ASSET_HUB config carried the old hash, so the host's chain-feature handshake rejected product-sdk descriptors regenerated against the new chain — the product app would sit disconnected in E2E even though the RPC was reachable. The new value is verified against the live chain via chain_getBlockHash(0).

What you need to do

  • Upgrade to 0.8.6. If you only use the built-in PASEO_ASSET_HUB config, no code changes are needed — the correct genesis comes with the upgrade.
  • If you hardcoded the old genesis (0x173cea…) in your own ChainConfig or test assertions, update it to 0xbf0488….