@parity/product-sdk-host 0.15.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,107 @@
1
+ import { TrUApiClient, ChainIdentifier, HexString } from '@parity/truapi';
2
+ import { ConnectionStatus } from '@parity/truapi/sandbox';
3
+
4
+ /**
5
+ * Access to the in-house TruAPI client (`@parity/truapi`) for the host package.
6
+ *
7
+ * Environment detection, the lazily-built cached client, and the connection-status
8
+ * signal come from `@parity/truapi/sandbox`; this module layers the
9
+ * product-sdk-specific glue on top — an async {@link getClient} accessor,
10
+ * {@link subscribeConnectionStatus}, and {@link subscribeWithInterrupt}, which
11
+ * adapts a truapi stream into the host's {@link HostSubscription} shape.
12
+ *
13
+ * @module
14
+ */
15
+
16
+ /**
17
+ * Test-only seam: force {@link getClient} / {@link getClientSync} to return
18
+ * `client`, and {@link isCorrectEnvironment} to report `true`. Pass `null` to
19
+ * restore normal detection. Exposed through `@parity/product-sdk-host/testing`,
20
+ * not the package's main entry.
21
+ *
22
+ * Calling this in a production build silently reroutes every host accessor to
23
+ * the injected client, so we warn — it almost always means a `/testing` import
24
+ * leaked into a production path.
25
+ *
26
+ * Injecting or clearing notifies {@link subscribeConnectionStatus} subscribers,
27
+ * so a product's "host lost" path can be exercised by disposing the fake host.
28
+ */
29
+ declare function setTruApiClient(client: TrUApiClient | null): void;
30
+ /**
31
+ * Host-container detection. `true` when a test client is injected, otherwise the
32
+ * sandbox heuristic (iframe / webview marker / injected message port).
33
+ */
34
+ declare function isCorrectEnvironment(): boolean;
35
+ /**
36
+ * Connection lifecycle of the host channel: `"connecting"` while the client waits
37
+ * for the host, `"connected"` once the channel is established, `"disconnected"`
38
+ * outside a host container or after the channel closes.
39
+ *
40
+ * Not the same concept as `@parity/product-sdk-signer`'s identically-shaped
41
+ * `ConnectionStatus`, which tracks a signer provider rather than the transport.
42
+ */
43
+ type HostConnectionStatus = ConnectionStatus;
44
+ /**
45
+ * Test-only: push `status` to every {@link subscribeConnectionStatus} subscriber,
46
+ * so a product can exercise its reconnecting / offline UI. The host-side
47
+ * counterpart of `@parity/product-sdk-signer`'s `FakeSignerProvider.emitStatus`.
48
+ * Exposed through `@parity/product-sdk-host/testing`, not the main entry.
49
+ */
50
+ declare function emitConnectionStatus(status: HostConnectionStatus): void;
51
+ /**
52
+ * Subscribe to host-channel connection status. The callback fires synchronously
53
+ * with the current status and again on every change; the returned function
54
+ * unsubscribes. Repeats of the status you already have are suppressed.
55
+ *
56
+ * This is the **transport** channel. For the host's account-level connection —
57
+ * what drives `@parity/product-sdk-signer`'s `ConnectionStatus` — use
58
+ * `AccountsProvider.subscribeAccountConnectionStatus` instead.
59
+ *
60
+ * Subscribing is not passive: outside an established channel the first subscribe
61
+ * builds the client and provider, so this can be what constructs the transport.
62
+ *
63
+ * Honours the `setTruApiClient` seam — an injected client is connected by
64
+ * definition, and injecting or clearing one notifies live subscribers.
65
+ */
66
+ declare function subscribeConnectionStatus(callback: (status: HostConnectionStatus) => void): () => void;
67
+
68
+ /**
69
+ * Host chain discovery. Resolves chain roles to genesis hashes against the
70
+ * host's configured environment instead of hard-coding them.
71
+ *
72
+ * The wire method takes one identifier per call, so the facade fires one
73
+ * concurrent call per requested identifier and caches the combined result
74
+ * for the lifetime of the connection. Consumed internally by chain-client.
75
+ * Products normally never call this directly.
76
+ *
77
+ * @module
78
+ */
79
+
80
+ /**
81
+ * Chain-role identifier. A closed protocol enum, not a free-form name. The
82
+ * host maps each role to the concrete chain of its configured environment.
83
+ */
84
+ type HostChainIdentifier = ChainIdentifier;
85
+ /** The host's configured environment plus per-identifier resolved genesis hashes. */
86
+ interface HostChainDiscovery {
87
+ /** Ecosystem the host is configured for, e.g. `"polkadot"`, `"paseo"`. */
88
+ network: string;
89
+ /** Present for every requested identifier the host serves. */
90
+ chains: Partial<Record<HostChainIdentifier, HexString>>;
91
+ }
92
+ /**
93
+ * Resolve chain roles against the current host.
94
+ *
95
+ * Returns `null` when discovery is unavailable: outside a container, on a
96
+ * legacy host, or when the host serves none of the requested identifiers.
97
+ * Callers treat `null` as "fall back to configured constants".
98
+ *
99
+ * One concurrent `getChainInfo` call is made per identifier. Identifiers
100
+ * the host answers `NotSupported` for are absent from `chains`. Stable
101
+ * answers are cached per client and identifier set. Unexpected wire failures
102
+ * and probe timeouts are logged, return `null` and are not cached, so a later
103
+ * call re-probes.
104
+ */
105
+ declare function getHostChainInfo(identifiers: readonly HostChainIdentifier[]): Promise<HostChainDiscovery | null>;
106
+
107
+ export { type HostChainDiscovery as H, type HostChainIdentifier as a, type HostConnectionStatus as b, setTruApiClient as c, emitConnectionStatus as e, getHostChainInfo as g, isCorrectEnvironment as i, subscribeConnectionStatus as s };
@@ -0,0 +1,89 @@
1
+ import { isCorrectEnvironment as isCorrectEnvironment$1, subscribeConnectionStatus as subscribeConnectionStatus$1, getClientSync as getClientSync$1 } from '@parity/truapi/sandbox';
2
+
3
+ // src/transport.ts
4
+ var clientOverride = null;
5
+ var localStatusListeners = /* @__PURE__ */ new Set();
6
+ function isProductionBuild() {
7
+ try {
8
+ return process.env.NODE_ENV === "production";
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+ function setTruApiClient(client) {
14
+ if (client !== null && isProductionBuild()) {
15
+ console.warn(
16
+ "[product-sdk] setTruApiClient() was called in a production build. This is a test-only seam from @parity/product-sdk-host/testing; a leaked import will silently reroute all host access to the injected client."
17
+ );
18
+ }
19
+ const wasOverridden = clientOverride !== null;
20
+ clientOverride = client;
21
+ if (wasOverridden !== (client !== null)) {
22
+ notifyLocalStatusListeners(client !== null ? "connected" : "disconnected");
23
+ }
24
+ }
25
+ function getClientSync() {
26
+ return clientOverride ?? getClientSync$1();
27
+ }
28
+ function isCorrectEnvironment() {
29
+ return clientOverride !== null || isCorrectEnvironment$1();
30
+ }
31
+ async function getClient() {
32
+ return getClientSync();
33
+ }
34
+ function latchDisconnected(previous, next) {
35
+ return next === "connecting" && previous === "disconnected" ? "disconnected" : next;
36
+ }
37
+ function notifyLocalStatusListeners(status) {
38
+ for (const listener of [...localStatusListeners]) listener(status);
39
+ }
40
+ function emitConnectionStatus(status) {
41
+ if (isProductionBuild()) {
42
+ console.warn(
43
+ "[product-sdk] emitConnectionStatus() was called in a production build. This is a test-only seam from @parity/product-sdk-host/testing; a leaked import will report a fabricated connection status to real subscribers."
44
+ );
45
+ }
46
+ notifyLocalStatusListeners(status);
47
+ }
48
+ function subscribeConnectionStatus(callback) {
49
+ let last = null;
50
+ const deliver = (status, fromSandbox) => {
51
+ const next = fromSandbox ? latchDisconnected(last, status) : status;
52
+ if (next === last) return;
53
+ last = next;
54
+ callback(next);
55
+ };
56
+ const onLocal = (status) => deliver(status, false);
57
+ localStatusListeners.add(onLocal);
58
+ if (clientOverride !== null) {
59
+ onLocal("connected");
60
+ return () => void localStatusListeners.delete(onLocal);
61
+ }
62
+ const unsubscribeSandbox = subscribeConnectionStatus$1((status) => deliver(status, true));
63
+ return () => {
64
+ localStatusListeners.delete(onLocal);
65
+ unsubscribeSandbox();
66
+ };
67
+ }
68
+ function subscribeWithInterrupt(observable, onNext) {
69
+ let interruptCallback;
70
+ const sub = observable.subscribe({
71
+ next: onNext,
72
+ error: (reason) => interruptCallback?.(reason),
73
+ complete: () => interruptCallback?.()
74
+ });
75
+ return {
76
+ subscriptionId: sub.subscriptionId,
77
+ unsubscribe: () => sub.unsubscribe(),
78
+ onInterrupt: (callback) => {
79
+ interruptCallback = callback;
80
+ return () => {
81
+ if (interruptCallback === callback) interruptCallback = void 0;
82
+ };
83
+ }
84
+ };
85
+ }
86
+
87
+ export { emitConnectionStatus, getClient, isCorrectEnvironment, setTruApiClient, subscribeConnectionStatus, subscribeWithInterrupt };
88
+ //# sourceMappingURL=chunk-PAKEUP2Q.js.map
89
+ //# sourceMappingURL=chunk-PAKEUP2Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport.ts"],"names":["sandboxGetClientSync","sandboxIsCorrectEnvironment","sandboxSubscribeConnectionStatus"],"mappings":"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","file":"chunk-PAKEUP2Q.js","sourcesContent":["// Copyright 2026 Parity Technologies (UK) Ltd.\n// SPDX-License-Identifier: Apache-2.0\n/**\n * Access to the in-house TruAPI client (`@parity/truapi`) for the host package.\n *\n * Environment detection, the lazily-built cached client, and the connection-status\n * signal come from `@parity/truapi/sandbox`; this module layers the\n * product-sdk-specific glue on top — an async {@link getClient} accessor,\n * {@link subscribeConnectionStatus}, and {@link subscribeWithInterrupt}, which\n * adapts a truapi stream into the host's {@link HostSubscription} shape.\n *\n * @module\n */\n\nimport type { ObservableLike, TrUApiClient } from \"@parity/truapi\";\nimport {\n type ConnectionStatus,\n getClientSync as sandboxGetClientSync,\n isCorrectEnvironment as sandboxIsCorrectEnvironment,\n subscribeConnectionStatus as sandboxSubscribeConnectionStatus,\n} from \"@parity/truapi/sandbox\";\n\nimport type { HostSubscription } from \"./types.js\";\n\n/** A {@link HostSubscription} carrying the transport-assigned subscription id. */\nexport interface TransportSubscription extends HostSubscription {\n readonly subscriptionId: string;\n}\n\n// Test-only override. When set — via `setTruApiClient`, exposed through\n// `@parity/product-sdk-host/testing` — every host accessor resolves this client\n// instead of the sandbox one. `null` in production, so the branches below are\n// no-ops there.\nlet clientOverride: TrUApiClient | null = null;\n\n// Status subscribers registered here rather than only in the sandbox, so that\n// flipping the test seam is an *event*. The sandbox tracks only the client it\n// built itself, so it cannot know an injected client appeared or went away.\nconst localStatusListeners = new Set<(status: HostConnectionStatus) => void>();\n\nfunction isProductionBuild(): boolean {\n try {\n // Must stay a plain `process.env.NODE_ENV` member expression: bundlers\n // (Vite, esbuild, webpack) substitute it textually, which is how this\n // check works in browser builds where `process` doesn't exist.\n return process.env.NODE_ENV === \"production\";\n } catch {\n // No `process` and no bundler define — can't tell, stay quiet.\n return false;\n }\n}\n\n/**\n * Test-only seam: force {@link getClient} / {@link getClientSync} to return\n * `client`, and {@link isCorrectEnvironment} to report `true`. Pass `null` to\n * restore normal detection. Exposed through `@parity/product-sdk-host/testing`,\n * not the package's main entry.\n *\n * Calling this in a production build silently reroutes every host accessor to\n * the injected client, so we warn — it almost always means a `/testing` import\n * leaked into a production path.\n *\n * Injecting or clearing notifies {@link subscribeConnectionStatus} subscribers,\n * so a product's \"host lost\" path can be exercised by disposing the fake host.\n */\nexport function setTruApiClient(client: TrUApiClient | null): void {\n if (client !== null && isProductionBuild()) {\n console.warn(\n \"[product-sdk] setTruApiClient() was called in a production build. This is a test-only seam from @parity/product-sdk-host/testing; a leaked import will silently reroute all host access to the injected client.\",\n );\n }\n const wasOverridden = clientOverride !== null;\n clientOverride = client;\n if (wasOverridden !== (client !== null)) {\n notifyLocalStatusListeners(client !== null ? \"connected\" : \"disconnected\");\n }\n}\n\n/**\n * Synchronous TruAPI client accessor. Returns the injected test client when one\n * is set, otherwise the sandbox client (`null` outside a host container).\n */\nexport function getClientSync(): TrUApiClient | null {\n return clientOverride ?? sandboxGetClientSync();\n}\n\n/**\n * Host-container detection. `true` when a test client is injected, otherwise the\n * sandbox heuristic (iframe / webview marker / injected message port).\n */\nexport function isCorrectEnvironment(): boolean {\n return clientOverride !== null || sandboxIsCorrectEnvironment();\n}\n\n/**\n * Get the TruAPI client. Returns `null` outside a host container. Async wrapper\n * over {@link getClientSync} for the host wrappers that already `await` it.\n */\nexport async function getClient(): Promise<TrUApiClient | null> {\n return getClientSync();\n}\n\n/**\n * Connection lifecycle of the host channel: `\"connecting\"` while the client waits\n * for the host, `\"connected\"` once the channel is established, `\"disconnected\"`\n * outside a host container or after the channel closes.\n *\n * Not the same concept as `@parity/product-sdk-signer`'s identically-shaped\n * `ConnectionStatus`, which tracks a signer provider rather than the transport.\n */\nexport type HostConnectionStatus = ConnectionStatus;\n\n/**\n * Correct one defect in the sandbox's status signal: `@parity/truapi` never clears\n * its cached client when the pipe closes, so a subscriber arriving after a\n * disconnect re-derives `\"connecting\"` from the dead client — and because the\n * sandbox fans every change out to all listeners, that rewrites everyone's state\n * with no way back. Hold `\"disconnected\"` until a real `\"connected\"` arrives.\n *\n * Applies to sandbox-sourced statuses only. A status pushed by the test seam is\n * deliberate and passes through, so a fake host can still drive a reconnect.\n *\n * Outstanding upstream, not tied to the version we happen to be on: `sandbox.js`\n * is byte-identical from 0.7.0 through 0.9.0 (npm latest) and still unfixed on\n * `paritytech/host-rust-core` main, the repo formerly named truapi. Remove once\n * it clears the cached client on close.\n */\nfunction latchDisconnected(\n previous: HostConnectionStatus | null,\n next: HostConnectionStatus,\n): HostConnectionStatus {\n return next === \"connecting\" && previous === \"disconnected\" ? \"disconnected\" : next;\n}\n\nfunction notifyLocalStatusListeners(status: HostConnectionStatus): void {\n // Iterate a snapshot: a listener that unsubscribes itself, or re-enters\n // `setTruApiClient`, must not mutate the set mid-loop.\n for (const listener of [...localStatusListeners]) listener(status);\n}\n\n/**\n * Test-only: push `status` to every {@link subscribeConnectionStatus} subscriber,\n * so a product can exercise its reconnecting / offline UI. The host-side\n * counterpart of `@parity/product-sdk-signer`'s `FakeSignerProvider.emitStatus`.\n * Exposed through `@parity/product-sdk-host/testing`, not the main entry.\n */\nexport function emitConnectionStatus(status: HostConnectionStatus): void {\n if (isProductionBuild()) {\n console.warn(\n \"[product-sdk] emitConnectionStatus() was called in a production build. This is a test-only seam from @parity/product-sdk-host/testing; a leaked import will report a fabricated connection status to real subscribers.\",\n );\n }\n notifyLocalStatusListeners(status);\n}\n\n/**\n * Subscribe to host-channel connection status. The callback fires synchronously\n * with the current status and again on every change; the returned function\n * unsubscribes. Repeats of the status you already have are suppressed.\n *\n * This is the **transport** channel. For the host's account-level connection —\n * what drives `@parity/product-sdk-signer`'s `ConnectionStatus` — use\n * `AccountsProvider.subscribeAccountConnectionStatus` instead.\n *\n * Subscribing is not passive: outside an established channel the first subscribe\n * builds the client and provider, so this can be what constructs the transport.\n *\n * Honours the `setTruApiClient` seam — an injected client is connected by\n * definition, and injecting or clearing one notifies live subscribers.\n */\nexport function subscribeConnectionStatus(\n callback: (status: HostConnectionStatus) => void,\n): () => void {\n let last: HostConnectionStatus | null = null;\n\n // One wrapped callback for both sources, so `last` stays coherent: the seam\n // and the sandbox must not each keep their own idea of what was delivered.\n const deliver = (status: HostConnectionStatus, fromSandbox: boolean): void => {\n const next = fromSandbox ? latchDisconnected(last, status) : status;\n if (next === last) return;\n last = next;\n callback(next);\n };\n\n const onLocal = (status: HostConnectionStatus) => deliver(status, false);\n localStatusListeners.add(onLocal);\n\n if (clientOverride !== null) {\n onLocal(\"connected\");\n return () => void localStatusListeners.delete(onLocal);\n }\n\n const unsubscribeSandbox = sandboxSubscribeConnectionStatus((status) => deliver(status, true));\n return () => {\n localStatusListeners.delete(onLocal);\n unsubscribeSandbox();\n };\n}\n\n/**\n * Adapt a truapi `ObservableLike` stream into the host's callback-style\n * {@link HostSubscription} (`unsubscribe` + `onInterrupt`). `onNext` fires for\n * each item; the registered `onInterrupt` callback fires when the host ends the\n * subscription server-side — which the generated client surfaces as either\n * `complete` (a host interrupt frame) or `error` (transport close). Shared by\n * the statement-store and preimage adapters, which both expose this shape.\n */\nexport function subscribeWithInterrupt<Item, Reason = never>(\n observable: ObservableLike<Item, Reason>,\n onNext: (item: Item) => void,\n): TransportSubscription {\n let interruptCallback: ((reason?: unknown) => void) | undefined;\n const sub = observable.subscribe({\n next: onNext,\n error: (reason) => interruptCallback?.(reason),\n complete: () => interruptCallback?.(),\n });\n return {\n subscriptionId: sub.subscriptionId,\n unsubscribe: () => sub.unsubscribe(),\n onInterrupt: (callback) => {\n interruptCallback = callback;\n return () => {\n if (interruptCallback === callback) interruptCallback = undefined;\n };\n },\n };\n}\n\nif (import.meta.vitest) {\n const { test, expect, afterEach } = import.meta.vitest;\n\n afterEach(() => setTruApiClient(null));\n\n // Environment detection and client building are covered by `@parity/truapi`'s\n // own sandbox tests; here we only assert the local glue degrades outside a\n // host container.\n test(\"getClientSync returns null outside a container\", () => {\n expect(getClientSync()).toBeNull();\n });\n\n test(\"getClient resolves null outside a container\", async () => {\n expect(await getClient()).toBeNull();\n });\n\n test(\"setTruApiClient overrides the client and container detection\", async () => {\n const fake = {} as TrUApiClient;\n setTruApiClient(fake);\n expect(getClientSync()).toBe(fake);\n expect(await getClient()).toBe(fake);\n expect(isCorrectEnvironment()).toBe(true);\n\n setTruApiClient(null);\n expect(getClientSync()).toBeNull();\n expect(isCorrectEnvironment()).toBe(false);\n });\n\n test(\"setTruApiClient warns when injecting in a production build\", () => {\n const original = process.env.NODE_ENV;\n const warnings: string[] = [];\n const realWarn = console.warn;\n console.warn = (...args: unknown[]) => void warnings.push(String(args[0]));\n try {\n process.env.NODE_ENV = \"production\";\n setTruApiClient({} as TrUApiClient);\n expect(warnings).toHaveLength(1);\n expect(warnings[0]).toContain(\"production build\");\n\n // Clearing the override must not warn.\n setTruApiClient(null);\n expect(warnings).toHaveLength(1);\n } finally {\n console.warn = realWarn;\n process.env.NODE_ENV = original;\n }\n });\n\n test(\"subscribeConnectionStatus reports disconnected outside a container\", () => {\n const statuses: HostConnectionStatus[] = [];\n\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n expect(statuses).toEqual([\"disconnected\"]);\n unsubscribe();\n });\n\n test(\"subscribeConnectionStatus reports connected for an injected client\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n // The sandbox only tracks the client it built itself, so without the\n // override branch this would report \"disconnected\" while every other\n // accessor resolved the injected client.\n expect(statuses).toEqual([\"connected\"]);\n unsubscribe();\n });\n\n test(\"disposing the injected client notifies live subscribers\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n setTruApiClient(null);\n\n expect(statuses).toEqual([\"connected\", \"disconnected\"]);\n unsubscribe();\n });\n\n test(\"injecting a client notifies subscribers that started without one\", () => {\n const statuses: HostConnectionStatus[] = [];\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n setTruApiClient({} as TrUApiClient);\n\n expect(statuses).toEqual([\"disconnected\", \"connected\"]);\n unsubscribe();\n });\n\n test(\"unsubscribe stops seam notifications\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n unsubscribe();\n setTruApiClient(null);\n\n expect(statuses).toEqual([\"connected\"]);\n expect(localStatusListeners.size).toBe(0);\n });\n\n test(\"emitConnectionStatus drives transitions, including a reconnect\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n emitConnectionStatus(\"disconnected\");\n // A seam-pushed \"connecting\" after \"disconnected\" is deliberate, so it must\n // survive the sandbox latch — otherwise no test could drive a reconnect.\n emitConnectionStatus(\"connecting\");\n emitConnectionStatus(\"connected\");\n\n expect(statuses).toEqual([\"connected\", \"disconnected\", \"connecting\", \"connected\"]);\n unsubscribe();\n });\n\n test(\"repeats of the current status are suppressed\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n const unsubscribe = subscribeConnectionStatus((status) => statuses.push(status));\n\n emitConnectionStatus(\"connected\");\n emitConnectionStatus(\"connected\");\n\n expect(statuses).toEqual([\"connected\"]);\n unsubscribe();\n });\n\n test(\"a listener that unsubscribes itself mid-notification is safe\", () => {\n setTruApiClient({} as TrUApiClient);\n const statuses: HostConnectionStatus[] = [];\n const handle: { unsubscribe?: () => void } = {};\n handle.unsubscribe = subscribeConnectionStatus((status) => {\n statuses.push(status);\n handle.unsubscribe?.();\n });\n\n setTruApiClient(null);\n\n expect(statuses).toEqual([\"connected\", \"disconnected\"]);\n expect(localStatusListeners.size).toBe(0);\n });\n\n // The sandbox latch can't be driven through the public surface — it needs a\n // real provider close — so the correction is pinned as a pure function.\n test(\"latchDisconnected holds disconnected through the stale-cache connecting\", () => {\n expect(latchDisconnected(\"disconnected\", \"connecting\")).toBe(\"disconnected\");\n });\n\n test(\"latchDisconnected passes every other transition through\", () => {\n expect(latchDisconnected(null, \"disconnected\")).toBe(\"disconnected\");\n expect(latchDisconnected(null, \"connecting\")).toBe(\"connecting\");\n expect(latchDisconnected(\"connecting\", \"connected\")).toBe(\"connected\");\n expect(latchDisconnected(\"connected\", \"disconnected\")).toBe(\"disconnected\");\n // A genuine reconnect still gets through once the channel re-establishes.\n expect(latchDisconnected(\"connected\", \"connecting\")).toBe(\"connecting\");\n });\n\n test(\"subscribeWithInterrupt preserves the transport subscription id\", () => {\n const observable = {\n subscribe: () => ({\n subscriptionId: \"p:17\",\n unsubscribe: () => {},\n }),\n [Symbol.observable]() {\n return this;\n },\n } as ObservableLike<never>;\n\n const subscription = subscribeWithInterrupt(observable, () => {});\n\n expect(subscription.subscriptionId).toBe(\"p:17\");\n });\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { JsonRpcProvider, PolkadotSigner } from 'polkadot-api';
2
- import { Topic, RemoteStatementStoreSubscribeItem, Statement, StatementProof, SignedStatement, HexString, scale, TrUApiClient, AllocatableResource, AllocationOutcome, VersionedHostGetUserIdError, HostRequestLoginResponse, VersionedHostRequestLoginError, ProductAccountId, ProductAccount as ProductAccount$1, VersionedHostAccountGetError, ProductProofContext, RingLocation, ContextualAlias as ContextualAlias$1, VersionedHostAccountGetAliasError, LegacyAccount, VersionedHostGetLegacyAccountsError, HostAccountCreateProofResponse, VersionedHostAccountCreateProofError, HostAccountConnectionStatusSubscribeItem, HostDevicePermissionRequest, RemotePermission, HostThemeSubscribeItem, ChatBotRegistrationStatus, HostChatCreateRoomRequest, ChatRoomRegistrationStatus, HostChatRegisterBotRequest, ChatMessageContent, ChatRoom, HostChatActionSubscribeItem, HostPaymentBalanceSubscribeItem, CoinPaymentPurseId, Balance, PaymentTopUpSource, HostPaymentStatusSubscribeItem, HostPushNotificationRequest, NotificationId } from '@parity/truapi';
3
- export { AllocatableResource, AllocationOutcome, ChatMessageContent, ChatRoom, DerivationIndex, HexString, HostPaymentBalanceSubscribeItem, HostPaymentStatusSubscribeItem, NotificationId, PaymentTopUpSource, ProductAccountId, ProductProofContext, HostPushNotificationError as PushNotificationError, RemotePermission, RingLocation, SignedStatement, Statement, StatementProof, ThemeName, ThemeVariant, Topic } from '@parity/truapi';
2
+ import { Topic, RemoteStatementStoreSubscribeItem, Statement, StatementProof, SignedStatement, HexString, scale, TrUApiClient, AllocatableResource, AllocationOutcome, VersionedHostGetUserIdError, HostRequestLoginResponse, VersionedHostRequestLoginError, ProductAccountId, ProductAccount as ProductAccount$1, VersionedHostAccountGetError, RingLocation, VersionedHostAccountRegisterRingVrfKeyError, RingVrfKeyDisclosure, RegisteredRingVrfKey as RegisteredRingVrfKey$1, VersionedHostAccountListRingVrfKeysError, ProductProofContext, ContextualAlias as ContextualAlias$1, VersionedHostAccountGetAliasError, LegacyAccount, VersionedHostGetLegacyAccountsError, HostAccountCreateProofResponse, VersionedHostAccountCreateProofError, VersionedHostAccountRingVrfSignError, VrfTranscriptItem as VrfTranscriptItem$1, VrfSignature as VrfSignature$1, VersionedHostAccountSignVrfError, HostAccountConnectionStatusSubscribeItem, HostDevicePermissionRequest, RemotePermission, HostThemeSubscribeItem, ChatBotRegistrationStatus, HostChatCreateRoomRequest, ChatRoomRegistrationStatus, HostChatRegisterBotRequest, ChatMessageContent, ChatRoom, HostChatActionSubscribeItem, HostPaymentBalanceSubscribeItem, CoinPaymentPurseId, Balance, PaymentTopUpSource, HostPaymentStatusSubscribeItem, HostPushNotificationRequest, NotificationId } from '@parity/truapi';
3
+ export { AllocatableResource, AllocationOutcome, ChatMessageContent, ChatRoom, DerivationIndex, HexString, HostPaymentBalanceSubscribeItem, HostPaymentStatusSubscribeItem, NotificationId, PaymentTopUpSource, ProductAccountId, ProductProofContext, HostPushNotificationError as PushNotificationError, RemotePermission, RingLocation, RingVrfKeyDisclosure, SignedStatement, Statement, StatementProof, ThemeName, ThemeVariant, Topic } from '@parity/truapi';
4
4
  import { SdkError } from '@parity/product-sdk-errors';
5
5
  export { SdkError, isSdkError } from '@parity/product-sdk-errors';
6
6
  import { Result } from '@parity/result';
7
7
  export { Result, err, ok } from '@parity/result';
8
+ export { H as HostChainDiscovery, a as HostChainIdentifier, b as HostConnectionStatus, g as getHostChainInfo, i as isInsideContainerSync, s as subscribeConnectionStatus } from './chain-discovery-BEvu7HaV.js';
8
9
  import { ResultAsync as ResultAsync$1 } from 'neverthrow';
9
- export { i as isInsideContainerSync } from './transport-B0cdhwrp.js';
10
+ import '@parity/truapi/sandbox';
10
11
 
11
12
  /**
12
13
  * Public types for the host wrappers.
@@ -156,12 +157,14 @@ declare function getStatementStore(): Promise<HostStatementStore | null>;
156
157
  * chain-specific endpoints used by multiple packages.
157
158
  */
158
159
  /**
159
- * Bulletin Chain RPC endpoints per network environment. `paseo` (Paseo Next v2)
160
- * and `devnet` (public Paseo testnet) are populated today; `polkadot` and
161
- * `kusama` are reserved for when those Bulletin deployments go live.
160
+ * Bulletin Chain RPC endpoints per network environment. `paseo` (Paseo Next v2),
161
+ * `previewnet` (zombienet, a step ahead of paseo), and `devnet` (public Paseo
162
+ * testnet) are populated today; `polkadot` and `kusama` are reserved for when
163
+ * those Bulletin deployments go live.
162
164
  */
163
165
  declare const BULLETIN_RPCS: {
164
166
  readonly paseo: readonly ["wss://paseo-bulletin-next-rpc.polkadot.io"];
167
+ readonly previewnet: readonly ["wss://previewnet.substrate.dev/bulletin"];
165
168
  readonly devnet: readonly ["wss://bulletin-paseo.tservices.es:8443"];
166
169
  readonly polkadot: string[];
167
170
  readonly kusama: string[];
@@ -370,7 +373,8 @@ interface ResultAsync<T, E> {
370
373
  * `getAccountsProvider()` returns the full accounts surface — user identity
371
374
  * (`getUserId` / `requestLogin`), the user's existing wallet accounts
372
375
  * (`getLegacyAccounts`), app-scoped product accounts (`getProductAccount` /
373
- * `getProductAccountAlias`), Ring VRF proofs (`createRingVRFProof`), connection
376
+ * `getProductAccountAlias`), Ring VRF proofs (`createRingVRFProof`), sr25519 VRF
377
+ * signatures over a caller-supplied Merlin transcript (`signVrf`), connection
374
378
  * status, and PAPI `PolkadotSigner` factories for both product and legacy
375
379
  * accounts.
376
380
  *
@@ -415,6 +419,41 @@ type ProductAccount = Omit<ProductAccountId, "derivationIndex"> & Omit<ProductAc
415
419
  /** Raw public key bytes. */
416
420
  publicKey: Uint8Array;
417
421
  };
422
+ /**
423
+ * How callers address a product account: app identifier plus an optional index,
424
+ * defaulting to 0. A {@link ProductAccount} satisfies this, so an account from
425
+ * {@link AccountsProvider.getProductAccount} can be passed straight back in.
426
+ */
427
+ type ProductAccountLookup = Omit<ProductAccountId, "derivationIndex"> & {
428
+ /** Plain account index within the product subtree. Defaults to 0. */
429
+ derivationIndex?: number;
430
+ };
431
+ declare const ringVrfKeyHandleBrand: unique symbol;
432
+ /**
433
+ * Opaque public name of a registered ring-VRF key.
434
+ *
435
+ * Handles come from {@link AccountsProvider.listRingVrfKeys}; product code
436
+ * cannot construct one from a derivation index.
437
+ */
438
+ type RingVrfKeyHandle = {
439
+ readonly [ringVrfKeyHandleBrand]: "RingVrfKeyHandle";
440
+ };
441
+ /** Ring-VRF member public key, decoded from the wire's hex string. */
442
+ type RingVrfPublicKey = Uint8Array;
443
+ /** Registered key metadata returned by the host. */
444
+ type RegisteredRingVrfKey = Omit<RegisteredRingVrfKey$1, "handle" | "publicKey"> & {
445
+ /** Opaque handle to pass back for alias and proof requests. */
446
+ handle: RingVrfKeyHandle;
447
+ /** Present when public-key disclosure was granted. */
448
+ publicKey?: RingVrfPublicKey;
449
+ };
450
+ /**
451
+ * Select a registered key by its declared ring and return its opaque handle.
452
+ *
453
+ * Consumers must not hard-code another product's derivation index. Registry
454
+ * order breaks ties when an owner declares multiple keys for the same ring.
455
+ */
456
+ declare function findRingVrfKeyHandle(keys: RegisteredRingVrfKey[], ring: RingLocation): RingVrfKeyHandle | undefined;
418
457
  /**
419
458
  * A contextual alias obtained from Ring VRF.
420
459
  *
@@ -439,6 +478,23 @@ type RingVRFProof = Omit<HostAccountCreateProofResponse, "proof" | "contextualAl
439
478
  /** Alias derived for the request's context. */
440
479
  contextualAlias: ContextualAlias;
441
480
  };
481
+ /**
482
+ * One `append_message(label, value)` call replayed against a VRF transcript.
483
+ * Merlin labels are ASCII by convention: use `utf8ToBytes("round")`.
484
+ *
485
+ * Derived from `@parity/truapi`'s `VrfTranscriptItem`, decoded to bytes.
486
+ */
487
+ type VrfTranscriptItem = {
488
+ [K in keyof VrfTranscriptItem$1]: Uint8Array;
489
+ };
490
+ /**
491
+ * An sr25519 VRF signature: the pre-output and its DLEQ proof.
492
+ *
493
+ * Derived from `@parity/truapi`'s `VrfSignature`, decoded to bytes.
494
+ */
495
+ type VrfSignature = {
496
+ [K in keyof VrfSignature$1]: Uint8Array;
497
+ };
442
498
  /**
443
499
  * Accounts provider handle, backed by `truApi.account.*` / `truApi.signing.*`.
444
500
  * Surfaces the user's wallet accounts, app-scoped product accounts, Ring VRF,
@@ -456,17 +512,53 @@ interface AccountsProvider {
456
512
  requestLogin(reason?: string): ResultAsync$1<HostRequestLoginResponse, scale.CallErrorValue<VersionedHostRequestLoginError>>;
457
513
  getProductAccount(dotNsIdentifier: string, derivationIndex?: number): ResultAsync$1<ProductAccount, scale.CallErrorValue<VersionedHostAccountGetError>>;
458
514
  /**
459
- * Derive the contextual alias for a proof context and ring. The host
460
- * selects the member key within the ring — no per-account addressing.
515
+ * Register a ring-VRF key owned by the calling product.
516
+ *
517
+ * `index` is the plain derivation index within the product's ring-VRF
518
+ * domain; the adapter wraps it into the wire's tagged selector.
519
+ *
520
+ * Registration returns the key's public key. Call {@link listRingVrfKeys}
521
+ * afterward to obtain the opaque handle required by alias and proof calls.
461
522
  */
462
- getProductAccountAlias(context: ProductProofContext, location: RingLocation): ResultAsync$1<ContextualAlias, scale.CallErrorValue<VersionedHostAccountGetAliasError>>;
523
+ registerRingVrfKey(index: number, ring: RingLocation): ResultAsync$1<RingVrfPublicKey, scale.CallErrorValue<VersionedHostAccountRegisterRingVrfKeyError>>;
524
+ /** List an owner's registered ring-VRF keys. */
525
+ listRingVrfKeys(owner: string, disclosure?: RingVrfKeyDisclosure): ResultAsync$1<RegisteredRingVrfKey[], scale.CallErrorValue<VersionedHostAccountListRingVrfKeysError>>;
526
+ /** Derive a contextual alias with an explicitly registered ring-VRF key. */
527
+ getProductAccountAlias(keyHandle: RingVrfKeyHandle, context: ProductProofContext, location: RingLocation): ResultAsync$1<ContextualAlias, scale.CallErrorValue<VersionedHostAccountGetAliasError>>;
463
528
  getLegacyAccounts(): ResultAsync$1<HostAccount[], scale.CallErrorValue<VersionedHostGetLegacyAccountsError>>;
464
529
  /**
465
- * Generate a Ring VRF proof binding `message` to the product-scoped
466
- * `context`. The host selects the member key within the ring; the result
467
- * carries the proof plus its verification values ({@link RingVRFProof}).
530
+ * Generate a Ring VRF proof with an explicitly registered key, binding
531
+ * `message` to the product-scoped `context`.
532
+ */
533
+ createRingVRFProof(keyHandle: RingVrfKeyHandle, context: ProductProofContext, location: RingLocation, message: Uint8Array): ResultAsync$1<RingVRFProof, scale.CallErrorValue<VersionedHostAccountCreateProofError>>;
534
+ /**
535
+ * Sign `message` directly with an explicitly registered ring-VRF key.
536
+ *
537
+ * Unlike {@link createRingVRFProof} this proves nothing about ring
538
+ * membership; it is the plain signature under the member key, for
539
+ * protocols that carry their own proof.
540
+ */
541
+ ringVrfSign(keyHandle: RingVrfKeyHandle, message: Uint8Array): ResultAsync$1<Uint8Array, scale.CallErrorValue<VersionedHostAccountRingVrfSignError>>;
542
+ /**
543
+ * Produce an sr25519 VRF signature from a product account (RFC-0023).
544
+ *
545
+ * The host builds a Merlin transcript from `transcriptLabel` and `items`,
546
+ * then signs it with the account's key. Unlike {@link createRingVRFProof},
547
+ * this names the signing account instead of proving ring membership.
548
+ *
549
+ * The caller owns four things the types cannot enforce:
550
+ *
551
+ * - Domain separation. A label borrowed from another protocol makes the
552
+ * output replayable across both.
553
+ * - Freshness. The VRF is deterministic, so per-round values belong in
554
+ * `items`.
555
+ * - Size. Hosts cap the transcript at 32 items and 8 KiB total.
556
+ * - Authorization. An `AutoSigning` allowance makes these calls silent. It
557
+ * is not VRF-scoped, so it covers other signing by that account too.
558
+ *
559
+ * Hosts predating the call reject it through the error channel.
468
560
  */
469
- createRingVRFProof(context: ProductProofContext, location: RingLocation, message: Uint8Array): ResultAsync$1<RingVRFProof, scale.CallErrorValue<VersionedHostAccountCreateProofError>>;
561
+ signVrf(account: ProductAccountLookup, transcriptLabel: Uint8Array, items: VrfTranscriptItem[]): ResultAsync$1<VrfSignature, scale.CallErrorValue<VersionedHostAccountSignVrfError>>;
470
562
  /**
471
563
  * Build a `PolkadotSigner` for a product account. Signing routes through the
472
564
  * host's `createTransaction` path: the host decodes the metadata and forwards
@@ -725,7 +817,7 @@ interface PaymentManager {
725
817
  * const payments = await getPaymentManager();
726
818
  * if (payments) {
727
819
  * const sub = payments.subscribeBalance((b) => { ... });
728
- * await payments.topUp(1_000_000n, { tag: "ProductAccount", value: { derivationIndex: { tag: "Left", value: 0 } } });
820
+ * await payments.topUp(1_000_000n, { tag: "ProductAccount", value: { derivationIndex: { tag: "Index", value: 0 } } });
729
821
  * const { id } = await payments.requestPayment(500n, "0x…");
730
822
  * sub.unsubscribe();
731
823
  * }
@@ -1018,4 +1110,4 @@ declare function broadcastTransaction(genesisHash: HexString, transaction: HexSt
1018
1110
  */
1019
1111
  declare function stopTransaction(genesisHash: HexString, operationId: string): Promise<Result<void, HostError>>;
1020
1112
 
1021
- export { type AccountsProvider, BULLETIN_RPCS, ChainNotSupportedError, type ChainProperties, type ChainSpec, type ChatBotRegistrationResult, type ChatManager, type ChatReceivedAction, type ChatRoomRegistrationResult, type ContextualAlias, DEFAULT_BULLETIN_ENDPOINT, type DevicePermissionKind, type Feature, type HostAccount, HostCallFailedError, HostError, type HostErrorPayload, type HostLocalStorage, type HostStatementStore, type HostSubscription, HostUnavailableError, type NotificationManager, type PaymentManager, type PreimageManager, type ProductAccount, type PushNotificationInput, type RemotePermissionItem, type ResultAsync, type RingVRFProof, type StatementTopicFilter, type StatementsPage, type ThemeMode, type ThemeProvider, type TruApi, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };
1113
+ export { type AccountsProvider, BULLETIN_RPCS, ChainNotSupportedError, type ChainProperties, type ChainSpec, type ChatBotRegistrationResult, type ChatManager, type ChatReceivedAction, type ChatRoomRegistrationResult, type ContextualAlias, DEFAULT_BULLETIN_ENDPOINT, type DevicePermissionKind, type Feature, type HostAccount, HostCallFailedError, HostError, type HostErrorPayload, type HostLocalStorage, type HostStatementStore, type HostSubscription, HostUnavailableError, type NotificationManager, type PaymentManager, type PreimageManager, type ProductAccount, type ProductAccountLookup, type PushNotificationInput, type RegisteredRingVrfKey, type RemotePermissionItem, type ResultAsync, type RingVRFProof, type RingVrfKeyHandle, type RingVrfPublicKey, type StatementTopicFilter, type StatementsPage, type ThemeMode, type ThemeProvider, type TruApi, type VrfSignature, type VrfTranscriptItem, broadcastTransaction, createHostLocalStorage, createHostPreimageManager, createProofAuthorized, deriveEntropy, featureSupported, findRingVrfKeyHandle, formatHostError, fromHex, getAccountsProvider, getChainSpec, getChatManager, getHostLocalStorage, getHostProvider, getNotificationManager, getPaymentManager, getPreimageManager, getStatementStore, getThemeProvider, getTruApi, isChainSupported, isHostError, isInsideContainer, navigateTo, requestDevicePermission, requestPermission, requestResourceAllocation, stopTransaction, toHex };