@parity/product-sdk-host 0.4.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/dist/index.d.ts +380 -225
- package/dist/index.js +132 -32
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/chains.ts +2 -8
- package/src/chat.ts +124 -0
- package/src/container.ts +45 -9
- package/src/entropy.ts +65 -0
- package/src/index.ts +35 -4
- package/src/payments.ts +98 -0
- package/src/permissions.ts +124 -18
- package/src/theme.ts +82 -0
- package/src/truapi.ts +115 -155
- package/src/types.ts +62 -71
package/src/theme.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Higher-level wrapper for the host's theme subscription.
|
|
3
|
+
*
|
|
4
|
+
* `hostApi.themeSubscribe` is reachable via {@link getTruApi}, but consumers
|
|
5
|
+
* have to wire the subscription envelope themselves. `getThemeProvider`
|
|
6
|
+
* returns the `@novasamatech/host-api-wrapper` theme provider object directly,
|
|
7
|
+
* giving callers a `subscribeTheme(cb)` method that resolves to a typed
|
|
8
|
+
* `ThemeMode` ("Light" | "Dark") and yields a `Subscription<void>` handle.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createLogger } from "@parity/product-sdk-logger";
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
createThemeProvider,
|
|
17
|
+
ThemeMode as NovasamaThemeMode,
|
|
18
|
+
} from "@novasamatech/host-api-wrapper";
|
|
19
|
+
|
|
20
|
+
const log = createLogger("host:theme");
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Host theme provider handle. Exposes `subscribeTheme(callback)` which
|
|
24
|
+
* receives a typed `ThemeMode` on every change and returns a
|
|
25
|
+
* `Subscription<void>` (`unsubscribe` + `onInterrupt`).
|
|
26
|
+
*
|
|
27
|
+
* Type identical to `createThemeProvider()` from
|
|
28
|
+
* `@novasamatech/host-api-wrapper`.
|
|
29
|
+
*/
|
|
30
|
+
export type ThemeProvider = ReturnType<typeof createThemeProvider>;
|
|
31
|
+
|
|
32
|
+
/** Host theme mode value. Re-exported from `@novasamatech/host-api-wrapper`. */
|
|
33
|
+
export type ThemeMode = NovasamaThemeMode;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get the host theme provider.
|
|
37
|
+
*
|
|
38
|
+
* Returns the theme-subscription handle exported by
|
|
39
|
+
* `@novasamatech/host-api-wrapper`, or `null` if the package is unavailable
|
|
40
|
+
* (running outside a host container or the optional peer dep isn't
|
|
41
|
+
* installed).
|
|
42
|
+
*
|
|
43
|
+
* Implementation note: upstream `@novasamatech/host-api-wrapper` exports only
|
|
44
|
+
* the `createThemeProvider` factory and no `themeProvider` singleton, so
|
|
45
|
+
* this getter constructs a fresh instance on each call (unlike
|
|
46
|
+
* {@link getPreimageManager} or {@link getHostLocalStorage}, which return
|
|
47
|
+
* upstream singletons). The constructed provider is cheap to allocate; it
|
|
48
|
+
* only opens a subscription when `subscribeTheme` is called.
|
|
49
|
+
*
|
|
50
|
+
* @returns The theme provider, or `null` if unavailable.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { getThemeProvider } from "@parity/product-sdk-host";
|
|
55
|
+
*
|
|
56
|
+
* const provider = await getThemeProvider();
|
|
57
|
+
* if (provider) {
|
|
58
|
+
* const sub = provider.subscribeTheme((mode) => {
|
|
59
|
+
* document.documentElement.dataset.theme = mode.toLowerCase();
|
|
60
|
+
* });
|
|
61
|
+
* // sub.unsubscribe() to stop listening
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export async function getThemeProvider(): Promise<ThemeProvider | null> {
|
|
66
|
+
try {
|
|
67
|
+
const sdk = await import("@novasamatech/host-api-wrapper");
|
|
68
|
+
return sdk.createThemeProvider();
|
|
69
|
+
} catch (err) {
|
|
70
|
+
log.debug("getThemeProvider unavailable", err);
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (import.meta.vitest) {
|
|
76
|
+
const { test, expect } = import.meta.vitest;
|
|
77
|
+
|
|
78
|
+
test("getThemeProvider returns provider when SDK is available", async () => {
|
|
79
|
+
const provider = await getThemeProvider();
|
|
80
|
+
expect(provider === null || typeof provider === "object").toBe(true);
|
|
81
|
+
});
|
|
82
|
+
}
|
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/
|
|
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
|
*
|
|
@@ -16,29 +16,56 @@ import type {
|
|
|
16
16
|
AllocationOutcome as AllocationOutcomeCodec,
|
|
17
17
|
CodecType,
|
|
18
18
|
RemotePermission as RemotePermissionCodec,
|
|
19
|
-
Statement as StatementCodec,
|
|
20
19
|
} from "@novasamatech/host-api";
|
|
20
|
+
import type { createAccountsProvider, preimageManager } from "@novasamatech/host-api-wrapper";
|
|
21
21
|
|
|
22
|
-
import
|
|
22
|
+
import { isInsideContainer } from "./container.js";
|
|
23
|
+
import type { Statement, StatementProof } from "./types.js";
|
|
23
24
|
|
|
24
25
|
const log = createLogger("host");
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
|
-
* Extract a human-readable message from
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
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.
|
|
31
36
|
*/
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
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
|
+
}
|
|
35
52
|
try {
|
|
36
|
-
return JSON.stringify(
|
|
53
|
+
return JSON.stringify(inner);
|
|
37
54
|
} catch {
|
|
38
|
-
return String(
|
|
55
|
+
return String(inner);
|
|
39
56
|
}
|
|
40
57
|
}
|
|
41
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
|
+
|
|
42
69
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
70
|
// Helpers from @novasamatech/host-api (re-exported from @novasamatech/scale)
|
|
44
71
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -99,16 +126,19 @@ export type { HexString } from "@novasamatech/host-api";
|
|
|
99
126
|
* The TruApi type - provides low-level methods for communicating with the host.
|
|
100
127
|
*
|
|
101
128
|
* Methods include:
|
|
102
|
-
* - `navigateTo(url)`
|
|
103
|
-
* - `permission(permissions)`
|
|
104
|
-
* - `localStorageRead/Write/Clear`
|
|
105
|
-
* - `sign(payload)`
|
|
106
|
-
* - `deriveEntropy(context)`
|
|
107
|
-
* - `themeSubscribe()`
|
|
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
|
|
108
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`.
|
|
109
140
|
*/
|
|
110
|
-
|
|
111
|
-
export type TruApi = any;
|
|
141
|
+
export type TruApi = typeof import("@novasamatech/host-api-wrapper").hostApi;
|
|
112
142
|
|
|
113
143
|
/** Cached TruApi instance */
|
|
114
144
|
let cachedTruApi: TruApi | null = null;
|
|
@@ -116,7 +146,7 @@ let cachedTruApi: TruApi | null = null;
|
|
|
116
146
|
/**
|
|
117
147
|
* Get the TruAPI instance for direct low-level access.
|
|
118
148
|
*
|
|
119
|
-
* Returns the `hostApi` object from `@novasamatech/
|
|
149
|
+
* Returns the `hostApi` object from `@novasamatech/host-api-wrapper` which provides
|
|
120
150
|
* methods for communicating directly with the host container. Returns `null`
|
|
121
151
|
* when running outside a container or when the SDK is unavailable.
|
|
122
152
|
*
|
|
@@ -149,7 +179,7 @@ export async function getTruApi(): Promise<TruApi | null> {
|
|
|
149
179
|
if (cachedTruApi) return cachedTruApi;
|
|
150
180
|
|
|
151
181
|
try {
|
|
152
|
-
const sdk = await import("@novasamatech/
|
|
182
|
+
const sdk = await import("@novasamatech/host-api-wrapper");
|
|
153
183
|
cachedTruApi = sdk.hostApi;
|
|
154
184
|
log.debug("TruAPI loaded");
|
|
155
185
|
return cachedTruApi;
|
|
@@ -185,34 +215,44 @@ export async function getTruApi(): Promise<TruApi | null> {
|
|
|
185
215
|
*/
|
|
186
216
|
export async function getPreimageManager(): Promise<PreimageManager | null> {
|
|
187
217
|
try {
|
|
188
|
-
const sdk = await import("@novasamatech/
|
|
218
|
+
const sdk = await import("@novasamatech/host-api-wrapper");
|
|
189
219
|
return sdk.preimageManager;
|
|
190
|
-
} catch {
|
|
220
|
+
} catch (err) {
|
|
221
|
+
log.debug("getPreimageManager unavailable", err);
|
|
191
222
|
return null;
|
|
192
223
|
}
|
|
193
224
|
}
|
|
194
225
|
|
|
195
226
|
/**
|
|
196
|
-
* Preimage manager
|
|
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`.
|
|
197
232
|
*/
|
|
198
|
-
export
|
|
199
|
-
/**
|
|
200
|
-
* Submit a preimage to the bulletin chain.
|
|
201
|
-
* @param data - The data to submit.
|
|
202
|
-
* @returns The preimage key (hex string).
|
|
203
|
-
*/
|
|
204
|
-
submit(data: Uint8Array): Promise<string>;
|
|
233
|
+
export type PreimageManager = typeof preimageManager;
|
|
205
234
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
+
}
|
|
216
256
|
}
|
|
217
257
|
|
|
218
258
|
/**
|
|
@@ -222,9 +262,10 @@ export interface PreimageManager {
|
|
|
222
262
|
*/
|
|
223
263
|
export async function getAccountsProvider(): Promise<AccountsProvider | null> {
|
|
224
264
|
try {
|
|
225
|
-
const sdk = await import("@novasamatech/
|
|
226
|
-
return sdk.createAccountsProvider()
|
|
227
|
-
} catch {
|
|
265
|
+
const sdk = await import("@novasamatech/host-api-wrapper");
|
|
266
|
+
return sdk.createAccountsProvider();
|
|
267
|
+
} catch (err) {
|
|
268
|
+
log.debug("getAccountsProvider unavailable", err);
|
|
228
269
|
return null;
|
|
229
270
|
}
|
|
230
271
|
}
|
|
@@ -296,7 +337,7 @@ export async function requestResourceAllocation(
|
|
|
296
337
|
return await truApi.requestResourceAllocation(enumValue("v1", resources)).match(
|
|
297
338
|
(envelope: { tag: "v1"; value: AllocationOutcome[] }) => envelope.value,
|
|
298
339
|
(err: unknown) => {
|
|
299
|
-
throw new Error(`requestResourceAllocation failed: ${
|
|
340
|
+
throw new Error(`requestResourceAllocation failed: ${formatHostError(err)}`, {
|
|
300
341
|
cause: err,
|
|
301
342
|
});
|
|
302
343
|
},
|
|
@@ -307,22 +348,6 @@ export async function requestResourceAllocation(
|
|
|
307
348
|
// Authorized Statement Store proof creation (RFC-10 §"Statement Store allowance")
|
|
308
349
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
309
350
|
|
|
310
|
-
/**
|
|
311
|
-
* A Statement payload destined for the Statement Store. Matches the
|
|
312
|
-
* `pallet-statement` Statement structure.
|
|
313
|
-
*
|
|
314
|
-
* The optional `proof` field is the same {@link StatementProof} shape that
|
|
315
|
-
* {@link createProofAuthorized} returns: pass `undefined` here, call
|
|
316
|
-
* `createProofAuthorized` to obtain the proof, then attach it before
|
|
317
|
-
* submitting via `HostStatementStore.submit`. The `OnChain` variant of
|
|
318
|
-
* `StatementProof` is a chain-attestation reference; the `Sr25519` /
|
|
319
|
-
* `Ed25519` / `Ecdsa` variants are signing proofs.
|
|
320
|
-
*
|
|
321
|
-
* Derived from the upstream codec so structural changes surface as compile
|
|
322
|
-
* errors here, not runtime decode failures.
|
|
323
|
-
*/
|
|
324
|
-
export type Statement = CodecType<typeof StatementCodec>;
|
|
325
|
-
|
|
326
351
|
/**
|
|
327
352
|
* Have the host sign a Statement using an allowance-bearing account it
|
|
328
353
|
* picks internally — RFC-10 §"Statement Store allowance".
|
|
@@ -378,7 +403,9 @@ export async function createProofAuthorized(statement: Statement): Promise<State
|
|
|
378
403
|
return await truApi.statementStoreCreateProofAuthorized(enumValue("v1", statement)).match(
|
|
379
404
|
(envelope: { tag: "v1"; value: StatementProof }) => envelope.value,
|
|
380
405
|
(err: unknown) => {
|
|
381
|
-
throw new Error(`createProofAuthorized failed: ${
|
|
406
|
+
throw new Error(`createProofAuthorized failed: ${formatHostError(err)}`, {
|
|
407
|
+
cause: err,
|
|
408
|
+
});
|
|
382
409
|
},
|
|
383
410
|
);
|
|
384
411
|
}
|
|
@@ -431,99 +458,16 @@ export interface ResultAsync<T, E> {
|
|
|
431
458
|
}
|
|
432
459
|
|
|
433
460
|
/**
|
|
434
|
-
* Accounts provider
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
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.
|
|
465
|
+
*
|
|
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.
|
|
438
469
|
*/
|
|
439
|
-
export
|
|
440
|
-
/**
|
|
441
|
-
* Get legacy accounts (user's external wallets connected to the host).
|
|
442
|
-
*
|
|
443
|
-
* Renamed from `getNonProductAccounts` in @novasamatech/product-sdk 0.7.
|
|
444
|
-
*
|
|
445
|
-
* @returns ResultAsync resolving to array of accounts.
|
|
446
|
-
*/
|
|
447
|
-
getLegacyAccounts: () => ResultAsync<HostAccount[], unknown>;
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Get a signer for a legacy account.
|
|
451
|
-
*
|
|
452
|
-
* Renamed from `getNonProductAccountSigner` in @novasamatech/product-sdk 0.7.
|
|
453
|
-
*
|
|
454
|
-
* @param account - The product account (used for public key lookup).
|
|
455
|
-
* @returns A PolkadotSigner for signing transactions.
|
|
456
|
-
*/
|
|
457
|
-
getLegacyAccountSigner: (account: ProductAccount) => import("polkadot-api").PolkadotSigner;
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Get an app-scoped product account from the host.
|
|
461
|
-
*
|
|
462
|
-
* Product accounts are derived by the host wallet for each app, identified
|
|
463
|
-
* by `dotNsIdentifier` (e.g., "mark3t.dot"). The user controls these accounts
|
|
464
|
-
* but they are scoped to the requesting app.
|
|
465
|
-
*
|
|
466
|
-
* @param dotNsIdentifier - App identifier (e.g., "mark3t.dot").
|
|
467
|
-
* @param derivationIndex - Derivation index within the app scope. Default: 0
|
|
468
|
-
* @returns ResultAsync resolving to the account.
|
|
469
|
-
*/
|
|
470
|
-
getProductAccount: (
|
|
471
|
-
dotNsIdentifier: string,
|
|
472
|
-
derivationIndex?: number,
|
|
473
|
-
) => ResultAsync<HostAccount, unknown>;
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Get a signer for a product account.
|
|
477
|
-
*
|
|
478
|
-
* @param account - The product account.
|
|
479
|
-
* @returns A PolkadotSigner for signing transactions.
|
|
480
|
-
*/
|
|
481
|
-
getProductAccountSigner: (account: ProductAccount) => import("polkadot-api").PolkadotSigner;
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Get a contextual alias for a product account via Ring VRF.
|
|
485
|
-
*
|
|
486
|
-
* Aliases prove account membership in a ring without revealing which
|
|
487
|
-
* account produced the alias.
|
|
488
|
-
*
|
|
489
|
-
* @param dotNsIdentifier - App identifier.
|
|
490
|
-
* @param derivationIndex - Derivation index. Default: 0
|
|
491
|
-
* @returns ResultAsync resolving to the contextual alias.
|
|
492
|
-
*/
|
|
493
|
-
getProductAccountAlias: (
|
|
494
|
-
dotNsIdentifier: string,
|
|
495
|
-
derivationIndex?: number,
|
|
496
|
-
) => ResultAsync<ContextualAlias, unknown>;
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Create a Ring VRF proof for anonymous operations.
|
|
500
|
-
*
|
|
501
|
-
* Proves that the signer is a member of the ring at the given location
|
|
502
|
-
* without revealing which member.
|
|
503
|
-
*
|
|
504
|
-
* @param dotNsIdentifier - App identifier.
|
|
505
|
-
* @param derivationIndex - Derivation index.
|
|
506
|
-
* @param location - Ring location on-chain.
|
|
507
|
-
* @param message - Message to sign.
|
|
508
|
-
* @returns ResultAsync resolving to the proof bytes.
|
|
509
|
-
*/
|
|
510
|
-
createRingVRFProof: (
|
|
511
|
-
dotNsIdentifier: string,
|
|
512
|
-
derivationIndex: number,
|
|
513
|
-
location: unknown,
|
|
514
|
-
message: Uint8Array,
|
|
515
|
-
) => ResultAsync<Uint8Array, unknown>;
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Subscribe to account connection status changes.
|
|
519
|
-
*
|
|
520
|
-
* @param callback - Called with status string ("connected" | "disconnected").
|
|
521
|
-
* @returns Unsubscribe handle.
|
|
522
|
-
*/
|
|
523
|
-
subscribeAccountConnectionStatus: (
|
|
524
|
-
callback: (status: string) => void,
|
|
525
|
-
) => { unsubscribe: () => void } | (() => void);
|
|
526
|
-
}
|
|
470
|
+
export type AccountsProvider = ReturnType<typeof createAccountsProvider>;
|
|
527
471
|
|
|
528
472
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
529
473
|
// Tests
|
|
@@ -546,6 +490,22 @@ if (import.meta.vitest) {
|
|
|
546
490
|
expect(manager === null || typeof manager === "object").toBe(true);
|
|
547
491
|
});
|
|
548
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
|
+
|
|
549
509
|
test("getAccountsProvider returns provider when SDK is available", async () => {
|
|
550
510
|
// In dev/test mode, product-sdk is installed, so this returns a provider
|
|
551
511
|
const provider = await getAccountsProvider();
|
package/src/types.ts
CHANGED
|
@@ -1,62 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
35
|
+
* signature schemes - `Sr25519`, `Ed25519`, `Ecdsa`, and `OnChain` (chain-
|
|
23
36
|
* attestation-based proofs).
|
|
24
37
|
*
|
|
25
|
-
*
|
|
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
|
-
|
|
29
|
-
|
|
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.
|
|
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 =
|
|
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
|
|
52
|
-
statements: unknown[];
|
|
53
|
-
isComplete: boolean;
|
|
54
|
-
}
|
|
72
|
+
export type StatementsPage = NovasamaStatementsPage;
|
|
55
73
|
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
*
|
|
88
|
+
* Type identical to `createStatementStore()` from
|
|
89
|
+
* `@novasamatech/host-api-wrapper`.
|
|
68
90
|
*/
|
|
69
|
-
export
|
|
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>;
|