@parity/product-sdk-host 0.3.0 → 0.5.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.
package/src/truapi.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TruAPI - the protocol for communicating between apps and the Polkadot host container.
3
3
  *
4
- * This module centralizes access to @novasamatech/product-sdk and @novasamatech/host-api,
4
+ * This module centralizes access to @novasamatech/host-api-wrapper and @novasamatech/host-api,
5
5
  * allowing other @parity/product-sdk-* packages to import from here rather than depending
6
6
  * directly on novasama packages.
7
7
  *
@@ -15,10 +15,57 @@ import type {
15
15
  AllocatableResource as AllocatableResourceCodec,
16
16
  AllocationOutcome as AllocationOutcomeCodec,
17
17
  CodecType,
18
+ RemotePermission as RemotePermissionCodec,
18
19
  } from "@novasamatech/host-api";
20
+ import type { createAccountsProvider, preimageManager } from "@novasamatech/host-api-wrapper";
21
+
22
+ import { isInsideContainer } from "./container.js";
23
+ import type { Statement, StatementProof } from "./types.js";
19
24
 
20
25
  const log = createLogger("host");
21
26
 
27
+ /**
28
+ * Extract a human-readable message from a host-side error. Hosts wrap
29
+ * errors in versioned envelopes (`{ tag: "v1", value: CodecError }`); this
30
+ * helper unwraps the envelope and renders the inner error's `name`/`message`
31
+ * so callers see the host's actual diagnostic instead of `"[object Object]"`
32
+ * (from `String(err)`) or a JSON-stringified envelope.
33
+ *
34
+ * Exported for the higher-level wrappers (`requestPermission`,
35
+ * `deriveEntropy`, etc.) that build their `throw new Error(...)` messages.
36
+ */
37
+ export function formatHostError(err: unknown): string {
38
+ // Single-level unwrap only; nested envelopes fall through to JSON.stringify.
39
+ const inner = isVersionedEnvelope(err) ? err.value : err;
40
+
41
+ if (inner instanceof Error) return inner.message;
42
+ if (typeof inner === "string") return inner;
43
+ if (
44
+ inner != null &&
45
+ typeof inner === "object" &&
46
+ "message" in inner &&
47
+ typeof (inner as { message: unknown }).message === "string"
48
+ ) {
49
+ const named = inner as { name?: unknown; message: string };
50
+ return typeof named.name === "string" ? `${named.name}: ${named.message}` : named.message;
51
+ }
52
+ try {
53
+ return JSON.stringify(inner);
54
+ } catch {
55
+ return String(inner);
56
+ }
57
+ }
58
+
59
+ function isVersionedEnvelope(value: unknown): value is { tag: string; value: unknown } {
60
+ return (
61
+ value != null &&
62
+ typeof value === "object" &&
63
+ "tag" in value &&
64
+ "value" in value &&
65
+ typeof (value as { tag: unknown }).tag === "string"
66
+ );
67
+ }
68
+
22
69
  // ─────────────────────────────────────────────────────────────────────────────
23
70
  // Helpers from @novasamatech/host-api (re-exported from @novasamatech/scale)
24
71
  // ─────────────────────────────────────────────────────────────────────────────
@@ -79,16 +126,19 @@ export type { HexString } from "@novasamatech/host-api";
79
126
  * The TruApi type - provides low-level methods for communicating with the host.
80
127
  *
81
128
  * Methods include:
82
- * - `navigateTo(url)` Navigate to a URL within the host
83
- * - `permission(permissions)` Request permissions from the host
84
- * - `localStorageRead/Write/Clear` Host-backed storage
85
- * - `sign(payload)` Request transaction signing
86
- * - `deriveEntropy(context)` Derive deterministic entropy
87
- * - `themeSubscribe()` Subscribe to host theme changes
129
+ * - `navigateTo(url)` - Navigate to a URL within the host
130
+ * - `permission(permissions)` - Request permissions from the host
131
+ * - `localStorageRead/Write/Clear` - Host-backed storage
132
+ * - `sign(payload)` - Request transaction signing
133
+ * - `deriveEntropy(context)` - Derive deterministic entropy
134
+ * - `themeSubscribe()` - Subscribe to host theme changes
88
135
  * - And many more...
136
+ *
137
+ * Type identical to `hostApi` from `@novasamatech/host-api-wrapper` so that
138
+ * `truApi.X(...)` calls keep their full inference (return types, method
139
+ * names, parameter shapes) instead of decaying to `any`.
89
140
  */
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
- export type TruApi = any;
141
+ export type TruApi = typeof import("@novasamatech/host-api-wrapper").hostApi;
92
142
 
93
143
  /** Cached TruApi instance */
94
144
  let cachedTruApi: TruApi | null = null;
@@ -96,7 +146,7 @@ let cachedTruApi: TruApi | null = null;
96
146
  /**
97
147
  * Get the TruAPI instance for direct low-level access.
98
148
  *
99
- * Returns the `hostApi` object from `@novasamatech/product-sdk` which provides
149
+ * Returns the `hostApi` object from `@novasamatech/host-api-wrapper` which provides
100
150
  * methods for communicating directly with the host container. Returns `null`
101
151
  * when running outside a container or when the SDK is unavailable.
102
152
  *
@@ -129,7 +179,7 @@ export async function getTruApi(): Promise<TruApi | null> {
129
179
  if (cachedTruApi) return cachedTruApi;
130
180
 
131
181
  try {
132
- const sdk = await import("@novasamatech/product-sdk");
182
+ const sdk = await import("@novasamatech/host-api-wrapper");
133
183
  cachedTruApi = sdk.hostApi;
134
184
  log.debug("TruAPI loaded");
135
185
  return cachedTruApi;
@@ -165,34 +215,44 @@ export async function getTruApi(): Promise<TruApi | null> {
165
215
  */
166
216
  export async function getPreimageManager(): Promise<PreimageManager | null> {
167
217
  try {
168
- const sdk = await import("@novasamatech/product-sdk");
218
+ const sdk = await import("@novasamatech/host-api-wrapper");
169
219
  return sdk.preimageManager;
170
- } catch {
220
+ } catch (err) {
221
+ log.debug("getPreimageManager unavailable", err);
171
222
  return null;
172
223
  }
173
224
  }
174
225
 
175
226
  /**
176
- * Preimage manager interface for bulletin chain operations.
227
+ * Preimage manager handle for bulletin chain operations. `lookup` returns a
228
+ * `Subscription<void>` (`unsubscribe` + `onInterrupt`); `submit` returns a
229
+ * `0x`-prefixed hex preimage key.
230
+ *
231
+ * Type identical to `preimageManager` from `@novasamatech/host-api-wrapper`.
177
232
  */
178
- export interface PreimageManager {
179
- /**
180
- * Submit a preimage to the bulletin chain.
181
- * @param data - The data to submit.
182
- * @returns The preimage key (hex string).
183
- */
184
- submit(data: Uint8Array): Promise<string>;
233
+ export type PreimageManager = typeof preimageManager;
185
234
 
186
- /**
187
- * Look up a preimage by key.
188
- * @param key - The preimage key (hex string).
189
- * @param callback - Called with the data when found, or null if not yet available.
190
- * @returns Subscription handle with unsubscribe method.
191
- */
192
- lookup(
193
- key: string,
194
- callback: (preimage: Uint8Array | null) => void,
195
- ): { unsubscribe: () => void; onInterrupt: (cb: () => void) => () => void };
235
+ /**
236
+ * Construct a fresh `PreimageManager` instance with an optional custom
237
+ * transport. Use this when you need a non-default transport; otherwise
238
+ * prefer {@link getPreimageManager}, which returns the shared singleton.
239
+ *
240
+ * Mirrors `createPreimageManager` from `@novasamatech/host-api-wrapper`.
241
+ *
242
+ * @param transport - Optional transport; defaults to the sandbox transport.
243
+ * @returns A new `PreimageManager` instance, or `null` if unavailable.
244
+ */
245
+ export async function createHostPreimageManager(
246
+ transport?: import("@novasamatech/host-api").Transport,
247
+ ): Promise<PreimageManager | null> {
248
+ if (!(await isInsideContainer())) return null;
249
+ try {
250
+ const sdk = await import("@novasamatech/host-api-wrapper");
251
+ return sdk.createPreimageManager(transport);
252
+ } catch (err) {
253
+ log.debug("createHostPreimageManager unavailable", err);
254
+ return null;
255
+ }
196
256
  }
197
257
 
198
258
  /**
@@ -202,9 +262,10 @@ export interface PreimageManager {
202
262
  */
203
263
  export async function getAccountsProvider(): Promise<AccountsProvider | null> {
204
264
  try {
205
- const sdk = await import("@novasamatech/product-sdk");
206
- return sdk.createAccountsProvider() as unknown as AccountsProvider;
207
- } catch {
265
+ const sdk = await import("@novasamatech/host-api-wrapper");
266
+ return sdk.createAccountsProvider();
267
+ } catch (err) {
268
+ log.debug("getAccountsProvider unavailable", err);
208
269
  return null;
209
270
  }
210
271
  }
@@ -220,6 +281,9 @@ export async function getAccountsProvider(): Promise<AccountsProvider | null> {
220
281
  */
221
282
  export type AllocatableResource = CodecType<typeof AllocatableResourceCodec>;
222
283
 
284
+ /** Tag-only view of {@link AllocatableResource} for places that just need the variant name. */
285
+ export type AllocatableResourceTag = AllocatableResource["tag"];
286
+
223
287
  /**
224
288
  * Per-resource outcome from {@link requestResourceAllocation}.
225
289
  * The host strips secret payloads from `Allocated` before returning, so
@@ -227,6 +291,21 @@ export type AllocatableResource = CodecType<typeof AllocatableResourceCodec>;
227
291
  */
228
292
  export type AllocationOutcome = CodecType<typeof AllocationOutcomeCodec>;
229
293
 
294
+ /** Tag-only view of {@link AllocationOutcome} (`"Allocated" | "Rejected" | "NotAvailable"`). */
295
+ export type AllocationOutcomeTag = AllocationOutcome["tag"];
296
+
297
+ /**
298
+ * Remote permission the dapp can ask the host to grant via
299
+ * {@link requestPermission}.
300
+ *
301
+ * Derived from the upstream codec so variant renames surface as compile
302
+ * errors, not runtime failures.
303
+ */
304
+ export type RemotePermission = CodecType<typeof RemotePermissionCodec>;
305
+
306
+ /** Tag-only view of {@link RemotePermission}. */
307
+ export type RemotePermissionTag = RemotePermission["tag"];
308
+
230
309
  /**
231
310
  * Request the host to pre-allocate one or more resource allowances.
232
311
  *
@@ -258,7 +337,75 @@ export async function requestResourceAllocation(
258
337
  return await truApi.requestResourceAllocation(enumValue("v1", resources)).match(
259
338
  (envelope: { tag: "v1"; value: AllocationOutcome[] }) => envelope.value,
260
339
  (err: unknown) => {
261
- throw new Error(`requestResourceAllocation failed: ${JSON.stringify(err)}`);
340
+ throw new Error(`requestResourceAllocation failed: ${formatHostError(err)}`, {
341
+ cause: err,
342
+ });
343
+ },
344
+ );
345
+ }
346
+
347
+ // ─────────────────────────────────────────────────────────────────────────────
348
+ // Authorized Statement Store proof creation (RFC-10 §"Statement Store allowance")
349
+ // ─────────────────────────────────────────────────────────────────────────────
350
+
351
+ /**
352
+ * Have the host sign a Statement using an allowance-bearing account it
353
+ * picks internally — RFC-10 §"Statement Store allowance".
354
+ *
355
+ * The product passes only the Statement payload; the host chooses the
356
+ * `//allowance//statement-store//{productId}` account that holds SSS
357
+ * allowance and signs with it. Allowance is provisioned implicitly on
358
+ * first use if the host hasn't already pre-allocated via
359
+ * {@link requestResourceAllocation}; products never see the signing
360
+ * account or its key material.
361
+ *
362
+ * Pairs with {@link getStatementStore}'s `submit`: call this to obtain
363
+ * a proof, attach it to the Statement, and submit the result.
364
+ *
365
+ * @param statement - The Statement to be signed.
366
+ * @returns The proof to attach before submitting.
367
+ * @throws If the host is unavailable or the host-side signing fails.
368
+ *
369
+ * @example
370
+ * ```ts
371
+ * import { createProofAuthorized, getStatementStore } from "@parity/product-sdk-host";
372
+ *
373
+ * const statement = {
374
+ * proof: undefined,
375
+ * decryptionKey: undefined,
376
+ * expiry: undefined,
377
+ * channel: undefined,
378
+ * topics: [],
379
+ * data: payload,
380
+ * };
381
+ * const proof = await createProofAuthorized(statement);
382
+ * const store = await getStatementStore();
383
+ * await store?.submit({ ...statement, proof });
384
+ * ```
385
+ *
386
+ * @remarks
387
+ * RFC-10 introduces this as a new, strictly additive TruAPI call. The
388
+ * pre-existing `HostStatementStore.createProof(accountId, statement)`
389
+ * surface stays available for products that own a non-allowance signing
390
+ * account; this wrapper is the sponsored-submission path.
391
+ */
392
+ export async function createProofAuthorized(statement: Statement): Promise<StatementProof> {
393
+ const truApi = await getTruApi();
394
+ if (!truApi) {
395
+ throw new Error("createProofAuthorized: TruAPI unavailable");
396
+ }
397
+ log.debug("createProofAuthorized", {
398
+ topics: statement.topics.length,
399
+ dataLen: statement.data?.length ?? 0,
400
+ });
401
+
402
+ // `.match()` because the host returns a neverthrow ResultAsync, not a Promise.
403
+ return await truApi.statementStoreCreateProofAuthorized(enumValue("v1", statement)).match(
404
+ (envelope: { tag: "v1"; value: StatementProof }) => envelope.value,
405
+ (err: unknown) => {
406
+ throw new Error(`createProofAuthorized failed: ${formatHostError(err)}`, {
407
+ cause: err,
408
+ });
262
409
  },
263
410
  );
264
411
  }
@@ -311,99 +458,16 @@ export interface ResultAsync<T, E> {
311
458
  }
312
459
 
313
460
  /**
314
- * Accounts provider interface from @novasamatech/product-sdk.
461
+ * Accounts provider handle from `@novasamatech/host-api-wrapper`. Surfaces the
462
+ * full upstream API - host wallet accounts, app-scoped product accounts,
463
+ * Ring VRF, user identity (`getUserId`, `requestLogin`), and connection
464
+ * status subscription.
315
465
  *
316
- * Provides methods for accessing host wallet accounts, product accounts,
317
- * and Ring VRF operations.
466
+ * Type identical to `createAccountsProvider()` from
467
+ * `@novasamatech/host-api-wrapper`; methods return neverthrow `ResultAsync`
468
+ * values with typed `CodecError` variants in the error channel.
318
469
  */
319
- export interface AccountsProvider {
320
- /**
321
- * Get legacy accounts (user's external wallets connected to the host).
322
- *
323
- * Renamed from `getNonProductAccounts` in @novasamatech/product-sdk 0.7.
324
- *
325
- * @returns ResultAsync resolving to array of accounts.
326
- */
327
- getLegacyAccounts: () => ResultAsync<HostAccount[], unknown>;
328
-
329
- /**
330
- * Get a signer for a legacy account.
331
- *
332
- * Renamed from `getNonProductAccountSigner` in @novasamatech/product-sdk 0.7.
333
- *
334
- * @param account - The product account (used for public key lookup).
335
- * @returns A PolkadotSigner for signing transactions.
336
- */
337
- getLegacyAccountSigner: (account: ProductAccount) => import("polkadot-api").PolkadotSigner;
338
-
339
- /**
340
- * Get an app-scoped product account from the host.
341
- *
342
- * Product accounts are derived by the host wallet for each app, identified
343
- * by `dotNsIdentifier` (e.g., "mark3t.dot"). The user controls these accounts
344
- * but they are scoped to the requesting app.
345
- *
346
- * @param dotNsIdentifier - App identifier (e.g., "mark3t.dot").
347
- * @param derivationIndex - Derivation index within the app scope. Default: 0
348
- * @returns ResultAsync resolving to the account.
349
- */
350
- getProductAccount: (
351
- dotNsIdentifier: string,
352
- derivationIndex?: number,
353
- ) => ResultAsync<HostAccount, unknown>;
354
-
355
- /**
356
- * Get a signer for a product account.
357
- *
358
- * @param account - The product account.
359
- * @returns A PolkadotSigner for signing transactions.
360
- */
361
- getProductAccountSigner: (account: ProductAccount) => import("polkadot-api").PolkadotSigner;
362
-
363
- /**
364
- * Get a contextual alias for a product account via Ring VRF.
365
- *
366
- * Aliases prove account membership in a ring without revealing which
367
- * account produced the alias.
368
- *
369
- * @param dotNsIdentifier - App identifier.
370
- * @param derivationIndex - Derivation index. Default: 0
371
- * @returns ResultAsync resolving to the contextual alias.
372
- */
373
- getProductAccountAlias: (
374
- dotNsIdentifier: string,
375
- derivationIndex?: number,
376
- ) => ResultAsync<ContextualAlias, unknown>;
377
-
378
- /**
379
- * Create a Ring VRF proof for anonymous operations.
380
- *
381
- * Proves that the signer is a member of the ring at the given location
382
- * without revealing which member.
383
- *
384
- * @param dotNsIdentifier - App identifier.
385
- * @param derivationIndex - Derivation index.
386
- * @param location - Ring location on-chain.
387
- * @param message - Message to sign.
388
- * @returns ResultAsync resolving to the proof bytes.
389
- */
390
- createRingVRFProof: (
391
- dotNsIdentifier: string,
392
- derivationIndex: number,
393
- location: unknown,
394
- message: Uint8Array,
395
- ) => ResultAsync<Uint8Array, unknown>;
396
-
397
- /**
398
- * Subscribe to account connection status changes.
399
- *
400
- * @param callback - Called with status string ("connected" | "disconnected").
401
- * @returns Unsubscribe handle.
402
- */
403
- subscribeAccountConnectionStatus: (
404
- callback: (status: string) => void,
405
- ) => { unsubscribe: () => void } | (() => void);
406
- }
470
+ export type AccountsProvider = ReturnType<typeof createAccountsProvider>;
407
471
 
408
472
  // ─────────────────────────────────────────────────────────────────────────────
409
473
  // Tests
@@ -426,6 +490,22 @@ if (import.meta.vitest) {
426
490
  expect(manager === null || typeof manager === "object").toBe(true);
427
491
  });
428
492
 
493
+ test("createHostPreimageManager returns null outside container", async () => {
494
+ expect(await createHostPreimageManager()).toBeNull();
495
+ });
496
+
497
+ test("formatHostError unwraps versioned envelopes and renders CodecError", () => {
498
+ expect(
499
+ formatHostError({
500
+ tag: "v1",
501
+ value: { name: "GenericError", message: "boom" },
502
+ }),
503
+ ).toBe("GenericError: boom");
504
+ expect(formatHostError(new Error("plain"))).toBe("plain");
505
+ expect(formatHostError("string err")).toBe("string err");
506
+ expect(formatHostError({ tag: "v1", value: { message: "no-name" } })).toBe("no-name");
507
+ });
508
+
429
509
  test("getAccountsProvider returns provider when SDK is available", async () => {
430
510
  // In dev/test mode, product-sdk is installed, so this returns a provider
431
511
  const provider = await getAccountsProvider();
@@ -449,4 +529,23 @@ if (import.meta.vitest) {
449
529
  expect(typeof requestResourceAllocation).toBe("function");
450
530
  }
451
531
  });
532
+
533
+ test("createProofAuthorized throws when TruAPI is unavailable", async () => {
534
+ cachedTruApi = null;
535
+ const api = await getTruApi();
536
+ if (api === null) {
537
+ await expect(
538
+ createProofAuthorized({
539
+ proof: undefined,
540
+ decryptionKey: undefined,
541
+ expiry: undefined,
542
+ channel: undefined,
543
+ topics: [],
544
+ data: undefined,
545
+ }),
546
+ ).rejects.toThrow(/TruAPI unavailable/);
547
+ } else {
548
+ expect(typeof createProofAuthorized).toBe("function");
549
+ }
550
+ });
452
551
  }
package/src/types.ts CHANGED
@@ -1,62 +1,83 @@
1
1
  /**
2
- * Persistent string and JSON storage exposed by the host container. Most
3
- * apps reach it indirectly through the Storage package's `KvStore`; reach for
4
- * it directly via {@link getHostLocalStorage} when you need raw host storage
5
- * without the KV abstraction.
2
+ * Public types for the host wrappers.
3
+ *
4
+ * These are re-exported from `@novasamatech/host-api-wrapper` (the runtime
5
+ * objects the host getters cast to) rather than hand-mirrored, so the
6
+ * Parity surface stays in lockstep with the upstream codec types.
6
7
  */
7
- export interface HostLocalStorage {
8
- readString(key: string): Promise<string | null>;
9
- writeString(key: string, value: string): Promise<void>;
10
- readJSON<T>(key: string): Promise<T | null>;
11
- writeJSON<T>(key: string, value: T): Promise<void>;
12
- /**
13
- * Clear a specific key from storage.
14
- * @param key - The key to clear
15
- */
16
- clear(key: string): Promise<void>;
17
- }
8
+
9
+ import type {
10
+ hostLocalStorage,
11
+ createStatementStore,
12
+ ProductAccountId as NovasamaProductAccountId,
13
+ SignedStatement as NovasamaSignedStatement,
14
+ Statement as NovasamaStatement,
15
+ StatementTopicFilter as NovasamaStatementTopicFilter,
16
+ StatementsPage as NovasamaStatementsPage,
17
+ Topic as NovasamaTopic,
18
+ } from "@novasamatech/host-api-wrapper";
19
+ import type { Subscription } from "@novasamatech/host-api";
20
+
21
+ /**
22
+ * Persistent storage exposed by the host container, including string, JSON
23
+ * and raw byte (`readBytes`/`writeBytes`) accessors. Most apps reach it
24
+ * indirectly through the Storage package's `KvStore`; reach for it directly
25
+ * via {@link getHostLocalStorage} when you need raw host storage without the
26
+ * KV abstraction.
27
+ *
28
+ * Type identical to `hostLocalStorage` from `@novasamatech/host-api-wrapper`.
29
+ */
30
+ export type HostLocalStorage = typeof hostLocalStorage;
18
31
 
19
32
  /**
20
33
  * Cryptographic proof attached to a statement before submission, returned by
21
34
  * {@link HostStatementStore.createProof}. Variants cover the supported
22
- * signature schemes `Sr25519`, `Ed25519`, `Ecdsa`, and `OnChain` (chain-
35
+ * signature schemes - `Sr25519`, `Ed25519`, `Ecdsa`, and `OnChain` (chain-
23
36
  * attestation-based proofs).
24
37
  *
25
- * Mirrors `@novasamatech/product-sdk@0.7`'s proof shape.
38
+ * Inferred from `createStatementStore().createProof`'s return type so codec
39
+ * changes surface here as compile errors, not runtime decode failures.
26
40
  */
27
- export type StatementProof =
28
- | { tag: "Sr25519"; value: { signature: Uint8Array; signer: Uint8Array } }
29
- | { tag: "Ed25519"; value: { signature: Uint8Array; signer: Uint8Array } }
30
- | { tag: "Ecdsa"; value: { signature: Uint8Array; signer: Uint8Array } }
31
- | {
32
- tag: "OnChain";
33
- value: { who: Uint8Array; blockHash: Uint8Array; event: bigint };
34
- };
41
+ export type StatementProof = Awaited<
42
+ ReturnType<ReturnType<typeof createStatementStore>["createProof"]>
43
+ >;
35
44
 
36
45
  /**
37
- * Topic-based subscription filter. Mirrors `StatementTopicFilter` from
38
- * `@novasamatech/product-sdk` — the host delivers statements that match
46
+ * Topic-based subscription filter. The host delivers statements that match
39
47
  * either *all* of the listed topics (`matchAll`) or *any* of them
40
- * (`matchAny`).
48
+ * (`matchAny`). Re-exported from `@novasamatech/host-api-wrapper`.
41
49
  */
42
- export type StatementTopicFilter = { matchAll: Uint8Array[] } | { matchAny: Uint8Array[] };
50
+ export type StatementTopicFilter = NovasamaStatementTopicFilter;
51
+
52
+ /** A single topic value used inside a {@link StatementTopicFilter}. Re-exported from `@novasamatech/host-api-wrapper`. */
53
+ export type Topic = NovasamaTopic;
54
+
55
+ /** `[ss58Address, chainPrefix]` tuple identifying a product account at the codec layer. Re-exported from `@novasamatech/host-api-wrapper`. */
56
+ export type ProductAccountId = NovasamaProductAccountId;
57
+
58
+ /** Unsigned statement payload. Re-exported from `@novasamatech/host-api-wrapper`. */
59
+ export type Statement = NovasamaStatement;
60
+
61
+ /** Statement bundled with its {@link StatementProof}. Re-exported from `@novasamatech/host-api-wrapper`. */
62
+ export type SignedStatement = NovasamaSignedStatement;
43
63
 
44
64
  /**
45
65
  * A page of signed statements delivered by {@link HostStatementStore.subscribe}.
46
66
  *
47
67
  * Pages arrive sequentially. `isComplete` is `true` on the final page of a
48
68
  * subscription's initial backfill; subsequent pages contain new statements
49
- * as they appear on chain.
69
+ * as they appear on chain. `statements` is `SignedStatement[]` (typed,
70
+ * not `unknown[]`).
50
71
  */
51
- export interface StatementsPage {
52
- statements: unknown[];
53
- isComplete: boolean;
54
- }
72
+ export type StatementsPage = NovasamaStatementsPage;
55
73
 
56
- /** Subscription handle returned by the host. */
57
- export interface HostSubscription {
58
- unsubscribe: () => void;
59
- }
74
+ /**
75
+ * Subscription handle returned by the host - equivalent to
76
+ * `Subscription<void>` from `@novasamatech/host-api`. Exposes
77
+ * `unsubscribe()` plus an `onInterrupt` hook that fires if the host
78
+ * interrupts the subscription server-side.
79
+ */
80
+ export type HostSubscription = Subscription<void>;
60
81
 
61
82
  /**
62
83
  * Statement Store handle exposed by the host container. Provides
@@ -64,37 +85,7 @@ export interface HostSubscription {
64
85
  * host's native binary protocol; the `statement-store` package layers a
65
86
  * higher-level client on top.
66
87
  *
67
- * Shape matches `@novasamatech/product-sdk@0.7`'s `createStatementStore()`.
88
+ * Type identical to `createStatementStore()` from
89
+ * `@novasamatech/host-api-wrapper`.
68
90
  */
69
- export interface HostStatementStore {
70
- /**
71
- * Subscribe to statements matching the given topic filter.
72
- *
73
- * The callback is invoked once per page of statements. After the initial
74
- * backfill completes (signaled by `page.isComplete === true`), subsequent
75
- * pages contain new statements as they're produced.
76
- *
77
- * @param filter - Topic match filter (`matchAll` or `matchAny`).
78
- * @param callback - Called with each `StatementsPage` from the host.
79
- * @returns Subscription handle with `unsubscribe`.
80
- */
81
- subscribe(
82
- filter: StatementTopicFilter,
83
- callback: (page: StatementsPage) => void,
84
- ): HostSubscription;
85
-
86
- /**
87
- * Create a proof for a statement using the given account.
88
- *
89
- * @param accountId - The account ID tuple `[ss58Address, chainPrefix]` from product-sdk.
90
- * @param statement - The unsigned statement.
91
- * @returns The proof (signature + signer info, or chain-attestation reference).
92
- */
93
- createProof(accountId: [string, number], statement: unknown): Promise<StatementProof>;
94
-
95
- /**
96
- * Submit a signed statement to the bulletin chain.
97
- * @param signedStatement - Statement with attached proof.
98
- */
99
- submit(signedStatement: unknown): Promise<void>;
100
- }
91
+ export type HostStatementStore = ReturnType<typeof createStatementStore>;