diff --git a/README.md b/README.md index 0cd742a45..978643d67 100644 --- a/README.md +++ b/README.md @@ -658,6 +658,17 @@ private storage and attachment custody stay with the one page core. Picker rows show verified contact names, with a generic label for unnamed contacts; raw account IDs are not displayed. +The multi-select picker opens with the current audience checked, preserves selections while searching, and applies them +only with **Use selection**. Confirming no checked contacts removes everyone; **Cancel**, Escape, and the backdrop leave +the audience unchanged. The original single-contact picker remains available. + +Contact names and account identities remain host-private. Products receive opaque contact handles and can reserve +clipped label boxes on their surface; the host draws verified contact usernames, or account identifiers when no username +is available, above the product frame. These labels do not require a shared profile or photo, and are independent of +Profile avatar placement. Same-wallet contact-directory changes clear stale names and refresh the latest placement +without waiting for the product to redraw. Product restart, navigation, wallet/session replacement, an empty placement, +and frame teardown cancel pending refreshes and remove labels. + Use the existing **List**, **Timeline**, and **Resolution** tabs for activity and diagnostics. Wallet does not duplicate their event viewer or capture controls. @@ -700,6 +711,29 @@ funds or import a real wallet. Debug builds can still access real networks and s Keep `VITE_APP_DEBUG` unset or false in production builds. +### Seity profiles + +Profile sharing uses the native core's separate **Profile Disclosure** consent. It does not authorize identity +disclosure, transaction signing, spending, or statement submission. Dismissing a disclosure prompt leaves it undecided; +an explicit denial is persisted by the core. + +The host resolves Seity contact references through the active network's registry and decrypts Bulletin content outside +the product frame. Profile references are bearer capabilities: their storage follows the existing encrypted native +wallet custody and wallet/network namespaces. A network without a configured registry has no contact profile to display. + +Profiles and contact-avatar layers are Solid host surfaces attached to the product's connection to the shared page core. +Closing or retiring the connection aborts pending loads, removes its drawer and avatars, and releases decrypted image +URLs. Profile content is self-described; verified Chat attribution confirms who shared a reference, not who an image +depicts. + +Opening a contact without a received, live profile reference still opens the host drawer. It shows the host-verified +contact name and **No information shared with you yet**, without an error style or an indefinite spinner. It does not +claim the contact has never shared: information may not have reached this host yet. Availability stays private from the +requesting product, whose completion reply is the same for shared and empty profiles. When a product-specific Chat name +is unavailable, the drawer resolves it from the same wallet- and People-network-bound verified directory used by contact +labels. This lookup never delays opening the drawer or returns the name to the requesting product. Missing or +unavailable directory names retain generic attribution. + ## Sandbox API Checker dApps rendered in dotli's sandboxed iframe should communicate exclusively through the container bridge (postMessage), diff --git a/apps/protocol/src/engine.ts b/apps/protocol/src/engine.ts index 2db512550..c7c746e31 100644 --- a/apps/protocol/src/engine.ts +++ b/apps/protocol/src/engine.ts @@ -11,6 +11,7 @@ import type { ManifestResult, RootManifest, ResolveOptions, + SeitySlot, } from '@dotli/resolver'; import { isExecutableKind } from '@dotli/shared'; import { @@ -52,6 +53,7 @@ export interface EngineOptions { * `@dotli/resolver` entry points so they can be wired by reference. */ resolveDotName?: (label: string, opts?: ResolveOptions) => Promise; resolveOwner?: (label: string, opts?: ResolveOptions) => Promise; + resolveSeitySlot?: (lookupKey: `0x${string}`, opts?: ResolveOptions) => Promise; /** * Product-manifest readers. * @@ -157,6 +159,23 @@ export function createEngine(options: EngineOptions): ProtocolEngine { return; } + case 'resolveSeitySlot': { + if (!options.resolveSeitySlot) { + throw new Error(PROTOCOL_APP_ERRORS.RESOLVE_SEITY_SLOT_UNSUPPORTED); + } + const payload = request.payload as ProtocolRequestMap['resolveSeitySlot']; + assertStr(payload.lookupKey, 'lookupKey'); + const slot = await options.resolveSeitySlot(payload.lookupKey as `0x${string}`, syncOptions); + respond({ + namespace: 'dotli:protocol', + kind: 'response', + id: request.id, + ok: true, + result: slot === null ? null : { ...slot, version: slot.version.toString() }, + }); + return; + } + case 'resolveOwner': { if (!options.resolveOwner) { throw new Error(PROTOCOL_APP_ERRORS.RESOLVE_OWNER_UNSUPPORTED); diff --git a/apps/protocol/src/errors.ts b/apps/protocol/src/errors.ts index 4c048ffc3..9b7cbfe65 100644 --- a/apps/protocol/src/errors.ts +++ b/apps/protocol/src/errors.ts @@ -14,6 +14,7 @@ export const PROTOCOL_APP_ERRORS = { INVALID_SHARED_AUTH_VALUE: 'Invalid shared auth value', RESOLVE_DOT_NAME_UNSUPPORTED: 'resolveDotName is not served by this protocol mode', RESOLVE_OWNER_UNSUPPORTED: 'resolveOwner is not served by this protocol mode', + RESOLVE_SEITY_SLOT_UNSUPPORTED: 'resolveSeitySlot is not served by this protocol mode', RESOLVE_EXECUTABLE_MANIFEST_UNSUPPORTED: 'resolveExecutableManifest is not served by this protocol mode', RESOLVE_ROOT_MANIFEST_UNSUPPORTED: 'resolveRootManifest is not served by this protocol mode', CHAIN_BROKER_FAILED: 'Failed to create chain broker', diff --git a/apps/protocol/src/main.ts b/apps/protocol/src/main.ts index 0e4e24dfb..28b62e44b 100644 --- a/apps/protocol/src/main.ts +++ b/apps/protocol/src/main.ts @@ -858,6 +858,7 @@ async function initDirectMode(): Promise { resolveExecutableManifest, resolveOwner, resolveRootManifest, + resolveSeitySlot, setResolverAssetHubProvider, setResolverPeopleProvider, waitForPeopleFinalized, @@ -1014,6 +1015,7 @@ async function initDirectMode(): Promise { }, resolveDotName, resolveOwner, + resolveSeitySlot, resolveExecutableManifest, resolveRootManifest, }); diff --git a/apps/protocol/src/protocol-shared-worker.ts b/apps/protocol/src/protocol-shared-worker.ts index 7854cab17..e57e068dc 100644 --- a/apps/protocol/src/protocol-shared-worker.ts +++ b/apps/protocol/src/protocol-shared-worker.ts @@ -25,6 +25,7 @@ import { resolveExecutableManifest, resolveOwner, resolveRootManifest, + resolveSeitySlot, setResolverAssetHubProvider, setResolverPeopleProvider, waitForAssetHubFinalized, @@ -368,6 +369,20 @@ async function handleRequest(port: MessagePort, request: ProtocolRequestEnvelope return; } + case 'resolveSeitySlot': { + const payload = request.payload as ProtocolRequestMap['resolveSeitySlot']; + assertString(payload.lookupKey, 'lookupKey'); + const slot = await resolveSeitySlot(payload.lookupKey as `0x${string}`, syncOptions); + sendToPort(port, { + namespace: 'dotli:protocol', + kind: 'response', + id: request.id, + ok: true, + result: slot === null ? null : { ...slot, version: slot.version.toString() }, + }); + return; + } + case 'resolveOwner': { const payload = request.payload as ProtocolRequestMap['resolveOwner']; assertString(payload.label, 'label'); diff --git a/docs/resolution-design.md b/docs/resolution-design.md index 58e03342d..6ea2d2622 100644 --- a/docs/resolution-design.md +++ b/docs/resolution-design.md @@ -10,6 +10,16 @@ ![Shared Smoldot](assets/smoldot-shared.svg) +### Seity profile resolution + +Seity profile reads use `resolveSeitySlot` through the canonical iframe engine +(`apps/protocol/src/engine.ts`) or the SharedWorker request handler. Both preserve +the resolver sync deadline and serialize the slot's bigint version as a decimal +string. Gateway mode instead calls `resolveSeitySlotViaRpc` directly. All three +paths use the same pinned `withContract` registry reader; an unconfigured registry +returns `null`. Profile resolution shares the canonical chain-pool lifecycle and +stopped-chain recovery rather than maintaining a separate engine or RPC retry loop. + ## Appendix Table I - Cold-start latency distribution. End-to-end domain resolution across 20 runs (2026-04-24). The *actor* column matches the components in the Architecture Overview above. diff --git a/packages/config/src/network.ts b/packages/config/src/network.ts index 0456ce8a1..505066663 100644 --- a/packages/config/src/network.ts +++ b/packages/config/src/network.ts @@ -63,6 +63,8 @@ export interface ServicesConfig { readonly decimals: number; }; readonly dotns: DotnsContracts; + /** Seity's slot registry on Asset Hub; absent where Seity is not deployed. */ + readonly seity?: { readonly REGISTRY: string }; } const BUILTIN_NETWORK_SERVICES: Record = { @@ -105,6 +107,8 @@ const BUILTIN_NETWORK_SERVICES: Record = { STORAGE_SLOTS: { REGISTRY_RECORDS: 0, CONTENTHASH: 0, TEXT_RECORDS: 1 }, TLD: 'paseo', }, + // paritytech/seity registry/deployments/paseo-next-v2/deployment.json + seity: { REGISTRY: '0x90ddece099d26f66d13bb46b9db49dbb2083cb15' }, }, [NetworkName.PREVIEWNET]: { label: 'Previewnet', diff --git a/packages/content/src/index.ts b/packages/content/src/index.ts index 634a29249..9711b1837 100644 --- a/packages/content/src/index.ts +++ b/packages/content/src/index.ts @@ -9,6 +9,6 @@ export { bitswapGet, listenForSandboxBitswap, onContentProgress } from './bitswa export { decryptContent, isEncrypted } from './decrypt.js'; export { type FetchResult } from './fetch.js'; export { fetchFromIpfs } from './ipfs.js'; -export { computePreimageKey, hashToCid } from './preimage.js'; +export { cidToPreimageKey, computePreimageKey, hashToCid } from './preimage.js'; export { assertBlockMatchesCid } from './verify.js'; export { loadFetch, type FetchModule } from './lazy.js'; diff --git a/packages/content/src/preimage.ts b/packages/content/src/preimage.ts index d07c2bf1f..7a0f0b70f 100644 --- a/packages/content/src/preimage.ts +++ b/packages/content/src/preimage.ts @@ -30,3 +30,21 @@ export function hashToCid(hashHex: string): CID { const digest = create(BLAKE2B_256_MULTIHASH_CODE, fromHex(hashHex)); return CID.createV1(RAW_CID_CODEC, digest); } + +/** + * Inverse of `hashToCid`: the Blake2b-256 preimage key a Bulletin CID names. + * Throws for any CID that is not CIDv1 raw with a Blake2b-256 multihash, the + * only shape the preimage API content-addresses. + */ +export function cidToPreimageKey(cid: string): `0x${string}` { + const parsed = CID.parse(cid); + if ( + parsed.version !== 1 || + parsed.code !== RAW_CID_CODEC || + parsed.multihash.code !== BLAKE2B_256_MULTIHASH_CODE || + parsed.multihash.digest.length !== 32 + ) { + throw new Error(`${cid} is not a raw Blake2b-256 CIDv1`); + } + return toHex(parsed.multihash.digest); +} diff --git a/packages/protocol/src/client.ts b/packages/protocol/src/client.ts index eea031900..f2de52604 100644 --- a/packages/protocol/src/client.ts +++ b/packages/protocol/src/client.ts @@ -656,7 +656,8 @@ async function postRequest( frameWindow.postMessage(envelope, getProtocolOrigin()); }); } -type ResolverRequestMethod = 'resolveDotName' | 'resolveOwner' | 'resolveExecutableManifest' | 'resolveRootManifest'; +type ResolverRequestMethod = + 'resolveDotName' | 'resolveOwner' | 'resolveSeitySlot' | 'resolveExecutableManifest' | 'resolveRootManifest'; function isStoppedResolverResponse(error: unknown): error is Error { return ( @@ -700,6 +701,20 @@ export async function resolveOwnerRemote(label: string): Promise return (await postResolverRequest('resolveOwner', { label })) as string | null; } +/** A Seity registry slot as the protocol returns it; `version` is a decimal string. */ +export interface RemoteSeitySlot { + readonly owner: `0x${string}`; + readonly cidDigest: `0x${string}`; + readonly version: string; +} + +/** Remote proxy for the Seity registry reader (null when the registry is absent). */ +export async function resolveSeitySlotRemote(lookupKey: `0x${string}`): Promise { + return (await postResolverRequest('resolveSeitySlot', { + lookupKey, + })) as RemoteSeitySlot | null; +} + /** * Remote proxy for the executable-manifest reader. * diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts index c9a5cbd92..b89c01d6c 100644 --- a/packages/protocol/src/index.ts +++ b/packages/protocol/src/index.ts @@ -49,6 +49,7 @@ export { resolveExecutableManifestRemote, resolveOwnerRemote, resolveRootManifestRemote, + resolveSeitySlotRemote, setProtocolSubMode, subscribeSharedAuthStorage, subscribeSharedWallet, @@ -57,6 +58,7 @@ export { warmupProtocol, writeSharedAuthStorage, writeSharedModeStorage, + type RemoteSeitySlot, } from './client.js'; export { CORE_CUSTODY_BUSY_ERROR, isCoreCustodyOperation, type CoreCustodyOperation } from './core-custody.js'; export { ProtocolFatalError, ProtocolInitFailedError } from './errors.js'; diff --git a/packages/protocol/src/messages.ts b/packages/protocol/src/messages.ts index 384d80f15..bffc37708 100644 --- a/packages/protocol/src/messages.ts +++ b/packages/protocol/src/messages.ts @@ -11,6 +11,7 @@ export interface ProtocolRequestMap { warmup: Record; resolveDotName: { label: string }; resolveOwner: { label: string }; + resolveSeitySlot: { lookupKey: string }; resolveExecutableManifest: { label: string; kind: 'app' | 'widget' | 'worker'; diff --git a/packages/protocol/src/method-timeouts.ts b/packages/protocol/src/method-timeouts.ts index 6ade9ef5b..6af2e4a25 100644 --- a/packages/protocol/src/method-timeouts.ts +++ b/packages/protocol/src/method-timeouts.ts @@ -34,6 +34,7 @@ export const METHOD_TIMEOUTS: Partial> = { chainConnect: 30_000, resolveDotName: 90_000, resolveOwner: 90_000, + resolveSeitySlot: 90_000, resolveExecutableManifest: 30_000, resolveRootManifest: 30_000, }; diff --git a/packages/resolver/src/abi.ts b/packages/resolver/src/abi.ts index c28cbd7ea..566f47a57 100644 --- a/packages/resolver/src/abi.ts +++ b/packages/resolver/src/abi.ts @@ -63,6 +63,21 @@ export function computeMappingSlot(key: `0x${string}`, slotNumber: number): `0x$ return toHex(new Uint8Array(keccak_256(concatBytes(hexToBytes(key), slotBytes)))); } +/** + * Compute the slot for `mapping(bytes32 => mapping(bytes32 => T))` at slot N, + * which is also how a pvm-contract-sdk `Mapping<([u8; 32], [u8; 32]), T>` + * lays out (pvm-storage chains tuple keys like Solidity nested mappings): + * keccak256(inner ++ keccak256(outer ++ uint256(N))) + */ +export function computeNestedBytes32MappingSlot( + outerKey: `0x${string}`, + innerKey: `0x${string}`, + slotNumber: number, +): `0x${string}` { + const midSlot = computeMappingSlot(outerKey, slotNumber); + return toHex(new Uint8Array(keccak_256(concatBytes(hexToBytes(innerKey), hexToBytes(midSlot))))); +} + /** * Compute the data slot for long Solidity `bytes` storage. * diff --git a/packages/resolver/src/index.ts b/packages/resolver/src/index.ts index 6a078e55a..e116a613d 100644 --- a/packages/resolver/src/index.ts +++ b/packages/resolver/src/index.ts @@ -39,12 +39,14 @@ export { resolveExecutableManifest, resolveOwner, resolveRootManifest, + resolveSeitySlot, setResolverAssetHubProvider, setResolverPeopleProvider, waitForAssetHubFinalized, waitForPeopleFinalized, type ResolveOptions, } from './resolve.js'; +export { type SeitySlot } from './seity-registry.js'; export { createCoreRpcChainProvider, getConnectedRpcEndpoint, isCoreRpcChainSupported } from './rpc-chain.js'; export { type ChainTransportHooks, type ConnectionStatus } from './transport-hooks.js'; export { diff --git a/packages/resolver/src/resolve.ts b/packages/resolver/src/resolve.ts index ea8aee5d5..f71ddb840 100644 --- a/packages/resolver/src/resolve.ts +++ b/packages/resolver/src/resolve.ts @@ -20,6 +20,7 @@ import type { PhaseCallback, StatusCallback } from './access-raw-storage.js'; import { createRawApi, type Api } from './api.js'; import { readExecutableManifest, readRootManifest } from './manifest.js'; import type { ExecutableKind, ExecutableManifest, ManifestResult, RootManifest } from './manifest.js'; +import { readSeitySlot, type SeitySlot } from './seity-registry.js'; export type { StatusCallback, PhaseCallback, ResolvePhase } from './access-raw-storage.js'; export { statusToPhase } from './access-raw-storage.js'; @@ -359,3 +360,16 @@ async function readOwner(label: string, opts: ResolveOptions): Promise { + const registry = getActiveServicesConfig().seity?.REGISTRY; + if (registry === undefined) { + return null; + } + const api = await ensureClient(opts); + return readSeitySlot(api, registry, lookupKey); +} diff --git a/packages/resolver/src/rpc-resolve.ts b/packages/resolver/src/rpc-resolve.ts index 4093f5af1..afaa4b945 100644 --- a/packages/resolver/src/rpc-resolve.ts +++ b/packages/resolver/src/rpc-resolve.ts @@ -31,6 +31,7 @@ import { createRawApi, type Api } from './api.js'; import { getConnectedRpcEndpoint } from './rpc-chain.js'; import { readExecutableManifest, readRootManifest } from './manifest.js'; import type { ExecutableKind, ExecutableManifest, ManifestResult, RootManifest } from './manifest.js'; +import { readSeitySlot, type SeitySlot } from './seity-registry.js'; export type { StatusCallback } from './access-raw-storage.js'; @@ -225,6 +226,19 @@ export function resolveOwnerViaRpc(label: string): Promise { }); } +/** + * Read one Seity registry slot over JSON-RPC: the gateway-mode counterpart of + * `resolveSeitySlot`. Null when the network has no Seity registry, matching + * the protocol-worker path. + */ +export async function resolveSeitySlotViaRpc(lookupKey: `0x${string}`): Promise { + const registry = getActiveServicesConfig().seity?.REGISTRY; + if (registry === undefined) { + return null; + } + return withRpcClient(api => readSeitySlot(api, registry, lookupKey)); +} + /** * Return the Asset Hub RPC endpoint URI the shared chain connection is * currently on, or `null` while none is open. The URI may not be the first diff --git a/packages/resolver/src/seity-registry.test.ts b/packages/resolver/src/seity-registry.test.ts new file mode 100644 index 000000000..c1e0f9431 --- /dev/null +++ b/packages/resolver/src/seity-registry.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, it } from 'vitest'; +import { hexToBytes } from '@noble/hashes/utils.js'; +import type { Api, ContractStorage } from './api.js'; +import { computeNestedBytes32MappingSlot } from './abi.js'; +import { readSeitySlot } from './seity-registry.js'; + +// The storage seity's registry contract wrote after `anchor(0x01…, 0x02…, +// 0x09…)` from 0xa1…, dumped by its mock host. The same keys are pinned in +// paritytech/seity `registry/lib.rs` (`storage_layout_is_what_raw_readers_compute`). +const DOMAIN = `0x${'01'.repeat(32)}` as const; +const LOOKUP = `0x${'02'.repeat(32)}` as const; +const DUMP: Record = { + '0x0178a5f3f52848d455b30bd72f348037540dbb9a30ce8884a49afb59d0a67708': `${'00'.repeat(12)}${'a1'.repeat(20)}`, + '0xf88c0b9de2397b913259aa0787c071c0b839f71070f539761a5e34e4dff53926': '09'.repeat(32), + '0x3cb365a0a73e582cda498139ee151defc9301d55b78c813e1fd1149e92817660': `${'00'.repeat(31)}01`, +}; + +function fakeApi(dump: Record): Api { + const storage: ContractStorage = { + readSlot: key => { + const word = dump[key]; + return Promise.resolve(word === undefined ? null : hexToBytes(word)); + }, + }; + return { + whenReady: () => Promise.resolve(), + withContract: (_address, read) => read(storage), + onStop: () => () => undefined, + destroy: () => undefined, + }; +} + +describe('seity registry', () => { + it('computes the slots the contract writes', () => { + expect(Object.keys(DUMP)).toEqual([0, 1, 2].map(n => computeNestedBytes32MappingSlot(DOMAIN, LOOKUP, n))); + }); + + it.each([ + { name: 'anchored', digest: '09'.repeat(32), version: 1n }, + { name: 'revoked', digest: '00'.repeat(32), version: 2n }, + { name: 'uint64 maximum', digest: '09'.repeat(32), version: 0xffffffffffffffffn }, + ])('reads a $name slot without losing its version', async ({ digest, version }) => { + const dump = { + ...DUMP, + '0xf88c0b9de2397b913259aa0787c071c0b839f71070f539761a5e34e4dff53926': digest, + '0x3cb365a0a73e582cda498139ee151defc9301d55b78c813e1fd1149e92817660': version.toString(16).padStart(64, '0'), + }; + await expect(readSeitySlot(fakeApi(dump), '0xregistry', LOOKUP, DOMAIN)).resolves.toEqual({ + owner: `0x${'a1'.repeat(20)}`, + cidDigest: `0x${digest}`, + version, + }); + }); + + it('reads a never-anchored slot as version 0', async () => { + await expect(readSeitySlot(fakeApi({}), '0xregistry', LOOKUP, DOMAIN)).resolves.toEqual({ + owner: `0x${'00'.repeat(20)}`, + cidDigest: `0x${'00'.repeat(32)}`, + version: 0n, + }); + }); +}); diff --git a/packages/resolver/src/seity-registry.ts b/packages/resolver/src/seity-registry.ts new file mode 100644 index 000000000..2a555de18 --- /dev/null +++ b/packages/resolver/src/seity-registry.ts @@ -0,0 +1,59 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// Seity's slot registry, read from raw contract storage. +// +// The registry (paritytech/seity `registry/lib.rs`) keeps three +// `Mapping<(domain, lookupKey), _>` fields: owners (slot 0, right-aligned +// 20 bytes), digests (slot 1, bytes32) and versions (slot 2, uint64). The +// layout is pinned on both sides by the same storage keys (seity's +// `storage_layout_is_what_raw_readers_compute`, and this package's test). pvm-storage lays +// them out as Solidity nested mappings, so the resolver's slot maths applies +// and no runtime call is needed. Version 0 means never anchored; a zero +// digest means revoked. + +import type { Api } from './api.js'; +import { computeNestedBytes32MappingSlot, toHex, wordToBigInt } from './abi.js'; + +/** blake2b-256("seity:domain:v1"): the registry domain every seity slot uses. */ +export const SEITY_REGISTRY_DOMAIN = '0x5c9584ba6e565351723d57394780b31b4c2156123e1269c4724ae5f01258bb53' as const; + +const SLOT_OWNERS = 0; +const SLOT_DIGESTS = 1; +const SLOT_VERSIONS = 2; + +export interface SeitySlot { + /** Right-aligned in its word, like an `address` (pinned by seity's registry layout test). */ + readonly owner: `0x${string}`; + readonly cidDigest: `0x${string}`; + readonly version: bigint; +} + +export async function readSeitySlot( + api: Api, + registry: string, + lookupKey: `0x${string}`, + domain: `0x${string}` = SEITY_REGISTRY_DOMAIN, +): Promise { + return api.withContract(registry, async storage => { + const slot = (n: number): `0x${string}` => computeNestedBytes32MappingSlot(domain, lookupKey, n); + const versionWord = await storage.readSlot(slot(SLOT_VERSIONS)); + const version = versionWord === null ? 0n : wordToBigInt(versionWord); + if (version === 0n) { + return { + owner: `0x${'00'.repeat(20)}`, + cidDigest: `0x${'00'.repeat(32)}`, + version, + }; + } + const [ownerWord, digestWord] = await Promise.all([ + storage.readSlot(slot(SLOT_OWNERS)), + storage.readSlot(slot(SLOT_DIGESTS)), + ]); + return { + owner: toHex((ownerWord ?? new Uint8Array(32)).slice(12)), + cidDigest: toHex(digestWord ?? new Uint8Array(32)), + version, + }; + }); +} diff --git a/packages/ui/src/bridge.ts b/packages/ui/src/bridge.ts index 7c707d96a..004e876e8 100644 --- a/packages/ui/src/bridge.ts +++ b/packages/ui/src/bridge.ts @@ -48,6 +48,9 @@ import type { TrUApiProductProvider } from '@parity/truapi-host'; import { createIframeHost } from '@parity/truapi-host/web'; import { buildAllowAttribute, registerPermissionAuthorizationProvider } from './permissions.js'; import { dispatchAuthState } from './host-callbacks/AuthState.js'; +import { createContactAvatars, installProfileDebugTrigger } from './host-callbacks/Profile.js'; +import type { AvatarSurfaceFit } from './profile/avatar-overlay.js'; +import { createContactLabelOverlay } from './contacts/label-overlay.js'; import { LoginRequestError } from './login-request-error.js'; import { attachProductFrame } from './product-frame-layout.js'; import { labelToProductId } from './runtime-config.js'; @@ -1087,6 +1090,7 @@ export function initBridgeEventListeners(modalCoordinator: BlockingModalCoordina bridgeEventListenersInitialized = true; (window as typeof window & { __dotliTruapiBridgeReady?: boolean }).__dotliTruapiBridgeReady = true; if (DEBUG) { + installProfileDebugTrigger(); window.addEventListener('storage', event => { if (event.key === LOCAL_WALLET_ENABLED_KEY || event.key === LOCAL_WALLET_REVISION_KEY || event.key === null) { disposePageCores(); @@ -1469,8 +1473,12 @@ async function createHost(args: { extraAllow?: readonly string[]; debugFlowId: string; viewInsetsRelay?: boolean; + /** How the product's avatar surface maps onto the frame. */ + avatarSurface?: AvatarSurfaceFit; }): Promise { const lease = await acquireCore(); + const contactAvatars = createContactAvatars(); + const contactLabels = createContactLabelOverlay(); let connection: CoreConnection; let chatCapable: boolean; try { @@ -1479,8 +1487,10 @@ async function createHost(args: { // The capability is primed by the host shell before rendering, so // this await settles from cache or the in-flight manifest read. chatCapable = await chatCapabilityFor(args.label); - connection = await lease.connect(chatCapable ? 'Worker' : 'App'); + connection = await lease.connect(chatCapable ? 'Worker' : 'App', { contactAvatars, contactLabels }); } catch (error) { + contactAvatars.dispose(); + contactLabels.dispose(); lease.release(); throw error; } @@ -1504,6 +1514,9 @@ async function createHost(args: { }; const connectProductPort = (port: MessagePort): void => { cleanupProductSide(); + // A new port is a restarted product: what it placed before is stale. + contactAvatars.clear(); + contactLabels.clear(); productProvider = createMessagePortProvider(port); disposePipe = pipeProviders(productProvider, coreProvider, pipeArgs); }; @@ -1512,6 +1525,8 @@ async function createHost(args: { unregisterChat(); cleanupProductSide(); coreProvider.dispose(); + contactAvatars.dispose(); + contactLabels.dispose(); lease.release(); }; try { @@ -1526,6 +1541,8 @@ async function createHost(args: { container: args.container, onPort: connectProductPort, }); + contactAvatars.attach(host.iframe, args.avatarSurface ?? 'viewport'); + contactLabels.attach(host.iframe, args.avatarSurface ?? 'viewport'); if (args.viewInsetsRelay === true) { disposeViewInsets = installPolkaVmViewInsetsRelay(host.iframe, args.allowedOrigin); } @@ -1711,26 +1728,36 @@ export async function renderIframe( }); } -function isPolkaVmExecutableManifest(value: string | null): boolean { - if (value === null) { - return false; - } +function field(value: unknown, key: string): unknown { + return value !== null && typeof value === 'object' && key in value + ? (value as Record)[key] + : undefined; +} + +/** + * Whether the executable is a PolkaVM App, and how its avatar surface lands on + * the frame. The sandbox fills the frame with the PolkaVM surface; only a + * framebuffer canvas is contain-fitted inside it, while Tri2D and WebGPU + * canvases stretch over all of it. Web products place in CSS pixels. + */ +function executableSurface(value: string | null): { + polkaVm: boolean; + avatarSurface: AvatarSurfaceFit; +} { + let manifest: unknown; try { - const manifest: unknown = JSON.parse(value); - if ( - manifest === null || - typeof manifest !== 'object' || - !('runtime' in manifest) || - manifest.runtime === null || - typeof manifest.runtime !== 'object' || - !('kind' in manifest.runtime) - ) { - return false; - } - return manifest.runtime.kind === 'polkavm'; + manifest = value === null ? null : JSON.parse(value); } catch { - return false; + manifest = null; } + if (field(field(manifest, 'runtime'), 'kind') !== 'polkavm') { + return { polkaVm: false, avatarSurface: 'viewport' }; + } + const profile = field(field(field(manifest, 'capabilities'), 'graphics'), 'profile'); + return { + polkaVm: true, + avatarSurface: profile === 'framebuffer' ? 'contain' : 'fill', + }; } /** @@ -1813,7 +1840,7 @@ export async function renderAppSubdomain( const keepLoading = previousHost === null; const iframeUrl = new URL(url); - const isPolkaVm = isPolkaVmExecutableManifest(executableManifest); + const surface = executableSurface(executableManifest); emitDotliDebugEvent({ layer: 'bridge', event: 'setup_begin', @@ -1834,8 +1861,9 @@ export async function renderAppSubdomain( sandbox: 'allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-popups', label, archiveCid: cid, - extraAllow: isPolkaVm ? ['accelerometer', 'gyroscope'] : [], - viewInsetsRelay: isPolkaVm, + extraAllow: surface.polkaVm ? ['accelerometer', 'gyroscope'] : [], + viewInsetsRelay: surface.polkaVm, + avatarSurface: surface.avatarSurface, container: app, debugFlowId: bridgeFlowId, }); diff --git a/packages/ui/src/components/overlays/ContactAvatars.tsx b/packages/ui/src/components/overlays/ContactAvatars.tsx new file mode 100644 index 000000000..9ab2d9ab7 --- /dev/null +++ b/packages/ui/src/components/overlays/ContactAvatars.tsx @@ -0,0 +1,46 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +import { For, Show, type Accessor } from 'solid-js'; +import type { JSX } from '@solidjs/web'; +import type { AvatarBox, AvatarSlotView } from '../../profile/avatar-overlay.js'; +import { MoodRing } from './MoodRing.js'; + +function boxStyle(box: AvatarBox): JSX.CSSProperties { + return { + transform: `translate3d(${String(box.x)}px, ${String(box.y)}px, 0)`, + width: `${String(box.w)}px`, + height: `${String(box.h)}px`, + }; +} + +export function ContactAvatars(props: { slots: Accessor }): JSX.Element { + return ( + + {slot => ( +
+
+ + {mood => ( + + )} + + + {url => ( +
+ +
+ )} +
+
+
+ )} +
+ ); +} diff --git a/packages/ui/src/components/overlays/Dialog.tsx b/packages/ui/src/components/overlays/Dialog.tsx index 69b57b75b..182254ac2 100644 --- a/packages/ui/src/components/overlays/Dialog.tsx +++ b/packages/ui/src/components/overlays/Dialog.tsx @@ -16,6 +16,8 @@ export interface DialogProps { /** Backdrop click and Escape. */ onDismiss: () => void; children: JSX.Element; + backdropClass?: string; + dialogClass?: string; } /** Where each open dialog returns focus when it closes. */ @@ -84,7 +86,7 @@ export function Dialog(props: DialogProps): JSX.Element { return (
{ backdrop = el; }} @@ -95,7 +97,7 @@ export function Dialog(props: DialogProps): JSX.Element { }} >
{ dialog = el; restoreTargets.set(el, previouslyFocused); diff --git a/packages/ui/src/components/overlays/MoodRing.tsx b/packages/ui/src/components/overlays/MoodRing.tsx new file mode 100644 index 000000000..b9b70f171 --- /dev/null +++ b/packages/ui/src/components/overlays/MoodRing.tsx @@ -0,0 +1,58 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +import { createMemo, createSignal, onSettled, Show, untrack } from 'solid-js'; +import type { JSX } from '@solidjs/web'; +import { animateMoodRing, moodAge, MOOD_PALETTE } from '../../profile/mood-ring.js'; +import type { Mood } from '../../profile/profile-record.js'; + +interface Animation { + mood: Mood; + size: number; +} + +function AnimatedMoodRing(props: { animation: Animation; onFallback: (fallback: boolean) => void }): JSX.Element { + let canvas!: HTMLCanvasElement; + onSettled(() => { + // The keyed animation owns this canvas and is replaced when mood or size changes. + const { animation, onFallback } = untrack(() => ({ + animation: props.animation, + onFallback: props.onFallback, + })); + const stop = animateMoodRing(canvas, animation.mood, animation.size); + onFallback(stop === null); + return stop ?? undefined; + }); + return ( + { + canvas = el; + }} + /> + ); +} + +export function MoodRing(props: { mood: Mood; size: number; animated?: boolean }): JSX.Element { + const [fallback, setFallback] = createSignal(false); + const animation = createMemo(() => (props.animated === true ? { mood: props.mood, size: props.size } : undefined)); + const palette = createMemo(() => MOOD_PALETTE[props.mood.kind]); + const staticRing = createMemo(() => props.animated !== true || fallback()); + return ( + + ); +} diff --git a/packages/ui/src/components/overlays/ProfileDrawer.tsx b/packages/ui/src/components/overlays/ProfileDrawer.tsx new file mode 100644 index 000000000..6d2c200e2 --- /dev/null +++ b/packages/ui/src/components/overlays/ProfileDrawer.tsx @@ -0,0 +1,173 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +import { createSignal, onCleanup, onSettled, Show, untrack } from 'solid-js'; +import type { JSX } from '@solidjs/web'; +import { log } from '@dotli/shared'; +import { rasterImageType, type ProfileDrawerOptions } from '../../profile/drawer.js'; +import { moodIsCurrent, type Mood } from '../../profile/profile-record.js'; +import { INTENSITY, MOOD_PALETTE } from '../../profile/mood-ring.js'; +import { Dialog } from './Dialog.js'; +import { MoodRing } from './MoodRing.js'; + +export function ProfileDrawer(props: { + options: ProfileDrawerOptions; + signal: AbortSignal; + onClose: () => void; +}): JSX.Element { + const initiallyLoading = untrack(() => props.options.loadProfile !== undefined); + const [loading, setLoading] = createSignal(initiallyLoading); + const [photo, setPhoto] = createSignal(null); + const [mood, setMood] = createSignal(undefined); + const [contactName, setContactName] = createSignal(untrack(() => props.options.contactName)); + const emptyMessage = 'No information shared with you yet.'; + const [status, setStatus] = createSignal(initiallyLoading ? 'Loading profile…' : emptyMessage); + const [failed, setFailed] = createSignal(false); + let objectUrl: string | undefined; + let closeButton: HTMLButtonElement | undefined; + let disposed = false; + onCleanup(() => { + disposed = true; + if (objectUrl !== undefined) { + URL.revokeObjectURL(objectUrl); + } + props.onClose(); + }); + const fail = (message: string): void => { + setFailed(true); + setStatus(message); + }; + // A root is created per presentation; start its loader after mount and + // retain that presentation's signal through every asynchronous continuation. + onSettled(() => { + const { options, signal } = untrack(() => ({ options: props.options, signal: props.signal })); + if (signal.aborted) { + return; + } + if (options.loadContactName !== undefined) { + void options.loadContactName(signal).then( + name => { + if (!disposed && !signal.aborted && name !== undefined) { + setContactName(name); + } + }, + // A missing/unavailable name keeps the generic attribution, not a profile error. + () => undefined, + ); + } + if (options.loadProfile === undefined) { + return; + } + void options.loadProfile(signal).then( + ({ avatar, mood: nextMood }) => { + if (disposed || signal.aborted) { + return; + } + setLoading(false); + const activeMood = nextMood !== undefined && moodIsCurrent(nextMood) ? nextMood : undefined; + setMood(activeMood); + setStatus(''); + if (avatar === null) { + if (activeMood === undefined) { + setStatus(emptyMessage); + } + return; + } + const type = rasterImageType(avatar); + if (type === null) { + fail('The profile image is not a supported format.'); + return; + } + objectUrl = URL.createObjectURL(new Blob([avatar as Uint8Array], { type })); + setPhoto(objectUrl); + }, + (error: unknown) => { + if (disposed || signal.aborted) { + return; + } + setLoading(false); + // Never include bearer references or decrypted content in diagnostics. + const name = error instanceof Error ? error.name : 'Error'; + log.warn('[profile] drawer load failed:', name); + fail( + name === 'TimeoutError' + ? 'The profile could not be fetched. Try again later.' + : name === 'OperationError' + ? 'The profile could not be opened. The reference may be wrong or out of date.' + : 'The profile is unavailable.', + ); + }, + ); + }); + return ( + closeButton} + onDismiss={() => { + props.onClose(); + }} + > +
+

Profile

+ +
+ {name =>

{name()}

}
+
+ {value => } +
+ +
+ + + {url => ( + Profile picture { + setPhoto(null); + fail('The profile image could not be displayed.'); + }} + /> + )} + +
+
+

+ + {value => ( + <>{`${MOOD_PALETTE[value().kind].label} · ${INTENSITY[value().intensity].label.toLowerCase()} · ${String(Math.max(1, Math.round((value().setAt + value().ttlSecs - Date.now() / 1000) / 3600)))} h left`} + )} + +

+

+ {status()} +

+

+ {props.options.loadProfile === undefined ? ( + `Shown in ${props.options.productId}. Shared information will appear here after it reaches this host.` + ) : contactName() === undefined ? ( + `Shown by ${props.options.productId}. Seity profile content is self-described; dot.li does not verify it.` + ) : ( + <> + Shared with you over Chat by {contactName()} · shown in {props.options.productId}. Profile content is + self-described; the host confirms who sent it, not who it depicts. + + )} +

+
+ ); +} diff --git a/packages/ui/src/components/overlays/SigningDialog.tsx b/packages/ui/src/components/overlays/SigningDialog.tsx index f87be7279..aa7be5b51 100644 --- a/packages/ui/src/components/overlays/SigningDialog.tsx +++ b/packages/ui/src/components/overlays/SigningDialog.tsx @@ -21,6 +21,10 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { const { id, view } = props.entry; const titleId = `overlay-modal-title-${String(id)}`; const [password, setPassword] = createSignal(''); + const [query, setQuery] = createSignal(''); + const [selected, setSelected] = createSignal(new Set(view.selection?.selected)); + const matches = (choice: { label: string }): boolean => + choice.label.toLowerCase().includes(query().trim().toLowerCase()); let input: HTMLInputElement | undefined; let firstChoice: HTMLButtonElement | undefined; @@ -35,7 +39,12 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { settleModal(id, button.result, password()); return; } - settleModal(id, button.result); + settleModal( + id, + button.result, + undefined, + view.selection !== undefined && button.variant === 'primary' ? [...selected()] : undefined, + ); }; const dismiss = (): void => { @@ -52,7 +61,12 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { }; return ( - input ?? firstChoice} onDismiss={dismiss}> + input ?? firstChoice} + onDismiss={dismiss} + dialogClass={view.choices === undefined ? 'signing-modal' : 'signing-modal contacts-modal'} + > {icon => ( // eslint-disable-next-line solid/no-innerhtml -- trusted SVG markup from ModalView.icon, not user input @@ -73,25 +87,74 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { )} {notice =>
{notice()}
}
+ + {selection => ( + <> + { + input = element; + }} + type="search" + class="contacts-picker-search" + placeholder="Search contacts" + aria-label="Search contacts" + onInput={event => setQuery(event.currentTarget.value)} + /> +

+ {selected().size === 0 + ? 'No contacts selected. Use selection to remove everyone.' + : `${String(selected().size)} selected${selected().size === selection().limit ? ' (selection limit)' : ''}`} +

+ + )} +
{choices => (
{choice => ( - + } > - {choice.label} - + {selection => ( + + )} + )} + +

No matching contacts

+
)}
diff --git a/packages/ui/src/components/shell/PermissionRow.tsx b/packages/ui/src/components/shell/PermissionRow.tsx index 22f3a27a6..8033b216d 100644 --- a/packages/ui/src/components/shell/PermissionRow.tsx +++ b/packages/ui/src/components/shell/PermissionRow.tsx @@ -26,6 +26,8 @@ export const PERM_ICONS: Readonly> = { '', IdentityDisclosure: '', + ProfileDisclosure: + '', ChatAuthority: '', ChainSubmit: diff --git a/packages/ui/src/contacts/label-overlay.ts b/packages/ui/src/contacts/label-overlay.ts new file mode 100644 index 000000000..a49960926 --- /dev/null +++ b/packages/ui/src/contacts/label-overlay.ts @@ -0,0 +1,226 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +import type { Bytes32 } from '@parity/truapi'; +import type { PlacedContactLabels } from '@parity/truapi-host'; +import { surfaceMapping, type AvatarSurfaceFit } from '../profile/avatar-overlay.js'; + +/** Host-owned names are painted outside the product document, without profiles. */ +export interface ContactLabelOverlay { + readonly signal: AbortSignal; + attach(frame: HTMLIFrameElement, fit: AvatarSurfaceFit): void; + place(placed: PlacedContactLabels, names: ReadonlyMap): void; + clear(): void; + dispose(): void; +} + +interface LabelView { + root: HTMLElement; + text: HTMLElement; + geometry: string; +} + +export function createContactLabelOverlay(): ContactLabelOverlay { + const layer = document.createElement('div'); + layer.className = 'contact-label-overlay'; + const views = new Map(); + let frame: HTMLIFrameElement | null = null; + let fit: AvatarSurfaceFit = 'viewport'; + let placed: PlacedContactLabels | null = null; + let names: ReadonlyMap = new Map(); + let generation = new AbortController(); + let frameRequest: number | null = null; + let settleTimer: number | null = null; + let untrack: (() => void) | undefined; + let disposed = false; + + const stopSettle = (): void => { + if (settleTimer !== null) { + clearTimeout(settleTimer); + settleTimer = null; + } + }; + const settle = (): void => { + stopSettle(); + settleTimer = window.setTimeout(() => { + settleTimer = null; + for (const view of views.values()) { + view.root.classList.remove('contact-label-moving'); + } + }, 150); + }; + const hideMoving = (): void => { + for (const view of views.values()) { + view.root.classList.add('contact-label-moving'); + } + if (views.size !== 0) { + settle(); + } + }; + const clear = (): void => { + if (disposed) { + return; + } + generation.abort(); + generation = new AbortController(); + placed = null; + names = new Map(); + if (frameRequest !== null) { + cancelAnimationFrame(frameRequest); + frameRequest = null; + } + stopSettle(); + views.clear(); + layer.replaceChildren(); + layer.remove(); + }; + const render = (): void => { + if (disposed || frame === null || placed === null) { + return; + } + const map = surfaceMapping(fit, placed.surfaceWidth, placed.surfaceHeight, frame.clientWidth, frame.clientHeight); + const drawn = new Set(); + let moved = false; + for (const label of placed.labels) { + const name = names.get(label.account); + if (name === undefined) { + continue; + } + const { rect, clip } = label; + const x0 = Math.max(clip.x, rect.x, 0); + const y0 = Math.max(clip.y, rect.y, 0); + const x1 = Math.min(clip.x + clip.width, rect.x + rect.width, placed.surfaceWidth); + const y1 = Math.min(clip.y + clip.height, rect.y + rect.height, placed.surfaceHeight); + if (x1 <= x0 || y1 <= y0) { + continue; + } + let view = views.get(label.slot); + if (view === undefined) { + const root = document.createElement('div'); + root.className = 'contact-label-slot'; + const text = document.createElement('div'); + text.className = 'contact-label'; + root.append(text); + view = { root, text, geometry: '' }; + views.set(label.slot, view); + layer.append(root); + } + drawn.add(label.slot); + const x = map.offsetX + x0 * map.scaleX; + const y = map.offsetY + y0 * map.scaleY; + const width = (x1 - x0) * map.scaleX; + const height = (y1 - y0) * map.scaleY; + const textX = (rect.x - x0) * map.scaleX; + const textY = (rect.y - y0) * map.scaleY; + const textWidth = rect.width * map.scaleX; + const textHeight = rect.height * map.scaleY; + const geometry = `${String(x)},${String(y)},${String(width)},${String(height)},${String(textX)},${String(textY)},${String(textWidth)},${String(textHeight)}`; + if (view.geometry !== geometry) { + view.geometry = geometry; + view.root.style.transform = `translate(${String(x)}px, ${String(y)}px)`; + view.root.style.width = `${String(width)}px`; + view.root.style.height = `${String(height)}px`; + view.text.style.transform = `translate(${String(textX)}px, ${String(textY)}px)`; + view.text.style.width = `${String(textWidth)}px`; + view.text.style.height = `${String(textHeight)}px`; + view.text.style.lineHeight = `${String(textHeight)}px`; + view.text.style.fontSize = `${String(Math.min(13 * map.scaleY, textHeight))}px`; + view.root.classList.add('contact-label-moving'); + moved = true; + } + const displayName = name === label.account ? `${label.account.slice(0, 8)}…${label.account.slice(-6)}` : name; + if (view.text.textContent !== displayName) { + view.text.textContent = displayName; + } + view.text.setAttribute('aria-label', name); + } + for (const [slot, view] of views) { + if (!drawn.has(slot)) { + view.root.remove(); + views.delete(slot); + } + } + if (views.size === 0) { + stopSettle(); + layer.remove(); + } else { + if (moved) { + settle(); + } + if (layer.parentNode !== frame.parentNode) { + frame.after(layer); + } + } + }; + const schedule = (): void => { + if (!disposed && frameRequest === null) { + frameRequest = requestAnimationFrame(() => { + frameRequest = null; + render(); + }); + } + }; + return { + get signal() { + return generation.signal; + }, + attach(target, surfaceFit) { + if (disposed) { + return; + } + untrack?.(); + frame = target; + fit = surfaceFit; + const mirror = (): void => { + layer.style.cssText = target.style.cssText; + layer.style.pointerEvents = 'none'; + layer.style.overflow = 'hidden'; + hideMoving(); + schedule(); + }; + const resize = (): void => { + hideMoving(); + schedule(); + }; + const styleObserver = new MutationObserver(mirror); + styleObserver.observe(target, { + attributes: true, + attributeFilter: ['style'], + }); + const resizeObserver = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(resize); + resizeObserver?.observe(target); + window.addEventListener('resize', resize); + // Navigation cannot leave names from the previous document painted over it. + target.addEventListener('load', clear); + untrack = () => { + styleObserver.disconnect(); + resizeObserver?.disconnect(); + window.removeEventListener('resize', resize); + target.removeEventListener('load', clear); + }; + mirror(); + }, + place(next, nextNames) { + if (disposed) { + return; + } + if (next.labels.length === 0) { + clear(); + return; + } + placed = next; + names = nextNames; + schedule(); + }, + clear, + dispose() { + if (!disposed) { + untrack?.(); + clear(); + disposed = true; + generation.abort(); + frame = null; + } + }, + }; +} diff --git a/packages/ui/src/host-callbacks/Contacts.ts b/packages/ui/src/host-callbacks/Contacts.ts index a1a556394..e5406421f 100644 --- a/packages/ui/src/host-callbacks/Contacts.ts +++ b/packages/ui/src/host-callbacks/Contacts.ts @@ -6,13 +6,16 @@ import type { CoreStorage, CoreStorageKey, NativeChatContactsSnapshot, + PlacedContactLabels, ProductContext, } from '@parity/truapi-host'; import type { WorkerSigningHostRuntime } from '@parity/truapi-host/web'; import { blockingModalAbortError, throwIfAborted, type BlockingModalScope } from '../blocking-modal-queue.js'; import { presentModal } from '../overlays/load.js'; +import type { ContactLabelOverlay } from '../contacts/label-overlay.js'; const HEX32 = /^0x[0-9a-f]{64}$/; +const MAX_CONTACTS = 256; type ContactsRuntime = Pick; @@ -167,12 +170,82 @@ function abortable(pending: Promise, signal: AbortSignal): Promise { export function createContactsPlatform( directory: NativeChatContactsDirectory, modalScope: BlockingModalScope, + labels?: ContactLabelOverlay, ): { callbacks: Required; dispose(): void } { const lifetime = new AbortController(); const operationSignal = (): AbortSignal => AbortSignal.any([lifetime.signal, directory.signal]); + let labelSnapshot: Promise> | undefined; + let labelDirectorySignal: AbortSignal | undefined; + let latestLabels: { placed: PlacedContactLabels; signal: AbortSignal } | undefined; + + const invalidateLabels = (): void => { + labelSnapshot = undefined; + labelDirectorySignal = undefined; + const previous = latestLabels; + const refresh = + labels !== undefined && previous !== undefined && !previous.signal.aborted && !lifetime.signal.aborted; + labels?.clear(); + latestLabels = refresh ? { placed: previous.placed, signal: labels.signal } : undefined; + const request = latestLabels; + if (request !== undefined) { + // invalidate() installs the replacement directory generation after aborting + // the old one. Navigation/empty placement/disposal may retire this request + // before the microtask starts, in which case nothing is replayed. + queueMicrotask(() => { + void paintLabels(request).catch(() => { + // Keep names hidden if the replacement session/read is unavailable. + // A new placement or directory invalidation may request them again. + }); + }); + } + }; + + const paintLabels = async (request: { placed: PlacedContactLabels; signal: AbortSignal }): Promise => { + if (labels === undefined || latestLabels !== request || request.signal.aborted || lifetime.signal.aborted) { + return; + } + const directorySignal = directory.signal; + if (labelDirectorySignal !== directorySignal) { + labelDirectorySignal?.removeEventListener('abort', invalidateLabels); + labelDirectorySignal = directorySignal; + labelDirectorySignal.addEventListener('abort', invalidateLabels, { + once: true, + }); + labelSnapshot = undefined; + } + const signal = AbortSignal.any([lifetime.signal, directorySignal]); + if (labelSnapshot === undefined) { + const pending = directory.snapshot(signal).then( + snapshot => + new Map( + snapshot.contacts.map(contact => { + const name = contact.username?.trim(); + return [contact.peerIdentity, name === undefined || name === '' ? contact.peerIdentity : name]; + }), + ), + ); + labelSnapshot = pending; + void pending.catch(() => { + // A failed read is not a reusable snapshot. Do not clear a newer read. + if (labelSnapshot === pending) { + labelSnapshot = undefined; + } + }); + } + const activeSignal = AbortSignal.any([signal, request.signal]); + const names = await abortable(labelSnapshot, activeSignal); + throwIfAborted(activeSignal); + if (latestLabels === request) { + labels.place(request.placed, names); + } + }; return { dispose() { + labelDirectorySignal?.removeEventListener('abort', invalidateLabels); + latestLabels = undefined; + labelSnapshot = undefined; lifetime.abort(blockingModalAbortError('Contact picker host closed')); + labels?.clear(); }, callbacks: { async contacts(lookup) { @@ -207,7 +280,8 @@ export function createContactsPlatform( if (snapshot.contacts.length === 0) { return { tag: 'NoContacts' as const }; } - const selected = await showContactPicker(product, snapshot.contacts, activeSignal); + const choices = await showContactPicker(product, snapshot.contacts, activeSignal); + const selected = choices?.[0]; throwIfAborted(activeSignal); if (selected === undefined) { return { tag: 'Dismissed' as const }; @@ -221,6 +295,54 @@ export function createContactsPlatform( signal, ); }, + async pickContacts(product, selection) { + const initial = selection.selected; + if (initial.length > MAX_CONTACTS) { + throw new Error('Too many selected Chat contacts'); + } + initial.forEach(assertHex32); + const selected = [...new Set(initial)]; + const signal = operationSignal(); + return abortable( + modalScope.enqueue(async queueSignal => { + const activeSignal = AbortSignal.any([signal, queueSignal]); + const snapshot = await directory.snapshot(activeSignal); + const available = new Set(snapshot.contacts.map(contact => contact.peerIdentity)); + if (selected.some(account => !available.has(account))) { + throw new Error('A selected Chat contact is no longer available'); + } + if (snapshot.contacts.length === 0) { + return { tag: 'NoContacts' as const }; + } + const accounts = await showContactPicker(product, snapshot.contacts, activeSignal, selected); + throwIfAborted(activeSignal); + if (accounts === undefined) { + return { tag: 'Dismissed' as const }; + } + const current = await directory.snapshot(activeSignal); + const currentAccounts = new Set(current.contacts.map(contact => contact.peerIdentity)); + if (accounts.some(account => !currentAccounts.has(account))) { + throw new Error('A selected Chat contact is no longer available'); + } + return { tag: 'Picked' as const, value: { accounts } }; + }), + signal, + ); + }, + async placeContactLabels(_product, placed) { + if (labels === undefined) { + return false; + } + if (placed.labels.length === 0) { + latestLabels = undefined; + labels.clear(); + return true; + } + const request = { placed, signal: labels.signal }; + latestLabels = request; + await paintLabels(request); + return true; + }, }, }; } @@ -229,22 +351,49 @@ async function showContactPicker( product: ProductContext, contacts: ContactSnapshot['contacts'], signal: AbortSignal, -): Promise { - const { result } = await presentModal( + initial?: readonly Bytes32[], +): Promise { + const multiple = initial !== undefined; + // A duplicate native roster entry must not become a second consent control. + const unique = new Map(contacts.map(contact => [contact.peerIdentity, contact])); + const { result, selected } = await presentModal( { - title: 'Choose a contact', + title: multiple ? 'Choose contacts' : 'Choose a contact', fields: [], - notice: `${product.productId} is asking you to choose a Chat contact. Names and account identities stay in this host picker.`, - choices: contacts.map(contact => ({ - label: contact.username !== undefined && contact.username !== '' ? contact.username : 'Chat contact', - result: contact.peerIdentity, - })), - buttons: [{ label: 'Cancel', variant: 'cancel', result: 'dismissed' }], + notice: `${product.productId} is asking you to choose ${multiple ? 'Chat contacts' : 'a Chat contact'}. Names and account identities stay in this host picker.`, + choices: [...unique.values()].map(contact => { + const name = contact.username?.trim(); + return { + label: name === undefined || name === '' ? 'Chat contact' : name, + result: contact.peerIdentity, + }; + }), + ...(initial === undefined ? {} : { selection: { selected: initial, limit: MAX_CONTACTS } }), + buttons: multiple + ? [ + { label: 'Cancel', variant: 'cancel', result: 'dismissed' }, + { label: 'Use selection', variant: 'primary', result: 'confirmed' }, + ] + : [{ label: 'Cancel', variant: 'cancel', result: 'dismissed' }], dismissOnBackdrop: true, dismissResult: 'dismissed', fallbackResult: 'dismissed', }, signal, ); - return result === 'dismissed' ? undefined : result; + if (result === 'dismissed') { + return undefined; + } + if (result !== 'confirmed') { + return [result]; + } + if (selected === undefined) { + throw new Error('Contact selection was not confirmed'); + } + return selected.map(account => { + if (account === 'confirmed' || account === 'dismissed') { + throw new Error('Invalid contact selection'); + } + return account; + }); } diff --git a/packages/ui/src/host-callbacks/Profile.ts b/packages/ui/src/host-callbacks/Profile.ts new file mode 100644 index 000000000..bbc1c0652 --- /dev/null +++ b/packages/ui/src/host-callbacks/Profile.ts @@ -0,0 +1,265 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// ProfilePlatform host callbacks: `profile.present`, `profile.presentContact` +// and the contact avatars a product places. +// +// The core has already screened the reference's shape. The host parses it, +// opens the drawer, and fetches and decrypts the avatar through its own +// preimage path. The call resolves once the drawer is up; fetch and decrypt +// failures are shown in the drawer, not returned, and nothing but success or +// a parse failure reaches the product. +// +// Placed avatars are drawn on the host's layer over the product frame from +// the same loader, and every placement answers success: the product must not +// learn which of its contacts shared a profile. + +import type { ProfilePlatform } from '@parity/truapi-host'; +import { bytesToHex } from '@parity/truapi/scale'; +import { fromHex, log } from '@dotli/shared'; +import { showProfileDrawer, type LoadedProfile, type ProfileDrawerOptions } from '../profile/drawer.js'; +import { + createAvatarProfileCache, + createContactAvatarOverlay, + type ContactAvatarOverlay, +} from '../profile/avatar-overlay.js'; +import { + isContactsReference, + openContactsRecord, + parseContactsReference, + type SeityContactsReference, +} from '../profile/contacts-reference.js'; +import { decodeProfileRecord } from '../profile/profile-record.js'; +import { openSeityBlob, parseSeityBlobReference } from '../profile/seity-reference.js'; +import { resolveSeitySlotRemote, type RemoteSeitySlot } from '@dotli/protocol'; +import { getBackend } from '@dotli/config'; +import { loadRpcResolve } from '@dotli/resolver'; +import { createPreimageAdapters } from './Preimage.js'; +import type { NativeChatContactsDirectory } from './Contacts.js'; + +/** Bulletin retrieval can wait on bitswap providers attaching. */ +const AVATAR_FETCH_TIMEOUT_MS = 90_000; + +async function fetchCiphertext(preimageKey: `0x${string}`, signal: AbortSignal): Promise> { + signal.throwIfAborted(); + const deadline = AbortSignal.any([signal, AbortSignal.timeout(AVATAR_FETCH_TIMEOUT_MS)]); + const { lookupPreimage } = createPreimageAdapters('profile'); + const iterator = lookupPreimage(fromHex(preimageKey))[Symbol.asyncIterator](); + let abort: (() => void) | undefined; + const stopped = new Promise((_, reject) => { + abort = () => { + reject( + deadline.reason instanceof Error ? deadline.reason : new DOMException('Profile load cancelled', 'AbortError'), + ); + }; + if (deadline.aborted) { + abort(); + } else { + deadline.addEventListener('abort', abort, { once: true }); + } + }); + // Settled by whichever finishes first; never left as an unhandled rejection. + stopped.catch(() => undefined); + try { + for (;;) { + const next = await Promise.race([iterator.next(), stopped]); + if (next.done === true) { + throw new Error('preimage lookup ended without a value'); + } + if (next.value.isErr()) { + throw new Error(next.value.error.reason); + } + if (next.value.value !== undefined) { + return new Uint8Array(next.value.value); + } + } + } finally { + if (abort !== undefined) { + deadline.removeEventListener('abort', abort); + } + void iterator.return?.(); + } +} + +/** + * Show the profile a reference names, attributed to `productId`. Rejects for a + * reference this host cannot parse, before any UI appears. + */ +export async function presentProfileReference( + productId: string, + reference: string, + signal?: AbortSignal, +): Promise { + signal?.throwIfAborted(); + await showProfileDrawer({ + productId, + loadProfile: profileLoader(reference), + ...(signal === undefined ? {} : { signal }), + }); +} + +/** How a contact the host knows no username for is named. */ +const UNNAMED_CONTACT = 'this contact'; + +/** + * Show a contact's shared profile or an empty-profile view when no reference + * has arrived. Names come from the core's verified contact directory, never + * from an address or the requesting product. A malformed reference fails + * before presentation; it is not treated as absent sharing. + */ +export async function presentContactProfileReference( + productId: string, + reference: string | undefined, + username: string | undefined, + signal?: AbortSignal, + loadContactName?: ProfileDrawerOptions['loadContactName'], +): Promise { + signal?.throwIfAborted(); + await showProfileDrawer({ + productId, + contactName: username === undefined || username === '' ? UNNAMED_CONTACT : username, + ...(reference === undefined ? {} : { loadProfile: profileLoader(reference) }), + ...(loadContactName === undefined ? {} : { loadContactName }), + ...(signal === undefined ? {} : { signal }), + }); +} + +/** + * Parse a reference into the loader the drawer runs. Throws for a reference + * this host cannot parse, so no UI appears for it. + * + * - `seity-contacts:v1:…` names a registry slot: read it, fetch and open the + * sealed record, then fetch and open the avatar the record names. + * - A bare `cid#key` names one avatar blob (the #287 path, unchanged). + */ +function profileLoader(reference: string): (signal: AbortSignal) => Promise { + if (isContactsReference(reference)) { + const parsed = parseContactsReference(reference); + return signal => loadContactsProfile(parsed, signal); + } + const parsed = parseSeityBlobReference(reference); + return async signal => ({ + avatar: await openSeityBlob(await fetchCiphertext(parsed.preimageKey, signal), parsed), + }); +} + +/** + * Read the registry slot through whichever chain path is active: the protocol + * worker's light client, or the gateway RPC for "Trusted Providers", which + * does not route resolution through the protocol iframe. + */ +async function readSeitySlot(lookupKey: `0x${string}`): Promise { + if (getBackend() === 'rpc-gateway') { + const { resolveSeitySlotViaRpc } = await loadRpcResolve(); + const slot = await resolveSeitySlotViaRpc(lookupKey); + return slot === null ? null : { ...slot, version: slot.version.toString() }; + } + return resolveSeitySlotRemote(lookupKey); +} + +async function loadContactsProfile(reference: SeityContactsReference, signal: AbortSignal): Promise { + signal.throwIfAborted(); + const slot = await readSeitySlot(reference.lookupKey); + signal.throwIfAborted(); + // Never anchored, revoked (zero digest) or no registry: nothing to show. + if (slot === null || slot.version === '0' || /^0x0{64}$/.test(slot.cidDigest)) { + return { avatar: null }; + } + const sealed = await fetchCiphertext(slot.cidDigest, signal); + const record = decodeProfileRecord(await openContactsRecord(sealed, reference)); + signal.throwIfAborted(); + if (record.avatarReference === undefined) { + return { avatar: null, ...(record.mood === undefined ? {} : { mood: record.mood }) }; + } + // An avatar that cannot be fetched or opened still leaves the mood, which + // the drawer shows on its own. + const avatar = await openAvatar(record.avatarReference, signal).catch(() => { + signal.throwIfAborted(); + return null; + }); + return { avatar, ...(record.mood === undefined ? {} : { mood: record.mood }) }; +} + +async function openAvatar(reference: string, signal: AbortSignal): Promise { + const parsed = parseSeityBlobReference(reference); + return openSeityBlob(await fetchCiphertext(parsed.preimageKey, signal), parsed); +} + +/** A product frame's avatar layer, with capabilities retired when it closes. */ +export function createContactAvatars(): ContactAvatarOverlay { + const cache = createAvatarProfileCache(profileLoader, 0); + const overlay = createContactAvatarOverlay(cache); + let disposed = false; + return { + ...overlay, + dispose() { + if (disposed) { + return; + } + disposed = true; + overlay.dispose(); + cache.clear(); + }, + }; +} + +/** + * `avatars` is the layer of the frame this connection serves. Connections + * without a frame (the landing and wallet hosts) draw nothing. + */ +export function createProfilePlatform( + avatars: ContactAvatarOverlay | null = null, + signal?: AbortSignal, + contactsDirectory?: NativeChatContactsDirectory, +): Required { + return { + presentProfile(product, request) { + return presentProfileReference(product.productId, request.reference, signal); + }, + presentContactProfile(product, presented) { + const username = presented.username?.trim(); + return presentContactProfileReference( + product.productId, + presented.shared?.reference, + username, + signal, + (username !== undefined && username !== '') || contactsDirectory === undefined + ? undefined + : async presentationSignal => { + const lookupSignal = AbortSignal.any([ + presentationSignal, + contactsDirectory.signal, + AbortSignal.timeout(2_000), + ]); + const snapshot = await contactsDirectory.snapshot(lookupSignal); + const peerIdentity = bytesToHex(presented.peerIdentity); + const name = snapshot.contacts.find(contact => contact.peerIdentity === peerIdentity)?.username?.trim(); + return name === '' ? undefined : name; + }, + ); + }, + placeContactAvatars(_product, placed) { + return Promise.resolve().then(() => { + signal?.throwIfAborted(); + avatars?.place(placed); + }); + }, + }; +} + +/** + * Debug builds only: `window.__dotliPresentProfile(reference)` opens the same + * drawer a product's `profile.present` does, so the reader and the drawer can + * be exercised without a product. + */ +export function installProfileDebugTrigger(): void { + ( + window as typeof window & { + __dotliPresentProfile?: (reference: string) => void; + } + ).__dotliPresentProfile = reference => { + void presentProfileReference('debug', reference).catch(() => { + log.warn('[dot.li] profile debug presentation failed'); + }); + }; +} diff --git a/packages/ui/src/host-callbacks/SessionStore.ts b/packages/ui/src/host-callbacks/SessionStore.ts index 3f397b2f3..1b221d8eb 100644 --- a/packages/ui/src/host-callbacks/SessionStore.ts +++ b/packages/ui/src/host-callbacks/SessionStore.ts @@ -373,6 +373,9 @@ export function createSessionStoreAdapters(custodyLease?: string): CoreStorage { case 'NativeChatFileChunk': case 'NativeChatProducts': case 'DeviceEncryptionKey': + case 'ProfileDisclosure': + case 'ProfileReferencesReceived': + case 'ProfilePersonalReferencesReceived': return encoded; case 'AuthSession': case 'PairingDeviceIdentity': @@ -518,6 +521,14 @@ function coreLocalStorageKey(key: CoreStorageKey): string { // grant expires without touching the others. case 'ProductManifest': return `${CORE_LOCAL_STORAGE_PREFIX}product-manifest:${key.value.productId}`; + // Bearer capabilities are scoped by wallet and chain in the encoded key. + case 'ProfileDisclosure': + return `${CORE_LOCAL_STORAGE_PREFIX}profile-disclosure:${hexNoPrefix(encodeCoreStorageKey(key))}`; + // Product-scoped received references remain separate from personal grants. + case 'ProfileReferencesReceived': + return `${CORE_LOCAL_STORAGE_PREFIX}profile-references-received:${hexNoPrefix(encodeCoreStorageKey(key))}`; + case 'ProfilePersonalReferencesReceived': + return `${CORE_LOCAL_STORAGE_PREFIX}profile-personal-references-received:${hexNoPrefix(encodeCoreStorageKey(key))}`; case 'MainPurseCoinage': case 'NativeChatDevice': case 'NativeChatFileChunk': @@ -531,7 +542,11 @@ function storesSecretMaterial(key: CoreStorageKey): boolean { key.tag === 'AllowanceKeys' || key.tag === 'AutoSigningKey' || key.tag === 'AutoSigningKeys' || - key.tag === 'DeviceEncryptionKey' + key.tag === 'DeviceEncryptionKey' || + // Bearer capabilities: whoever reads one can open the profile it names. + key.tag === 'ProfileDisclosure' || + key.tag === 'ProfileReferencesReceived' || + key.tag === 'ProfilePersonalReferencesReceived' ); } diff --git a/packages/ui/src/host-callbacks/UserConfirmation.ts b/packages/ui/src/host-callbacks/UserConfirmation.ts index c4fc8262c..1bdf80988 100644 --- a/packages/ui/src/host-callbacks/UserConfirmation.ts +++ b/packages/ui/src/host-callbacks/UserConfirmation.ts @@ -9,6 +9,7 @@ import type { PermissionDecision, PreimageSubmitReview, ProductSubtreeReview, + ProfileDisclosureReview, ResourceAllocationReview, SignPayloadReview, SignRawReview, @@ -117,6 +118,8 @@ function confirmationDisplay(label: string, review: ModalReview): { fields: Conf return { fields: createChatAuthorityFields(review.value) }; case 'MainPurseChatPayment': return { fields: createMainPurseChatPaymentFields(review.value) }; + case 'ProfileDisclosure': + return { fields: createProfileDisclosureFields(review.value) }; case 'ResourceAllocation': return { fields: createResourceAllocationFields(review.value) }; } @@ -308,6 +311,22 @@ function createChatAuthorityFields(review: ChatAuthorityReview): ConfirmationFie ]; } +function createProfileDisclosureFields(review: ProfileDisclosureReview): ConfirmationField[] { + return [ + { label: 'Requesting product', value: review.productId }, + { + label: 'Permission', + value: + "Share this app's profile with app audiences or selected contacts. Personally shared profiles may be shown across the recipients' apps.", + }, + { + label: 'Audience changes', + value: + 'This authorizes the app to choose and update recipients. Always allow remembers that permission; it does not ask again for each audience change.', + }, + ]; +} + function createMainPurseChatPaymentFields(review: MainPurseChatPaymentReview): ConfirmationField[] { const services = getActiveServicesConfig(); if ( @@ -434,6 +453,12 @@ function confirmationCopy(review: ModalReview): ConfirmationCopy { }; case 'ResourceAllocation': return { title: 'Resource Allocation', action: 'Allow' }; + case 'ProfileDisclosure': + return { + title: 'Allow Profile Sharing', + action: 'Allow', + cancelAction: 'Deny', + }; } } @@ -457,6 +482,11 @@ async function handleConfirmationReview( if (decision === 'dismissed' && review.tag === 'IdentityDisclosure') { throw new Error(ERRORS.IDENTITY_DISCLOSURE_DISMISSED); } + // A failed prompt leaves the grant undetermined in the core, so dismissing + // the dialog asks again next time instead of storing a refusal. + if (decision === 'dismissed' && review.tag === 'ProfileDisclosure') { + throw new Error(ERRORS.PERMISSION_DIALOG_DISMISSED); + } return decision; } diff --git a/packages/ui/src/host-callbacks/handlers.ts b/packages/ui/src/host-callbacks/handlers.ts index 3af5fa4bf..ca83a5f9e 100644 --- a/packages/ui/src/host-callbacks/handlers.ts +++ b/packages/ui/src/host-callbacks/handlers.ts @@ -26,6 +26,9 @@ import { createThemeSubscribe } from './Theme.js'; import { createLocaleSubscribe } from './Locale.js'; import { createAuthStateChanged } from './AuthState.js'; import { createChatPlatform } from './Chat.js'; +import { createProfilePlatform } from './Profile.js'; +import type { NativeChatContactsDirectory } from './Contacts.js'; +import type { ContactAvatarOverlay } from '../profile/avatar-overlay.js'; import { createSessionStoreAdapters } from './SessionStore.js'; import { createUserConfirmationAdapters } from './UserConfirmation.js'; import { createBlockingModalScope, type BlockingModalScope } from '../blocking-modal-queue.js'; @@ -37,7 +40,12 @@ export interface CreateHostCallbacksOptions { pairingHostGlobal?: boolean | undefined; blockingModalScope?: BlockingModalScope; custodyLease?: string; + /** Avatar layer of the product frame this connection serves, if any. */ + contactAvatars?: ContactAvatarOverlay; + /** Retires Profile presentations and loads with the native connection. */ + profileSignal?: AbortSignal; contacts?: Required; + contactsDirectory?: NativeChatContactsDirectory; } export function createHostCallbacks(options: CreateHostCallbacksOptions): RequiredHostCallbacks { @@ -48,7 +56,10 @@ export function createHostCallbacks(options: CreateHostCallbacksOptions): Requir pairingHostGlobal, blockingModalScope = createBlockingModalScope(), custodyLease, + contactAvatars, + profileSignal, contacts, + contactsDirectory, } = options; return { navigation: { navigateTo: createNavigateTo() }, @@ -81,6 +92,10 @@ export function createHostCallbacks(options: CreateHostCallbacksOptions): Requir // Always served; the core itself denies chat calls on non-Chat // executions and without an active session. chat: createChatPlatform(), + // Any product may ask the host to show a profile it references; the + // drawer attributes it to the product and returns nothing to it. Placed + // contact avatars are drawn on the frame's own host layer. + profile: createProfilePlatform(contactAvatars, profileSignal, contactsDirectory), ...(contacts === undefined ? {} : { contacts }), }; } diff --git a/packages/ui/src/page-core.ts b/packages/ui/src/page-core.ts index 0c50f289a..5c963eae3 100644 --- a/packages/ui/src/page-core.ts +++ b/packages/ui/src/page-core.ts @@ -49,6 +49,13 @@ import { } from './host-callbacks/SessionStore.js'; import { createTruapiRuntimeConfig, labelToProductId } from './runtime-config.js'; import { showNotification } from './notification.js'; +import type { ContactAvatarOverlay } from './profile/avatar-overlay.js'; +import type { ContactLabelOverlay } from './contacts/label-overlay.js'; + +export interface CoreConnectionOptions { + contactAvatars?: ContactAvatarOverlay; + contactLabels?: ContactLabelOverlay; +} export interface PageProduct { label: string; @@ -77,7 +84,7 @@ export interface CoreConnection { export interface CoreLease { runtime: PageRuntime; wallet: LiveLocalWallet | undefined; - connect(executionKind?: ProductExecutionKind): Promise; + connect(executionKind?: ProductExecutionKind, options?: CoreConnectionOptions): Promise; release(): void; } @@ -88,7 +95,7 @@ interface Core { leases: number; persistent: boolean; faulted: boolean; - openCallbacks(): { callbacks: RequiredHostCallbacks; dispose(): void }; + openCallbacks(options: CoreConnectionOptions): { callbacks: RequiredHostCallbacks; dispose(): void }; dispose(): void; } @@ -200,7 +207,7 @@ export async function acquireCore(): Promise { if (!cores.has(core)) { throw new Error('Page core retired before it became ready'); } - return { runtime, wallet: core.wallet, connect: kind => connect(core, runtime, kind), release }; + return { runtime, wallet: core.wallet, connect: (kind, options) => connect(core, runtime, kind, options), release }; } catch (error) { release(); throw error; @@ -253,6 +260,7 @@ function createCore(product: PageProduct): Core { } const coordinator = modalCoordinator; const blockingModalScope = coordinator.createScope(); + const profileLifetime = new AbortController(); const connectionDisposers = new Set<() => void>(); let runtimeCallbacks: RequiredHostCallbacks | undefined; const context = isExperimentalWalletActive() ? localWalletContext() : undefined; @@ -322,8 +330,10 @@ function createCore(product: PageProduct): Core { pairingDotSuffix: product.pairing?.dotSuffix, pairingHostGlobal: product.pairing?.hostGlobal, blockingModalScope, + profileSignal: profileLifetime.signal, ...(custodyLease === undefined ? {} : { custodyLease }), ...(nativeContacts === undefined ? {} : { contacts: nativeContacts.callbacks }), + ...(contactsDirectory === undefined ? {} : { contactsDirectory }), }); runtimeCallbacks = callbacks; if (contactsDirectory !== undefined) { @@ -520,17 +530,24 @@ function createCore(product: PageProduct): Core { leases: 0, persistent: context !== undefined, faulted: false, - openCallbacks() { + openCallbacks(options) { if (disposed || runtimeCallbacks === undefined) { throw new Error('Page core callbacks are unavailable'); } const scope = coordinator.createScope(); - const contacts = contactsDirectory === undefined ? undefined : createContactsPlatform(contactsDirectory, scope); + const connectionLifetime = new AbortController(); + const contacts = + contactsDirectory === undefined + ? undefined + : createContactsPlatform(contactsDirectory, scope, options.contactLabels); const callbacks = createHostCallbacks({ label: product.label, blockingModalScope: scope, + profileSignal: connectionLifetime.signal, + ...(options.contactAvatars === undefined ? {} : { contactAvatars: options.contactAvatars }), ...(custodyLease === undefined ? {} : { custodyLease }), ...(contacts === undefined ? {} : { contacts: contacts.callbacks }), + ...(contactsDirectory === undefined ? {} : { contactsDirectory }), }); // Session state, encrypted storage and file custody belong to the core. // Interactive product prompts belong only to their live connection. @@ -552,6 +569,9 @@ function createCore(product: PageProduct): Core { return; } closed = true; + connectionLifetime.abort(); + options.contactAvatars?.dispose(); + options.contactLabels?.dispose(); connectionDisposers.delete(dispose); contacts?.dispose(); scope.dispose(); @@ -564,6 +584,7 @@ function createCore(product: PageProduct): Core { return; } disposed = true; + profileLifetime.abort(); cores.delete(core); if (current === core) { current = null; @@ -606,12 +627,13 @@ async function connect( core: Core, runtime: PageRuntime, executionKind: ProductExecutionKind = 'App', + options: CoreConnectionOptions = {}, ): Promise { if (!cores.has(core)) { throw new Error('Page core is closed'); } const productId = productIdOf(core.product); - const callbacks = core.openCallbacks(); + const callbacks = core.openCallbacks(options); let provider: TrUApiProductProvider; try { provider = await runtime.createProvider({ productId, executionKind }, callbacks.callbacks); diff --git a/packages/ui/src/permission-modal.ts b/packages/ui/src/permission-modal.ts index 9a48b40f5..d85279ad6 100644 --- a/packages/ui/src/permission-modal.ts +++ b/packages/ui/src/permission-modal.ts @@ -32,6 +32,8 @@ export const PERMISSION_DESCRIPTIONS: Record Biometrics: 'Authenticate with a platform passkey or biometric prompt', ChatAuthority: "Bind this app's device account to your wallet Chat identity and encrypt or decrypt Chat routing data", IdentityDisclosure: 'Share your primary DotNS identity with this app', + ProfileDisclosure: + "Share this app's profile with app audiences or selected contacts, including personal sharing across recipients' apps", ChainSubmit: 'Sign and submit on-chain transactions on your behalf', PreimageSubmit: 'Store preimage data on-chain via the Bulletin network', StatementSubmit: 'Submit signed statements to the statement store', @@ -83,6 +85,12 @@ const PERMISSION_ICONS: Record = { '' + '' + '', + ProfileDisclosure: + '' + + '' + + '' + + '' + + '', ChainSubmit: '' + '' + diff --git a/packages/ui/src/permissions.ts b/packages/ui/src/permissions.ts index cfd8c0b76..c89b105a5 100644 --- a/packages/ui/src/permissions.ts +++ b/packages/ui/src/permissions.ts @@ -22,7 +22,13 @@ import type { export type DevicePermissionName = HostDevicePermissionRequest; export type PermissionName = - DevicePermissionName | 'ChainSubmit' | 'ChatAuthority' | 'IdentityDisclosure' | 'PreimageSubmit' | 'StatementSubmit'; + | DevicePermissionName + | 'ChainSubmit' + | 'ChatAuthority' + | 'IdentityDisclosure' + | 'PreimageSubmit' + | 'ProfileDisclosure' + | 'StatementSubmit'; /** Device permissions the host can't actually gate (see AUTO_GRANT_DEVICE_PERMISSIONS). */ export type AutoGrantDevicePermission = 'OpenUrl'; @@ -92,6 +98,7 @@ export const ALL_PERMISSIONS: readonly { { name: 'Biometrics', label: 'Biometrics' }, { name: 'ChatAuthority', label: 'Chat Identity Authority' }, { name: 'IdentityDisclosure', label: 'Identity Disclosure' }, + { name: 'ProfileDisclosure', label: 'Profile Disclosure' }, { name: 'ChainSubmit', label: 'Sign Transactions' }, { name: 'PreimageSubmit', label: 'Submit Preimages' }, { name: 'StatementSubmit', label: 'Submit Statements' }, @@ -148,6 +155,9 @@ export function authorizationRequest(permission: PermissionName): PermissionAuth if (permission === 'IdentityDisclosure') { return { tag: 'IdentityDisclosure' }; } + if (permission === 'ProfileDisclosure') { + return { tag: 'ProfileDisclosure' }; + } return { tag: 'Device', value: permission }; } diff --git a/packages/ui/src/profile/avatar-overlay.ts b/packages/ui/src/profile/avatar-overlay.ts new file mode 100644 index 000000000..c54fefd9c --- /dev/null +++ b/packages/ui/src/profile/avatar-overlay.ts @@ -0,0 +1,650 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// Host-drawn Solid contact avatars over a product frame. +// +// A product reports where its contact avatars sit; the core keeps only the +// contacts who shared a profile with the user and hands each slot's +// reference to the host. The host draws the photo and mood ring on its own +// layer above the product iframe. The layer takes no pointer events, so taps +// still reach the product, and nothing is ever posted back into the frame: +// the product never learns who shared or what they shared. + +import type { AvatarRect } from '@parity/truapi'; +import type { PlacedAvatars } from '@parity/truapi-host'; +import { log } from '@dotli/shared'; +import { createComponent, createSignal, type Accessor } from 'solid-js'; +import { mountRoot } from '../mount/root.js'; +import { ContactAvatars } from '../components/overlays/ContactAvatars.js'; +import { rasterImageType, type LoadedProfile } from './drawer.js'; +import { moodIsCurrent, type Mood } from './profile-record.js'; + +/** + * How a product's surface units land on its iframe's CSS box. + * + * - `viewport`: a web product; one unit is one CSS pixel of the iframe. + * - `contain`: a PolkaVM framebuffer, contain-fitted and centred, as the + * sandbox draws `#dotli-polkavm-canvas[data-polkavm-profile="framebuffer"]`. + * - `fill`: a PolkaVM Tri2D or WebGPU canvas stretched over the whole frame. + */ +export type AvatarSurfaceFit = 'viewport' | 'contain' | 'fill'; + +export interface SurfaceMapping { + readonly scaleX: number; + readonly scaleY: number; + readonly offsetX: number; + readonly offsetY: number; +} + +/** Map a `surfaceWidth` x `surfaceHeight` surface onto a `boxWidth` x `boxHeight` frame. */ +export function surfaceMapping( + fit: AvatarSurfaceFit, + surfaceWidth: number, + surfaceHeight: number, + boxWidth: number, + boxHeight: number, +): SurfaceMapping { + if (fit === 'viewport') { + return { scaleX: 1, scaleY: 1, offsetX: 0, offsetY: 0 }; + } + if (fit === 'fill') { + return { + scaleX: boxWidth / surfaceWidth, + scaleY: boxHeight / surfaceHeight, + offsetX: 0, + offsetY: 0, + }; + } + const scale = Math.min(boxWidth / surfaceWidth, boxHeight / surfaceHeight); + return { + scaleX: scale, + scaleY: scale, + offsetX: (boxWidth - surfaceWidth * scale) / 2, + offsetY: (boxHeight - surfaceHeight * scale) / 2, + }; +} + +/** What the overlay draws for one reference: a photo, a mood, both or neither. */ +export interface AvatarProfile { + readonly photoUrl: string | null; + readonly mood?: Mood; +} + +/** Parse a reference into its loader; throws for one the host cannot parse. */ +export type AvatarProfileLoader = (reference: string) => (signal: AbortSignal) => Promise; + +/** + * Loaded profiles shared by every overlay, keyed by reference. References a + * placement shows are retained; released ones stay for a while so a list + * scrolling back does not refetch, and their blob URLs are revoked when they + * are evicted. + * + * A contact reuses one reference across shares, so each placement also says + * when the share arrived: a later share reloads the reference, and the old + * profile stays drawn until the new one has loaded. + */ +export interface AvatarProfileCache { + /** The settled profile; `null` when there is nothing to draw, `undefined` while unknown. */ + peek(reference: string): AvatarProfile | null | undefined; + /** Load a reference once per share, however many overlays ask. */ + load(reference: string): Promise; + /** Note the share time of a placed reference; a later one makes it reload. */ + renew(reference: string, sharedAt: bigint): void; + retain(reference: string): void; + release(reference: string): void; + clear(): void; +} + +interface CacheEntry { + users: number; + value: AvatarProfile | null | undefined; + loading: Promise | null; + aborter: AbortController; + /** Latest share time seen; `null` before any placement names one. */ + sharedAt: bigint | null; + /** A later share arrived after `value` was loaded. */ + stale: boolean; +} + +/** Released references kept loaded by default. */ +const KEEP_UNUSED = 32; + +export function createAvatarProfileCache(loader: AvatarProfileLoader, keepUnused = KEEP_UNUSED): AvatarProfileCache { + const entries = new Map(); + // Insertion order is release order: the first is the next to go. + const unused = new Set(); + + const entryFor = (reference: string): CacheEntry => { + let entry = entries.get(reference); + if (entry === undefined) { + entry = { + users: 0, + value: undefined, + loading: null, + aborter: new AbortController(), + sharedAt: null, + stale: false, + }; + entries.set(reference, entry); + } + return entry; + }; + + const evict = (reference: string): void => { + const entry = entries.get(reference); + unused.delete(reference); + if (entry === undefined) { + return; + } + entries.delete(reference); + entry.aborter.abort(); + const photoUrl = entry.value?.photoUrl; + if (photoUrl !== undefined && photoUrl !== null) { + URL.revokeObjectURL(photoUrl); + } + }; + + const settle = ( + reference: string, + entry: CacheEntry, + aborter: AbortController, + loaded: LoadedProfile | null, + ): void => { + // A newer share or an eviction superseded this load. + if (entries.get(reference) !== entry || entry.aborter !== aborter) { + return; + } + entry.loading = null; + entry.stale = false; + const bytes = loaded?.avatar ?? null; + const type = bytes === null ? null : rasterImageType(bytes); + const photoUrl = + bytes === null || type === null + ? null + : URL.createObjectURL(new Blob([bytes as Uint8Array], { type })); + // The superseded photo is revoked only now, so it stays drawn until then. + const previous = entry.value?.photoUrl; + entry.value = + loaded === null || (photoUrl === null && loaded.mood === undefined) + ? null + : { photoUrl, ...(loaded.mood === undefined ? {} : { mood: loaded.mood }) }; + if (previous !== undefined && previous !== null) { + URL.revokeObjectURL(previous); + } + }; + + return { + clear() { + for (const reference of entries.keys()) { + evict(reference); + } + }, + peek(reference) { + return entries.get(reference)?.value; + }, + load(reference) { + const entry = entryFor(reference); + if (entry.value !== undefined && !entry.stale) { + return Promise.resolve(); + } + if (entry.loading !== null) { + return entry.loading; + } + const aborter = entry.aborter; + let run: (signal: AbortSignal) => Promise; + try { + run = loader(reference); + } catch { + // An unparseable reference draws nothing; the product is not told. + settle(reference, entry, aborter, null); + return Promise.resolve(); + } + entry.loading = run(aborter.signal).then( + loaded => { + settle(reference, entry, aborter, loaded); + }, + (error: unknown) => { + // Name only: no error on this path carries the reference. + log.debug('[profile] contact avatar load failed:', error instanceof Error ? error.name : typeof error); + // A renewed share that fails to load keeps drawing the last one. + if (entry.stale && entry.aborter === aborter) { + entry.loading = null; + entry.stale = false; + return; + } + settle(reference, entry, aborter, null); + }, + ); + return entry.loading; + }, + renew(reference, sharedAt) { + const entry = entryFor(reference); + if (entry.sharedAt !== null && sharedAt <= entry.sharedAt) { + return; + } + const first = entry.sharedAt === null; + entry.sharedAt = sharedAt; + if (first && entry.value === undefined) { + return; + } + // Drop any load of the older share; the next `load` starts afresh. + entry.aborter.abort(); + entry.aborter = new AbortController(); + entry.loading = null; + entry.stale = entry.value !== undefined; + }, + retain(reference) { + entryFor(reference).users += 1; + unused.delete(reference); + }, + release(reference) { + const entry = entries.get(reference); + if (entry === undefined || entry.users === 0) { + return; + } + entry.users -= 1; + if (entry.users > 0) { + return; + } + // A failed load is retried the next time the reference is placed. + if (entry.value === null) { + evict(reference); + return; + } + unused.add(reference); + for (const oldest of unused) { + if (unused.size <= keepUnused) { + break; + } + evict(oldest); + } + }, + }; +} + +/** One product frame's avatar layer. */ +export interface ContactAvatarOverlay { + /** Draw over `frame`; placements made before this wait for it. */ + attach(frame: HTMLIFrameElement, fit: AvatarSurfaceFit): void; + /** Replace everything drawn with `placed`; no avatars clears the layer. */ + place(placed: PlacedAvatars): void; + /** Draw nothing until the next placement, as when the product restarts. */ + clear(): void; + /** Remove the layer and stop tracking the frame for good. */ + dispose(): void; +} + +/** A CSS pixel box, relative to its parent. */ +export interface AvatarBox { + readonly x: number; + readonly y: number; + readonly w: number; + readonly h: number; +} + +export interface AvatarSlotState { + readonly rootBox: AvatarBox; + readonly anchorBox: AvatarBox; + readonly moving: boolean; + readonly photoUrl: string | null; + readonly mood: Mood | undefined; +} + +export interface AvatarSlotView { + readonly state: Accessor; + readonly update: (state: AvatarSlotState) => void; +} + +/** Latest a timer can be armed for (setTimeout's signed 32-bit bound). */ +const MAX_TIMER_MS = 2_147_483_647; + +/** Shifts up to this are layout rounding, not motion. */ +const MOTION_PX = 0.5; + +/** How long positions must hold still before moved avatars show again. */ +const SETTLE_MS = 150; + +let overlayId = 0; + +function sameBox(a: AvatarBox | null, b: AvatarBox): boolean { + return ( + a !== null && + Math.abs(a.x - b.x) <= MOTION_PX && + Math.abs(a.y - b.y) <= MOTION_PX && + Math.abs(a.w - b.w) <= MOTION_PX && + Math.abs(a.h - b.h) <= MOTION_PX + ); +} + +function setMoving(view: AvatarSlotView, moving: boolean): void { + const state = view.state(); + if (state.moving !== moving) { + view.update({ ...state, moving }); + } +} + +export function createContactAvatarOverlay(cache: AvatarProfileCache): ContactAvatarOverlay { + const layer = document.createElement('div'); + layer.className = 'contact-avatar-overlay'; + layer.setAttribute('aria-hidden', 'true'); + + const views = new Map(); + const [slots, setSlots] = createSignal([]); + const disposeView = mountRoot(`contact-avatars-${String(++overlayId)}`, layer, () => + createComponent(ContactAvatars, { slots }), + ); + const waiting = new Map>(); + let retained: readonly string[] = []; + let placed: PlacedAvatars | null = null; + let frame: HTMLIFrameElement | null = null; + let fit: AvatarSurfaceFit = 'viewport'; + let mirrored = ''; + let frameSize = ''; + let lapseTimer: number | null = null; + let settleTimer: number | null = null; + let frameRequest: number | null = null; + let untrack: (() => void) | null = null; + let disposed = false; + + // The layer copies the frame's inline geometry (fixed box, topbar + // transform and its transition), so it moves with the frame exactly. + // Returns whether that geometry changed. + const mirror = (): boolean => { + if (frame === null || frame.style.cssText === mirrored) { + return false; + } + mirrored = frame.style.cssText; + layer.style.cssText = mirrored; + layer.style.pointerEvents = 'none'; + return true; + }; + + const stopSettle = (): void => { + if (settleTimer !== null) { + clearTimeout(settleTimer); + settleTimer = null; + } + }; + + // Positions reach the host a few frames after the product drew them, so a + // moving avatar would trail its row. Moved slots stay hidden until nothing + // has moved for SETTLE_MS; every movement starts the wait again. + const armSettle = (): void => { + stopSettle(); + settleTimer = window.setTimeout(() => { + settleTimer = null; + for (const view of views.values()) { + setMoving(view, false); + } + }, SETTLE_MS); + }; + + /** The frame itself moved: every avatar trails until the product re-places them. */ + const frameMoved = (): void => { + if (views.size === 0) { + return; + } + for (const view of views.values()) { + setMoving(view, true); + } + armSettle(); + }; + + const clearViews = (): void => { + views.clear(); + setSlots([]); + stopSettle(); + }; + + /** Draw one slot; returns whether it moved or first appeared. */ + const updateView = ( + slot: number, + rect: AvatarRect, + clip: { x0: number; y0: number; x1: number; y1: number }, + map: SurfaceMapping, + profile: AvatarProfile, + mood: Mood | undefined, + ): boolean => { + const view = views.get(slot); + const width = rect.width * map.scaleX; + const height = rect.height * map.scaleY; + const rootBox: AvatarBox = { + x: map.offsetX + clip.x0 * map.scaleX, + y: map.offsetY + clip.y0 * map.scaleY, + w: (clip.x1 - clip.x0) * map.scaleX, + h: (clip.y1 - clip.y0) * map.scaleY, + }; + const anchorBox: AvatarBox = { + x: (rect.x - clip.x0) * map.scaleX, + y: (rect.y - clip.y0) * map.scaleY, + w: width, + h: height, + }; + const previous = view?.state(); + const moved = !sameBox(previous?.rootBox ?? null, rootBox) || !sameBox(previous?.anchorBox ?? null, anchorBox); + const next: AvatarSlotState = { + rootBox, + anchorBox, + moving: moved || previous?.moving === true, + photoUrl: profile.photoUrl, + mood, + }; + if (view === undefined) { + const [state, update] = createSignal(next); + views.set(slot, { state, update }); + setSlots([...views.values()]); + } else { + view.update(next); + } + return moved; + }; + + /** Load `reference` if it is not already, and draw once it arrives. */ + const request = (reference: string): void => { + // The cache hands back the same promise while one load runs; a renewed + // share starts another, which is followed too. + const loading = cache.load(reference); + if (waiting.get(reference) === loading) { + return; + } + waiting.set(reference, loading); + // Draw into whatever placement is current once it arrives. + void loading.then(() => { + if (waiting.get(reference) === loading) { + waiting.delete(reference); + } + schedule(); + }); + }; + + const render = (): void => { + if (lapseTimer !== null) { + clearTimeout(lapseTimer); + lapseTimer = null; + } + if (disposed || frame === null || placed === null) { + clearViews(); + layer.remove(); + return; + } + const current = placed; + const map = surfaceMapping(fit, current.surfaceWidth, current.surfaceHeight, frame.clientWidth, frame.clientHeight); + const nowSecs = Math.floor(Date.now() / 1000); + let nextLapse = Number.POSITIVE_INFINITY; + let moved = false; + const drawn = new Set(); + for (const avatar of current.avatars) { + const profile = cache.peek(avatar.reference); + if (profile === undefined) { + request(avatar.reference); + continue; + } + if (profile === null) { + continue; + } + const mood = profile.mood !== undefined && moodIsCurrent(profile.mood, nowSecs) ? profile.mood : undefined; + if (profile.photoUrl === null && mood === undefined) { + continue; + } + const { rect, clip } = avatar; + // The slot box is the product's clip cut to the surface. It hides + // whatever of the photo circle and its ring falls outside, so the + // photo shows the circle's box within the clip. + const visible = { + x0: Math.max(clip.x, 0), + y0: Math.max(clip.y, 0), + x1: Math.min(clip.x + clip.width, current.surfaceWidth), + y1: Math.min(clip.y + clip.height, current.surfaceHeight), + }; + if ( + Math.min(visible.x1, rect.x + rect.width) <= Math.max(visible.x0, rect.x) || + Math.min(visible.y1, rect.y + rect.height) <= Math.max(visible.y0, rect.y) + ) { + continue; + } + if (mood !== undefined) { + nextLapse = Math.min(nextLapse, mood.setAt + mood.ttlSecs); + } + drawn.add(avatar.slot); + if (updateView(avatar.slot, rect, visible, map, profile, mood)) { + moved = true; + } + } + let removed = false; + for (const slot of views.keys()) { + if (!drawn.has(slot)) { + views.delete(slot); + removed = true; + } + } + if (removed) { + setSlots([...views.values()]); + } + if (views.size === 0) { + stopSettle(); + layer.remove(); + } else { + if (moved) { + armSettle(); + } + if (layer.previousElementSibling !== frame) { + frame.after(layer); + } + } + if (Number.isFinite(nextLapse)) { + lapseTimer = window.setTimeout(schedule, Math.min(MAX_TIMER_MS, Math.max(0, (nextLapse - nowSecs) * 1000))); + } + }; + + // Placements can arrive faster than the screen redraws: draw only the + // latest, once per animation frame. + function schedule(): void { + if (frameRequest === null && !disposed) { + frameRequest = requestAnimationFrame(() => { + frameRequest = null; + render(); + }); + } + } + + /** Draw now, dropping any pending frame, so removals are never late. */ + const flush = (): void => { + if (frameRequest !== null) { + cancelAnimationFrame(frameRequest); + frameRequest = null; + } + render(); + }; + + const show = (next: PlacedAvatars | null): void => { + const references = next?.avatars.map(avatar => avatar.reference) ?? []; + // Retain the new set before releasing the old, so a reference in both + // is never evicted in between. + for (const reference of references) { + cache.retain(reference); + } + for (const reference of retained) { + cache.release(reference); + } + retained = references; + placed = next; + if (next === null) { + flush(); + return; + } + // A later share of a placed reference reloads it; loads start now rather + // than at the next frame. + for (const avatar of next.avatars) { + cache.renew(avatar.reference, avatar.sharedAt); + request(avatar.reference); + } + schedule(); + }; + + return { + attach(target, surfaceFit) { + if (disposed) { + return; + } + untrack?.(); + frame = target; + fit = surfaceFit; + mirrored = ''; + mirror(); + frameSize = `${String(target.clientWidth)}x${String(target.clientHeight)}`; + const onStyle = (): void => { + if (mirror()) { + frameMoved(); + schedule(); + } + }; + const onResize = (): void => { + const size = `${String(target.clientWidth)}x${String(target.clientHeight)}`; + if (size !== frameSize) { + frameSize = size; + frameMoved(); + } + schedule(); + }; + const onWindowResize = (): void => { + frameMoved(); + onResize(); + }; + const styleObserver = new MutationObserver(onStyle); + styleObserver.observe(target, { + attributes: true, + attributeFilter: ['style'], + }); + const resizeObserver = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(onResize); + resizeObserver?.observe(target); + window.addEventListener('resize', onWindowResize); + untrack = () => { + styleObserver.disconnect(); + resizeObserver?.disconnect(); + window.removeEventListener('resize', onWindowResize); + untrack = null; + }; + schedule(); + }, + place(next) { + if (!disposed) { + show(next.avatars.length === 0 ? null : next); + } + }, + clear() { + if (!disposed) { + show(null); + } + }, + dispose() { + if (disposed) { + return; + } + untrack?.(); + show(null); + disposed = true; + frame = null; + disposeView(); + }, + }; +} diff --git a/packages/ui/src/profile/contacts-reference.ts b/packages/ui/src/profile/contacts-reference.ts new file mode 100644 index 000000000..0aeb1dd52 --- /dev/null +++ b/packages/ui/src/profile/contacts-reference.ts @@ -0,0 +1,65 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// Seity contacts references: `"seity-contacts:v1:"`. +// +// Unlike a `cid#key` blob reference, this names a registry slot rather than a +// blob, so it stays the same while the profile behind it changes. Resolving it +// takes one registry read (raw contract storage, no runtime call), one +// preimage fetch of the sealed record, one AES-GCM open, and then the record's +// avatar is an ordinary blob reference fetched the same way. +// +// Format and seal are pinned by Seity's profile-core (`contacts.ts`) and its +// committed vector. The reference is a bearer capability: parsed and used +// here, never logged or handed back to the product. + +import { InvalidProfileReferenceError } from './seity-reference.js'; + +export const CONTACTS_REFERENCE_PREFIX = 'seity-contacts:v1:'; +const BODY_PATTERN = /^[0-9a-f]{128}$/; +const NONCE_BYTES = 12; + +export interface SeityContactsReference { + /** Registry lookup key, public. */ + readonly lookupKey: `0x${string}`; + /** AES-256-GCM key for the sealed record. */ + readonly seed: Uint8Array; +} + +export function isContactsReference(reference: string): boolean { + return reference.startsWith(CONTACTS_REFERENCE_PREFIX); +} + +export function parseContactsReference(reference: string): SeityContactsReference { + // Hex is case-insensitive, like the blob references; the lookup key is + // normalised because it becomes a storage-slot input. + const body = reference.slice(CONTACTS_REFERENCE_PREFIX.length).toLowerCase(); + if (!isContactsReference(reference) || !BODY_PATTERN.test(body)) { + throw new InvalidProfileReferenceError('expected seity-contacts:v1:<32-byte lookup key><32-byte seed>'); + } + const seed = new Uint8Array(32); + for (let i = 0; i < 32; i++) { + seed[i] = Number.parseInt(body.slice(64 + i * 2, 66 + i * 2), 16); + } + return { lookupKey: `0x${body.slice(0, 64)}`, seed }; +} + +/** + * Open a sealed record: `nonce(12) ‖ ciphertext ‖ tag`. AES-GCM + * authenticates, so the wrong seed or substituted bytes reject. + */ +export async function openContactsRecord( + sealed: Uint8Array, + reference: Pick, +): Promise { + if (sealed.length <= NONCE_BYTES) { + throw new Error('sealed profile record is truncated'); + } + const key = await crypto.subtle.importKey('raw', reference.seed, 'AES-GCM', false, ['decrypt']); + const plaintext = await crypto.subtle.decrypt( + { name: 'AES-GCM', iv: sealed.slice(0, NONCE_BYTES) }, + key, + sealed.slice(NONCE_BYTES), + ); + return new Uint8Array(plaintext); +} diff --git a/packages/ui/src/profile/drawer.ts b/packages/ui/src/profile/drawer.ts new file mode 100644 index 000000000..cb548965c --- /dev/null +++ b/packages/ui/src/profile/drawer.ts @@ -0,0 +1,111 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// Host-owned profile drawer, rendered by the Solid overlay surface. +// +// A product asks the host to show a profile it holds a reference to; the host +// fetches and decrypts it and renders it here, so the image never enters the +// product. Without a received reference it shows an empty state immediately; +// otherwise it loads the avatar and mood. It asks nothing, and presenting +// another profile replaces the one on screen. + +import { createComponent } from 'solid-js'; +import { mountRoot } from '../mount/root.js'; +import { ensureOverlayRoot } from '../mount/overlay-root.js'; +import type { Mood } from './profile-record.js'; + +/** What a reference opened to. Either half may be missing. */ +export interface LoadedProfile { + readonly avatar: Uint8Array | null; + readonly mood?: Mood; +} + +export interface ProfileDrawerOptions { + /** Product that asked for the presentation, shown as attribution. */ + readonly productId: string; + /** + * The contact's host-verified username, or a generic phrase when unknown. + * Never an address or a product-supplied name. + */ + readonly contactName?: string; + /** Best-effort host-directory lookup; never delays opening or reaches the product. */ + readonly loadContactName?: (signal: AbortSignal) => Promise; + /** Fetch and decrypt a received profile; absent when no reference was shared. */ + readonly loadProfile?: (signal: AbortSignal) => Promise; + /** The product connection owns this presentation's lifetime. */ + readonly signal?: AbortSignal; +} + +export interface ProfileDrawerHandle { + readonly close: () => void; +} + +let current: ProfileDrawerHandle | null = null; + +/** + * Raster formats a profile image may use. Anything else, SVG included, is + * refused rather than handed to the renderer. + */ +export function rasterImageType(bytes: Uint8Array): string | null { + const starts = (...prefix: number[]): boolean => prefix.every((byte, index) => bytes[index] === byte); + if (starts(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a)) { + return 'image/png'; + } + if (starts(0xff, 0xd8, 0xff)) { + return 'image/jpeg'; + } + if (starts(0x47, 0x49, 0x46, 0x38)) { + return 'image/gif'; + } + if ( + starts(0x52, 0x49, 0x46, 0x46) && + bytes[8] === 0x57 && + bytes[9] === 0x45 && + bytes[10] === 0x42 && + bytes[11] === 0x50 + ) { + return 'image/webp'; + } + return null; +} + +export async function showProfileDrawer(options: ProfileDrawerOptions): Promise { + options.signal?.throwIfAborted(); + current?.close(); + const aborter = new AbortController(); + let dispose: (() => void) | undefined; + const handle: ProfileDrawerHandle = { + close() { + aborter.abort(); + options.signal?.removeEventListener('abort', handle.close); + dispose?.(); + if (current === handle) { + current = null; + } + }, + }; + current = handle; + options.signal?.addEventListener('abort', handle.close, { once: true }); + try { + // Keep profile presentation off the startup path, as with the other host overlays. + const { ProfileDrawer } = await import('../components/overlays/ProfileDrawer.js'); + aborter.signal.throwIfAborted(); + const container = document.createElement('div'); + ensureOverlayRoot().appendChild(container); + dispose = mountRoot( + 'profile-drawer', + container, + () => + createComponent(ProfileDrawer, { + options, + signal: aborter.signal, + onClose: handle.close, + }), + { removeContainer: true, onBroken: handle.close }, + ); + return handle; + } catch (error) { + handle.close(); + throw error; + } +} diff --git a/packages/ui/src/profile/mood-ring.ts b/packages/ui/src/profile/mood-ring.ts new file mode 100644 index 000000000..35419e624 --- /dev/null +++ b/packages/ui/src/profile/mood-ring.ts @@ -0,0 +1,235 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// The mood ring drawn around a profile avatar. +// +// One WebGL program, a few numbers per mood: three colours, a tempo and a +// turbulence, scaled by intensity and faded by age. Ported from Seity's mood +// ring mockup; the palette is the standard six moods by three intensities. +// Without WebGL it falls back to a static conic gradient, and under +// prefers-reduced-motion it draws one still frame. + +import type { Mood, MoodIntensity, MoodKind } from './profile-record.js'; + +interface Palette { + readonly label: string; + readonly a: string; + readonly b: string; + readonly c: string; + readonly speed: number; + readonly turb: number; +} + +export const MOOD_PALETTE: Record = { + calm: { + label: 'Calm', + a: '#2dd4bf', + b: '#38bdf8', + c: '#0e7490', + speed: 0.25, + turb: 0.3, + }, + focused: { + label: 'Focused', + a: '#8b5cf6', + b: '#c4b5fd', + c: '#4338ca', + speed: 0.4, + turb: 0.15, + }, + hyped: { + label: 'Hyped', + a: '#e6007a', + b: '#ff8a3d', + c: '#ffd166', + speed: 1.3, + turb: 0.9, + }, + social: { + label: 'Social', + a: '#fbbf24', + b: '#fde68a', + c: '#ea580c', + speed: 0.8, + turb: 0.5, + }, + 'low-key': { + label: 'Low-key', + a: '#b48ead', + b: '#6b4d78', + c: '#3b2a4a', + speed: 0.2, + turb: 0.2, + }, + away: { + label: 'Away', + a: '#8c8f98', + b: '#dadbe0', + c: '#404249', + speed: 0.08, + turb: 0.05, + }, +}; + +export const INTENSITY: Record = { + soft: { label: 'Soft', k: 0.55 }, + steady: { label: 'Steady', k: 1 }, + loud: { label: 'Loud', k: 1.8 }, +}; + +const VS = `attribute vec2 a_pos;varying vec2 v_uv; +void main(){v_uv=a_pos;gl_Position=vec4(a_pos,0.0,1.0);}`; + +const FS = `precision highp float;varying vec2 v_uv; +uniform float u_time,u_speed,u_turb,u_age,u_inner,u_width,u_half,u_bright,u_halo;uniform vec3 u_a,u_b,u_c; +float hash(vec2 p){p=fract(p*vec2(123.34,456.21));p+=dot(p,p+45.32);return fract(p.x*p.y);} +float noise(vec2 p){vec2 i=floor(p),f=fract(p);f=f*f*(3.0-2.0*f);float a=hash(i),b=hash(i+vec2(1,0)),c=hash(i+vec2(0,1)),d=hash(i+vec2(1,1));return mix(mix(a,b,f.x),mix(c,d,f.x),f.y);} +float fbm(vec2 p){float v=0.0,a=0.5;for(int i=0;i<4;i++){v+=a*noise(p);p*=2.03;a*=0.5;}return v;} +vec3 ramp(float x){float f=x*3.0;if(f<1.0)return mix(u_a,u_b,f);if(f<2.0)return mix(u_b,u_c,f-1.0);return mix(u_c,u_a,f-2.0);} +void main(){ + float r=length(v_uv);float ang=atan(v_uv.y,v_uv.x);float t=u_time*u_speed; + vec2 onCircle=vec2(cos(ang),sin(ang)); + float n=fbm(onCircle*(1.6+u_turb*1.4)+vec2(t*0.45,-t*0.3)); + float n2=fbm(onCircle*3.0-vec2(t*0.2,t*0.35)+7.0); + float w=u_width*(0.78+0.44*n)*mix(1.0,0.72,u_age); + float aa=1.5/u_half; + float r0=u_inner,r1=u_inner+w; + float band=smoothstep(r0-aa,r0+aa,r)*(1.0-smoothstep(r1-aa,r1+aa,r)); + float flow=fract(ang/6.2831853+t*0.12+(n2-0.5)*u_turb*0.6); + vec3 col=ramp(flow)*u_bright; + float d=max(0.0,r-r1);float outside=smoothstep(r1-aa,r1+aa,r); + float glow=outside*exp(-d*d*u_half*u_half*(0.05/max(u_halo,0.3)))*(0.14+0.2*u_halo+0.15*n); + float fade=mix(1.0,0.38,u_age); + float alpha=clamp(band+glow*(1.0-band),0.0,1.0)*fade*smoothstep(u_inner-2.0*aa,u_inner,r); + gl_FragColor=vec4(col*alpha,alpha); +}`; + +function rgb(hex: string): [number, number, number] { + return [ + Number.parseInt(hex.slice(1, 3), 16) / 255, + Number.parseInt(hex.slice(3, 5), 16) / 255, + Number.parseInt(hex.slice(5, 7), 16) / 255, + ]; +} + +/** How far through its life the mood is, 0 (just set) to 1 (about to lapse). */ +export function moodAge(mood: Mood, nowSecs = Date.now() / 1000): number { + if (mood.ttlSecs <= 0) { + return 0; + } + return Math.min(1, Math.max(0, (nowSecs - mood.setAt) / mood.ttlSecs)); +} + +/** Paint into a Solid-owned canvas; null requests the static CSS fallback. */ +export function animateMoodRing(canvas: HTMLCanvasElement, mood: Mood, avatarPx: number): (() => void) | null { + const palette = MOOD_PALETTE[mood.kind]; + const k = INTENSITY[mood.intensity].k; + const age = moodAge(mood); + const size = Math.round(avatarPx * 1.5); + + const gl = canvas.getContext('webgl', { + alpha: true, + premultipliedAlpha: true, + antialias: true, + }); + if (gl === null) { + return null; + } + const compile = (type: number, source: string): WebGLShader | null => { + const shader = gl.createShader(type); + if (shader === null) { + return null; + } + gl.shaderSource(shader, source); + gl.compileShader(shader); + return shader; + }; + const vs = compile(gl.VERTEX_SHADER, VS); + const fs = compile(gl.FRAGMENT_SHADER, FS); + const program = gl.createProgram(); + if (vs === null || fs === null) { + if (vs !== null) { + gl.deleteShader(vs); + } + if (fs !== null) { + gl.deleteShader(fs); + } + gl.deleteProgram(program); + gl.getExtension('WEBGL_lose_context')?.loseContext(); + return null; + } + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!(gl.getProgramParameter(program, gl.LINK_STATUS) as boolean)) { + gl.deleteShader(vs); + gl.deleteShader(fs); + gl.deleteProgram(program); + gl.getExtension('WEBGL_lose_context')?.loseContext(); + return null; + } + gl.useProgram(program); + + const dpr = Math.min(2, window.devicePixelRatio || 1); + canvas.width = Math.round(size * dpr); + canvas.height = Math.round(size * dpr); + + const buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]), gl.STATIC_DRAW); + const position = gl.getAttribLocation(program, 'a_pos'); + gl.enableVertexAttribArray(position); + gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0); + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + gl.viewport(0, 0, canvas.width, canvas.height); + + const u = (name: string): WebGLUniformLocation | null => gl.getUniformLocation(program, name); + const half = (size / 2) * dpr; + const widthPx = Math.max(3, Math.min(6, avatarPx * 0.05)) * (0.7 + 0.32 * k) * dpr; + gl.uniform1f(u('u_half'), half); + gl.uniform1f(u('u_inner'), ((avatarPx / 2 + 3) * dpr) / half); + gl.uniform1f(u('u_width'), widthPx / half); + gl.uniform1f(u('u_speed'), palette.speed * k); + gl.uniform1f(u('u_turb'), Math.min(1, palette.turb * k)); + gl.uniform1f(u('u_bright'), 0.62 + 0.36 * k); + gl.uniform1f(u('u_halo'), k); + gl.uniform1f(u('u_age'), age); + gl.uniform3f(u('u_a'), ...rgb(palette.a)); + gl.uniform3f(u('u_b'), ...rgb(palette.b)); + gl.uniform3f(u('u_c'), ...rgb(palette.c)); + const timeUniform = u('u_time'); + + const draw = (ms: number): void => { + gl.uniform1f(timeUniform, ms / 1000); + gl.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawArrays(gl.TRIANGLES, 0, 6); + }; + + const still = window.matchMedia('(prefers-reduced-motion: reduce)').matches; + let frame = 0; + let stopped = false; + const loop = (ms: number): void => { + if (stopped) { + return; + } + draw(ms); + frame = requestAnimationFrame(loop); + }; + if (still) { + draw(0); + } else { + frame = requestAnimationFrame(loop); + } + + return () => { + stopped = true; + cancelAnimationFrame(frame); + gl.deleteBuffer(buffer); + gl.deleteShader(vs); + gl.deleteShader(fs); + gl.deleteProgram(program); + gl.getExtension('WEBGL_lose_context')?.loseContext(); + }; +} diff --git a/packages/ui/src/profile/profile-record.ts b/packages/ui/src/profile/profile-record.ts new file mode 100644 index 000000000..dbeb7975e --- /dev/null +++ b/packages/ui/src/profile/profile-record.ts @@ -0,0 +1,141 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// The profile record a Seity contacts reference opens. +// +// A SCALE `Vec<{ kind: String, payload: Vec }>`, pinned by Seity's +// profile-core (`profile-record.ts`) and its committed vector. Kinds this host +// draws: `avatar` (a UTF-8 `cid#key` blob reference, read by +// seity-reference.ts) and `mood`. Unknown kinds are skipped, so the record can +// grow without this host changing. + +export const MOOD_KINDS = ['calm', 'focused', 'hyped', 'social', 'low-key', 'away'] as const; +export const MOOD_INTENSITIES = ['soft', 'steady', 'loud'] as const; +export type MoodKind = (typeof MOOD_KINDS)[number]; +export type MoodIntensity = (typeof MOOD_INTENSITIES)[number]; + +export interface Mood { + readonly kind: MoodKind; + readonly intensity: MoodIntensity; + /** Unix seconds. */ + readonly setAt: number; + readonly ttlSecs: number; +} + +export interface ProfileRecord { + readonly avatarReference?: string; + readonly mood?: Mood; +} + +const MAX_RECORD_BYTES = 8 * 1024; + +class Reader { + private offset = 0; + private readonly bytes: Uint8Array; + private readonly view: DataView; + constructor(bytes: Uint8Array) { + this.bytes = bytes; + this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + } + + private take(n: number): Uint8Array { + if (this.offset + n > this.bytes.length) { + throw new Error('profile record is truncated'); + } + const out = this.bytes.subarray(this.offset, this.offset + n); + this.offset += n; + return out; + } + + u8(): number { + const value = this.view.getUint8(this.offset); + this.offset++; + return value; + } + + u32(): number { + const value = this.view.getUint32(this.offset, true); + this.offset += 4; + return value; + } + + u64(): number { + const lo = this.u32(); + const hi = this.u32(); + return hi * 2 ** 32 + lo; + } + + compact(): number { + const first = this.u8(); + switch (first & 3) { + case 0: + return first >> 2; + case 1: + return ((first | (this.u8() << 8)) >>> 2) & 0x3fff; + case 2: { + return ((first | (this.u8() << 8) | (this.u8() << 16) | (this.u8() << 24)) >>> 2) >>> 0; + } + default: + throw new Error('profile record uses a big-integer length'); + } + } + + bytesField(): Uint8Array { + return this.take(this.compact()); + } + + done(): boolean { + return this.offset === this.bytes.length; + } +} + +/** Undefined for a payload this build cannot read, so a newer palette degrades to "no mood". */ +function decodeMood(payload: Uint8Array): Mood | undefined { + if (payload.length !== 14) { + return undefined; + } + const reader = new Reader(payload); + const kind = MOOD_KINDS.at(reader.u8()); + const intensity = MOOD_INTENSITIES.at(reader.u8()); + const setAt = reader.u64(); + const ttlSecs = reader.u32(); + if (kind === undefined || intensity === undefined) { + return undefined; + } + return { kind, intensity, setAt, ttlSecs }; +} + +export function decodeProfileRecord(bytes: Uint8Array): ProfileRecord { + if (bytes.length > MAX_RECORD_BYTES) { + throw new Error('profile record is too large'); + } + const reader = new Reader(bytes); + const text = new TextDecoder('utf-8', { fatal: true }); + const lenient = new TextDecoder('utf-8'); + const count = reader.compact(); + let avatarReference: string | undefined; + let mood: Mood | undefined; + for (let i = 0; i < count; i++) { + const kind = text.decode(reader.bytesField()); + const payload = reader.bytesField(); + // One unreadable signal degrades the drawer; it never sinks the read. A + // malformed avatar reference is refused later by its own parser. + if (kind === 'avatar' && avatarReference === undefined) { + avatarReference = lenient.decode(payload); + } else if (kind === 'mood' && mood === undefined) { + mood = decodeMood(payload); + } + } + if (!reader.done()) { + throw new Error('profile record has trailing bytes'); + } + return { + ...(avatarReference === undefined ? {} : { avatarReference }), + ...(mood === undefined ? {} : { mood }), + }; +} + +/** True while the mood still counts, on this host's clock. */ +export function moodIsCurrent(mood: Mood, nowSecs: number = Math.floor(Date.now() / 1000)): boolean { + return nowSecs < mood.setAt + mood.ttlSecs; +} diff --git a/packages/ui/src/profile/seity-reference.ts b/packages/ui/src/profile/seity-reference.ts new file mode 100644 index 000000000..2d386d162 --- /dev/null +++ b/packages/ui/src/profile/seity-reference.ts @@ -0,0 +1,78 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +// Seity encrypted-blob references: `"#"`. +// +// The format is pinned by Seity's profile-core (`blob.ts`): the CID is a +// CIDv1 raw/Blake2b-256 address of AES-256-GCM ciphertext on Bulletin, and the +// fragment carries the 32-byte key followed by the 12-byte IV, hex-encoded. +// profile-core is not published as a package dotli can depend on, so the two +// operations the host needs live here and are pinned against a vector produced +// with profile-core's own primitives (see the test). +// +// The reference is a bearer capability. It is parsed and used here, in the +// host, and never logged or handed back to the product. + +import { cidToPreimageKey } from '@dotli/content'; + +const KEY_BYTES = 32; +const IV_BYTES = 12; +const FRAGMENT_PATTERN = new RegExp(`^[0-9a-fA-F]{${String((KEY_BYTES + IV_BYTES) * 2)}}$`); + +export interface SeityBlobReference { + /** Blake2b-256 preimage key the ciphertext is stored under. */ + readonly preimageKey: `0x${string}`; + readonly aesKey: Uint8Array; + readonly iv: Uint8Array; +} + +export class InvalidProfileReferenceError extends Error { + constructor(reason: string) { + // The reference itself stays out of the message: it is a capability. + super(`invalid profile reference: ${reason}`); + this.name = 'InvalidProfileReferenceError'; + } +} + +function hexBytes(hex: string): Uint8Array { + const bytes = new Uint8Array(hex.length / 2); + for (let i = 0; i < bytes.length; i++) { + bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16); + } + return bytes; +} + +export function parseSeityBlobReference(reference: string): SeityBlobReference { + const hash = reference.indexOf('#'); + if (hash < 1 || hash !== reference.lastIndexOf('#')) { + throw new InvalidProfileReferenceError('expected #'); + } + const fragment = reference.slice(hash + 1); + if (!FRAGMENT_PATTERN.test(fragment)) { + throw new InvalidProfileReferenceError('fragment must be a 32-byte key and 12-byte IV in hex'); + } + let preimageKey: `0x${string}`; + try { + preimageKey = cidToPreimageKey(reference.slice(0, hash)); + } catch { + throw new InvalidProfileReferenceError('CID must be a raw Blake2b-256 CIDv1'); + } + return { + preimageKey, + aesKey: hexBytes(fragment.slice(0, KEY_BYTES * 2)), + iv: hexBytes(fragment.slice(KEY_BYTES * 2)), + }; +} + +/** + * Decrypt a fetched blob. AES-GCM authenticates, so a wrong key, IV or + * substituted ciphertext rejects rather than yielding bytes. + */ +export async function openSeityBlob( + ciphertext: Uint8Array, + reference: Pick, +): Promise { + const key = await crypto.subtle.importKey('raw', reference.aesKey, 'AES-GCM', false, ['decrypt']); + const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: reference.iv }, key, ciphertext); + return new Uint8Array(plaintext); +} diff --git a/packages/ui/src/state/modals.ts b/packages/ui/src/state/modals.ts index 1adcced59..2a7ebc134 100644 --- a/packages/ui/src/state/modals.ts +++ b/packages/ui/src/state/modals.ts @@ -44,6 +44,8 @@ export interface ModalView { input?: ModalPasswordInput; /** Host-owned choices, rendered separately from the action footer. */ choices?: ModalChoice[]; + /** Checkbox choices retain edits until a primary action confirms them. */ + selection?: { selected: readonly R[]; limit: number }; /** Display order. */ buttons: ModalButton[]; dismissOnBackdrop: boolean; @@ -57,6 +59,8 @@ export interface ModalOutcome { result: R; /** The password input's value, for views with an input. */ value?: string; + /** Confirmed checkbox choices; absent on dismissal and fallback. */ + selected?: R[]; } export interface ModalEntry { @@ -115,8 +119,12 @@ export function openModal(view: ModalView, signal?: AbortSi } /** Settle one dialog. Ignored if it has already settled. */ -export function settleModal(id: number, result: string, value?: string): void { - take(id)?.resolve(value === undefined ? { result } : { result, value }); +export function settleModal(id: number, result: string, value?: string, selected?: string[]): void { + take(id)?.resolve({ + result, + ...(value === undefined ? {} : { value }), + ...(selected === undefined ? {} : { selected }), + }); } /** Settle every open dialog with its fallback result. */ diff --git a/packages/ui/src/styles.css b/packages/ui/src/styles.css index e0a3a7f23..ac482ca52 100644 --- a/packages/ui/src/styles.css +++ b/packages/ui/src/styles.css @@ -12,6 +12,8 @@ @import './styles/topbar.css'; @import './styles/modals.css'; @import './styles/signing.css'; +@import './styles/profile-drawer.css'; +@import './styles/contact-avatars.css'; @import './styles/password-prompt.css'; @import './styles/toasts.css'; @import './styles/landing.css'; diff --git a/packages/ui/src/styles/contact-avatars.css b/packages/ui/src/styles/contact-avatars.css new file mode 100644 index 000000000..1c6f83657 --- /dev/null +++ b/packages/ui/src/styles/contact-avatars.css @@ -0,0 +1,95 @@ +/* Copyright 2026 Parity Technologies (UK) Ltd. */ +/* SPDX-License-Identifier: AGPL-3.0-only */ + +/* dot.li — Host-drawn contact avatars over a product frame */ + +/* The frame's inline geometry is copied onto the layer; these are fallbacks + and what the product must never get: pointer events. Above the frame, below + the loading screen, toasts, the topbar, modals and the profile drawer. */ +.contact-avatar-overlay, +.contact-label-overlay { + position: fixed; + z-index: 5; + overflow: hidden; + pointer-events: none; + user-select: none; + -webkit-user-select: none; + contain: layout paint; +} +.contact-avatar-overlay *, +.contact-label-overlay * { + pointer-events: none; +} +/* The product's clip: the ring and photo are cut where it ends. Slots and + circles are placed by transform, so moving them needs no layout. */ +.contact-avatar-slot { + position: absolute; + left: 0; + top: 0; + overflow: hidden; + transition: opacity 120ms ease-out; +} +/* Positions arrive a few frames after the product drew them, so a moving + avatar would trail its row: it fades out until positions settle. */ +.contact-avatar-slot.contact-avatar-moving { + opacity: 0; + transition-duration: 80ms; + will-change: transform, opacity; +} +@media (prefers-reduced-motion: reduce) { + .contact-avatar-slot, + .contact-avatar-slot.contact-avatar-moving { + transition: none; + } +} +/* The circle's box. */ +.contact-avatar { + position: absolute; + left: 0; + top: 0; +} +/* The ring is wider than the circle it wraps, so auto margins cannot centre + it; translate instead. */ +.contact-avatar > .profile-mood-ring { + inset: auto; + left: 50%; + top: 50%; + margin: 0; + transform: translate(-50%, -50%); +} +.contact-avatar-photo { + position: absolute; + inset: 0; + border-radius: 50%; + overflow: hidden; +} +.contact-avatar-photo img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +/* Contact names do not depend on a shared profile or its photo. */ +.contact-label-slot { + position: absolute; + left: 0; + top: 0; + overflow: hidden; +} +.contact-label-slot.contact-label-moving { + visibility: hidden; +} +.contact-label { + position: absolute; + left: 0; + top: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; + font-family: system-ui, sans-serif; + color: #f3f3f3; + background: #151515; + border-radius: 4px; +} diff --git a/packages/ui/src/styles/profile-drawer.css b/packages/ui/src/styles/profile-drawer.css new file mode 100644 index 000000000..8fc0b4910 --- /dev/null +++ b/packages/ui/src/styles/profile-drawer.css @@ -0,0 +1,138 @@ +/* Copyright 2026 Parity Technologies (UK) Ltd. */ +/* SPDX-License-Identifier: AGPL-3.0-only */ + +/* dot.li — Host-owned profile drawer (bottom sheet) */ + +.profile-drawer-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.55); + z-index: 2900; + display: flex; + align-items: flex-end; + justify-content: center; + padding: var(--safe-top) var(--safe-right) 0 var(--safe-left); +} +.profile-drawer { + background: #151515; + border: 1px solid #2a2a2a; + border-bottom: none; + color: #e0e0e0; + border-radius: 16px 16px 0 0; + padding: 16px 24px calc(24px + var(--safe-bottom)); + width: 100%; + max-width: 420px; + max-height: calc(100dvh - var(--safe-top) - 32px); + overflow-y: auto; + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + animation: profile-drawer-in 0.18s ease-out; +} +@keyframes profile-drawer-in { + from { + transform: translateY(24px); + opacity: 0; + } +} +@media (prefers-reduced-motion: reduce) { + .profile-drawer { + animation: none; + } +} +.profile-drawer-header { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} +.profile-drawer-header h2 { + font-size: 1rem; + color: #fff; +} +.profile-drawer-contact { + max-width: 100%; + overflow-wrap: anywhere; + color: #ddd; + font-size: 0.95rem; +} +.profile-drawer-close { + width: 32px; + height: 32px; + border: 1px solid #333; + border-radius: 8px; + background: transparent; + color: #aaa; + font-size: 1.1rem; + line-height: 1; + cursor: pointer; +} +.profile-drawer-close:hover { + background: #1a1a1a; +} +.profile-drawer-avatar { + width: 160px; + height: 160px; + border-radius: 50%; + background: #0d0d0d; + border: 1px solid #2a2a2a; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} +.profile-drawer-avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} +.profile-drawer-avatar-empty { + border-style: dashed; +} +.profile-drawer-status { + min-height: 1.2em; + font-size: 0.85rem; + color: #aaa; + text-align: center; +} +.profile-drawer-status-error { + color: #f0c060; +} +.profile-drawer-attribution { + font-size: 0.75rem; + color: #777; + text-align: center; + line-height: 1.4; +} +.profile-drawer-portrait { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 240px; + height: 240px; +} +.profile-mood-ring { + position: absolute; + inset: 0; + margin: auto; + pointer-events: none; +} +.profile-mood-ring canvas { + width: 100%; + height: 100%; +} +/* No WebGL: a still ring from the same three colours. */ +.profile-mood-ring-static { + border-radius: 50%; + background: conic-gradient(var(--ring-a), var(--ring-b), var(--ring-c), var(--ring-a)); + -webkit-mask: radial-gradient(circle, transparent 54%, #000 55%, #000 60%, transparent 61%); + mask: radial-gradient(circle, transparent 54%, #000 55%, #000 60%, transparent 61%); +} +.profile-drawer-mood { + min-height: 1.2em; + font-size: 0.85rem; + color: #ddd; + text-align: center; +} diff --git a/packages/ui/src/styles/signing.css b/packages/ui/src/styles/signing.css index cc36b5510..9a7458062 100644 --- a/packages/ui/src/styles/signing.css +++ b/packages/ui/src/styles/signing.css @@ -160,12 +160,43 @@ display: flex; flex-direction: column; gap: 8px; + max-height: 40dvh; + overflow-y: auto; margin-bottom: 20px; } .contacts-picker-choice { display: flex; - flex-direction: column; gap: 6px; text-align: left; overflow-wrap: anywhere; + flex-shrink: 0; +} +.contacts-picker-choice[hidden] { + display: none; +} +.contacts-picker-choice input[type='checkbox'] { + flex-shrink: 0; + align-self: center; + width: 18px; + height: 18px; + accent-color: #e6007a; +} +.contacts-picker-text { + min-width: 0; +} +.contacts-picker-search { + width: 100%; + box-sizing: border-box; + padding: 10px 12px; + margin-bottom: 12px; + border: 1px solid #555; + border-radius: 8px; + background: #0d0d0d; + color: #e0e0e0; + font: inherit; +} +.contacts-modal input:focus-visible, +.contacts-modal button:focus-visible { + outline: 2px solid #f6a7d0; + outline-offset: 2px; } diff --git a/packages/ui/src/styles/themes.css b/packages/ui/src/styles/themes.css index 527f0154b..27bb2af22 100644 --- a/packages/ui/src/styles/themes.css +++ b/packages/ui/src/styles/themes.css @@ -773,3 +773,36 @@ [data-theme='light'] .more-popover.chains-popover { background: rgb(245, 245, 245); } + +/* Profile drawer */ +[data-theme='light'] .profile-drawer { + background: #fff; + border-color: #ddd; + color: #333; +} +[data-theme='light'] .profile-drawer-header h2 { + color: #111; +} +[data-theme='light'] .profile-drawer-close { + border-color: #ddd; + color: #555; +} +[data-theme='light'] .profile-drawer-close:hover { + background: #f2f2f2; +} +[data-theme='light'] .profile-drawer-avatar { + background: #f5f5f5; + border-color: #ddd; +} +[data-theme='light'] .profile-drawer-status { + color: #555; +} +[data-theme='light'] .profile-drawer-status-error { + color: #9a6a00; +} +[data-theme='light'] .profile-drawer-attribution { + color: #777; +} +[data-theme='light'] .profile-drawer-mood { + color: #333; +} diff --git a/packages/ui/src/topbar.ts b/packages/ui/src/topbar.ts index 5221d95fc..e4038963d 100644 --- a/packages/ui/src/topbar.ts +++ b/packages/ui/src/topbar.ts @@ -54,6 +54,7 @@ function scheduleIdle(callback: () => void): void { } /** + * Reveal the network button. The host calls this once a product is on * screen, so the icon appears with the app rather than during the load. * Writes the store the chains island renders. diff --git a/packages/ui/tests/components/shell/permissions-popover.test.tsx b/packages/ui/tests/components/shell/permissions-popover.test.tsx index a11a4247d..3cc582b8d 100644 --- a/packages/ui/tests/components/shell/permissions-popover.test.tsx +++ b/packages/ui/tests/components/shell/permissions-popover.test.tsx @@ -42,6 +42,7 @@ function nameOf(request: PermissionAuthorizationRequest): string { case 'AccountAccess': case 'ChatAuthority': case 'StatementStoreAllowance': + case 'ProfileDisclosure': return request.tag; } } diff --git a/packages/ui/tests/contact-avatars.test.ts b/packages/ui/tests/contact-avatars.test.ts new file mode 100644 index 000000000..09f51d59a --- /dev/null +++ b/packages/ui/tests/contact-avatars.test.ts @@ -0,0 +1,482 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import type { PlacedAvatar, PlacedAvatars } from '@parity/truapi-host'; +import type { Window as HappyWindow } from 'happy-dom'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { + createAvatarProfileCache, + createContactAvatarOverlay, + type AvatarProfileCache, + type AvatarSurfaceFit, + type ContactAvatarOverlay, +} from '../src/profile/avatar-overlay.js'; +import type { LoadedProfile } from '../src/profile/drawer.js'; +import type { Mood } from '../src/profile/profile-record.js'; +import { flush } from 'solid-js'; +const revokeUrl = vi.fn<(url: string) => void>(); + +const PNG = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 0]); +const NOW_SECS = 1_800_000_000; + +function mood(ttlSecs = 3_600): Mood { + return { kind: 'calm', intensity: 'steady', setAt: NOW_SECS - 60, ttlSecs }; +} + +/** What each test reference opens to. */ +const PROFILES: Record = { + both: { avatar: PNG, mood: mood() }, + photo: { avatar: PNG }, + mood: { avatar: null, mood: mood() }, + lapsing: { avatar: null, mood: { ...mood(), ttlSecs: 70 } }, + nothing: { avatar: null }, + expired: { avatar: null, mood: { ...mood(), ttlSecs: 30 } }, + svg: { avatar: new TextEncoder().encode('') }, +}; + +let loads: string[]; +let urls: number; +const LOAD_MS = 10; + +function loader(reference: string): () => Promise { + const profile = PROFILES[reference]; + if (profile === undefined) { + throw new Error('unparseable'); + } + return () => { + loads.push(reference); + return new Promise(resolve => { + setTimeout(() => { + resolve(profile); + }, LOAD_MS); + }); + }; +} + +function frame(width: number, height: number): HTMLIFrameElement { + const iframe = document.createElement('iframe'); + iframe.style.cssText = 'position:fixed;top:56px;left:0px;width:100%;height:500px;border:none;'; + Object.defineProperty(iframe, 'clientWidth', { + configurable: true, + get: () => width, + }); + Object.defineProperty(iframe, 'clientHeight', { + configurable: true, + get: () => height, + }); + document.body.appendChild(iframe); + return iframe; +} + +function slot( + id: number, + reference: string, + rect: [number, number, number], + clip: [number, number, number, number] = [0, 0, 10_000, 10_000], + sharedAt = 1n, +): PlacedAvatar { + return { + slot: id, + reference, + rect: { x: rect[0], y: rect[1], width: rect[2], height: rect[2] }, + clip: { x: clip[0], y: clip[1], width: clip[2], height: clip[3] }, + sharedAt, + }; +} + +function placement(surfaceWidth: number, surfaceHeight: number, avatars: PlacedAvatar[]): PlacedAvatars { + return { surfaceWidth, surfaceHeight, avatars }; +} + +function layer(): HTMLElement | null { + flush(); + return document.querySelector('.contact-avatar-overlay'); +} + +function slots(): HTMLElement[] { + flush(); + return [...document.querySelectorAll('.contact-avatar-slot')]; +} + +/** An element's `[x, y, width, height]` as the overlay placed it. */ +function box(element: Element | null | undefined): number[] { + const style = (element as HTMLElement).style; + const at = /^translate3d\(([-\d.]+)px, ([-\d.]+)px, 0\)$/.exec(style.transform); + return [at?.[1], at?.[2], style.width, style.height].map(value => Number.parseFloat(value ?? '')); +} + +function hidden(element: Element | undefined): boolean { + flush(); + return getComputedStyle(element as HTMLElement).opacity === '0'; +} + +function fades(element: Element | undefined): boolean { + flush(); + return getComputedStyle(element as HTMLElement).transition !== 'none'; +} + +/** Let loads finish and the next animation frame draw them. */ +async function settle(): Promise { + await vi.advanceTimersByTimeAsync(LOAD_MS); + vi.advanceTimersToNextFrame(); + flush(); +} + +/** How long positions must hold still before a moved avatar shows again. */ +const SETTLE_MS = 150; + +function useStyles(): HTMLStyleElement { + const style = document.createElement('style'); + style.textContent = readFileSync(resolve(import.meta.dirname, '../src/styles/contact-avatars.css'), 'utf8'); + document.head.appendChild(style); + return style; +} + +// The test window is happy-dom's, whose device settings drive CSS media queries. +const happyWindow = window as unknown as HappyWindow; + +describe('host-drawn contact avatars', () => { + let cache: AvatarProfileCache; + let overlay: ContactAvatarOverlay; + + beforeEach(() => { + vi.useFakeTimers({ now: NOW_SECS * 1000 }); + loads = []; + urls = 0; + vi.spyOn(URL, 'createObjectURL').mockImplementation(() => { + urls += 1; + return `blob:avatar-${String(urls)}`; + }); + revokeUrl.mockReset(); + vi.spyOn(URL, 'revokeObjectURL').mockImplementation(revokeUrl); + cache = createAvatarProfileCache(loader, 1); + overlay = createContactAvatarOverlay(cache); + }); + + afterEach(() => { + overlay.dispose(); + cache.clear(); + document.body.replaceChildren(); + vi.useRealTimers(); + vi.restoreAllMocks(); + }); + + async function draw( + fit: AvatarSurfaceFit, + size: [number, number], + placed: PlacedAvatars, + ): Promise { + const iframe = frame(...size); + overlay.attach(iframe, fit); + overlay.place(placed); + await settle(); + return iframe; + } + + it("places a web product's avatars in the frame's CSS pixels", async () => { + const iframe = await draw( + 'viewport', + [400, 800], + placement(400, 800, [slot(1, 'photo', [16, 120, 44], [0, 100, 400, 600])]), + ); + + expect(layer()?.previousElementSibling).toBe(iframe); + expect(box(slots()[0])).toEqual([0, 100, 400, 600]); + expect(box(slots()[0]?.querySelector('.contact-avatar'))).toEqual([16, 20, 44, 44]); + }); + + it('contain-fits a letterboxed PolkaVM framebuffer, centred', async () => { + // 200x100 framebuffer in a 400x400 frame: scale 2, 100px bars above and below. + await draw('contain', [400, 400], placement(200, 100, [slot(1, 'photo', [10, 20, 30], [0, 10, 200, 80])])); + + expect(box(slots()[0])).toEqual([0, 120, 400, 160]); + expect(box(slots()[0]?.querySelector('.contact-avatar'))).toEqual([20, 20, 60, 60]); + }); + + it('stretches a Tri2D surface over the whole frame', async () => { + await draw('fill', [400, 300], placement(800, 600, [slot(1, 'photo', [100, 200, 88], [0, 0, 800, 600])])); + + expect(box(slots()[0])).toEqual([0, 0, 400, 300]); + expect(box(slots()[0]?.querySelector('.contact-avatar'))).toEqual([50, 100, 44, 44]); + }); + + it("cuts avatars to the product's clip and drops those outside it", async () => { + await draw( + 'viewport', + [400, 800], + placement(400, 800, [ + // Half scrolled under the header that ends at y = 100. + slot(1, 'photo', [16, 80, 44], [0, 100, 400, 600]), + // Scrolled away entirely. + slot(2, 'photo', [16, 20, 44], [0, 100, 400, 600]), + // Clip beyond the surface is cut to it. + slot(3, 'photo', [16, 760, 44], [0, 700, 400, 400]), + ]), + ); + + const [first, last] = slots(); + expect(slots()).toHaveLength(2); + expect(box(first)).toEqual([0, 100, 400, 600]); + expect(box(first?.querySelector('.contact-avatar'))).toEqual([16, -20, 44, 44]); + expect(box(last)).toEqual([0, 700, 400, 100]); + }); + + it('draws the photo with its ring, the ring alone, or nothing', async () => { + await draw( + 'viewport', + [400, 800], + placement(400, 800, [ + slot(1, 'both', [0, 0, 44]), + slot(2, 'mood', [0, 50, 44]), + slot(3, 'nothing', [0, 100, 44]), + slot(4, 'expired', [0, 150, 44]), + slot(5, 'svg', [0, 200, 44]), + slot(6, 'not a reference', [0, 250, 44]), + ]), + ); + + const [both, ring] = slots(); + expect(slots()).toHaveLength(2); + expect(both?.querySelector('img')?.getAttribute('src')).toBe('blob:avatar-1'); + expect(both?.querySelector('.profile-mood-ring')).not.toBeNull(); + expect(ring?.querySelector('img')).toBeNull(); + const ringElement = ring?.querySelector('.profile-mood-ring'); + // The static ring wraps the circle and leaves its centre clear. + expect(ringElement?.classList.contains('profile-mood-ring-static')).toBe(true); + expect(ringElement?.style.width).toBe('66px'); + expect(ring?.querySelector('canvas')).toBeNull(); + }); + + it('stops drawing a mood when it lapses', async () => { + await draw( + 'viewport', + [400, 800], + placement(400, 800, [slot(1, 'lapsing', [0, 0, 44]), slot(2, 'both', [0, 50, 44])]), + ); + expect(slots()).toHaveLength(2); + + await vi.advanceTimersByTimeAsync(11_000); + + expect(slots()).toHaveLength(1); + expect(slots()[0]?.querySelector('img')).not.toBeNull(); + expect(slots()[0]?.querySelector('.profile-mood-ring')).not.toBeNull(); + }); + + it('reloads a renewed share and keeps the old photo until it arrives', async () => { + const clip: [number, number, number, number] = [0, 0, 400, 800]; + await draw('viewport', [400, 800], placement(400, 800, [slot(1, 'photo', [0, 0, 44], clip, 5n)])); + const src = (): string | null | undefined => slots()[0]?.querySelector('img')?.getAttribute('src'); + expect(src()).toBe('blob:avatar-1'); + + // The same share placed again is served from the cache. + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44], clip, 5n)])); + await settle(); + expect(loads).toEqual(['photo']); + + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44], clip, 6n)])); + vi.advanceTimersToNextFrame(); + expect(loads).toEqual(['photo', 'photo']); + expect(src()).toBe('blob:avatar-1'); + expect(revokeUrl).not.toHaveBeenCalled(); + + await settle(); + expect(src()).toBe('blob:avatar-2'); + expect(revokeUrl).toHaveBeenCalledWith('blob:avatar-1'); + + // An older share arriving late does not reload. + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44], clip, 5n)])); + await settle(); + expect(loads).toEqual(['photo', 'photo']); + expect(src()).toBe('blob:avatar-2'); + }); + + it('replaces the previous placement and removes the layer when cleared', async () => { + await draw( + 'viewport', + [400, 800], + placement(400, 800, [slot(1, 'photo', [0, 0, 44]), slot(2, 'mood', [0, 50, 44])]), + ); + const kept = slots()[1]; + + overlay.place(placement(400, 800, [slot(2, 'mood', [0, 60, 44])])); + await settle(); + expect(slots()).toEqual([kept]); + expect(box(kept?.querySelector('.contact-avatar'))).toEqual([0, 60, 44, 44]); + + overlay.place(placement(400, 800, [])); + expect(layer()).toBeNull(); + + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + await settle(); + overlay.clear(); + expect(layer()).toBeNull(); + + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + await settle(); + overlay.dispose(); + expect(layer()).toBeNull(); + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + await settle(); + expect(layer()).toBeNull(); + }); + + it('draws a load begun under an earlier placement into the current one', async () => { + const iframe = frame(400, 800); + overlay.attach(iframe, 'viewport'); + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + overlay.place(placement(400, 800, [slot(2, 'photo', [0, 60, 44])])); + await settle(); + + expect(slots()).toHaveLength(1); + expect(box(slots()[0]?.querySelector('.contact-avatar'))).toEqual([0, 60, 44, 44]); + expect(loads).toEqual(['photo']); + }); + + it("follows the frame's geometry and size", async () => { + let width = 400; + const iframe = frame(0, 0); + Object.defineProperty(iframe, 'clientWidth', { get: () => width }); + Object.defineProperty(iframe, 'clientHeight', { get: () => 400 }); + overlay.attach(iframe, 'contain'); + overlay.place(placement(100, 100, [slot(1, 'photo', [0, 0, 10])])); + await settle(); + + iframe.style.transform = 'translateY(56px)'; + await settle(); + expect(layer()?.style.transform).toBe('translateY(56px)'); + expect(layer()?.style.top).toBe('56px'); + + width = 800; + window.dispatchEvent(new Event('resize')); + vi.advanceTimersToNextFrame(); + expect(box(slots()[0])).toEqual([200, 0, 400, 400]); + }); + + it('loads a reference once and revokes its photo URL when evicted', async () => { + const other = createContactAvatarOverlay(cache); + const iframe = frame(400, 800); + overlay.attach(iframe, 'viewport'); + other.attach(iframe, 'viewport'); + // Both ask while the first load is still in flight. + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + other.place(placement(400, 800, [slot(7, 'photo', [0, 0, 44])])); + await settle(); + expect(loads).toEqual(['photo']); + + // Released but kept: the cache holds one unused reference. + overlay.place(placement(400, 800, [])); + other.dispose(); + expect(revokeUrl).not.toHaveBeenCalled(); + + // A second released reference pushes the first out. + overlay.place(placement(400, 800, [slot(1, 'both', [0, 0, 44])])); + await settle(); + overlay.place(placement(400, 800, [])); + expect(revokeUrl).toHaveBeenCalledWith('blob:avatar-1'); + expect(revokeUrl).not.toHaveBeenCalledWith('blob:avatar-2'); + }); + + it('never takes pointer events or reaches into the product frame', async () => { + const style = useStyles(); + const iframe = frame(400, 800); + iframe.style.pointerEvents = 'auto'; + const post = vi.fn(); + Object.defineProperty(iframe, 'contentWindow', { + get: () => ({ postMessage: post }), + }); + overlay.attach(iframe, 'viewport'); + overlay.place(placement(400, 800, [slot(1, 'both', [0, 0, 44])])); + await settle(); + + const root = layer(); + expect(root?.getAttribute('aria-hidden')).toBe('true'); + expect(root?.style.pointerEvents).toBe('none'); + for (const element of [root, ...(root?.querySelectorAll('*') ?? [])] as Element[]) { + expect(getComputedStyle(element).pointerEvents).toBe('none'); + } + expect(post).not.toHaveBeenCalled(); + style.remove(); + }); + + it('hides a moving avatar until positions hold still', async () => { + const style = useStyles(); + await draw( + 'viewport', + [400, 800], + placement(400, 800, [slot(1, 'photo', [0, 0, 44]), slot(2, 'photo', [0, 50, 44])]), + ); + const [still, moving] = slots(); + // New avatars fade in once positions settle. + expect([hidden(still), hidden(moving)]).toEqual([true, true]); + expect(fades(still)).toBe(true); + await vi.advanceTimersByTimeAsync(SETTLE_MS); + expect([hidden(still), hidden(moving)]).toEqual([false, false]); + + // Scrolling: slot 2 moves with every placement, slot 1 shifts by less + // than half a pixel. + for (const y of [60, 70, 80]) { + overlay.place(placement(400, 800, [slot(1, 'photo', [0, 0.4, 44]), slot(2, 'photo', [0, y, 44])])); + vi.advanceTimersToNextFrame(); + expect([hidden(still), hidden(moving)]).toEqual([false, true]); + await vi.advanceTimersByTimeAsync(SETTLE_MS - 50); + } + expect(hidden(moving)).toBe(true); + await vi.advanceTimersByTimeAsync(50); + expect(hidden(moving)).toBe(false); + expect(box(moving?.querySelector('.contact-avatar'))).toEqual([0, 80, 44, 44]); + style.remove(); + }); + + it('hides every avatar while the frame itself moves', async () => { + const style = useStyles(); + const iframe = await draw( + 'viewport', + [400, 800], + placement(400, 800, [slot(1, 'photo', [0, 0, 44]), slot(2, 'photo', [0, 50, 44])]), + ); + await vi.advanceTimersByTimeAsync(SETTLE_MS); + expect(slots().map(hidden)).toEqual([false, false]); + + // The topbar autohides: the frame slides up. + iframe.style.transform = 'translateY(-56px)'; + await vi.advanceTimersByTimeAsync(1); + expect(slots().map(hidden)).toEqual([true, true]); + await vi.advanceTimersByTimeAsync(SETTLE_MS); + expect(slots().map(hidden)).toEqual([false, false]); + + window.dispatchEvent(new Event('resize')); + expect(slots().map(hidden)).toEqual([true, true]); + await vi.advanceTimersByTimeAsync(SETTLE_MS); + expect(slots().map(hidden)).toEqual([false, false]); + style.remove(); + }); + + it('draws only the latest of several placements, once per frame', async () => { + await draw('viewport', [400, 800], placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + const anchor = slots()[0]?.querySelector('.contact-avatar'); + + for (const y of [10, 20, 30]) { + overlay.place(placement(400, 800, [slot(1, 'photo', [0, y, 44])])); + } + flush(); + expect(box(anchor)).toEqual([0, 0, 44, 44]); + vi.advanceTimersToNextFrame(); + flush(); + expect(box(anchor)).toEqual([0, 30, 44, 44]); + }); + + it('hides and shows without fading under reduced motion', async () => { + const style = useStyles(); + const device = happyWindow.happyDOM.settings.device; + device.prefersReducedMotion = 'reduce'; + try { + await draw('viewport', [400, 800], placement(400, 800, [slot(1, 'photo', [0, 0, 44])])); + const [drawn] = slots(); + expect([hidden(drawn), fades(drawn)]).toEqual([true, false]); + await vi.advanceTimersByTimeAsync(SETTLE_MS); + expect([hidden(drawn), fades(drawn)]).toEqual([false, false]); + } finally { + device.prefersReducedMotion = 'no-preference'; + style.remove(); + } + }); +}); diff --git a/packages/ui/tests/contacts.test.ts b/packages/ui/tests/contacts.test.ts index ef1ce9468..c0e7965ea 100644 --- a/packages/ui/tests/contacts.test.ts +++ b/packages/ui/tests/contacts.test.ts @@ -1,9 +1,17 @@ -import type { ContactsPlatform, CoreStorage, NativeChatContactsSnapshot, ProductContext } from '@parity/truapi-host'; +import type { + ContactsPlatform, + CoreStorage, + NativeChatContactsSnapshot, + PlacedContactLabels, + ProductContext, +} from '@parity/truapi-host'; import { afterEach, describe, expect, it } from 'vitest'; import { createContactsPlatform, NativeChatContactsDirectory } from '../src/host-callbacks/Contacts.js'; import { createBlockingModalCoordinator, type BlockingModalCoordinator } from '../src/blocking-modal-queue.js'; import { overlaysReady, resetOverlays } from './helpers/overlays.js'; +import { settle } from './helpers/solid.js'; import { must } from './support.js'; +import { createContactLabelOverlay, type ContactLabelOverlay } from '../src/contacts/label-overlay.js'; const walletPublicKey = `0x${'11'.repeat(32)}` as const; const genesisHash = `0x${'55'.repeat(32)}` as const; @@ -27,14 +35,16 @@ afterEach(() => { document.body.replaceChildren(); }); -function fixture(): { +interface ContactsFixture { directory: NativeChatContactsDirectory; adapter: { callbacks: Required; dispose(): void }; coordinator: BlockingModalCoordinator; snapshot: NativeChatContactsSnapshot; setRead(value: () => Promise): void; switchSession(): void; -} { +} + +function fixture(labels?: ContactLabelOverlay): ContactsFixture { let snapshot: NativeChatContactsSnapshot = { walletPublicKey, genesisHash, @@ -53,7 +63,7 @@ function fixture(): { ); const coordinator = createBlockingModalCoordinator(); const scope = coordinator.createScope(); - const adapter = createContactsPlatform(directory, scope); + const adapter = createContactsPlatform(directory, scope, labels); cleanups.push(() => { adapter.dispose(); directory.dispose(); @@ -79,10 +89,70 @@ function fixture(): { }; } -async function choices(): Promise { +async function choices(): Promise { await overlaysReady(); await expect.poll(() => document.querySelector('.contacts-picker-choice')).not.toBeNull(); - return Array.from(document.querySelectorAll('.contacts-picker-choice')); + return Array.from(document.querySelectorAll('.contacts-picker-choice')); +} + +async function labelFixture(): Promise<{ + state: ContactsFixture; + adapter: ContactsFixture['adapter']; + frame: HTMLIFrameElement; + placed: PlacedContactLabels; +}> { + const frame = document.createElement('iframe'); + Object.defineProperties(frame, { + clientWidth: { value: 200 }, + clientHeight: { value: 120 }, + }); + const loaded = new Promise(resolve => { + frame.addEventListener( + 'load', + () => { + resolve(); + }, + { once: true }, + ); + }); + document.body.append(frame); + // Place into the loaded document, not the initial about:blank navigation. + await loaded; + const labels = createContactLabelOverlay(); + labels.attach(frame, 'contain'); + cleanups.push(() => { + labels.dispose(); + }); + const state = fixture(labels); + const placed: PlacedContactLabels = { + surfaceWidth: 200, + surfaceHeight: 120, + labels: [ + { + slot: 0, + account: alice, + rect: { x: 0, y: 20, width: 100, height: 32 }, + clip: { x: 0, y: 0, width: 200, height: 120 }, + }, + { + slot: 1, + account: bob, + rect: { x: 100, y: 20, width: 100, height: 32 }, + clip: { x: 0, y: 0, width: 200, height: 120 }, + }, + ], + }; + return { state, adapter: state.adapter, frame, placed }; +} + +async function redraw(): Promise { + await new Promise(resolve => { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + resolve(); + }); + }); + }); } describe('native Chat contacts', () => { @@ -281,4 +351,137 @@ describe('native Chat contacts', () => { ); await expect(picked).resolves.toEqual({ tag: 'Dismissed' }); }); + + it('keeps preselected contacts when search hides them and confirms multiple people', async () => { + const { adapter, snapshot } = fixture(); + must(snapshot.contacts[1], 'Bob contact').username = 'bob.paseo'; + const picked = adapter.callbacks.pickContacts(product, { + selected: [alice], + }); + const rows = await choices(); + expect(document.querySelector('[role=dialog]')?.textContent).not.toMatch(/0x[0-9a-f]{64}/i); + const firstRow = must(rows[0], 'First contact choice'); + const secondRow = must(rows[1], 'Second contact choice'); + const first = must(firstRow.querySelector('input[type="checkbox"]'), 'First contact checkbox'); + const second = must(secondRow.querySelector('input[type="checkbox"]'), 'Second contact checkbox'); + expect(first.checked).toBe(true); + expect(second.checked).toBe(false); + const search = must(document.querySelector('input[type="search"]'), 'Contact search'); + search.value = 'bob'; + search.dispatchEvent(new Event('input', { bubbles: true })); + await expect.poll(() => firstRow.hidden).toBe(true); + expect(secondRow.hidden).toBe(false); + second.click(); + await settle(); + must(document.querySelector('.signing-btn-sign'), 'Confirm selection').click(); + await expect(picked).resolves.toEqual({ + tag: 'Picked', + value: { accounts: [alice, bob] }, + }); + }); + + it('distinguishes confirmed empty selection from canceled checkbox edits', async () => { + const { adapter } = fixture(); + const cleared = adapter.callbacks.pickContacts(product, { + selected: [alice], + }); + const rows = await choices(); + must( + must(rows[0], 'First contact choice').querySelector('input[type="checkbox"]'), + 'First contact checkbox', + ).click(); + await settle(); + must(document.querySelector('.signing-btn-sign'), 'Confirm selection').click(); + await expect(cleared).resolves.toEqual({ + tag: 'Picked', + value: { accounts: [] }, + }); + + const canceled = adapter.callbacks.pickContacts(product, { + selected: [alice], + }); + const reopened = await choices(); + expect( + must( + must(reopened[0], 'First reopened contact').querySelector('input[type="checkbox"]'), + 'First reopened checkbox', + ).checked, + ).toBe(true); + must( + must(reopened[1], 'Second reopened contact').querySelector('input[type="checkbox"]'), + 'Second reopened checkbox', + ).click(); + await settle(); + must(document.querySelector('.signing-btn-cancel'), 'Cancel selection').click(); + await expect(canceled).resolves.toEqual({ tag: 'Dismissed' }); + }); + + it('does not memoize a failed label-directory read', async () => { + const { state, adapter, placed } = await labelFixture(); + state.setRead(() => Promise.reject(new Error('Directory temporarily unavailable'))); + await expect(adapter.callbacks.placeContactLabels(product, placed)).rejects.toThrow( + 'Directory temporarily unavailable', + ); + state.setRead(() => Promise.resolve(state.snapshot)); + await adapter.callbacks.placeContactLabels(product, placed); + await expect.poll(() => document.querySelector('.contact-label')?.textContent).toBe('alice.paseo'); + }); + + it('refreshes the latest labels after a same-wallet directory change without another placement', async () => { + const { state, adapter, placed } = await labelFixture(); + await adapter.callbacks.placeContactLabels(product, placed); + await expect.poll(() => document.querySelector('.contact-label')?.textContent).toBe('alice.paseo'); + expect(document.querySelectorAll('.contact-label')[1]?.getAttribute('aria-label')).toBe(bob); + state.snapshot = { + ...state.snapshot, + contacts: [{ peerIdentity: alice, username: 'renamed.paseo' }], + }; + state.directory.invalidate(); + expect(document.querySelector('.contact-label')).toBeNull(); + await expect.poll(() => document.querySelector('.contact-label')?.textContent).toBe('renamed.paseo'); + expect(document.querySelector(`[aria-label="${bob}"]`)).toBeNull(); + }); + + it.each(['navigation', 'empty placement', 'provider close', 'wallet switch'])( + 'does not replay an in-flight directory refresh after %s', + async ending => { + const { state, adapter, placed, frame } = await labelFixture(); + await adapter.callbacks.placeContactLabels(product, placed); + await expect.poll(() => document.querySelector('.contact-label')?.textContent).toBe('alice.paseo'); + const pending = Promise.withResolvers(); + const started = Promise.withResolvers(); + state.setRead(() => { + started.resolve(undefined); + return pending.promise; + }); + state.directory.invalidate(); + await started.promise; + if (ending === 'navigation') { + frame.dispatchEvent(new Event('load')); + } else if (ending === 'empty placement') { + await adapter.callbacks.placeContactLabels(product, { + ...placed, + labels: [], + }); + } else if (ending === 'provider close') { + adapter.dispose(); + } else { + state.switchSession(); + } + expect(document.querySelector('.contact-label')).toBeNull(); + pending.resolve(state.snapshot); + await redraw(); + expect(document.querySelector('.contact-label')).toBeNull(); + }, + ); + + it('does not replay a queued directory refresh after navigation', async () => { + const { state, adapter, placed, frame } = await labelFixture(); + await adapter.callbacks.placeContactLabels(product, placed); + await expect.poll(() => document.querySelector('.contact-label')?.textContent).toBe('alice.paseo'); + state.directory.invalidate(); + frame.dispatchEvent(new Event('load')); + await redraw(); + expect(document.querySelector('.contact-label')).toBeNull(); + }); }); diff --git a/packages/ui/tests/fixtures/seity-contacts-v1.json b/packages/ui/tests/fixtures/seity-contacts-v1.json new file mode 100644 index 000000000..3379d64bb --- /dev/null +++ b/packages/ui/tests/fixtures/seity-contacts-v1.json @@ -0,0 +1,21 @@ +{ + "reference": "seity-contacts:v1:be1954b54b4a001d6f466d7f8780d7aaa30bc7b5c23ff2cca32606a1466421f76d5e940494d34b965a5f714441dd2943dcac6dbbfd4cd9c38fbbd8a7177e82ac", + "registry": { + "lookupKey": "0xbe1954b54b4a001d6f466d7f8780d7aaa30bc7b5c23ff2cca32606a1466421f7", + "cidDigest": "0x43edd9991161b5f16b50447098569e4f570e79a631b954351880526de70986db", + "version": 1 + }, + "blobs": { + "0x43edd9991161b5f16b50447098569e4f570e79a631b954351880526de70986db": "ba5da44344adbc6a7e4f48480cad82fcc78d3b4fc1e929d2ceeda81d959769130e8c765ddbef6da50d58a80071de41813bdda4fa43c6bad6dfca2c7dec9554cacb8df8aa40e741d3d91e4f84fcd15d837deb34cbb994cebd9a9d4b7a40d48b1bb044f2eece8f30d633a1ddf1ee3148a4ac46321e71917ca8c08933384fcb2af1b29b39308e873503b72898b908f50d5fd6b0dd278eedb6b8e6cb851a01d1d016f5391da868fa6bf1cdbee2651012f83347fdfe8603fc2f5662e8eb10c77c4ee7c503659d1b2f5a04454421b9e749613691", + "0x074f73f4cd0fc5ca1f8bef7c2ba6384f6c20695827465726c13f46db50dd498f": "4ce11c7109089210221721c72c30ceb700cbeb7b0ac06cec466d379d4b75f0cc5a7c7f009154e8e3e1923b541655e730f2e90267cfa23dc7a349dc0e8a3e6e449d530b924a71fd7a53fa9dca400c119ec436" + }, + "expect": { + "avatarPlaintext": "89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c4890000000d49444154789c6360000002000154a24f5d0000000049454e44ae426082", + "mood": { + "kind": "hyped", + "intensity": "loud", + "setAt": 1790000000, + "ttlSecs": 86400 + } + } +} diff --git a/packages/ui/tests/permissions.test.ts b/packages/ui/tests/permissions.test.ts index b54219136..1bd05ccef 100644 --- a/packages/ui/tests/permissions.test.ts +++ b/packages/ui/tests/permissions.test.ts @@ -71,6 +71,8 @@ function requestKey(request: PermissionAuthorizationRequest): string { return `StatementStoreAllowance:${JSON.stringify(request.value.derivationIndex)}`; case 'IdentityDisclosure': return 'IdentityDisclosure'; + case 'ProfileDisclosure': + return 'ProfileDisclosure'; case 'AccountAccess': return `AccountAccess:${request.value.targetProductId}`; } @@ -163,6 +165,20 @@ describe('resetPermission', () => { await resetPermission('myapp', 'Camera'); expect(await getPermissionStatus('myapp', 'Camera')).toBe('ask'); }); + + it('As a dotli user, revoking profile disclosure leaves identity disclosure granted', async () => { + // Given + await setPermissionStatus('myapp', 'ProfileDisclosure', 'granted'); + await setPermissionStatus('myapp', 'IdentityDisclosure', 'granted'); + expect(myappStore.get('ProfileDisclosure')).toBe('Authorized'); + + // When + await resetPermission('myapp', 'ProfileDisclosure'); + + // Then + expect(await getPermissionStatus('myapp', 'ProfileDisclosure')).toBe('ask'); + expect(await getPermissionStatus('myapp', 'IdentityDisclosure')).toBe('granted'); + }); }); describe('hasAnyGrant', () => { diff --git a/packages/ui/tests/profile-contacts.test.ts b/packages/ui/tests/profile-contacts.test.ts new file mode 100644 index 000000000..3536c3a41 --- /dev/null +++ b/packages/ui/tests/profile-contacts.test.ts @@ -0,0 +1,211 @@ +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import type { ProductContext } from '@parity/truapi-host'; +import { fromHex } from '@dotli/shared'; +import { hashToCid } from '@dotli/content'; +import { createProfilePlatform } from '../src/host-callbacks/Profile.js'; +import { parseContactsReference } from '../src/profile/contacts-reference.js'; +import { InvalidProfileReferenceError } from '../src/profile/seity-reference.js'; +import { resetOverlays } from './helpers/overlays.js'; +import type * as Content from '@dotli/content'; +import type * as Config from '@dotli/config'; +import type * as Protocol from '@dotli/protocol'; +import type * as Resolver from '@dotli/resolver'; + +// Produced by Seity's profile-core (`test/vectors/contacts-v1.json`): the +// reference a contact's host is handed, the registry slot it names, the two +// blobs it fetches (sealed record, re-sealed avatar), and what it must draw. +const VECTOR = JSON.parse( + // happy-dom replaces import.meta.url, so resolve from the package root vitest runs in. + readFileSync(join(process.cwd(), 'tests/fixtures/seity-contacts-v1.json'), 'utf8'), +) as { + reference: string; + registry: { + lookupKey: `0x${string}`; + cidDigest: `0x${string}`; + version: number; + }; + blobs: Record; + expect: { + avatarPlaintext: string; + mood: { kind: string; intensity: string; setAt: number; ttlSecs: number }; + }; +}; + +const mocks = vi.hoisted(() => ({ + backend: 'smoldot-direct', + bitswapGet: vi.fn((_cid: string): Promise => Promise.resolve(new Uint8Array())), + resolveSeitySlotRemote: vi.fn(), + resolveSeitySlotViaRpc: vi.fn(), +})); + +vi.mock('@dotli/content', async importOriginal => ({ + ...(await importOriginal()), + bitswapGet: mocks.bitswapGet, + fetchFromIpfs: async (cid: string) => ({ data: await mocks.bitswapGet(cid) }), +})); +vi.mock('@dotli/config', async importOriginal => ({ + ...(await importOriginal()), + getBackend: () => mocks.backend, +})); +vi.mock('@dotli/protocol', async importOriginal => ({ + ...(await importOriginal()), + resolveSeitySlotRemote: mocks.resolveSeitySlotRemote, +})); +vi.mock('@dotli/resolver', async importOriginal => ({ + ...(await importOriginal()), + loadRpcResolve: () => + Promise.resolve({ + resolveSeitySlotViaRpc: mocks.resolveSeitySlotViaRpc, + }), +})); + +const product: ProductContext = { + productId: 'egui-chat.dot', + executionKind: 'App', +}; +const BLOBS_BY_CID = new Map( + Object.entries(VECTOR.blobs).map(([digest, hex]) => [hashToCid(digest).toString(), fromHex(hex)]), +); + +function drawer(): HTMLElement | null { + return document.querySelector('.profile-drawer'); +} + +/** + * Two preimage polls (record, then avatar), each after the poller's first delay. + * WebCrypto and the envelope decode run on real time, not the fake clock, so + * each check advances the fake timers a little and then yields real time. + */ +async function settle(): Promise { + await vi.waitFor( + () => { + expect(drawer()?.querySelector('.spinner')).toBeNull(); + }, + { timeout: 10_000, interval: 50 }, + ); +} + +describe('Seity contacts references', () => { + beforeEach(() => { + vi.useFakeTimers(); + mocks.backend = 'smoldot-direct'; + mocks.resolveSeitySlotViaRpc.mockReset(); + // An hour after the vector's mood was set, so it is still current. + vi.setSystemTime((VECTOR.expect.mood.setAt + 3600) * 1000); + mocks.bitswapGet.mockReset(); + mocks.bitswapGet.mockImplementation((cid: string) => { + const bytes = BLOBS_BY_CID.get(cid); + return bytes === undefined ? Promise.reject(new Error(`no blob for ${cid}`)) : Promise.resolve(bytes); + }); + mocks.resolveSeitySlotRemote.mockReset(); + mocks.resolveSeitySlotRemote.mockImplementation((lookupKey: string) => + Promise.resolve( + lookupKey === VECTOR.registry.lookupKey + ? { + owner: `0x${'aa'.repeat(20)}`, + cidDigest: VECTOR.registry.cidDigest, + version: '1', + } + : { + owner: `0x${'00'.repeat(20)}`, + cidDigest: `0x${'00'.repeat(32)}`, + version: '0', + }, + ), + ); + }); + + afterEach(() => { + document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + resetOverlays(); + vi.useRealTimers(); + }); + + it('parses the reference profile-core writes', () => { + expect(parseContactsReference(VECTOR.reference).lookupKey).toBe(VECTOR.registry.lookupKey); + }); + + it('resolves the slot, opens the record and draws the avatar with its mood', async () => { + await createProfilePlatform().presentProfile(product, { + reference: VECTOR.reference, + }); + await settle(); + + expect(mocks.resolveSeitySlotRemote).toHaveBeenCalledWith(VECTOR.registry.lookupKey); + expect(drawer()?.querySelector('img')?.getAttribute('src')).toMatch(/^blob:/); + expect(drawer()?.querySelector('.profile-drawer-mood')?.textContent).toBe('Hyped · loud · 23 h left'); + expect(drawer()?.querySelector('.profile-mood-ring')).not.toBeNull(); + }); + + it('hides a lapsed mood but still draws the avatar', async () => { + vi.setSystemTime((VECTOR.expect.mood.setAt + VECTOR.expect.mood.ttlSecs + 1) * 1000); + await createProfilePlatform().presentProfile(product, { + reference: VECTOR.reference, + }); + await settle(); + + expect(drawer()?.querySelector('img')).not.toBeNull(); + expect(drawer()?.querySelector('.profile-mood-ring')).toBeNull(); + }); + + it('reads the slot over the gateway RPC on the Trusted Providers backend', async () => { + mocks.backend = 'rpc-gateway'; + mocks.resolveSeitySlotViaRpc.mockResolvedValue({ + owner: `0x${'aa'.repeat(20)}`, + cidDigest: VECTOR.registry.cidDigest, + version: 1n, + }); + await createProfilePlatform().presentProfile(product, { + reference: VECTOR.reference, + }); + await settle(); + + expect(mocks.resolveSeitySlotViaRpc).toHaveBeenCalledWith(VECTOR.registry.lookupKey); + expect(mocks.resolveSeitySlotRemote).not.toHaveBeenCalled(); + expect(drawer()?.querySelector('img')).not.toBeNull(); + expect(drawer()?.querySelector('.profile-mood-ring')).not.toBeNull(); + }); + + it('keeps the mood when the avatar cannot be opened', async () => { + // The record opens; the avatar's decrypt (the second one) fails, as a + // re-sealed avatar would. + const decrypt = crypto.subtle.decrypt.bind(crypto.subtle); + let calls = 0; + const spy = vi + .spyOn(crypto.subtle, 'decrypt') + .mockImplementation((...args: Parameters) => + ++calls === 2 ? Promise.reject(new DOMException('bad tag', 'OperationError')) : decrypt(...args), + ); + try { + await createProfilePlatform().presentProfile(product, { + reference: VECTOR.reference, + }); + await settle(); + } finally { + spy.mockRestore(); + } + + expect(calls).toBe(2); + expect(drawer()?.querySelector('img')).toBeNull(); + expect(drawer()?.querySelector('.profile-mood-ring')).not.toBeNull(); + expect(drawer()?.querySelector('.profile-drawer-mood')?.textContent).toBe('Hyped · loud · 23 h left'); + }); + + it('accepts a contacts reference spelled in uppercase hex', () => { + const prefix = 'seity-contacts:v1:'; + const body = VECTOR.reference.slice(prefix.length); + expect(parseContactsReference(prefix + body.toUpperCase()).lookupKey).toBe(VECTOR.registry.lookupKey); + }); + + it('rejects a malformed contacts reference without opening UI or echoing the seed', async () => { + const bad = VECTOR.reference.slice(0, -2); + const call = createProfilePlatform().presentProfile(product, { + reference: bad, + }); + await expect(call).rejects.toBeInstanceOf(InvalidProfileReferenceError); + await expect(call).rejects.not.toThrow(bad.slice(-64)); + expect(drawer()).toBeNull(); + }); +}); diff --git a/packages/ui/tests/profile.test.ts b/packages/ui/tests/profile.test.ts new file mode 100644 index 000000000..749d5f3fe --- /dev/null +++ b/packages/ui/tests/profile.test.ts @@ -0,0 +1,391 @@ +import { afterEach, beforeEach, describe, expect, it, onTestFinished, vi } from 'vitest'; +import type { NativeChatContactsSnapshot, PlacedAvatar, ProductContext } from '@parity/truapi-host'; +import { fromHex } from '@dotli/shared'; +import { createContactAvatars, createProfilePlatform } from '../src/host-callbacks/Profile.js'; +import { NativeChatContactsDirectory } from '../src/host-callbacks/Contacts.js'; +import { + InvalidProfileReferenceError, + openSeityBlob, + parseSeityBlobReference, +} from '../src/profile/seity-reference.js'; +import { resetOverlays } from './helpers/overlays.js'; +import type * as Content from '@dotli/content'; +import type * as Config from '@dotli/config'; + +// Produced with profile-core's primitives (product-sdk-crypto AES-256-GCM, +// Blake2b-256 digest, CIDv1 raw/Blake2b-256) over a 1x1 PNG: the interop +// contract this host must read. +const VECTOR = { + reference: + 'bafk2bzacebczvuhgd5yzd4s3r7e4chyrkxct4vd4aoyla3hupu6osyd2b5wjq#0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20a0a1a2a3a4a5a6a7a8a9aaab', + digest: '0x459ad0e61f7191f25b8fc9c11f1155c53e547c03b0b06cf47d3ce9607a0f6c98', + ciphertext: + '30817321f0bf400e7f0ea266b8cd64d657d7b018586860852f5dd5fd5251cdf1b8d199c8e29bf475790e5cfac6364e2519b7246683c6fed548e4cab58c72a92accc0e0947f8f7b4c1bff0d251d4f61314e90', + plaintext: + '89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c4890000000d49444154789c6360000002000154a24f5d0000000049454e44ae426082', +} as const; +const WRONG_KEY_REFERENCE = VECTOR.reference.replace('#01', '#ff'); + +const mocks = vi.hoisted(() => ({ + bitswapGet: vi.fn((): Promise => Promise.resolve(new Uint8Array())), +})); + +vi.mock('@dotli/content', async importOriginal => ({ + ...(await importOriginal()), + bitswapGet: mocks.bitswapGet, + fetchFromIpfs: vi.fn(), +})); +vi.mock('@dotli/config', async importOriginal => ({ + ...(await importOriginal()), + getBackend: () => 'smoldot-direct', +})); + +const product: ProductContext = { + productId: 'egui-chat.dot', + executionKind: 'App', +}; + +function drawer(): HTMLElement | null { + return document.querySelector('.profile-drawer'); +} + +async function settle(): Promise { + // Initial preimage poll, then the fetch, decrypt and render microtasks. + await vi.advanceTimersByTimeAsync(1_000); + await vi.waitFor(() => { + expect(drawer()?.querySelector('.spinner')).toBeNull(); + }); +} + +const walletPublicKey = `0x${'11'.repeat(32)}` as const; +const genesisHash = `0x${'55'.repeat(32)}` as const; +const contactIdentity = new Uint8Array(32).fill(0xab); +const contactSnapshot: NativeChatContactsSnapshot = { + walletPublicKey, + genesisHash, + contacts: [{ peerIdentity: `0x${'ab'.repeat(32)}`, username: 'alice.paseo' }], +}; + +function contactDirectory( + read: () => Promise = () => Promise.resolve(contactSnapshot), +): NativeChatContactsDirectory { + const directory = new NativeChatContactsDirectory(() => true); + directory.bind({ getNativeChatContacts: read, notifyContactsChanged: () => undefined }, walletPublicKey, genesisHash); + onTestFinished(() => { + directory.dispose(); + }); + return directory; +} + +describe('Seity blob references', () => { + it('reads the reference profile-core writes', async () => { + const parsed = parseSeityBlobReference(VECTOR.reference); + + expect(parsed.preimageKey).toBe(VECTOR.digest); + const plaintext = await openSeityBlob(fromHex(VECTOR.ciphertext) as Uint8Array, parsed); + expect(Array.from(plaintext)).toEqual(Array.from(fromHex(VECTOR.plaintext))); + }); + + it('refuses to yield bytes under the wrong key', async () => { + await expect( + openSeityBlob( + fromHex(VECTOR.ciphertext) as Uint8Array, + parseSeityBlobReference(WRONG_KEY_REFERENCE), + ), + ).rejects.toMatchObject({ name: 'OperationError' }); + }); + + it.each([ + ['no fragment', VECTOR.reference.slice(0, VECTOR.reference.indexOf('#'))], + ['a short fragment', VECTOR.reference.slice(0, -2)], + ['two fragments', `${VECTOR.reference}#00`], + [ + 'a sha2-256 CID', + `bafkreigh2akiscaildc6ybwhxslp6rx2u4m2vpbhgvzhpsfkyzxiezxcnq#${VECTOR.reference.slice(VECTOR.reference.indexOf('#') + 1)}`, + ], + ])('rejects %s without echoing the capability', (_case, reference) => { + expect(() => parseSeityBlobReference(reference)).toThrow(InvalidProfileReferenceError); + try { + parseSeityBlobReference(reference); + } catch (error) { + expect(String(error)).not.toContain(VECTOR.reference.slice(VECTOR.reference.indexOf('#') + 1)); + } + }); +}); + +describe('profile drawer', () => { + beforeEach(() => { + vi.useFakeTimers(); + mocks.bitswapGet.mockReset(); + }); + + afterEach(() => { + document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + resetOverlays(); + vi.useRealTimers(); + }); + + it('opens before the fetch completes, then shows the decrypted avatar', async () => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + + await createProfilePlatform().presentProfile(product, { + reference: VECTOR.reference, + }); + + expect(drawer()?.querySelector('.spinner')).not.toBeNull(); + expect(drawer()?.textContent).toContain('Shown by egui-chat.dot'); + await settle(); + const img = drawer()?.querySelector('img'); + expect(img?.getAttribute('src')).toMatch(/^blob:/); + expect(mocks.bitswapGet).toHaveBeenCalledWith(VECTOR.reference.split('#')[0], expect.any(AbortSignal)); + }); + + it('shows a failure in the drawer when the reference does not open', async () => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + + await createProfilePlatform().presentProfile(product, { + reference: WRONG_KEY_REFERENCE, + }); + await settle(); + + expect(drawer()?.querySelector('img')).toBeNull(); + expect(drawer()?.querySelector('.profile-drawer-status-error')).not.toBeNull(); + }); + + it('rejects an unparseable reference without opening UI', async () => { + await expect(createProfilePlatform().presentProfile(product, { reference: 'nope' })).rejects.toBeInstanceOf( + InvalidProfileReferenceError, + ); + expect(drawer()).toBeNull(); + }); + + // Anything that reads as an address: a 0x prefix or a long hex run. + const ADDRESS_LIKE = /0x|[0-9a-f]{8,}/i; + + it('names a contact by the username the host resolved, as plain text', async () => { + mocks.bitswapGet.mockReturnValue(new Promise(() => undefined)); + const peerIdentity = Uint8Array.from({ length: 32 }, (_, i) => i); + + await createProfilePlatform().presentContactProfile( + { ...product, productId: 'echat.paseo' }, + { + shared: { reference: VECTOR.reference, sharedAt: 1_700_000n }, + peerIdentity, + username: 'alice.01', + }, + ); + + const attribution = drawer()?.querySelector('.profile-drawer-attribution'); + expect(drawer()?.querySelector('.profile-drawer-contact')?.textContent).toBe('alice.01'); + expect(attribution?.textContent).toContain('echat.paseo'); + expect(attribution?.children).toHaveLength(0); + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + }); + + it('names a contact generically, never by address, when the host knows no username', async () => { + mocks.bitswapGet.mockReturnValue(new Promise(() => undefined)); + + await createProfilePlatform().presentContactProfile(product, { + shared: { reference: VECTOR.reference, sharedAt: 1_700_000n }, + peerIdentity: new Uint8Array(32).fill(0xab), + }); + + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + }); + it.each([false, true])('resolves the wallet-wide name outside Chat, shared profile: %s', async shared => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + await createProfilePlatform(null, undefined, contactDirectory()).presentContactProfile( + { ...product, productId: 'testing-seity-contacts.paseo' }, + { + peerIdentity: contactIdentity, + ...(shared ? { shared: { reference: VECTOR.reference, sharedAt: 1_700_000n } } : {}), + }, + ); + await settle(); + expect(drawer()?.querySelector('.profile-drawer-contact')?.textContent).toBe('alice.paseo'); + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + if (shared) { + expect(drawer()?.querySelector('.profile-drawer-attribution')?.textContent).toContain('alice.paseo'); + expect(drawer()?.querySelector('img')).not.toBeNull(); + } else { + expect(drawer()?.querySelector('img')).toBeNull(); + } + }); + + it('opens without waiting for the directory and discards its name after another presentation', async () => { + const pending = Promise.withResolvers(); + const platform = createProfilePlatform( + null, + undefined, + contactDirectory(() => pending.promise), + ); + await platform.presentContactProfile(product, { peerIdentity: contactIdentity }); + expect(drawer()).not.toBeNull(); + await platform.presentContactProfile(product, { peerIdentity: new Uint8Array(32), username: 'bob.paseo' }); + pending.resolve(contactSnapshot); + await vi.advanceTimersByTimeAsync(50); + expect(drawer()?.querySelector('.profile-drawer-contact')?.textContent).toBe('bob.paseo'); + expect(drawer()?.textContent).not.toContain('alice.paseo'); + }); + + it('never displays a name from an invalidated directory lookup', async () => { + const pending = Promise.withResolvers(); + const directory = contactDirectory(() => pending.promise); + await createProfilePlatform(null, undefined, directory).presentContactProfile(product, { + peerIdentity: contactIdentity, + }); + directory.invalidate(); + pending.resolve(contactSnapshot); + await vi.advanceTimersByTimeAsync(50); + expect(drawer()).not.toBeNull(); + expect(drawer()?.textContent).not.toContain('alice.paseo'); + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + }); + + it.each(['walletPublicKey', 'genesisHash'] as const)( + 'keeps the profile available without attributing another %s snapshot', + async field => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + const directory = contactDirectory(() => + Promise.resolve({ ...contactSnapshot, [field]: `0x${'77'.repeat(32)}` }), + ); + await createProfilePlatform(null, undefined, directory).presentContactProfile(product, { + peerIdentity: contactIdentity, + shared: { reference: VECTOR.reference, sharedAt: 1_700_000n }, + }); + await settle(); + expect(drawer()?.querySelector('img')).not.toBeNull(); + expect(drawer()?.textContent).not.toContain('alice.paseo'); + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + }, + ); + + it('rejects an unparseable contact reference without opening UI', async () => { + await expect( + createProfilePlatform().presentContactProfile(product, { + shared: { reference: 'nope', sharedAt: 0n }, + peerIdentity: new Uint8Array(32), + }), + ).rejects.toBeInstanceOf(InvalidProfileReferenceError); + expect(drawer()).toBeNull(); + }); + + it('replaces a loaded profile with an empty contact drawer without fetching or leaking the old image', async () => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + const controller = new AbortController(); + const platform = createProfilePlatform(null, controller.signal); + await platform.presentProfile(product, { reference: VECTOR.reference }); + await settle(); + expect(drawer()?.querySelector('img')).not.toBeNull(); + mocks.bitswapGet.mockClear(); + + const contact = { peerIdentity: new Uint8Array(32).fill(0xab), username: 'alice.01' }; + await platform.presentContactProfile(product, contact); + expect(document.querySelectorAll('.profile-drawer')).toHaveLength(1); + const name = drawer()?.querySelector('.profile-drawer-contact'); + expect(name?.textContent).toBe(contact.username); + expect(name?.children).toHaveLength(0); + expect(drawer()?.querySelector('img')).toBeNull(); + expect(drawer()?.querySelector('.spinner')).toBeNull(); + expect(drawer()?.querySelector('.profile-drawer-status-error')).toBeNull(); + expect(drawer()?.textContent).not.toMatch(ADDRESS_LIKE); + await vi.advanceTimersByTimeAsync(1_000); + expect(mocks.bitswapGet).not.toHaveBeenCalled(); + + controller.abort(); + expect(drawer()).toBeNull(); + await expect(platform.presentContactProfile(product, contact)).rejects.toMatchObject({ name: 'AbortError' }); + expect(drawer()).toBeNull(); + }); + + it('replaces the drawer on screen and closes on Escape', async () => { + mocks.bitswapGet.mockReturnValue(new Promise(() => undefined)); + const platform = createProfilePlatform(); + + await platform.presentProfile(product, { reference: VECTOR.reference }); + await platform.presentProfile(product, { reference: VECTOR.reference }); + expect(document.querySelectorAll('.profile-drawer')).toHaveLength(1); + + document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + expect(drawer()).toBeNull(); + }); + + it('retires a presented profile and rejects late calls when its connection closes', async () => { + mocks.bitswapGet.mockReturnValue(new Promise(() => undefined)); + const controller = new AbortController(); + const platform = createProfilePlatform(null, controller.signal); + await platform.presentProfile(product, { reference: VECTOR.reference }); + expect(drawer()).not.toBeNull(); + + controller.abort(); + expect(drawer()).toBeNull(); + await expect(platform.presentProfile(product, { reference: VECTOR.reference })).rejects.toMatchObject({ + name: 'AbortError', + }); + expect(drawer()).toBeNull(); + }); +}); + +describe('placed contact avatars', () => { + beforeEach(() => { + vi.useFakeTimers(); + mocks.bitswapGet.mockReset(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('draws the shared photo over the frame and answers the product alike either way', async () => { + mocks.bitswapGet.mockResolvedValue(fromHex(VECTOR.ciphertext)); + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + const avatars = createContactAvatars(); + avatars.attach(iframe, 'viewport'); + const at = (slot: number, reference: string): PlacedAvatar => ({ + slot, + reference, + sharedAt: 1n, + rect: { x: 0, y: slot * 50, width: 44, height: 44 }, + clip: { x: 0, y: 0, width: 400, height: 800 }, + }); + const platform = createProfilePlatform(avatars); + + await expect( + platform.placeContactAvatars(product, { + surfaceWidth: 400, + surfaceHeight: 800, + avatars: [at(1, VECTOR.reference), at(2, 'not a reference')], + }), + ).resolves.toBeUndefined(); + await expect( + platform.placeContactAvatars(product, { + surfaceWidth: 400, + surfaceHeight: 800, + avatars: [at(2, 'not a reference')], + }), + ).resolves.toBeUndefined(); + await expect( + createProfilePlatform().placeContactAvatars(product, { + surfaceWidth: 400, + surfaceHeight: 800, + avatars: [at(1, VECTOR.reference)], + }), + ).resolves.toBeUndefined(); + expect(document.querySelector('.contact-avatar-overlay')).toBeNull(); + + await platform.placeContactAvatars(product, { + surfaceWidth: 400, + surfaceHeight: 800, + avatars: [at(1, VECTOR.reference), at(2, 'not a reference')], + }); + await vi.advanceTimersByTimeAsync(1_000); + await vi.waitFor(() => { + expect(document.querySelectorAll('.contact-avatar-overlay img')).toHaveLength(1); + }); + expect(document.querySelector('.contact-avatar-overlay img')?.getAttribute('src')).toMatch(/^blob:/); + + avatars.dispose(); + iframe.remove(); + }); +}); diff --git a/packages/ui/tests/session-store.test.ts b/packages/ui/tests/session-store.test.ts index df25a0ec1..be6d15d0a 100644 --- a/packages/ui/tests/session-store.test.ts +++ b/packages/ui/tests/session-store.test.ts @@ -396,6 +396,70 @@ describe('session-store host callbacks', () => { expect(Array.from((await storage.readCoreStorage(otherSession)) ?? [])).toEqual([14]); }); + it('As a dotli user, my profile references stay with the wallet and chain they were disclosed on', async () => { + // Given + const storage = createSessionStoreAdapters(); + const scope = { + rootPublicKey: new Uint8Array(32).fill(1), + genesisHash: new Uint8Array(32).fill(2), + }; + const disclosure = { + tag: 'ProfileDisclosure', + value: scope, + } satisfies CoreStorageKey; + const otherWallet = { + tag: 'ProfileDisclosure', + value: { ...scope, rootPublicKey: new Uint8Array(32).fill(3) }, + } satisfies CoreStorageKey; + const received = { + tag: 'ProfileReferencesReceived', + value: { ...scope, productId: 'egui-chat.dot' }, + } satisfies CoreStorageKey; + const otherChain = { + tag: 'ProfileReferencesReceived', + value: { + ...scope, + genesisHash: new Uint8Array(32).fill(4), + productId: 'egui-chat.dot', + }, + } satisfies CoreStorageKey; + // Same scope as the disclosure: the two must not share a slot. + const personal = { + tag: 'ProfilePersonalReferencesReceived', + value: scope, + } satisfies CoreStorageKey; + + // When + await storage.writeCoreStorage(disclosure, new Uint8Array([21])); + await storage.writeCoreStorage(otherWallet, new Uint8Array([22])); + await storage.writeCoreStorage(received, new Uint8Array([23])); + await storage.writeCoreStorage(otherChain, new Uint8Array([24])); + await storage.writeCoreStorage(personal, new Uint8Array([25])); + + // Then + // The references are bearer capabilities, so every slot is encrypted. + expect(localStorage.length).toBe(5); + for (let index = 0; index < localStorage.length; index += 1) { + expect(localStorage.getItem(localStorage.key(index) ?? '')).toMatch(/^enc1:0x/); + } + expect(Array.from((await storage.readCoreStorage(disclosure)) ?? [])).toEqual([21]); + expect(Array.from((await storage.readCoreStorage(otherWallet)) ?? [])).toEqual([22]); + expect(Array.from((await storage.readCoreStorage(received)) ?? [])).toEqual([23]); + expect(Array.from((await storage.readCoreStorage(otherChain)) ?? [])).toEqual([24]); + expect(Array.from((await storage.readCoreStorage(personal)) ?? [])).toEqual([25]); + + // When + await storage.clearCoreStorage(disclosure); + await storage.clearCoreStorage(received); + + // Then + expect(await storage.readCoreStorage(disclosure)).toBeUndefined(); + expect(await storage.readCoreStorage(received)).toBeUndefined(); + expect(Array.from((await storage.readCoreStorage(otherWallet)) ?? [])).toEqual([22]); + expect(Array.from((await storage.readCoreStorage(otherChain)) ?? [])).toEqual([24]); + expect(Array.from((await storage.readCoreStorage(personal)) ?? [])).toEqual([25]); + }); + it('As a dotli integrator, the host stores the SSO responder replay ledger per wallet and peer', async () => { // Given const storage = createSessionStoreAdapters(); diff --git a/packages/ui/tests/user-confirmation.test.ts b/packages/ui/tests/user-confirmation.test.ts index 4e627b341..5ef42a025 100644 --- a/packages/ui/tests/user-confirmation.test.ts +++ b/packages/ui/tests/user-confirmation.test.ts @@ -793,6 +793,36 @@ describe('user confirmation modal', () => { await expect(decision).rejects.toThrow('User dismissed identity disclosure dialog'); }); + it('As a dotli user, always allowing profile disclosure is remembered', async () => { + // Given + const decision = createUserConfirmationAdapters('localhost:3000').confirmPermission({ + tag: 'ProfileDisclosure', + value: { productId: 'egui-chat.dot' }, + }); + await overlaysReady(); + + // When + document.querySelector('.signing-btn-secondary')?.click(); + + // Then + await expect(decision).resolves.toBe('AllowAlways'); + }); + + it('As a dotli user, dismissing profile disclosure records no decision', async () => { + // Given + const decision = createUserConfirmationAdapters('localhost:3000').confirmPermission({ + tag: 'ProfileDisclosure', + value: { productId: 'egui-chat.dot' }, + }); + await overlaysReady(); + + // When + document.querySelector('.signing-modal-backdrop')?.click(); + + // Then + await expect(decision).rejects.toThrow('User dismissed permission dialog'); + }); + it('As a dotli user, a per-action confirmation keeps two buttons', async () => { // When void createUserConfirmationAdapters('localhost:3000').confirmUserAction({ diff --git a/vendor/truapi-host.lock.json b/vendor/truapi-host.lock.json index c60dd01b0..84c41934e 100644 --- a/vendor/truapi-host.lock.json +++ b/vendor/truapi-host.lock.json @@ -1,27 +1,27 @@ { "schemaVersion": 1, "upstreamRepository": "https://github.com/paritytech/trinity-user-agents", - "upstreamBranch": "feat/chat-v2-product-authority", - "upstreamRevision": "901a3e754d86d9bc64bf647f103e9ea0a18de470", - "pullRequest": "https://github.com/paritytech/trinity-user-agents/pull/709", + "upstreamBranch": "feat/chat-seity-profile", + "upstreamRevision": "bd55ec2af4b5db75afaf827404f63d11f6881a02", + "pullRequest": "https://github.com/paritytech/trinity-user-agents/pull/1001", "packages": { "vendor/truapi": { "name": "@parity/truapi", "version": "0.23.0", - "sourceArchiveSha256": "df7b537877be29d79561bc4a3d6bf4d6edb1b1d037acbcd56a9eba336a8aa3e9", - "clientSha256": "81022e6ad71842cec42396dac1ec3ed72e39e906e3867dc57d65f1142b402b69" + "sourceArchiveSha256": "59f26eb2d74343958888a9fc09ecd5e4ac424366de8057e3550baa9c97c72c8a", + "clientSha256": "93cfaec49a733117b20557ea02bfb761891b752bc74428fe38fc4410448f5011" }, "vendor/truapi-host": { "name": "@parity/truapi-host", "version": "0.23.0", - "sourceArchiveSha256": "67b2ea10da5d36cf07fb7c629b6231f690226c8ade1da4485e1e215f056a056a", + "sourceArchiveSha256": "ca342bee6cfdcc6561facdff181b825c660a8144b9b79f31b7b5e74018c1b5c1", "dependencyOverride": "@parity/truapi=file:../truapi", - "wasmSha256": "90b586ec9a2ee0aea25477430f75be6b3c3911df69ae92006b3e00f5724ce4e7", - "testingWasmSha256": "1a1187ac05737c8e1098f7d0791d6ac99e080fc20c45d93a3402da30c9ae9a54", + "wasmSha256": "2a2da416abcefa98e02391bee662daa5cd87e346360fb897c930cec076573bf7", + "testingWasmSha256": "7b1557bfc1aadf2e1258fc581f1be4e56c0ab37002ae93ae5b029dc94d5338d6", "wasmFeatures": [ "wasm-signing-host" ] } }, - "wasmUpstreamRevision": "901a3e754d86d9bc64bf647f103e9ea0a18de470" + "wasmUpstreamRevision": "bd55ec2af4b5db75afaf827404f63d11f6881a02" } diff --git a/vendor/truapi-host/README.md b/vendor/truapi-host/README.md index bf128f90e..8e7283cab 100644 --- a/vendor/truapi-host/README.md +++ b/vendor/truapi-host/README.md @@ -21,8 +21,6 @@ The package exposes tree-shakeable subpath exports — import only what your env | `@parity/truapi-host/testing/host-page` | The browser half the fixture drives, for a suite that boots its own page. | | `@parity/truapi-host/wasm/testing` | The raw glue for the signing-enabled bundle the test host runs on. | -The shipped WASM includes `WasmSigningHostRuntime`. Its configuration requires `runtimeConfig.networkSuffix`: the bare -TLD (`dot`, `paseo`, or `testnet`) matching the People chain and the wallet's onboarding configuration. `scripts/build-wasm.mjs` builds two WASM bundles, both `--no-default-features`. `wasm/web` is the production browser host and excludes `WasmSigningHostRuntime`; `wasm/testing` adds the Rust `wasm-signing-host` and `test-host` features, which is what lets the test host hold keys and answer resource allocation as granted without allocating anything. A real @@ -194,6 +192,7 @@ const callbacks: HostCallbacks = { chat, // optional: leave it out and chat products get `Unsupported` permissionStatus, // optional: reports live OS permission state pocket, // optional: serves the host's Pocket card collection + profile, // optional: shows profiles and draws contact avatars in host UI contacts, // optional: leave it out and contacts calls get `Unsupported` }; ``` @@ -206,6 +205,47 @@ reading as usable. Omit it and a stored grant answers on its own. replacement, and `removePocketCard` takes one out. The host owns the collection: removing an absent card succeeds, and a card the host pins is refused with `Privileged`. +`profile.presentProfile` shows the profile a product references in host-owned UI and resolves once it is shown, not +when the user dismisses it. The reference is a bearer capability: the host fetches, decrypts and renders it, and the +profile's bytes never return to the product. The core forwards only references that are non-empty, at most 2048 bytes +and printable ASCII without whitespace; parsing the format is the host's. + +`profile.presentContactProfile(product, presented)` opens host-owned contact profile UI when a product calls +`profile.presentContact`. `presented` carries the `peerIdentity`, an optional `shared` record containing the bearer +`reference` and `sharedAt` freshness timestamp (`bigint`), and the contact's optional verified `username`. +An absent `shared` requests friendly empty-profile feedback, not a fetch or an error. The username is the one the core's +Chat roster verified for that contact, else the contact's verified dotNS name, looked up for at most 2 seconds; never a +name from the product. Without one, name the contact generically, never by address. It names who sent the reference, +not whose profile it is: the record is not signed by its owner, and a contact can forward someone else's. Same contract +as `presentProfile` otherwise. The default adapter can present a shared reference through `presentProfile`; +hosts implement `presentContactProfile` to show empty-profile feedback. V2 never reports availability or rendering +failures to the product. A failed reference lookup is not represented as an empty profile. + +`profile.placeContactAvatars(product, placed)` draws contacts' avatars over a chat product. `placed` carries the +product's surface size and, per avatar, the product's `slot` id, a square `rect`, the `clip` region it is cut to, all in +surface units (framebuffer pixels for a PolkaVM product, CSS pixels of the viewport for a web product), and the +`reference` that contact disclosed, so the host can draw their photo and mood ring, with a `sharedAt` freshness token +(`bigint`). Contact tokens use Unix ms, advanced monotonically for personal revisions across relay actors; the own +avatar uses the disclosure revision, not a date. A changed token invalidates cached contents. Each call replaces what was +drawn for the product; an empty `avatars` clears it. The core calls it again with the same geometry when a contact +shares, re-shares or withdraws a profile, and with no avatars when the product's connection goes away. Draw on a layer +the product cannot +read that lets pointer input through, and never tell the product what was drawn. The host runtimes take +`RequiredHostCallbacks`, so a `profile` group implements it and `presentContactProfile` alongside `presentProfile`. + +`profile.disclose` needs no `profile` group, but the first call from a product asks the user through +`userConfirmation.confirmPermission` with a `ProfileDisclosure` review naming that product. V1 shares app-scoped +references with every ready Chat contact; V2 can select apps or opaque Contacts handles. Personal grants are +host-renderable across recipient apps. The answer is kept like any other permission, as `ProfileDisclosure`. +Audience mutations currently reuse that product-level consent. A host that cannot render the +review should reject the call rather than answer `Deny`: the product is refused, but no refusal is remembered. + +`presentContact` V2 accepts peer or Contacts-handle selectors and hides sharing availability; V1 remains app-only. +`placeContactAvatars` V3 accepts those selectors alongside the V2 own slot. V1/V2 placement bytes remain compatible. +Hosts must call `notifyContactsChanged()` after directory changes so stale handle resolution and overlays clear. +These APIs do not create a Chat channel or a group editor. See the +[Profile RFC](../../../docs/rfcs/profile-disclosure.md) for audience, transport and withdrawal semantics. + Under `createWebWorkerPairingHostRuntime` the presence of each optional group is reported to the worker in its `init` message, so the core sees the same capability set on both sides of the boundary. @@ -313,16 +353,32 @@ A running fixture answers the same address through `testHost.getProductAccountAddress(productId?, index?)`, which reads the session the host actually holds and so returns `undefined` while it is signed out. -`contacts` needs both callbacks, or the group counts as absent. `pickContact` -draws the picker and returns the chosen account, or `NoContacts` when there is -nobody to show. `contacts({ handleKey, handles })` resolves the handles a -transaction names: one entry per handle, in order, the account or `undefined`. +The optional `contacts` group resolves handles through `contacts({ handleKey, handles })`: +one entry per handle, in order, the account or `undefined`. `pickContact` draws a single +picker and returns the chosen account. `pickContacts(product, { selected })` edits a +complete selection of at most 256 resolved accounts, returning `Picked { accounts }`, +`Dismissed`, or `NoContacts`. A confirmed empty array is `Picked`, not dismissal. +Missing picker callbacks answer `Unsupported`. A contact's handle is BLAKE2b-256 keyed with `handleKey` over its 32-byte account (`blake2b(account, { key: handleKey, dkLen: 32 })` in `@noble/hashes`). The core re-checks every account returned. It caches what it resolves, so call `notifyContactsChanged()` whenever a contact is removed or blocked. Omit blocked contacts from both. See the contacts RFC (`docs/rfcs/contacts-api.md`). +`placeContactLabels(product, placed)` receives surface dimensions and +`labels: [{ slot, account, rect, clip }]`. Draw names from the host's contact directory, +using an account fallback when no username exists. Profile-photo absence must not +hide a name. Keep this UI host-owned: return no label or per-slot availability. +Return `true` when the host supports label placement, even when no contact resolves. +Return `false` when that UI is unsupported; the adapter supplies this answer when +the callback is omitted. This capability acknowledgment never reports individual +contact availability. Background Workers are denied label placement. +Empty placements clear the previous names and cancel queued refreshes. Clear names +and cancel pending work on frame load, navigation or disconnect. On same-wallet +directory invalidation, clear stale names and refresh the latest live placement +without waiting for the product to resend it. The core serializes placements per +connection and rejects selections from changed sessions. + Browser signing hosts can back this UI with `runtime.getNativeChatContacts()`. It returns `{ walletPublicKey, genesisHash, contacts: [{ peerIdentity, username? }] }` to trusted host code only. The directory restores encrypted native Chat actors, checks their current authorization, includes only authenticated diff --git a/vendor/truapi-host/dist/adapter-support.d.ts b/vendor/truapi-host/dist/adapter-support.d.ts index d557c2e4f..4be39f2d1 100644 --- a/vendor/truapi-host/dist/adapter-support.d.ts +++ b/vendor/truapi-host/dist/adapter-support.d.ts @@ -1,6 +1,8 @@ import { type GenericError, type Result } from "@parity/truapi"; import type { ChainConnect, HopConnect } from "./runtime.js"; -import type { ChainProvider, CoinageWalletHost, HopProvider, NativeChatFilesHost } from "./generated/host-callbacks.js"; +import type { ChainProvider, CoinageWalletHost, ContactsPlatform, HopProvider, NativeChatFilesHost, ProfilePlatform } from "./generated/host-callbacks.js"; +/** Optional Contacts UI stays unsupported rather than confirming an empty selection. */ +export declare function contactsHostAdapter(host: ContactsPlatform | undefined): Required | undefined; type WireResult = { success: true; value: T; @@ -27,6 +29,12 @@ export declare function chainConnectAdapter(host: Pick export declare const unavailableHopProvider: Required; /** Native exceptions may contain bearer material; preserve only typed failure values. */ export declare function coinageWalletHostAdapter(host: Required | undefined): Required | undefined; +/** + * A profile host built before `presentContactProfile` still shows a contact's + * profile: without it, the contact's reference is presented as + * `presentProfile` would. Empty-profile feedback requires the contact callback. + */ +export declare function profileHostAdapter(host: Required | undefined): Required | undefined; /** Optional SDK embeddings must fail closed, never invent successful file handles. */ export declare const unavailableNativeChatFilesHost: Required; export declare function hopConnectAdapter(host: Required): HopConnect; diff --git a/vendor/truapi-host/dist/adapter-support.js b/vendor/truapi-host/dist/adapter-support.js index fdb0e31cd..822227238 100644 --- a/vendor/truapi-host/dist/adapter-support.js +++ b/vendor/truapi-host/dist/adapter-support.js @@ -5,6 +5,18 @@ // and the chain-connection handle. import { hexToBytes } from "@parity/truapi/scale"; import { errorMessage } from "./error.js"; +/** Optional Contacts UI stays unsupported rather than confirming an empty selection. */ +export function contactsHostAdapter(host) { + if (host === undefined) + return undefined; + return { + contacts: (lookup) => host.contacts(lookup), + pickContact: (product) => host.pickContact?.(product) ?? Promise.resolve({ tag: "Unsupported" }), + pickContacts: (product, selection) => host.pickContacts?.(product, selection) ?? + Promise.resolve({ tag: "Unsupported" }), + placeContactLabels: (product, placed) => host.placeContactLabels?.(product, placed) ?? Promise.resolve(false), + }; +} /** * Normalize both generated `Result` values and the plain * `{ success, value }` envelope used by some JS fixtures into a raw item. @@ -129,6 +141,26 @@ export function coinageWalletHostAdapter(host) { }, }; } +/** + * A profile host built before `presentContactProfile` still shows a contact's + * profile: without it, the contact's reference is presented as + * `presentProfile` would. Empty-profile feedback requires the contact callback. + */ +export function profileHostAdapter(host) { + if (host === undefined || typeof host.presentContactProfile === "function") + return host; + return { + presentProfile: (product, request) => host.presentProfile(product, request), + presentContactProfile: (product, presented) => { + if (presented.shared === undefined) + return Promise.reject(new Error("Contact profile feedback is unavailable")); + return host.presentProfile(product, { + reference: presented.shared.reference, + }); + }, + placeContactAvatars: (product, placed) => host.placeContactAvatars(product, placed), + }; +} /** Optional SDK embeddings must fail closed, never invent successful file handles. */ export const unavailableNativeChatFilesHost = { async pickChatFiles() { diff --git a/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts b/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts index 28dd67f4f..285f113a6 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts +++ b/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts @@ -16,6 +16,8 @@ export interface RawCallbacks { nativeCoinage?(request: Uint8Array): Promise; contacts?(lookup: Uint8Array): Promise; pickContact?(product: Uint8Array): Promise; + pickContacts?(product: Uint8Array, selection: Uint8Array): Promise; + placeContactLabels?(product: Uint8Array, placed: Uint8Array): Promise; readCoreStorage(key: Uint8Array): Promise; writeCoreStorage(key: Uint8Array, value: Uint8Array): Promise; clearCoreStorage(key: Uint8Array): Promise; @@ -48,6 +50,9 @@ export interface RawCallbacks { write(key: string, value: Uint8Array): Promise; clear(key: string): Promise; subscribeStorage(key: string, sendItem: (item?: Uint8Array) => void, sendError: (error: GenericError) => void): (() => void) | void; + presentProfile?(product: Uint8Array, request: Uint8Array): Promise; + presentContactProfile?(product: Uint8Array, presented: Uint8Array): Promise; + placeContactAvatars?(product: Uint8Array, placed: Uint8Array): Promise; subscribeTheme(sendItem: (item?: Uint8Array) => void, sendError: (error: GenericError) => void): (() => void) | void; confirmPermission(review: Uint8Array): Promise; confirmUserAction(review: Uint8Array): Promise; diff --git a/vendor/truapi-host/dist/generated/host-callbacks-adapter.js b/vendor/truapi-host/dist/generated/host-callbacks-adapter.js index 8e740f168..20d31f767 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks-adapter.js +++ b/vendor/truapi-host/dist/generated/host-callbacks-adapter.js @@ -5,9 +5,9 @@ // platform-local types cross as SCALE bytes (`.enc`/`.dec`); strings, // primitives and byte blobs pass through unchanged. import * as S from "@parity/truapi/scale"; -import { HostChatCreateRoomRequest, HostChatCreateRoomResponse, HostChatListSubscribeItem, HostChatPostMessageRequest, HostChatPostMessageResponse, HostChatRegisterBotRequest, HostChatRegisterBotResponse, HostDevicePermissionRequest, HostFeatureSupportedRequest, HostFeatureSupportedResponse, HostLocalStorageChangeItem, HostLocaleLocalizeTimestampsRequest, HostLocaleLocalizeTimestampsResponse, HostLocaleSubscribeItem, HostPocketListSubscribeItem, HostPocketRemoveCardRequest, HostPushNotificationRequest, HostPushNotificationResponse, HostThemeSubscribeItem, HostWorkerBeginOperationResponse, RemotePermissionRequest, } from "@parity/truapi"; -import { AuthState, CoreStorageKey, DevicePermissionStatus, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageRequest, NativeCoinageResponse, PermissionDecision, ProductContext, UserConfirmationReview, } from "./host-callbacks.js"; -import { chainConnectAdapter, coinageWalletHostAdapter, driveResultStream, hopConnectAdapter, unavailableHopProvider, unavailableNativeChatFilesHost, } from "../adapter-support.js"; +import { HostChatCreateRoomRequest, HostChatCreateRoomResponse, HostChatListSubscribeItem, HostChatPostMessageRequest, HostChatPostMessageResponse, HostChatRegisterBotRequest, HostChatRegisterBotResponse, HostDevicePermissionRequest, HostFeatureSupportedRequest, HostFeatureSupportedResponse, HostLocalStorageChangeItem, HostLocaleLocalizeTimestampsRequest, HostLocaleLocalizeTimestampsResponse, HostLocaleSubscribeItem, HostPocketListSubscribeItem, HostPocketRemoveCardRequest, HostProfilePresentRequest, HostPushNotificationRequest, HostPushNotificationResponse, HostThemeSubscribeItem, HostWorkerBeginOperationResponse, RemotePermissionRequest, } from "@parity/truapi"; +import { AuthState, ContactSelection, CoreStorageKey, DevicePermissionStatus, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, HostContactsPick, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageRequest, NativeCoinageResponse, PermissionDecision, PlacedAvatars, PlacedContactLabels, PresentedContactProfile, ProductContext, UserConfirmationReview, } from "./host-callbacks.js"; +import { chainConnectAdapter, coinageWalletHostAdapter, contactsHostAdapter, driveResultStream, hopConnectAdapter, profileHostAdapter, unavailableHopProvider, unavailableNativeChatFilesHost, } from "../adapter-support.js"; const allowedHopEndpointsResultCodec = S.Vector(S.str); const identityUsernameCandidatesResultCodec = S.Vector(S.Bytes(32)); const pickChatFilesResultCodec = S.Vector(NativeChatPickedFile); @@ -16,10 +16,11 @@ const pickChatFilesResultCodec = S.Vector(NativeChatPickedFile); export function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); - const contacts = callbacks.contacts; + const contacts = contactsHostAdapter(callbacks.contacts); const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const profile = profileHostAdapter(callbacks.profile); const hop = callbacks.hop ?? unavailableHopProvider; const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { @@ -42,6 +43,8 @@ export function createWasmRawCallbacks(callbacks) { ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))), + pickContacts: async (product, selection) => HostContactsPick.enc(await contacts.pickContacts(ProductContext.dec(product), ContactSelection.dec(selection))), + placeContactLabels: async (product, placed) => await contacts.placeContactLabels(ProductContext.dec(product), PlacedContactLabels.dec(placed)), } : {}), readCoreStorage: async (key) => await callbacks.coreStorage.readCoreStorage(CoreStorageKey.dec(key)), @@ -88,6 +91,13 @@ export function createWasmRawCallbacks(callbacks) { write: async (key, value) => await callbacks.productStorage.write(key, value), clear: async (key) => await callbacks.productStorage.clear(key), subscribeStorage: (key, sendItem, sendError) => driveResultStream(callbacks.productStorage.subscribeStorage(key), (item) => sendItem(HostLocalStorageChangeItem.enc(item)), sendError), + ...(profile + ? { + presentProfile: async (product, request) => await profile.presentProfile(ProductContext.dec(product), HostProfilePresentRequest.dec(request)), + presentContactProfile: async (product, presented) => await profile.presentContactProfile(ProductContext.dec(product), PresentedContactProfile.dec(presented)), + placeContactAvatars: async (product, placed) => await profile.placeContactAvatars(ProductContext.dec(product), PlacedAvatars.dec(placed)), + } + : {}), subscribeTheme: (sendItem, sendError) => driveResultStream(callbacks.theme.subscribeTheme(), (item) => sendItem(HostThemeSubscribeItem.enc(item)), sendError), confirmPermission: async (review) => PermissionDecision.enc(await callbacks.userConfirmation.confirmPermission(UserConfirmationReview.dec(review))), confirmUserAction: async (review) => await callbacks.userConfirmation.confirmUserAction(UserConfirmationReview.dec(review)), diff --git a/vendor/truapi-host/dist/generated/host-callbacks.d.ts b/vendor/truapi-host/dist/generated/host-callbacks.d.ts index eb370561f..b8ad91240 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks.d.ts +++ b/vendor/truapi-host/dist/generated/host-callbacks.d.ts @@ -1,6 +1,6 @@ import * as S from "@parity/truapi/scale"; -import { AllocatableResource, Bytes32, ChainIdentifier, DerivationIndex, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostNativeChatAttachmentMetadata, HostNativeChatPayment, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation } from "@parity/truapi"; -import type { GenericError, HostChatCreateRoomRequest, HostChatCreateRoomResponse, HostChatListSubscribeItem, HostChatPostMessageRequest, HostChatPostMessageResponse, HostChatRegisterBotRequest, HostChatRegisterBotResponse, HostFeatureSupportedRequest, HostFeatureSupportedResponse, HostLocalStorageChangeItem, HostLocaleLocalizeTimestampsRequest, HostLocaleLocalizeTimestampsResponse, HostLocaleSubscribeItem, HostPocketListSubscribeItem, HostPocketRemoveCardRequest, HostPushNotificationRequest, HostPushNotificationResponse, HostThemeSubscribeItem, HostWorkerBeginOperationResponse, Result } from "@parity/truapi"; +import { AllocatableResource, AvatarRect, Bytes32, ChainIdentifier, DerivationIndex, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostNativeChatAttachmentMetadata, HostNativeChatPayment, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation } from "@parity/truapi"; +import type { GenericError, HostChatCreateRoomRequest, HostChatCreateRoomResponse, HostChatListSubscribeItem, HostChatPostMessageRequest, HostChatPostMessageResponse, HostChatRegisterBotRequest, HostChatRegisterBotResponse, HostFeatureSupportedRequest, HostFeatureSupportedResponse, HostLocalStorageChangeItem, HostLocaleLocalizeTimestampsRequest, HostLocaleLocalizeTimestampsResponse, HostLocaleSubscribeItem, HostPocketListSubscribeItem, HostPocketRemoveCardRequest, HostProfilePresentRequest, HostPushNotificationRequest, HostPushNotificationResponse, HostThemeSubscribeItem, HostWorkerBeginOperationResponse, Result } from "@parity/truapi"; /** * Review shown before a product asks to access another product account. */ @@ -90,6 +90,15 @@ export interface ChatAuthorityReview { */ productId: string; } +/** + * Host-private initial selection for a multi-contact picker. + */ +export interface ContactSelection { + /** + * Resolved accounts to preselect, deduplicated and bounded to 256. + */ + selected: Array; +} /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -278,6 +287,47 @@ export type CoreStorageKey = rootPublicKey: Uint8Array; genesisHash: Uint8Array; }; +} +/** + * The profile reference the user disclosed to their chat contacts on one + * Chat network, with the product that disclosed it. Wallet-owned: one per + * wallet and network, whichever product wrote it. The reference is a + * bearer capability. + * + * Known gap (docs/rfcs/profile-disclosure.md): one slot, so the last product to disclose replaces + * the others. + */ + | { + tag: "ProfileDisclosure"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + }; +} +/** + * Profile references the contacts on one Chat product's roster disclosed, + * the newest per contact, withdrawals included. Scoped like the + * `NativeChatDevice` roster it shadows, and product-indexed so clearing + * the product clears them. The references are bearer capabilities. + */ + | { + tag: "ProfileReferencesReceived"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + productId: string; + }; +} +/** + * Wallet-wide personal profile grants, including replay tombstones. + * These bearer capabilities are independent of the receiving product. + */ + | { + tag: "ProfilePersonalReferencesReceived"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + }; }; /** * Review shown before a product creates a ring-VRF proof (RFC 0004). @@ -429,6 +479,40 @@ export type HostContactPick = tag: "Unsupported"; value?: undefined; }; +/** + * The user's complete selection in a host-owned multi-contact picker. + */ +export type HostContactsPick = +/** + * Confirmed accounts, including an empty selection. Never sent to products. + */ +{ + tag: "Picked"; + value: { + accounts: Array; + }; +} +/** + * The user cancelled without changing the selection. + */ + | { + tag: "Dismissed"; + value?: undefined; +} +/** + * There are no contacts to show. + */ + | { + tag: "NoContacts"; + value?: undefined; +} +/** + * This host cannot present a multi-contact picker. + */ + | { + tag: "Unsupported"; + value?: undefined; +}; /** * Review shown before a product learns the user's primary identity. */ @@ -850,6 +934,14 @@ export type PermissionAuthorizationRequest = value: { derivationIndex?: DerivationIndex; }; +} +/** + * Product-scoped permission to disclose a profile reference to the user's + * Chat contacts. + */ + | { + tag: "ProfileDisclosure"; + value?: undefined; }; /** * Authorization status for a permission request. @@ -862,6 +954,93 @@ export type PermissionAuthorizationStatus = "NotDetermined" | "Denied" | "Author * User decision including how long an authorization should last. */ export type PermissionDecision = "AllowOnce" | "AllowAlways" | "Deny"; +/** + * One avatar to draw over a product. + */ +export interface PlacedAvatar { + /** + * The product's id for this on-screen avatar, stable across updates. + */ + slot: number; + /** + * Bounding box of the avatar circle, in surface units. + */ + rect: AvatarRect; + /** + * Visible region the avatar is cut to, in surface units. + */ + clip: AvatarRect; + /** + * The profile reference the contact disclosed. A bearer capability, as + * in `ProfilePlatform::present_profile`. + */ + reference: string; + /** + * Freshness token for this reference. Contact shares use Unix + * milliseconds, advanced monotonically for personal revisions even + * across relay actors with different clocks. The own avatar uses the + * disclosure revision. A changed token invalidates cached contents; + * do not interpret an own-profile token as a wall-clock date. + */ + sharedAt: bigint; +} +/** + * The avatars the core found drawable in one product's placement: the slots + * whose contact shared a profile with the user, each with the reference that + * contact disclosed. + */ +export interface PlacedAvatars { + /** + * Width of the product's surface, in the units of every rect. + */ + surfaceWidth: number; + /** + * Height of the product's surface, in the same units. + */ + surfaceHeight: number; + /** + * Avatars to draw, in the product's slot order. + */ + avatars: Array; +} +/** + * One contact name to render in host-owned UI, without any Profile grant. + */ +export interface PlacedContactLabel { + /** + * Stable, product-chosen placement id. + */ + slot: number; + /** + * Resolved contact account, never sent to the product. + */ + account: Bytes32; + /** + * Name bounds in surface units. + */ + rect: AvatarRect; + /** + * Visible region in surface units. + */ + clip: AvatarRect; +} +/** + * Complete replacement of names drawn over one product connection. + */ +export interface PlacedContactLabels { + /** + * Width of the product surface. + */ + surfaceWidth: number; + /** + * Height of the product surface. + */ + surfaceHeight: number; + /** + * Host-resolved names to draw. Empty clears the placement. + */ + labels: Array; +} /** * Review shown before a preimage is submitted. */ @@ -871,6 +1050,29 @@ export interface PreimageSubmitReview { */ size: bigint; } +/** + * Host-only presentation of a contact's shared profile or its absence. + */ +export interface PresentedContactProfile { + /** + * The profile currently shared with the user. ``undefined`` means no received, + * unretracted profile, never a storage or loading failure. + */ + shared?: SharedContactProfile; + /** + * The contact being presented. When shared, their authenticated Chat + * device delivered the reference, not necessarily their own profile. + */ + peerIdentity: Uint8Array; + /** + * The contact's username, when the core knows one: the name its Chat + * roster holds for `peer_identity`, verified when the contact was bound + * or first authenticated, else the peer's verified dotNS name. Never a + * name from the product. ``undefined`` when neither is known in time; show the + * contact without a name then, never by address. + */ + username?: string; +} /** * Product identity attached to one product-facing TrUAPI connection. * @@ -911,6 +1113,18 @@ export interface ProductSubtreeReview { */ productId: string; } +/** + * Review shown before a product discloses a profile reference to an app + * audience or selected contacts. Personal grants permit host rendering across + * recipient apps. This authorizes the product, not individual audience edits. + * The prompt names the product, never the contacts or the reference. + */ +export interface ProfileDisclosureReview { + /** + * Product asking to disclose the profile. + */ + productId: string; +} /** * Review shown before allocating resources for a product. Names the * beneficiary product so the user knows which product receives the @@ -972,6 +1186,21 @@ export interface SessionUiInfo { */ fullUsername?: string; } +/** + * A profile reference received from an authenticated Chat contact. + */ +export interface SharedContactProfile { + /** + * The profile reference the contact disclosed. A bearer capability, as + * in `ProfilePlatform::present_profile`. + */ + reference: string; + /** + * The share's freshness timestamp, as in `PlacedAvatar::shared_at`. + * Personal grants advance it monotonically across relay actors. + */ + sharedAt: bigint; +} /** * Review shown before a sign-payload request is sent to the paired wallet. */ @@ -1155,6 +1384,14 @@ export type UserConfirmationReview = | { tag: "MainPurseChatPayment"; value: MainPurseChatPaymentReview; +} +/** + * Allow a product to disclose a profile reference to the user's Chat + * contacts. + */ + | { + tag: "ProfileDisclosure"; + value: ProfileDisclosureReview; }; /** * Review shown before a product asks to access another product account. @@ -1174,6 +1411,10 @@ export declare const AuthState: S.Codec; * Review shown before a product binds or uses wallet-held Chat identity authority. */ export declare const ChatAuthorityReview: S.Codec; +/** + * Host-private initial selection for a multi-contact picker. + */ +export declare const ContactSelection: S.Codec; /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -1228,6 +1469,10 @@ export declare const HostContactMatches: S.Codec; * How a host's contact picker ended. */ export declare const HostContactPick: S.Codec; +/** + * The user's complete selection in a host-owned multi-contact picker. + */ +export declare const HostContactsPick: S.Codec; /** * Review shown before a product learns the user's primary identity. */ @@ -1305,10 +1550,32 @@ export declare const PermissionAuthorizationStatus: S.Codec; +/** + * One avatar to draw over a product. + */ +export declare const PlacedAvatar: S.Codec; +/** + * The avatars the core found drawable in one product's placement: the slots + * whose contact shared a profile with the user, each with the reference that + * contact disclosed. + */ +export declare const PlacedAvatars: S.Codec; +/** + * One contact name to render in host-owned UI, without any Profile grant. + */ +export declare const PlacedContactLabel: S.Codec; +/** + * Complete replacement of names drawn over one product connection. + */ +export declare const PlacedContactLabels: S.Codec; /** * Review shown before a preimage is submitted. */ export declare const PreimageSubmitReview: S.Codec; +/** + * Host-only presentation of a contact's shared profile or its absence. + */ +export declare const PresentedContactProfile: S.Codec; /** * Product identity attached to one product-facing TrUAPI connection. * @@ -1331,6 +1598,13 @@ export declare const ProductExecutionKind: S.Codec; * when the value is not cached and the core must ask the Account Holder. */ export declare const ProductSubtreeReview: S.Codec; +/** + * Review shown before a product discloses a profile reference to an app + * audience or selected contacts. Personal grants permit host rendering across + * recipient apps. This authorizes the product, not individual audience edits. + * The prompt names the product, never the contacts or the reference. + */ +export declare const ProfileDisclosureReview: S.Codec; /** * Review shown before allocating resources for a product. Names the * beneficiary product so the user knows which product receives the @@ -1342,6 +1616,10 @@ export declare const ResourceAllocationReview: S.Codec * parsing the opaque session blob the core persists through `CoreStorage`. */ export declare const SessionUiInfo: S.Codec; +/** + * A profile reference received from an authenticated Chat contact. + */ +export declare const SharedContactProfile: S.Codec; /** * Review shown before a sign-payload request is sent to the paired wallet. */ @@ -1485,11 +1763,7 @@ export interface ContactsPlatform { * implements `Self::contacts` alone still compiles and its products get * a truthful answer rather than a dismissal they would retry forever. * - * A JS host reaches the same answer by another route: the generated - * surface types this method optional, but a capability group counts as - * served only when every callback in it is present, so omitting this one - * makes the whole group absent and `contacts.pick` answers `Unsupported` - * before any of it is reached. + * JS adapters apply the same unsupported default when the host omits UI. * * The core cannot draw UI, so a selection has to come from the host; the * whole point is that the host renders the names rather than shipping @@ -1498,6 +1772,22 @@ export interface ContactsPlatform { * `HostContactPick::NoContacts` instead of drawing an empty overlay. */ pickContact?(product: ProductContext): Promise; + /** + * Edit the complete selection in host-owned UI. Cancellation is not an + * empty confirmed selection. Accounts and names stay host-side. + */ + pickContacts?(product: ProductContext, selection: ContactSelection): Promise; + /** + * Draw names from the host's contact directory, with an account fallback + * when no username exists. Profile sharing must not affect labels. + * + * Replace the connection's previous placement, and clear it on navigation + * or disconnect. On directory invalidation, clear stale names and refresh + * the live placement from current contacts. No per-contact result is returned. + * Returns whether this host supports label placement, never whether any + * individual contact resolved. JS adapters return false for omitted UI. + */ + placeContactLabels?(product: ProductContext, placed: PlacedContactLabels): Promise; } /** * Core-owned administration API exposed to host UI. @@ -1913,6 +2203,53 @@ export interface ProductStorage { */ subscribeStorage(key: string): AsyncIterable>; } +/** + * Host-implemented adapter that shows a product-referenced profile in + * host-owned UI. Optional: a host that omits it leaves Profile requests + * answered `Unsupported`. See `OptionalPlatform`. + * + * The reference is a bearer capability. The host resolves, decrypts and + * renders it; profile bytes and the reference's key never return to the + * product. The core screens only the reference's shape, so parsing it and + * deciding what it may fetch are the host's. + */ +export interface ProfilePlatform { + /** + * Take one presentation and return once it is shown, never waiting for + * the user to dismiss it. Report an unparseable reference as + * `InvalidReference`; show load and fetch failures in the UI instead. + */ + presentProfile(product: ProductContext, request: HostProfilePresentRequest): Promise; + /** + * Show a Chat contact's shared profile, or host-owned feedback when no + * profile is shared. Return once it is shown, without waiting for dismissal. + * Report an unparseable shared reference as `InvalidReference`. + * + * The core holds this reference because it arrived over the + * authenticated Chat channel from `peer_identity`'s own device, so the + * host can name that contact as who shared it, rather than the product + * that asked. It cannot vouch for more: the record behind the reference + * is not signed by its owner, so a contact can forward someone else's + * reference. The default presents a shared profile as + * `ProfilePlatform::present_profile` would, without the contact, and + * reports an error when empty-profile feedback is unsupported. + */ + presentContactProfile?(product: ProductContext, presented: PresentedContactProfile): Promise; + /** + * Draw the contact avatars a product placed, on the host's own layer over + * the product's surface, replacing what was drawn for it before; an empty + * `avatars` clears it. The layer must let pointer input through to the + * product and must never tell the product what it drew. + * + * The core calls this again, with the product's last geometry, whenever + * a contact on it shares, re-shares or withdraws a profile, and with no + * avatars once + * the product's connection goes away. Answer `Unsupported` if this host + * cannot draw over the product; the product is told so. The default draws + * nothing. + */ + placeContactAvatars?(product: ProductContext, placed: PlacedAvatars): Promise; +} /** * Host theme source. */ @@ -1967,6 +2304,7 @@ export interface HostCallbacks { identityBackend?: IdentityBackendHost; permissionStatus?: PermissionStatusHost; pocket?: PocketPlatform; + profile?: ProfilePlatform; } export interface RequiredHostCallbacks { navigation: Required; @@ -1986,8 +2324,9 @@ export interface RequiredHostCallbacks { productOperations: Required; chat?: Required; coinageWallet?: Required; - contacts?: Required; + contacts?: ContactsPlatform; identityBackend?: Required; permissionStatus?: Required; pocket?: Required; + profile?: Required; } diff --git a/vendor/truapi-host/dist/generated/host-callbacks.js b/vendor/truapi-host/dist/generated/host-callbacks.js index 6ad1c295f..260cb95cf 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks.js +++ b/vendor/truapi-host/dist/generated/host-callbacks.js @@ -4,7 +4,7 @@ // capability traits. One interface per Rust trait + a composite // `HostCallbacks` interface that mirrors the `Platform` super-trait. import * as S from "@parity/truapi/scale"; -import { AllocatableResource, Bytes32, ChainIdentifier, DerivationIndex, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostNativeChatAttachmentMetadata, HostNativeChatPayment, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation, } from "@parity/truapi"; +import { AllocatableResource, AvatarRect, Bytes32, ChainIdentifier, DerivationIndex, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostNativeChatAttachmentMetadata, HostNativeChatPayment, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation, } from "@parity/truapi"; /** * Review shown before a product asks to access another product account. */ @@ -23,6 +23,10 @@ export const AuthState = S.lazy(() => S.TaggedUnion({ Disconnected: S._void, Pai * Review shown before a product binds or uses wallet-held Chat identity authority. */ export const ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str })); +/** + * Host-private initial selection for a multi-contact picker. + */ +export const ContactSelection = S.lazy(() => S.Struct({ selected: S.Vector(Bytes32) })); /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -30,7 +34,7 @@ export const ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str })); * Storage is host-local; `storage.md` records the current status quo: * */ -export const CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); +export const CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileDisclosure: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), ProfilePersonalReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); /** * Review shown before a product creates a ring-VRF proof (RFC 0004). */ @@ -77,6 +81,10 @@ export const HostContactMatches = S.lazy(() => S.Struct({ accounts: S.Vector(S.O * How a host's contact picker ended. */ export const HostContactPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ account: Bytes32 }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); +/** + * The user's complete selection in a host-owned multi-contact picker. + */ +export const HostContactsPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ accounts: S.Vector(Bytes32) }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); /** * Review shown before a product learns the user's primary identity. */ @@ -142,7 +150,7 @@ export const NativeCoinageTopUpOutcome = S.lazy(() => S.TaggedUnion({ Cleared: S * Permission request whose authorization status can be inspected or updated * by host administration UI. */ -export const PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: HostDevicePermissionRequest, Remote: RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(DerivationIndex) }) })); +export const PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: HostDevicePermissionRequest, Remote: RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(DerivationIndex) }), ProfileDisclosure: S._void })); /** * Authorization status for a permission request. * @@ -154,10 +162,32 @@ export const PermissionAuthorizationStatus = S.lazy(() => S.Status("NotDetermine * User decision including how long an authorization should last. */ export const PermissionDecision = S.lazy(() => S.Status("AllowOnce", "AllowAlways", "Deny")); +/** + * One avatar to draw over a product. + */ +export const PlacedAvatar = S.lazy(() => S.Struct({ slot: S.u32, rect: AvatarRect, clip: AvatarRect, reference: S.str, sharedAt: S.u64 })); +/** + * The avatars the core found drawable in one product's placement: the slots + * whose contact shared a profile with the user, each with the reference that + * contact disclosed. + */ +export const PlacedAvatars = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, avatars: S.Vector(PlacedAvatar) })); +/** + * One contact name to render in host-owned UI, without any Profile grant. + */ +export const PlacedContactLabel = S.lazy(() => S.Struct({ slot: S.u32, account: Bytes32, rect: AvatarRect, clip: AvatarRect })); +/** + * Complete replacement of names drawn over one product connection. + */ +export const PlacedContactLabels = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, labels: S.Vector(PlacedContactLabel) })); /** * Review shown before a preimage is submitted. */ export const PreimageSubmitReview = S.lazy(() => S.Struct({ size: S.u64 })); +/** + * Host-only presentation of a contact's shared profile or its absence. + */ +export const PresentedContactProfile = S.lazy(() => S.Struct({ shared: S.Option(SharedContactProfile), peerIdentity: S.Bytes(32), username: S.Option(S.str) })); /** * Product identity attached to one product-facing TrUAPI connection. * @@ -180,6 +210,13 @@ export const ProductExecutionKind = S.lazy(() => S.Status("App", "Widget", "Work * when the value is not cached and the core must ask the Account Holder. */ export const ProductSubtreeReview = S.lazy(() => S.Struct({ productId: S.str })); +/** + * Review shown before a product discloses a profile reference to an app + * audience or selected contacts. Personal grants permit host rendering across + * recipient apps. This authorizes the product, not individual audience edits. + * The prompt names the product, never the contacts or the reference. + */ +export const ProfileDisclosureReview = S.lazy(() => S.Struct({ productId: S.str })); /** * Review shown before allocating resources for a product. Names the * beneficiary product so the user knows which product receives the @@ -191,6 +228,10 @@ export const ResourceAllocationReview = S.lazy(() => S.Struct({ callingProductId * parsing the opaque session blob the core persists through `CoreStorage`. */ export const SessionUiInfo = S.lazy(() => S.Struct({ publicKey: Bytes32, identityAccountId: S.Option(Bytes32), chatPublicKey: S.Option(Bytes32), deviceEncPublicKey: S.Option(Bytes32), peerStatementAccountId: S.Option(Bytes32), deviceStatementAccountId: S.Option(Bytes32), liteUsername: S.Option(S.str), fullUsername: S.Option(S.str) })); +/** + * A profile reference received from an authenticated Chat contact. + */ +export const SharedContactProfile = S.lazy(() => S.Struct({ reference: S.str, sharedAt: S.u64 })); /** * Review shown before a sign-payload request is sent to the paired wallet. */ @@ -215,4 +256,4 @@ export const StatementStoreProductSignReview = S.lazy(() => S.Struct({ callingPr /** * Review shown before a user-confirmed core action continues. */ -export const UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview })); +export const UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview, ProfileDisclosure: ProfileDisclosureReview })); diff --git a/vendor/truapi-host/dist/generated/worker-callbacks.d.ts b/vendor/truapi-host/dist/generated/worker-callbacks.d.ts index e66f8be5b..faf7a3f0d 100644 --- a/vendor/truapi-host/dist/generated/worker-callbacks.d.ts +++ b/vendor/truapi-host/dist/generated/worker-callbacks.d.ts @@ -1,7 +1,7 @@ import type { RawCallbacks } from "./host-callbacks-adapter.js"; import type { GenericError } from "@parity/truapi"; import type { ChainConnect, HopConnect } from "../runtime.js"; -export declare const CALLBACK_NAMES: readonly ["authStateChanged", "createChatRoom", "registerChatBot", "postChatMessage", "nativeCoinage", "contacts", "pickContact", "readCoreStorage", "writeCoreStorage", "clearCoreStorage", "featureSupported", "supportedChains", "allowedHopEndpoints", "identityUsernameCandidates", "localizeTimestamps", "pickChatFiles", "readChatFile", "releaseChatFile", "beginChatFileExport", "writeChatFileExport", "finishChatFileExport", "cancelChatFileExport", "navigateTo", "pushNotification", "cancelNotification", "devicePermissionStatus", "devicePermission", "remotePermission", "removePocketCard", "beginOperation", "endOperation", "read", "write", "clear", "confirmPermission", "confirmUserAction"]; +export declare const CALLBACK_NAMES: readonly ["authStateChanged", "createChatRoom", "registerChatBot", "postChatMessage", "nativeCoinage", "contacts", "pickContact", "pickContacts", "placeContactLabels", "readCoreStorage", "writeCoreStorage", "clearCoreStorage", "featureSupported", "supportedChains", "allowedHopEndpoints", "identityUsernameCandidates", "localizeTimestamps", "pickChatFiles", "readChatFile", "releaseChatFile", "beginChatFileExport", "writeChatFileExport", "finishChatFileExport", "cancelChatFileExport", "navigateTo", "pushNotification", "cancelNotification", "devicePermissionStatus", "devicePermission", "remotePermission", "removePocketCard", "beginOperation", "endOperation", "read", "write", "clear", "presentProfile", "presentContactProfile", "placeContactAvatars", "confirmPermission", "confirmUserAction"]; export type CallbackName = typeof CALLBACK_NAMES[number]; export declare const SUBSCRIPTION_NAMES: readonly ["subscribeChatRooms", "subscribeLocale", "subscribePocketCards", "lookupPreimage", "subscribeStorage", "subscribeTheme"]; export type SubscriptionName = typeof SUBSCRIPTION_NAMES[number]; @@ -29,6 +29,8 @@ export interface OptionalCapabilities { permissionStatus?: boolean; /** Whether the host serves this capability. */ pocket?: boolean; + /** Whether the host serves this capability. */ + profile?: boolean; } export declare function createWorkerRawCallbacks(bridge: WorkerCallbackBridge, capabilities?: OptionalCapabilities): Record; export declare function startRawSubscription(callbacks: RawCallbacks, name: SubscriptionName, payload: Uint8Array | string | null, sendItem: (value?: unknown) => void, sendError: (error: GenericError) => void): (() => void) | void; diff --git a/vendor/truapi-host/dist/generated/worker-callbacks.js b/vendor/truapi-host/dist/generated/worker-callbacks.js index a3f9d73a0..089f17550 100644 --- a/vendor/truapi-host/dist/generated/worker-callbacks.js +++ b/vendor/truapi-host/dist/generated/worker-callbacks.js @@ -12,6 +12,8 @@ export const CALLBACK_NAMES = [ "nativeCoinage", "contacts", "pickContact", + "pickContacts", + "placeContactLabels", "readCoreStorage", "writeCoreStorage", "clearCoreStorage", @@ -39,6 +41,9 @@ export const CALLBACK_NAMES = [ "read", "write", "clear", + "presentProfile", + "presentContactProfile", + "placeContactAvatars", "confirmPermission", "confirmUserAction", ]; @@ -106,6 +111,8 @@ function contactsRawCallbacks(bridge) { return { contacts: (lookup) => bridge.callbackRequest("contacts", [lookup]), pickContact: (product) => bridge.callbackRequest("pickContact", [product]), + pickContacts: (product, selection) => bridge.callbackRequest("pickContacts", [product, selection]), + placeContactLabels: (product, placed) => bridge.callbackRequest("placeContactLabels", [product, placed]), }; } function identityBackendRawCallbacks(bridge) { @@ -124,6 +131,13 @@ function pocketRawCallbacks(bridge) { removePocketCard: (product, request) => bridge.callbackRequest("removePocketCard", [product, request]), }; } +function profileRawCallbacks(bridge) { + return { + presentProfile: (product, request) => bridge.callbackRequest("presentProfile", [product, request]), + presentContactProfile: (product, presented) => bridge.callbackRequest("presentContactProfile", [product, presented]), + placeContactAvatars: (product, placed) => bridge.callbackRequest("placeContactAvatars", [product, placed]), + }; +} export function createWorkerRawCallbacks(bridge, capabilities = {}) { const callbacks = { ...rawCallbacks(bridge), @@ -143,6 +157,8 @@ export function createWorkerRawCallbacks(bridge, capabilities = {}) { Object.assign(callbacks, permissionStatusRawCallbacks(bridge)); if (capabilities.pocket) Object.assign(callbacks, pocketRawCallbacks(bridge)); + if (capabilities.profile) + Object.assign(callbacks, profileRawCallbacks(bridge)); return callbacks; } export function startRawSubscription(callbacks, name, payload, sendItem, sendError) { diff --git a/vendor/truapi-host/dist/testing/create-mock-client.cjs b/vendor/truapi-host/dist/testing/create-mock-client.cjs index 078fefb8f..31022e562 100644 --- a/vendor/truapi-host/dist/testing/create-mock-client.cjs +++ b/vendor/truapi-host/dist/testing/create-mock-client.cjs @@ -547,7 +547,7 @@ var require_index_cjs = __commonJS({ }); // dist/generated/host-callbacks.js -var S, import_truapi3, AccountAccessReview, AccountAliasReview, AuthState, ChatAuthorityReview, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, IdentityDisclosureReview, LoginFailureKind, MainPurseChatPaymentReview, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageFailure, NativeCoinageMemo, NativeCoinageOperation, NativeCoinagePaymentIntent, NativeCoinageRequest, NativeCoinageResponse, NativeCoinageScope, NativeCoinageTopUpOutcome, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PreimageSubmitReview, ProductContext, ProductExecutionKind, ProductSubtreeReview, ResourceAllocationReview, SessionUiInfo, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; +var S, import_truapi3, AccountAccessReview, AccountAliasReview, AuthState, ChatAuthorityReview, ContactSelection, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, HostContactsPick, IdentityDisclosureReview, LoginFailureKind, MainPurseChatPaymentReview, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageFailure, NativeCoinageMemo, NativeCoinageOperation, NativeCoinagePaymentIntent, NativeCoinageRequest, NativeCoinageResponse, NativeCoinageScope, NativeCoinageTopUpOutcome, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PlacedAvatar, PlacedAvatars, PlacedContactLabel, PlacedContactLabels, PreimageSubmitReview, PresentedContactProfile, ProductContext, ProductExecutionKind, ProductSubtreeReview, ProfileDisclosureReview, ResourceAllocationReview, SessionUiInfo, SharedContactProfile, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; var init_host_callbacks = __esm({ "dist/generated/host-callbacks.js"() { "use strict"; @@ -557,7 +557,8 @@ var init_host_callbacks = __esm({ AccountAliasReview = S.lazy(() => S.Struct({ callingProductId: S.str, context: import_truapi3.ProductProofContext, ringLocation: import_truapi3.RingLocation })); AuthState = S.lazy(() => S.TaggedUnion({ Disconnected: S._void, Pairing: S.Struct({ deeplink: S.str }), Connected: SessionUiInfo, LoginFailed: S.Struct({ kind: LoginFailureKind, reason: S.str }), Authenticating: S._void })); ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str })); - CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); + ContactSelection = S.lazy(() => S.Struct({ selected: S.Vector(import_truapi3.Bytes32) })); + CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileDisclosure: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), ProfilePersonalReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); CreateProofReview = S.lazy(() => S.Struct({ callingProductId: S.str, context: import_truapi3.ProductProofContext, ringLocation: import_truapi3.RingLocation, message: S.Bytes() })); CreateTransactionReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), payload: import_truapi3.ProductAccountTxPayload }), LegacyAccount: import_truapi3.LegacyAccountTxPayload })); DevicePermissionStatus = S.lazy(() => S.Status("Granted", "Denied", "NotDetermined", "NotApplicable")); @@ -566,6 +567,7 @@ var init_host_callbacks = __esm({ HostContactLookup = S.lazy(() => S.Struct({ handleKey: import_truapi3.Bytes32, handles: S.Vector(import_truapi3.Bytes32) })); HostContactMatches = S.lazy(() => S.Struct({ accounts: S.Vector(S.Option(import_truapi3.Bytes32)) })); HostContactPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ account: import_truapi3.Bytes32 }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); + HostContactsPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ accounts: S.Vector(import_truapi3.Bytes32) }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); IdentityDisclosureReview = S.lazy(() => S.Struct({ productId: S.str })); LoginFailureKind = S.lazy(() => S.Status("NoFreeAllowanceSlots", "Other")); MainPurseChatPaymentReview = S.lazy(() => S.Struct({ callingProductId: S.str, recipientIdentity: S.Bytes(32), recipientUsername: S.Option(S.str), amountCents: S.u64, maxDebitCents: S.u64, genesisHash: S.Bytes(32), coinageInstanceId: S.Option(S.u32), operationId: S.Bytes(32) })); @@ -580,20 +582,27 @@ var init_host_callbacks = __esm({ NativeCoinageResponse = S.lazy(() => S.TaggedUnion({ Denomination: S.Struct({ centsUnitRaw: S.str }), Prepared: S.Struct({ payment: import_truapi3.HostNativeChatPayment, memo: S.Option(NativeCoinageMemo) }), Payments: S.Struct({ payments: S.Vector(import_truapi3.HostNativeChatPayment) }), TopUp: S.Struct({ outcome: NativeCoinageTopUpOutcome }), Done: S._void, Failed: S.Struct({ reason: NativeCoinageFailure }) })); NativeCoinageScope = S.lazy(() => S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), coinageInstanceId: S.Option(S.u32) })); NativeCoinageTopUpOutcome = S.lazy(() => S.TaggedUnion({ Cleared: S._void, Partial: S.Struct({ creditedAmountRaw: S.str }), Pending: S._void, NotClaimed: S._void })); - PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi3.HostDevicePermissionRequest, Remote: import_truapi3.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(import_truapi3.DerivationIndex) }) })); + PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi3.HostDevicePermissionRequest, Remote: import_truapi3.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(import_truapi3.DerivationIndex) }), ProfileDisclosure: S._void })); PermissionAuthorizationStatus = S.lazy(() => S.Status("NotDetermined", "Denied", "Authorized")); PermissionDecision = S.lazy(() => S.Status("AllowOnce", "AllowAlways", "Deny")); + PlacedAvatar = S.lazy(() => S.Struct({ slot: S.u32, rect: import_truapi3.AvatarRect, clip: import_truapi3.AvatarRect, reference: S.str, sharedAt: S.u64 })); + PlacedAvatars = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, avatars: S.Vector(PlacedAvatar) })); + PlacedContactLabel = S.lazy(() => S.Struct({ slot: S.u32, account: import_truapi3.Bytes32, rect: import_truapi3.AvatarRect, clip: import_truapi3.AvatarRect })); + PlacedContactLabels = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, labels: S.Vector(PlacedContactLabel) })); PreimageSubmitReview = S.lazy(() => S.Struct({ size: S.u64 })); + PresentedContactProfile = S.lazy(() => S.Struct({ shared: S.Option(SharedContactProfile), peerIdentity: S.Bytes(32), username: S.Option(S.str) })); ProductContext = S.lazy(() => S.Struct({ productId: S.str, executionKind: ProductExecutionKind })); ProductExecutionKind = S.lazy(() => S.Status("App", "Widget", "Worker")); ProductSubtreeReview = S.lazy(() => S.Struct({ productId: S.str })); + ProfileDisclosureReview = S.lazy(() => S.Struct({ productId: S.str })); ResourceAllocationReview = S.lazy(() => S.Struct({ callingProductId: S.str, resources: S.Vector(import_truapi3.AllocatableResource) })); SessionUiInfo = S.lazy(() => S.Struct({ publicKey: import_truapi3.Bytes32, identityAccountId: S.Option(import_truapi3.Bytes32), chatPublicKey: S.Option(import_truapi3.Bytes32), deviceEncPublicKey: S.Option(import_truapi3.Bytes32), peerStatementAccountId: S.Option(import_truapi3.Bytes32), deviceStatementAccountId: S.Option(import_truapi3.Bytes32), liteUsername: S.Option(S.str), fullUsername: S.Option(S.str) })); + SharedContactProfile = S.lazy(() => S.Struct({ reference: S.str, sharedAt: S.u64 })); SignPayloadReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), request: import_truapi3.HostSignPayloadRequest }), LegacyAccount: import_truapi3.HostSignPayloadWithLegacyAccountRequest })); SignRawReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), request: import_truapi3.HostSignRawRequest, watermarked: S.bool }), LegacyAccount: S.Struct({ request: import_truapi3.HostSignRawWithLegacyAccountRequest, watermarked: S.bool }) })); SignVrfReview = S.lazy(() => S.Struct({ callingProductId: S.str, request: import_truapi3.HostAccountSignVrfRequest })); StatementStoreProductSignReview = S.lazy(() => S.Struct({ callingProductId: S.Option(S.str), account: import_truapi3.ProductAccountId, payload: S.Bytes() })); - UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview })); + UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview, ProfileDisclosure: ProfileDisclosureReview })); } }); @@ -612,6 +621,16 @@ var init_error = __esm({ }); // dist/adapter-support.js +function contactsHostAdapter(host) { + if (host === void 0) + return void 0; + return { + contacts: (lookup) => host.contacts(lookup), + pickContact: (product) => host.pickContact?.(product) ?? Promise.resolve({ tag: "Unsupported" }), + pickContacts: (product, selection) => host.pickContacts?.(product, selection) ?? Promise.resolve({ tag: "Unsupported" }), + placeContactLabels: (product, placed) => host.placeContactLabels?.(product, placed) ?? Promise.resolve(false) + }; +} function unwrapStreamResult(item) { if ("success" in item) { if (item.success === false) { @@ -696,6 +715,21 @@ function coinageWalletHostAdapter(host) { } }; } +function profileHostAdapter(host) { + if (host === void 0 || typeof host.presentContactProfile === "function") + return host; + return { + presentProfile: (product, request) => host.presentProfile(product, request), + presentContactProfile: (product, presented) => { + if (presented.shared === void 0) + return Promise.reject(new Error("Contact profile feedback is unavailable")); + return host.presentProfile(product, { + reference: presented.shared.reference + }); + }, + placeContactAvatars: (product, placed) => host.placeContactAvatars(product, placed) + }; +} function hopConnectAdapter(host) { return async (genesisHash, endpoint, onResponse, onClosed) => { const genesis = (0, import_scale.hexToBytes)(genesisHash); @@ -801,10 +835,11 @@ __export(host_callbacks_adapter_exports, { function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); - const contacts = callbacks.contacts; + const contacts = contactsHostAdapter(callbacks.contacts); const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const profile = profileHostAdapter(callbacks.profile); const hop = callbacks.hop ?? unavailableHopProvider; const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { @@ -821,7 +856,9 @@ function createWasmRawCallbacks(callbacks) { } : {}, ...contacts ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), - pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))) + pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))), + pickContacts: async (product, selection) => HostContactsPick.enc(await contacts.pickContacts(ProductContext.dec(product), ContactSelection.dec(selection))), + placeContactLabels: async (product, placed) => await contacts.placeContactLabels(ProductContext.dec(product), PlacedContactLabels.dec(placed)) } : {}, readCoreStorage: async (key) => await callbacks.coreStorage.readCoreStorage(CoreStorageKey.dec(key)), writeCoreStorage: async (key, value) => await callbacks.coreStorage.writeCoreStorage(CoreStorageKey.dec(key), value), @@ -861,6 +898,11 @@ function createWasmRawCallbacks(callbacks) { write: async (key, value) => await callbacks.productStorage.write(key, value), clear: async (key) => await callbacks.productStorage.clear(key), subscribeStorage: (key, sendItem, sendError) => driveResultStream(callbacks.productStorage.subscribeStorage(key), (item) => sendItem(import_truapi4.HostLocalStorageChangeItem.enc(item)), sendError), + ...profile ? { + presentProfile: async (product, request) => await profile.presentProfile(ProductContext.dec(product), import_truapi4.HostProfilePresentRequest.dec(request)), + presentContactProfile: async (product, presented) => await profile.presentContactProfile(ProductContext.dec(product), PresentedContactProfile.dec(presented)), + placeContactAvatars: async (product, placed) => await profile.placeContactAvatars(ProductContext.dec(product), PlacedAvatars.dec(placed)) + } : {}, subscribeTheme: (sendItem, sendError) => driveResultStream(callbacks.theme.subscribeTheme(), (item) => sendItem(import_truapi4.HostThemeSubscribeItem.enc(item)), sendError), confirmPermission: async (review) => PermissionDecision.enc(await callbacks.userConfirmation.confirmPermission(UserConfirmationReview.dec(review))), confirmUserAction: async (review) => await callbacks.userConfirmation.confirmUserAction(UserConfirmationReview.dec(review)) diff --git a/vendor/truapi-host/dist/testing/host-page.cjs b/vendor/truapi-host/dist/testing/host-page.cjs index 77b55bf51..21f5bbf3b 100644 --- a/vendor/truapi-host/dist/testing/host-page.cjs +++ b/vendor/truapi-host/dist/testing/host-page.cjs @@ -44,7 +44,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // dist/generated/host-callbacks.js -var S, import_truapi, AccountAccessReview, AccountAliasReview, AuthState, ChatAuthorityReview, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, IdentityDisclosureReview, LoginFailureKind, MainPurseChatPaymentReview, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageFailure, NativeCoinageMemo, NativeCoinageOperation, NativeCoinagePaymentIntent, NativeCoinageRequest, NativeCoinageResponse, NativeCoinageScope, NativeCoinageTopUpOutcome, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PreimageSubmitReview, ProductContext, ProductExecutionKind, ProductSubtreeReview, ResourceAllocationReview, SessionUiInfo, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; +var S, import_truapi, AccountAccessReview, AccountAliasReview, AuthState, ChatAuthorityReview, ContactSelection, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, HostContactsPick, IdentityDisclosureReview, LoginFailureKind, MainPurseChatPaymentReview, NativeChatFileExportRequest, NativeChatFilePickRequest, NativeChatPickedFile, NativeCoinageFailure, NativeCoinageMemo, NativeCoinageOperation, NativeCoinagePaymentIntent, NativeCoinageRequest, NativeCoinageResponse, NativeCoinageScope, NativeCoinageTopUpOutcome, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PlacedAvatar, PlacedAvatars, PlacedContactLabel, PlacedContactLabels, PreimageSubmitReview, PresentedContactProfile, ProductContext, ProductExecutionKind, ProductSubtreeReview, ProfileDisclosureReview, ResourceAllocationReview, SessionUiInfo, SharedContactProfile, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; var init_host_callbacks = __esm({ "dist/generated/host-callbacks.js"() { "use strict"; @@ -54,7 +54,8 @@ var init_host_callbacks = __esm({ AccountAliasReview = S.lazy(() => S.Struct({ callingProductId: S.str, context: import_truapi.ProductProofContext, ringLocation: import_truapi.RingLocation })); AuthState = S.lazy(() => S.TaggedUnion({ Disconnected: S._void, Pairing: S.Struct({ deeplink: S.str }), Connected: SessionUiInfo, LoginFailed: S.Struct({ kind: LoginFailureKind, reason: S.str }), Authenticating: S._void })); ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str })); - CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); + ContactSelection = S.lazy(() => S.Struct({ selected: S.Vector(import_truapi.Bytes32) })); + CoreStorageKey = S.lazy(() => S.TaggedUnion({ AuthSession: S._void, PairingDeviceIdentity: S._void, PermissionAuthorization: S.Struct({ productId: S.str, request: PermissionAuthorizationRequest }), AllowanceKeys: S.Struct({ sessionId: S.str }), LastProcessedPairingStatement: S._void, AutoSigningKey: S.Struct({ productId: S.str }), AutoSigningKeys: S._void, RingVrfRegistry: S.Struct({ rootPublicKey: S.Bytes(32) }), StatementRenewalTargets: S._void, DeviceEncryptionKey: S._void, ProductSubtree: S.Struct({ sessionId: S.str, productId: S.str }), SsoResponderRequestLedger: S.Struct({ rootPublicKey: S.Bytes(32), peerStatementAccountId: S.Bytes(32), peerEncryptionPublicKey: S.Bytes(32) }), ProductManifest: S.Struct({ productId: S.str }), MainPurseCoinage: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), NativeChatDevice: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), NativeChatFileChunk: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str, attachmentId: S.Bytes(32), chunkIndex: S.u32 }), NativeChatProducts: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileDisclosure: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }), ProfileReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), productId: S.str }), ProfilePersonalReferencesReceived: S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32) }) })); CreateProofReview = S.lazy(() => S.Struct({ callingProductId: S.str, context: import_truapi.ProductProofContext, ringLocation: import_truapi.RingLocation, message: S.Bytes() })); CreateTransactionReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), payload: import_truapi.ProductAccountTxPayload }), LegacyAccount: import_truapi.LegacyAccountTxPayload })); DevicePermissionStatus = S.lazy(() => S.Status("Granted", "Denied", "NotDetermined", "NotApplicable")); @@ -63,6 +64,7 @@ var init_host_callbacks = __esm({ HostContactLookup = S.lazy(() => S.Struct({ handleKey: import_truapi.Bytes32, handles: S.Vector(import_truapi.Bytes32) })); HostContactMatches = S.lazy(() => S.Struct({ accounts: S.Vector(S.Option(import_truapi.Bytes32)) })); HostContactPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ account: import_truapi.Bytes32 }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); + HostContactsPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ accounts: S.Vector(import_truapi.Bytes32) }), Dismissed: S._void, NoContacts: S._void, Unsupported: S._void })); IdentityDisclosureReview = S.lazy(() => S.Struct({ productId: S.str })); LoginFailureKind = S.lazy(() => S.Status("NoFreeAllowanceSlots", "Other")); MainPurseChatPaymentReview = S.lazy(() => S.Struct({ callingProductId: S.str, recipientIdentity: S.Bytes(32), recipientUsername: S.Option(S.str), amountCents: S.u64, maxDebitCents: S.u64, genesisHash: S.Bytes(32), coinageInstanceId: S.Option(S.u32), operationId: S.Bytes(32) })); @@ -77,20 +79,27 @@ var init_host_callbacks = __esm({ NativeCoinageResponse = S.lazy(() => S.TaggedUnion({ Denomination: S.Struct({ centsUnitRaw: S.str }), Prepared: S.Struct({ payment: import_truapi.HostNativeChatPayment, memo: S.Option(NativeCoinageMemo) }), Payments: S.Struct({ payments: S.Vector(import_truapi.HostNativeChatPayment) }), TopUp: S.Struct({ outcome: NativeCoinageTopUpOutcome }), Done: S._void, Failed: S.Struct({ reason: NativeCoinageFailure }) })); NativeCoinageScope = S.lazy(() => S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), coinageInstanceId: S.Option(S.u32) })); NativeCoinageTopUpOutcome = S.lazy(() => S.TaggedUnion({ Cleared: S._void, Partial: S.Struct({ creditedAmountRaw: S.str }), Pending: S._void, NotClaimed: S._void })); - PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi.HostDevicePermissionRequest, Remote: import_truapi.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(import_truapi.DerivationIndex) }) })); + PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi.HostDevicePermissionRequest, Remote: import_truapi.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }), ChatAuthority: S._void, StatementStoreAllowance: S.Struct({ derivationIndex: S.Option(import_truapi.DerivationIndex) }), ProfileDisclosure: S._void })); PermissionAuthorizationStatus = S.lazy(() => S.Status("NotDetermined", "Denied", "Authorized")); PermissionDecision = S.lazy(() => S.Status("AllowOnce", "AllowAlways", "Deny")); + PlacedAvatar = S.lazy(() => S.Struct({ slot: S.u32, rect: import_truapi.AvatarRect, clip: import_truapi.AvatarRect, reference: S.str, sharedAt: S.u64 })); + PlacedAvatars = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, avatars: S.Vector(PlacedAvatar) })); + PlacedContactLabel = S.lazy(() => S.Struct({ slot: S.u32, account: import_truapi.Bytes32, rect: import_truapi.AvatarRect, clip: import_truapi.AvatarRect })); + PlacedContactLabels = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, labels: S.Vector(PlacedContactLabel) })); PreimageSubmitReview = S.lazy(() => S.Struct({ size: S.u64 })); + PresentedContactProfile = S.lazy(() => S.Struct({ shared: S.Option(SharedContactProfile), peerIdentity: S.Bytes(32), username: S.Option(S.str) })); ProductContext = S.lazy(() => S.Struct({ productId: S.str, executionKind: ProductExecutionKind })); ProductExecutionKind = S.lazy(() => S.Status("App", "Widget", "Worker")); ProductSubtreeReview = S.lazy(() => S.Struct({ productId: S.str })); + ProfileDisclosureReview = S.lazy(() => S.Struct({ productId: S.str })); ResourceAllocationReview = S.lazy(() => S.Struct({ callingProductId: S.str, resources: S.Vector(import_truapi.AllocatableResource) })); SessionUiInfo = S.lazy(() => S.Struct({ publicKey: import_truapi.Bytes32, identityAccountId: S.Option(import_truapi.Bytes32), chatPublicKey: S.Option(import_truapi.Bytes32), deviceEncPublicKey: S.Option(import_truapi.Bytes32), peerStatementAccountId: S.Option(import_truapi.Bytes32), deviceStatementAccountId: S.Option(import_truapi.Bytes32), liteUsername: S.Option(S.str), fullUsername: S.Option(S.str) })); + SharedContactProfile = S.lazy(() => S.Struct({ reference: S.str, sharedAt: S.u64 })); SignPayloadReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), request: import_truapi.HostSignPayloadRequest }), LegacyAccount: import_truapi.HostSignPayloadWithLegacyAccountRequest })); SignRawReview = S.lazy(() => S.TaggedUnion({ Product: S.Struct({ callingProductId: S.Option(S.str), request: import_truapi.HostSignRawRequest, watermarked: S.bool }), LegacyAccount: S.Struct({ request: import_truapi.HostSignRawWithLegacyAccountRequest, watermarked: S.bool }) })); SignVrfReview = S.lazy(() => S.Struct({ callingProductId: S.str, request: import_truapi.HostAccountSignVrfRequest })); StatementStoreProductSignReview = S.lazy(() => S.Struct({ callingProductId: S.Option(S.str), account: import_truapi.ProductAccountId, payload: S.Bytes() })); - UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview })); + UserConfirmationReview = S.lazy(() => S.TaggedUnion({ SignPayload: SignPayloadReview, SignRaw: SignRawReview, StatementStoreProductSign: StatementStoreProductSignReview, CreateTransaction: CreateTransactionReview, AccountAlias: AccountAliasReview, CreateProof: CreateProofReview, IdentityDisclosure: IdentityDisclosureReview, ResourceAllocation: ResourceAllocationReview, PreimageSubmit: PreimageSubmitReview, AccountAccess: AccountAccessReview, SignVrf: SignVrfReview, ProductSubtree: ProductSubtreeReview, ChatAuthority: ChatAuthorityReview, MainPurseChatPayment: MainPurseChatPaymentReview, ProfileDisclosure: ProfileDisclosureReview })); } }); @@ -112,6 +121,16 @@ var init_error = __esm({ }); // dist/adapter-support.js +function contactsHostAdapter(host) { + if (host === void 0) + return void 0; + return { + contacts: (lookup) => host.contacts(lookup), + pickContact: (product) => host.pickContact?.(product) ?? Promise.resolve({ tag: "Unsupported" }), + pickContacts: (product, selection) => host.pickContacts?.(product, selection) ?? Promise.resolve({ tag: "Unsupported" }), + placeContactLabels: (product, placed) => host.placeContactLabels?.(product, placed) ?? Promise.resolve(false) + }; +} function unwrapStreamResult(item) { if ("success" in item) { if (item.success === false) { @@ -196,6 +215,21 @@ function coinageWalletHostAdapter(host) { } }; } +function profileHostAdapter(host) { + if (host === void 0 || typeof host.presentContactProfile === "function") + return host; + return { + presentProfile: (product, request) => host.presentProfile(product, request), + presentContactProfile: (product, presented) => { + if (presented.shared === void 0) + return Promise.reject(new Error("Contact profile feedback is unavailable")); + return host.presentProfile(product, { + reference: presented.shared.reference + }); + }, + placeContactAvatars: (product, placed) => host.placeContactAvatars(product, placed) + }; +} function hopConnectAdapter(host) { return async (genesisHash, endpoint, onResponse, onClosed) => { const genesis = (0, import_scale.hexToBytes)(genesisHash); @@ -301,10 +335,11 @@ __export(host_callbacks_adapter_exports, { function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); - const contacts = callbacks.contacts; + const contacts = contactsHostAdapter(callbacks.contacts); const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const profile = profileHostAdapter(callbacks.profile); const hop = callbacks.hop ?? unavailableHopProvider; const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { @@ -321,7 +356,9 @@ function createWasmRawCallbacks(callbacks) { } : {}, ...contacts ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), - pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))) + pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))), + pickContacts: async (product, selection) => HostContactsPick.enc(await contacts.pickContacts(ProductContext.dec(product), ContactSelection.dec(selection))), + placeContactLabels: async (product, placed) => await contacts.placeContactLabels(ProductContext.dec(product), PlacedContactLabels.dec(placed)) } : {}, readCoreStorage: async (key) => await callbacks.coreStorage.readCoreStorage(CoreStorageKey.dec(key)), writeCoreStorage: async (key, value) => await callbacks.coreStorage.writeCoreStorage(CoreStorageKey.dec(key), value), @@ -361,6 +398,11 @@ function createWasmRawCallbacks(callbacks) { write: async (key, value) => await callbacks.productStorage.write(key, value), clear: async (key) => await callbacks.productStorage.clear(key), subscribeStorage: (key, sendItem, sendError) => driveResultStream(callbacks.productStorage.subscribeStorage(key), (item) => sendItem(import_truapi2.HostLocalStorageChangeItem.enc(item)), sendError), + ...profile ? { + presentProfile: async (product, request) => await profile.presentProfile(ProductContext.dec(product), import_truapi2.HostProfilePresentRequest.dec(request)), + presentContactProfile: async (product, presented) => await profile.presentContactProfile(ProductContext.dec(product), PresentedContactProfile.dec(presented)), + placeContactAvatars: async (product, placed) => await profile.placeContactAvatars(ProductContext.dec(product), PlacedAvatars.dec(placed)) + } : {}, subscribeTheme: (sendItem, sendError) => driveResultStream(callbacks.theme.subscribeTheme(), (item) => sendItem(import_truapi2.HostThemeSubscribeItem.enc(item)), sendError), confirmPermission: async (review) => PermissionDecision.enc(await callbacks.userConfirmation.confirmPermission(UserConfirmationReview.dec(review))), confirmUserAction: async (review) => await callbacks.userConfirmation.confirmUserAction(UserConfirmationReview.dec(review)) @@ -2654,6 +2696,7 @@ function createWebWorkerHostRuntime(worker, host, options) { chat: host.chat !== void 0, permissionStatus: host.permissionStatus !== void 0, pocket: host.pocket !== void 0, + profile: host.profile !== void 0, identityBackend: host.identityBackend !== void 0, coinageWallet: callbacks.nativeCoinage !== void 0, contacts: host.contacts !== void 0 @@ -2763,6 +2806,7 @@ function buildRuntime(state) { contacts: callbacks.contacts !== void 0, permissionStatus: callbacks.permissionStatus !== void 0, pocket: callbacks.pocket !== void 0, + profile: callbacks.profile !== void 0, identityBackend: callbacks.identityBackend !== void 0, coinageWallet: state.rawCallbacks.nativeCoinage !== void 0 } diff --git a/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts b/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts index 702732591..a06e7faa0 100644 --- a/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts +++ b/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts @@ -467,12 +467,12 @@ export interface InitOutput { readonly wasmsigninghostruntime_setPermissionAuthorizationStatus: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number; readonly wasmsigninghostruntime_setWithheldResources: (a: number, b: number, c: number) => void; readonly wireSchemaHash: (a: number) => void; - readonly __wasm_bindgen_func_elem_9530: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_9588: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_4412: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_4405: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_9411: (a: number, b: number) => void; - readonly __wasm_bindgen_func_elem_4409: (a: number, b: number) => void; + readonly __wasm_bindgen_func_elem_9895: (a: number, b: number, c: number, d: number) => void; + readonly __wasm_bindgen_func_elem_9953: (a: number, b: number, c: number, d: number) => void; + readonly __wasm_bindgen_func_elem_4599: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_4592: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_9776: (a: number, b: number) => void; + readonly __wasm_bindgen_func_elem_4596: (a: number, b: number) => void; readonly __wbindgen_export: (a: number, b: number) => number; readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_export3: (a: number) => void; diff --git a/vendor/truapi-host/dist/wasm/testing/truapi_server.js b/vendor/truapi-host/dist/wasm/testing/truapi_server.js index bab57384d..7fbf465ce 100644 --- a/vendor/truapi-host/dist/wasm/testing/truapi_server.js +++ b/vendor/truapi-host/dist/wasm/testing/truapi_server.js @@ -1260,7 +1260,7 @@ function __wbg_get_imports() { const a = state0.a; state0.a = 0; try { - return __wasm_bindgen_func_elem_9588(a, state0.b, arg0, arg1); + return __wasm_bindgen_func_elem_9953(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -1397,28 +1397,28 @@ function __wbg_get_imports() { console.warn(getObject(arg0)); }, __wbindgen_cast_0000000000000001: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 377, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9530); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 379, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9895); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 96, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_4412); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 98, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_4599); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 164, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9411); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 165, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9776); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 92, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4405); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 94, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. + const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4592); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 94, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4409); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 96, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. + const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4596); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0) { @@ -1462,22 +1462,22 @@ function __wbg_get_imports() { }; } -function __wasm_bindgen_func_elem_9411(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_9411(arg0, arg1); +function __wasm_bindgen_func_elem_9776(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_9776(arg0, arg1); } -function __wasm_bindgen_func_elem_4409(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_4409(arg0, arg1); +function __wasm_bindgen_func_elem_4596(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_4596(arg0, arg1); } -function __wasm_bindgen_func_elem_4412(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_4412(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_4599(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_4599(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_4405(arg0, arg1) { +function __wasm_bindgen_func_elem_4592(arg0, arg1) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_4405(retptr, arg0, arg1); + wasm.__wasm_bindgen_func_elem_4592(retptr, arg0, arg1); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1488,10 +1488,10 @@ function __wasm_bindgen_func_elem_4405(arg0, arg1) { } } -function __wasm_bindgen_func_elem_9530(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_9895(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_9530(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_9895(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1502,8 +1502,8 @@ function __wasm_bindgen_func_elem_9530(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_9588(arg0, arg1, arg2, arg3) { - wasm.__wasm_bindgen_func_elem_9588(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +function __wasm_bindgen_func_elem_9953(arg0, arg1, arg2, arg3) { + wasm.__wasm_bindgen_func_elem_9953(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); } const WasmPairingHostRuntimeFinalization = (typeof FinalizationRegistry === 'undefined') diff --git a/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm b/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm index 9d226571c..ec063458a 100644 Binary files a/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm and b/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm differ diff --git a/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm.d.ts b/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm.d.ts index 101de6001..e0afc7fe4 100644 --- a/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm.d.ts +++ b/vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm.d.ts @@ -68,12 +68,12 @@ export const wasmsigninghostruntime_setGrantAllowancesUnchecked: (a: number, b: export const wasmsigninghostruntime_setPermissionAuthorizationStatus: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number; export const wasmsigninghostruntime_setWithheldResources: (a: number, b: number, c: number) => void; export const wireSchemaHash: (a: number) => void; -export const __wasm_bindgen_func_elem_9530: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_9588: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_4412: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_4405: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_9411: (a: number, b: number) => void; -export const __wasm_bindgen_func_elem_4409: (a: number, b: number) => void; +export const __wasm_bindgen_func_elem_9895: (a: number, b: number, c: number, d: number) => void; +export const __wasm_bindgen_func_elem_9953: (a: number, b: number, c: number, d: number) => void; +export const __wasm_bindgen_func_elem_4599: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_4592: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_9776: (a: number, b: number) => void; +export const __wasm_bindgen_func_elem_4596: (a: number, b: number) => void; export const __wbindgen_export: (a: number, b: number) => number; export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_export3: (a: number) => void; diff --git a/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts b/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts index 93261ead2..cd76e604f 100644 --- a/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts +++ b/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts @@ -437,12 +437,12 @@ export interface InitOutput { readonly wasmsigninghostruntime_sessionChatIdentityKey: (a: number, b: number) => void; readonly wasmsigninghostruntime_setPermissionAuthorizationStatus: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number; readonly wireSchemaHash: (a: number) => void; - readonly __wasm_bindgen_func_elem_9506: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_9564: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_4340: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_4333: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_9387: (a: number, b: number) => void; - readonly __wasm_bindgen_func_elem_4337: (a: number, b: number) => void; + readonly __wasm_bindgen_func_elem_9871: (a: number, b: number, c: number, d: number) => void; + readonly __wasm_bindgen_func_elem_9929: (a: number, b: number, c: number, d: number) => void; + readonly __wasm_bindgen_func_elem_4527: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_4520: (a: number, b: number, c: number) => void; + readonly __wasm_bindgen_func_elem_9752: (a: number, b: number) => void; + readonly __wasm_bindgen_func_elem_4524: (a: number, b: number) => void; readonly __wbindgen_export: (a: number, b: number) => number; readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_export3: (a: number) => void; diff --git a/vendor/truapi-host/dist/wasm/web/truapi_server.js b/vendor/truapi-host/dist/wasm/web/truapi_server.js index 66ea9e24d..72fb85677 100644 --- a/vendor/truapi-host/dist/wasm/web/truapi_server.js +++ b/vendor/truapi-host/dist/wasm/web/truapi_server.js @@ -1218,7 +1218,7 @@ function __wbg_get_imports() { const a = state0.a; state0.a = 0; try { - return __wasm_bindgen_func_elem_9564(a, state0.b, arg0, arg1); + return __wasm_bindgen_func_elem_9929(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -1355,28 +1355,28 @@ function __wbg_get_imports() { console.warn(getObject(arg0)); }, __wbindgen_cast_0000000000000001: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 376, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9506); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 378, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9871); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 96, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_4340); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 98, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_4527); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 164, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9387); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 165, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_9752); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 92, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4333); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 94, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. + const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4520); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 94, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4337); + // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 96, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. + const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_4524); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0) { @@ -1420,22 +1420,22 @@ function __wbg_get_imports() { }; } -function __wasm_bindgen_func_elem_9387(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_9387(arg0, arg1); +function __wasm_bindgen_func_elem_9752(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_9752(arg0, arg1); } -function __wasm_bindgen_func_elem_4337(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_4337(arg0, arg1); +function __wasm_bindgen_func_elem_4524(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_4524(arg0, arg1); } -function __wasm_bindgen_func_elem_4340(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_4340(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_4527(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_4527(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_4333(arg0, arg1) { +function __wasm_bindgen_func_elem_4520(arg0, arg1) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_4333(retptr, arg0, arg1); + wasm.__wasm_bindgen_func_elem_4520(retptr, arg0, arg1); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1446,10 +1446,10 @@ function __wasm_bindgen_func_elem_4333(arg0, arg1) { } } -function __wasm_bindgen_func_elem_9506(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_9871(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_9506(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_9871(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1460,8 +1460,8 @@ function __wasm_bindgen_func_elem_9506(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_9564(arg0, arg1, arg2, arg3) { - wasm.__wasm_bindgen_func_elem_9564(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +function __wasm_bindgen_func_elem_9929(arg0, arg1, arg2, arg3) { + wasm.__wasm_bindgen_func_elem_9929(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); } const WasmPairingHostRuntimeFinalization = (typeof FinalizationRegistry === 'undefined') diff --git a/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm b/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm index 2ee5cb137..18bc739ac 100644 Binary files a/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm and b/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm differ diff --git a/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.d.ts b/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.d.ts index 8e036c588..534eba94c 100644 --- a/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.d.ts +++ b/vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.d.ts @@ -65,12 +65,12 @@ export const wasmsigninghostruntime_releaseWorker: (a: number, b: number, c: num export const wasmsigninghostruntime_sessionChatIdentityKey: (a: number, b: number) => void; export const wasmsigninghostruntime_setPermissionAuthorizationStatus: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => number; export const wireSchemaHash: (a: number) => void; -export const __wasm_bindgen_func_elem_9506: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_9564: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_4340: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_4333: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_9387: (a: number, b: number) => void; -export const __wasm_bindgen_func_elem_4337: (a: number, b: number) => void; +export const __wasm_bindgen_func_elem_9871: (a: number, b: number, c: number, d: number) => void; +export const __wasm_bindgen_func_elem_9929: (a: number, b: number, c: number, d: number) => void; +export const __wasm_bindgen_func_elem_4527: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_4520: (a: number, b: number, c: number) => void; +export const __wasm_bindgen_func_elem_9752: (a: number, b: number) => void; +export const __wasm_bindgen_func_elem_4524: (a: number, b: number) => void; export const __wbindgen_export: (a: number, b: number) => number; export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_export3: (a: number) => void; diff --git a/vendor/truapi-host/dist/web/create-worker-host-runtime.js b/vendor/truapi-host/dist/web/create-worker-host-runtime.js index 0b1a2534f..faa5506d3 100644 --- a/vendor/truapi-host/dist/web/create-worker-host-runtime.js +++ b/vendor/truapi-host/dist/web/create-worker-host-runtime.js @@ -1062,6 +1062,7 @@ function createWebWorkerHostRuntime(worker, host, options) { chat: host.chat !== undefined, permissionStatus: host.permissionStatus !== undefined, pocket: host.pocket !== undefined, + profile: host.profile !== undefined, identityBackend: host.identityBackend !== undefined, coinageWallet: callbacks.nativeCoinage !== undefined, contacts: host.contacts !== undefined, @@ -1179,6 +1180,7 @@ function buildRuntime(state) { contacts: callbacks.contacts !== undefined, permissionStatus: callbacks.permissionStatus !== undefined, pocket: callbacks.pocket !== undefined, + profile: callbacks.profile !== undefined, identityBackend: callbacks.identityBackend !== undefined, coinageWallet: state.rawCallbacks.nativeCoinage !== undefined, }, diff --git a/vendor/truapi/dist/explorer/codegen/types.js b/vendor/truapi/dist/explorer/codegen/types.js index 9de73d4e6..4f6293287 100644 --- a/vendor/truapi/dist/explorer/codegen/types.js +++ b/vendor/truapi/dist/explorer/codegen/types.js @@ -120,6 +120,35 @@ export const types = [ }, ], }, + { + id: "avatar-rect", + name: "AvatarRect", + category: "profile", + definition: "export interface AvatarRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}", + description: "A rectangle in surface units, relative to the surface's top-left corner.", + fields: [ + { + name: "x", + type: "number", + description: "Left edge.", + }, + { + name: "y", + type: "number", + description: "Top edge.", + }, + { + name: "width", + type: "number", + description: "Width.", + }, + { + name: "height", + type: "number", + description: "Height.", + }, + ], + }, { id: "background", name: "Background", @@ -927,6 +956,35 @@ export const types = [ }, ], }, + { + id: "contact-avatar-slot", + name: "ContactAvatarSlot", + category: "profile", + definition: "export interface ContactAvatarSlot {\n slot: number;\n peerIdentity: HexString;\n rect: AvatarRect;\n clip: AvatarRect;\n}", + description: "One avatar the product draws for a chat contact.", + fields: [ + { + name: "slot", + type: "number", + description: "Product-chosen id, stable for one on-screen avatar (a list row, a\nheader). The host uses it only to keep what it draws stable across\nupdates.", + }, + { + name: "peer_identity", + type: "HexString", + description: "The contact's authenticated root identity, as the chat API names it.", + }, + { + name: "rect", + type: "AvatarRect", + description: "Bounding box of the avatar circle: square, 1 to 1024 units a side.", + }, + { + name: "clip", + type: "AvatarRect", + description: "Visible region the avatar is cut to, such as the scroll area.", + }, + ], + }, { id: "contact-handle", name: "ContactHandle", @@ -941,6 +999,59 @@ export const types = [ }, ], }, + { + id: "contact-label-slot", + name: "ContactLabelSlot", + category: "contacts", + definition: "export interface ContactLabelSlot {\n slot: number;\n handle: ContactHandle;\n rect: AvatarRect;\n clip: AvatarRect;\n}", + description: "Geometry for a host-owned contact name, independent of profile sharing.", + fields: [ + { + name: "slot", + type: "number", + description: "Product-chosen id, unique within this placement.", + }, + { + name: "handle", + type: "ContactHandle", + description: "Opaque handle for the contact whose name the host draws.", + }, + { + name: "rect", + type: "AvatarRect", + description: "Name bounds in surface units, with sides from 1 to 16384.", + }, + { + name: "clip", + type: "AvatarRect", + description: "Visible region in surface units; a zero side hides the label.", + }, + ], + }, + { + id: "contact-pick-many-outcome", + name: "ContactPickManyOutcome", + category: "contacts", + definition: 'export type ContactPickManyOutcome =\n | { tag: "Picked"; value: { handles: Array } }\n | { tag: "Dismissed"; value?: undefined }\n | { tag: "NoContacts"; value?: undefined }\n;', + description: "Selection confirmed in the host's multi-contact picker.", + variants: [ + { + name: "Picked", + type: '{ tag: "Picked"; value: { handles: Array } }', + description: "The user confirmed this complete selection, including an empty one.", + }, + { + name: "Dismissed", + type: '{ tag: "Dismissed"; value?: undefined }', + description: "The user closed the picker without confirming a change.", + }, + { + name: "NoContacts", + type: '{ tag: "NoContacts"; value?: undefined }', + description: "There are no contacts to show.", + }, + ], + }, { id: "contact-pick-outcome", name: "ContactPickOutcome", @@ -2034,6 +2145,58 @@ export const types = [ }, ], }, + { + id: "host-contacts-pick-many-error", + name: "HostContactsPickManyError", + category: "contacts", + definition: 'export type HostContactsPickManyError =\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "InvalidSelection"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Failure before a complete selection can be confirmed.", + variants: [ + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No active session, or the session changed while choosing.", + }, + { + name: "InvalidSelection", + type: '{ tag: "InvalidSelection"; value?: undefined }', + description: "The selection exceeds the bound or contains an unresolved handle.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "The host could not complete the picker.", + }, + ], + }, + { + id: "host-contacts-pick-many-request", + name: "HostContactsPickManyRequest", + category: "contacts", + definition: "export interface HostContactsPickManyRequest {\n selected: Array;\n}", + description: "Open the host's picker with the product's current selection.", + fields: [ + { + name: "selected", + type: "Array", + description: "At most 256 handles. Duplicates are ignored; an unresolved handle\nrejects the entire request rather than changing the selected audience.", + }, + ], + }, + { + id: "host-contacts-pick-many-response", + name: "HostContactsPickManyResponse", + category: "contacts", + definition: "export interface HostContactsPickManyResponse {\n outcome: ContactPickManyOutcome;\n}", + description: "The user's confirmed selection or reason no selection was made.", + fields: [ + { + name: "outcome", + type: "ContactPickManyOutcome", + description: "How the picker ended.", + }, + ], + }, { id: "host-contacts-pick-request", name: "HostContactsPickRequest", @@ -2056,6 +2219,67 @@ export const types = [ }, ], }, + { + id: "host-contacts-place-labels-error", + name: "HostContactsPlaceLabelsError", + category: "contacts", + definition: 'export type HostContactsPlaceLabelsError =\n | { tag: "Unsupported"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "InvalidPlacement"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Placement failure, never the availability of any individual contact.", + variants: [ + { + name: "Unsupported", + type: '{ tag: "Unsupported"; value?: undefined }', + description: "The host cannot draw labels over the product surface.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No active session, or it changed while placing labels.", + }, + { + name: "InvalidPlacement", + type: '{ tag: "InvalidPlacement"; value?: undefined }', + description: "The surface, slot count, slot ids or rectangles are invalid.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "The host could not place the labels.", + }, + ], + }, + { + id: "host-contacts-place-labels-request", + name: "HostContactsPlaceLabelsRequest", + category: "contacts", + definition: "export interface HostContactsPlaceLabelsRequest {\n surfaceWidth: number;\n surfaceHeight: number;\n slots: Array;\n}", + description: "Replace the contact names drawn over a product's surface.", + fields: [ + { + name: "surface_width", + type: "number", + description: "Surface width in framebuffer pixels or web viewport CSS pixels, 1 to 16384.", + }, + { + name: "surface_height", + type: "number", + description: "Surface height in the same units, 1 to 16384.", + }, + { + name: "slots", + type: "Array", + description: "At most 256 slots. Empty clears the previous placement.", + }, + ], + }, + { + id: "host-contacts-place-labels-response", + name: "HostContactsPlaceLabelsResponse", + category: "contacts", + definition: "export interface HostContactsPlaceLabelsResponse {\n}", + description: "Acknowledges placement without revealing any contact's name or availability.", + fields: [], + }, { id: "host-create-transaction-error", name: "HostCreateTransactionError", @@ -3840,6 +4064,269 @@ export const types = [ }, ], }, + { + id: "host-profile-disclose-error", + name: "HostProfileDiscloseError", + category: "profile", + definition: 'export type HostProfileDiscloseError =\n | { tag: "InvalidReference"; value?: undefined }\n | { tag: "PermissionDenied"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Profile disclosure failure.", + variants: [ + { + name: "InvalidReference", + type: '{ tag: "InvalidReference"; value?: undefined }', + description: "The reference is empty, too long, or not printable ASCII.", + }, + { + name: "PermissionDenied", + type: '{ tag: "PermissionDenied"; value?: undefined }', + description: "The user declined to let this product disclose a profile to their\nchat contacts.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in, so there are no contacts to disclose to.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, + { + id: "host-profile-disclose-request", + name: "HostProfileDiscloseRequest", + category: "profile", + definition: "export interface HostProfileDiscloseRequest {\n reference: string;\n audiences: Array;\n}", + description: "Replace the user's disclosed reference and its complete set of audiences.\n\nAn empty audience retains the user's own profile but withdraws all delivery\ngrants. A contact handle that no longer resolves rejects the whole request.", + fields: [ + { + name: "reference", + type: "string", + description: "Opaque bearer reference, retained and relayed only by the host.", + }, + { + name: "audiences", + type: "Array", + description: "Independent grants for this reference, at most 64.", + }, + ], + }, + { + id: "host-profile-own-status-error", + name: "HostProfileOwnStatusError", + category: "profile", + definition: 'export type HostProfileOwnStatusError =\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Failure while querying the signed-in user's profile status.", + variants: [ + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, + { + id: "host-profile-own-status-response", + name: "HostProfileOwnStatusResponse", + category: "profile", + definition: "export interface HostProfileOwnStatusResponse {\n configured: boolean;\n}", + description: "Whether the signed-in user currently has a profile disclosed through the\nhost. The reference itself never crosses into the product.", + fields: [ + { + name: "configured", + type: "boolean", + description: "`true` when the host holds a current own-profile reference.", + }, + ], + }, + { + id: "host-profile-place-contact-avatars-error", + name: "HostProfilePlaceContactAvatarsError", + category: "profile", + definition: 'export type HostProfilePlaceContactAvatarsError =\n | { tag: "Unsupported"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Contact avatar placement failure. Says nothing about any one slot.", + variants: [ + { + name: "Unsupported", + type: '{ tag: "Unsupported"; value?: undefined }', + description: "This host cannot draw over the product's surface.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all, including a malformed placement.", + }, + ], + }, + { + id: "host-profile-place-contact-avatars-request", + name: "HostProfilePlaceContactAvatarsRequest", + category: "profile", + definition: "export interface HostProfilePlaceContactAvatarsRequest {\n surfaceWidth: number;\n surfaceHeight: number;\n own?: OwnAvatarSlot;\n slots: Array;\n}", + description: "A host-rendered avatar placement using peer identities or opaque handles.", + fields: [ + { + name: "surface_width", + type: "number", + description: "Width of the drawing surface, from 1 to 16384 units.", + }, + { + name: "surface_height", + type: "number", + description: "Height of the drawing surface, from 1 to 16384 units.", + }, + { + name: "own", + type: "OwnAvatarSlot | undefined", + description: "Optional slot for the signed-in user's own disclosed profile.", + }, + { + name: "slots", + type: "Array", + description: "Complete replacement of the contact slots, at most 64.", + }, + ], + }, + { + id: "host-profile-present-contact-error", + name: "HostProfilePresentContactError", + category: "profile", + definition: 'export type HostProfilePresentContactError =\n | { tag: "NotShared"; value?: undefined }\n | { tag: "InvalidReference"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Contact profile presentation failure.", + variants: [ + { + name: "NotShared", + type: '{ tag: "NotShared"; value?: undefined }', + description: "This contact has not shared a profile with the user.", + }, + { + name: "InvalidReference", + type: '{ tag: "InvalidReference"; value?: undefined }', + description: "The host holds a reference it cannot parse.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, + { + id: "host-profile-present-contact-request", + name: "HostProfilePresentContactRequest", + category: "profile", + definition: "export interface HostProfilePresentContactRequest {\n contact: ProfileContact;\n}", + description: "Ask the host to present a contact's available profile.\n\nUnknown handles, absent profiles and presentation failures return success,\nwithout disclosing whether the contact shares a profile.", + fields: [ + { + name: "contact", + type: "ProfileContact", + description: "The contact whose profile the host may present.", + }, + ], + }, + { + id: "host-profile-present-error", + name: "HostProfilePresentError", + category: "profile", + definition: 'export type HostProfilePresentError =\n | { tag: "InvalidReference"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Profile presentation failure.", + variants: [ + { + name: "InvalidReference", + type: '{ tag: "InvalidReference"; value?: undefined }', + description: "The reference is malformed or names a format this host cannot open.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, + { + id: "host-profile-present-own-error", + name: "HostProfilePresentOwnError", + category: "profile", + definition: 'export type HostProfilePresentOwnError =\n | { tag: "NotConfigured"; value?: undefined }\n | { tag: "InvalidReference"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Failure while presenting the signed-in user's profile.", + variants: [ + { + name: "NotConfigured", + type: '{ tag: "NotConfigured"; value?: undefined }', + description: "The signed-in user has not configured a profile.", + }, + { + name: "InvalidReference", + type: '{ tag: "InvalidReference"; value?: undefined }', + description: "The host holds a reference it cannot parse.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, + { + id: "host-profile-present-request", + name: "HostProfilePresentRequest", + category: "profile", + definition: "export interface HostProfilePresentRequest {\n reference: string;\n}", + description: "Request to show a profile the calling product references in host-owned UI.\n\nThe reference is a bearer capability: whoever holds it can read the profile\nit names. The host resolves and renders it itself, so profile bytes, the\navatar image included, never reach the product.", + fields: [ + { + name: "reference", + type: "string", + description: "Opaque profile reference, e.g. a Seity `#` blob reference.", + }, + ], + }, + { + id: "host-profile-retract-error", + name: "HostProfileRetractError", + category: "profile", + definition: 'export type HostProfileRetractError =\n | { tag: "NotDiscloser"; value?: undefined }\n | { tag: "NotConnected"; value?: undefined }\n | { tag: "Unknown"; value: { reason: string } }\n;', + description: "Profile retraction failure.", + variants: [ + { + name: "NotDiscloser", + type: '{ tag: "NotDiscloser"; value?: undefined }', + description: "Another product disclosed the reference the host holds.", + }, + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "No user is signed in.", + }, + { + name: "Unknown", + type: '{ tag: "Unknown"; value: { reason: string } }', + description: "Catch-all.", + }, + ], + }, { id: "host-push-notification-cancel-request", name: "HostPushNotificationCancelRequest", @@ -4516,6 +5003,30 @@ export const types = [ }, ], }, + { + id: "own-avatar-slot", + name: "OwnAvatarSlot", + category: "profile", + definition: "export interface OwnAvatarSlot {\n slot: number;\n rect: AvatarRect;\n clip: AvatarRect;\n}", + description: "Where the product draws the signed-in user's own avatar.", + fields: [ + { + name: "slot", + type: "number", + description: "Product-chosen id, unique within this placement.", + }, + { + name: "rect", + type: "AvatarRect", + description: "Bounding box of the avatar circle: square, 1 to 1024 units a side.", + }, + { + name: "clip", + type: "AvatarRect", + description: "Visible region the avatar is cut to.", + }, + ], + }, { id: "payment-top-up-source", name: "PaymentTopUpSource", @@ -4683,6 +5194,49 @@ export const types = [ }, ], }, + { + id: "profile-audience", + name: "ProfileAudience", + category: "profile", + definition: 'export type ProfileAudience =\n | { tag: "ChatApps"; value?: undefined }\n | { tag: "App"; value: { productId: string } }\n | { tag: "Contacts"; value: { handles: Array } }\n;', + description: "Recipients of one profile reference. Multiple audiences form a union.", + variants: [ + { + name: "ChatApps", + type: '{ tag: "ChatApps"; value?: undefined }', + description: "Every ready Chat App, with profiles scoped to that App.", + }, + { + name: "App", + type: '{ tag: "App"; value: { productId: string } }', + description: "Contacts of this Chat App, with profiles scoped to that App.", + }, + { + name: "Contacts", + type: '{ tag: "Contacts"; value: { handles: Array } }', + description: "Selected contacts, with profiles available in any receiving App.", + }, + ], + }, + { + id: "profile-contact", + name: "ProfileContact", + category: "profile", + definition: 'export type ProfileContact =\n | { tag: "Peer"; value: { peerIdentity: HexString } }\n | { tag: "Handle"; value: { handle: ContactHandle } }\n;', + description: "A contact named without exposing a handle's account to the product.", + variants: [ + { + name: "Peer", + type: '{ tag: "Peer"; value: { peerIdentity: HexString } }', + description: "An authenticated Chat network identity already known to the product.", + }, + { + name: "Handle", + type: '{ tag: "Handle"; value: { handle: ContactHandle } }', + description: "An opaque host-issued contact selection.", + }, + ], + }, { id: "raw-payload", name: "RawPayload", @@ -6107,6 +6661,58 @@ export const types = [ }, ], }, + { + id: "v-01-host-profile-disclose-request", + name: "V01HostProfileDiscloseRequest", + category: "profile", + definition: "export interface V01HostProfileDiscloseRequest {\n reference: string;\n}", + description: "Request to give the user's chat contacts a profile reference.\n\nThe reference is a bearer capability for everyone the host relays it to.\nThe host stores it as the user's own and never parses it.", + fields: [ + { + name: "reference", + type: "string", + description: "Opaque profile reference, e.g. a Seity contacts reference.", + }, + ], + }, + { + id: "v-01-host-profile-place-contact-avatars-request", + name: "V01HostProfilePlaceContactAvatarsRequest", + category: "profile", + definition: "export interface V01HostProfilePlaceContactAvatarsRequest {\n surfaceWidth: number;\n surfaceHeight: number;\n slots: Array;\n}", + description: "Where a chat product draws contact avatars, so the host can draw the\nphoto and mood ring each contact shared over them, on its own layer.\n\nThe product sends geometry only. The host decides which slots it can fill\nand never says which, so the product cannot learn who shared a profile.", + fields: [ + { + name: "surface_width", + type: "number", + description: "Width of the product's drawing surface, in the units of every rect:\nframebuffer pixels for a PolkaVM product, CSS pixels of its viewport\nfor a web product. 1 to 16384.", + }, + { + name: "surface_height", + type: "number", + description: "Height of the drawing surface, in the same units. 1 to 16384.", + }, + { + name: "slots", + type: "Array", + description: "Replaces the product's previous placement entirely; empty clears it.\nAt most 64, each with its own `slot`.", + }, + ], + }, + { + id: "v-01-host-profile-present-contact-request", + name: "V01HostProfilePresentContactRequest", + category: "profile", + definition: "export interface V01HostProfilePresentContactRequest {\n peerIdentity: HexString;\n}", + description: "Request to show a chat contact's profile in host-owned UI.\n\nThe product names the contact, never a reference: the host looks up the\nreference that contact's host sent, so the product cannot read, keep or\nsubstitute it.", + fields: [ + { + name: "peer_identity", + type: "HexString", + description: "The contact's authenticated root identity, as the chat API names it.", + }, + ], + }, { id: "v-02-host-product-device-chat-request", name: "V02HostProductDeviceChatRequest", @@ -6215,6 +6821,64 @@ export const types = [ }, ], }, + { + id: "v-02-host-profile-place-contact-avatars-request", + name: "V02HostProfilePlaceContactAvatarsRequest", + category: "profile", + definition: "export interface V02HostProfilePlaceContactAvatarsRequest {\n surfaceWidth: number;\n surfaceHeight: number;\n own?: OwnAvatarSlot;\n slots: Array;\n}", + description: "Where a chat product draws avatars the host fills in: its contacts' and,\noptionally, the signed-in user's own.\n\nv0.2 adds `own` to the v0.1 placement. A v0.1 placement is this one with no\nown slot, which is exactly what v0.1 meant. Both kinds live in one\nplacement so a product never has two placements replacing each other's\noverlay.", + fields: [ + { + name: "surface_width", + type: "number", + description: "Width of the product's drawing surface, in the units of every rect:\nframebuffer pixels for a PolkaVM product, CSS pixels of its viewport\nfor a web product. 1 to 16384.", + }, + { + name: "surface_height", + type: "number", + description: "Height of the drawing surface, in the same units. 1 to 16384.", + }, + { + name: "own", + type: "OwnAvatarSlot | undefined", + description: "Where the signed-in user's own avatar is drawn, if the product draws\none. The host fills it only when the user has disclosed a profile.", + }, + { + name: "slots", + type: "Array", + description: "Replaces the product's previous placement entirely; empty clears it.\nAt most 64, each with its own `slot`, unique across `own` too.", + }, + ], + }, + { + id: "v-03-contact-avatar-slot", + name: "V03ContactAvatarSlot", + category: "profile", + definition: "export interface V03ContactAvatarSlot {\n slot: number;\n contact: ProfileContact;\n rect: AvatarRect;\n clip: AvatarRect;\n}", + description: "Geometry and opaque contact selection for one host-rendered avatar.", + fields: [ + { + name: "slot", + type: "number", + description: "Product-chosen id, unique across contact and own slots.", + }, + { + name: "contact", + type: "ProfileContact", + description: "A peer identity or host-issued handle. Unresolved handles remain blank.", + }, + { + name: "rect", + type: "AvatarRect", + description: "Square avatar bounds, from 1 to 1024 units per side.", + }, + { + name: "clip", + type: "AvatarRect", + description: "Visible region to which the avatar is clipped.", + }, + ], + }, { id: "vertical-alignment", name: "VerticalAlignment", diff --git a/vendor/truapi/dist/generated/client.d.ts b/vendor/truapi/dist/generated/client.d.ts index ca699c9f5..0218137da 100644 --- a/vendor/truapi/dist/generated/client.d.ts +++ b/vendor/truapi/dist/generated/client.d.ts @@ -6,9 +6,9 @@ import type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Obs import * as T from './types.js'; export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; -export declare const TRUAPI_VERSION: 2; +export declare const TRUAPI_VERSION: 3; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "6bbdd3b23a6400bb"; /** Account lookup, aliasing, and proof generation. */ export declare class AccountClient { #private; @@ -186,8 +186,8 @@ export declare class CoinPaymentClient { * * A product never reads the contact list. It opens the host's picker; the host * renders an overlay from the chat lists its chat extensions hold, and - * returns only the person the user selected. Names, accounts, and every other - * contact the user did not pick stay host-side. + * returns only handles for the people the user selected. Names, accounts, and + * every other contact the user did not pick stay host-side. * * That is also why there is no permission to request: the user choosing a * contact in host UI is the consent, and a product that is never handed the @@ -202,13 +202,30 @@ export declare class ContactsClient { * Resolves with the chosen contact's handle, or with why nothing was * chosen. A host that serves no picker answers `Unsupported`. * - * The handle is not an address and cannot be turned into one. To pay the - * person it names, put the handle where the recipient goes in the call and - * list it in `contacts` on the transaction payload: the host replaces it - * with their account before anything is signed or shown. A handle sent - * anywhere else is 32 bytes that resolve to nobody. + * The handle is not an address and cannot be turned into one by a product. + * To pay the person, put the handle where the recipient goes in the call + * and list it in `contacts` on the transaction payload: the host replaces + * it with their account before anything is signed or shown. Profile also + * accepts handles as disclosure recipients and as contacts to present or + * draw avatars for, without returning accounts or profile contents. */ pick(request: T.HostContactsPickRequest, options?: CallOptions): ResultAsync>; + /** + * Edit a complete selection in the host's multi-select contact picker. + * + * `selected` preselects existing handles. Confirming none returns `Picked` + * with an empty `handles` list; dismissing never changes the selection. + * Unresolvable initial handles reject the entire request. + */ + pickMany(request: T.HostContactsPickManyRequest, options?: CallOptions): ResultAsync>; + /** + * Draw contact names in host-owned rectangles over the product surface. + * + * Labels do not require a shared Profile photo or disclosure. The response + * reveals no name, identity or per-slot availability. Each call replaces + * the previous placement; empty `slots` clears it. + */ + placeLabels(request: T.HostContactsPlaceLabelsRequest, options?: CallOptions): ResultAsync>; } /** Deterministic entropy derivation. */ export declare class EntropyClient { @@ -337,6 +354,86 @@ export declare class PreimageClient { /** Submit a preimage. Returns the preimage key (hash) on success. */ submit(request: HexString, options?: CallOptions): ResultAsync>; } +/** + * Profiles shown in host-owned UI. + * + * The product hands over an opaque reference; the host resolves, decrypts and + * renders it. Profile bytes never return to the product. + */ +export declare class ProfileClient { + #private; + constructor(transport: TrUApiTransport); + /** + * Show the referenced profile in host-owned UI. + * + * Resolves once the host has taken the presentation, not when the user + * dismisses it. Loading and fetch failures are shown to the user, not + * returned; a reference this host cannot parse is `InvalidReference`. + */ + present(request: T.HostProfilePresentRequest, options?: CallOptions): ResultAsync>; + /** + * Store the user's profile and replace its independent delivery audiences. + * + * `ChatApps` shares within every ready Chat App. `App` selects one Chat + * App's audience. `Contacts` shares personally with picked opaque handles; + * those received profiles may render in any App. An empty audience list + * retains the own profile but withdraws all grants. Unknown handles reject + * the whole disclosure. App executions only. The first disclosure asks + * the user once per product; a refusal is `PermissionDenied`. + * v0.1 callers retain the `ChatApps` audience. + */ + disclose(request: T.HostProfileDiscloseRequest, options?: CallOptions): ResultAsync>; + /** + * Withdraw the reference this product disclosed. Contacts are told to + * drop what they hold. A product that did not disclose it is refused. + */ + retract(options?: CallOptions): ResultAsync>; + /** + * Show a contact's available profile in host-owned UI. + * + * The selector names a Chat peer or a picked opaque handle. App-scoped + * profiles take precedence over personal profiles. References, names, + * resolved accounts and availability never return to the product. Unknown + * handles, absent profiles and host presentation failures return the same + * success. v0.1 callers retain their `NotShared` and presentation errors + * for App-scoped shares only; personal drawers require v0.2 so a legacy + * raw-peer request cannot disclose personal sharing availability. + */ + presentContact(request: T.HostProfilePresentContactRequest, options?: CallOptions): ResultAsync>; + /** + * Tell the host where this product draws contacts' avatars, and + * optionally the signed-in user's own, so it can draw each shared photo + * and mood ring over them on its own layer. + * + * Each call replaces the product's placement; an empty `slots` and no + * `own` clears it. The own slot is filled only while the user has + * disclosed a profile, and redrawn when they disclose or retract one. + * The host draws only for contacts who shared a profile with the user, + * and keeps the placement current as they share or withdraw one, until + * the product replaces it or goes away. The answer is the same whoever + * shared: nothing about any slot, and no profile data, returns to the + * product. Taps still reach the product, which opens a profile with + * `presentContact`. + * + * App executions only. Rects are in the units of the surface size the + * product gives: framebuffer pixels for a PolkaVM product, CSS pixels of + * its viewport for a web product. A placement with more than 64 slots, a + * surface side outside 1 to 16384, an avatar that is not square or is + * outside 1 to 1024 a side, or a `slot` repeated across `own` and `slots` + * is `Unknown`. A host that cannot draw over the product is + * `Unsupported`; with no user signed in the call is `NotConnected`. + */ + placeContactAvatars(request: T.HostProfilePlaceContactAvatarsRequest, options?: CallOptions): ResultAsync>; + /** + * Report whether the signed-in user has configured a profile. + * + * Only the boolean status returns. The profile reference and contents + * remain host-owned. + */ + ownStatus(options?: CallOptions): ResultAsync>; + /** Show the signed-in user's profile in host-owned UI. */ + presentOwn(options?: CallOptions): ResultAsync>; +} /** Product-rendered bodies and the actions triggered inside them. */ export declare class RendererClient { #private; @@ -540,6 +637,7 @@ export interface TrUApiClient { readonly permissions: PermissionsClient; readonly pocket: PocketClient; readonly preimage: PreimageClient; + readonly profile: ProfileClient; readonly renderer: RendererClient; readonly resourceAllocation: ResourceAllocationClient; readonly signing: SigningClient; diff --git a/vendor/truapi/dist/generated/client.js b/vendor/truapi/dist/generated/client.js index 89b379618..430c7b375 100644 --- a/vendor/truapi/dist/generated/client.js +++ b/vendor/truapi/dist/generated/client.js @@ -5,9 +5,9 @@ import { SubscriptionError } from '../transport.js'; import * as T from './types.js'; import * as W from './wire-table.js'; export { ResultAsync, SubscriptionError }; -export const TRUAPI_VERSION = 2; +export const TRUAPI_VERSION = 3; export const TRUAPI_CODEC_VERSION = 3; -export const TRUAPI_WIRE_SCHEMA_HASH = "f7be28c22289b365"; +export const TRUAPI_WIRE_SCHEMA_HASH = "6bbdd3b23a6400bb"; function toSubscriptionError(error) { if (error instanceof SubscriptionError) return error; @@ -695,8 +695,8 @@ export class CoinPaymentClient { * * A product never reads the contact list. It opens the host's picker; the host * renders an overlay from the chat lists its chat extensions hold, and - * returns only the person the user selected. Names, accounts, and every other - * contact the user did not pick stay host-side. + * returns only handles for the people the user selected. Names, accounts, and + * every other contact the user did not pick stay host-side. * * That is also why there is no permission to request: the user choosing a * contact in host UI is the consent, and a product that is never handed the @@ -713,11 +713,12 @@ export class ContactsClient { * Resolves with the chosen contact's handle, or with why nothing was * chosen. A host that serves no picker answers `Unsupported`. * - * The handle is not an address and cannot be turned into one. To pay the - * person it names, put the handle where the recipient goes in the call and - * list it in `contacts` on the transaction payload: the host replaces it - * with their account before anything is signed or shown. A handle sent - * anywhere else is 32 bytes that resolve to nobody. + * The handle is not an address and cannot be turned into one by a product. + * To pay the person, put the handle where the recipient goes in the call + * and list it in `contacts` on the transaction payload: the host replaces + * it with their account before anything is signed or shown. Profile also + * accepts handles as disclosure recipients and as contacts to present or + * draw avatars for, without returning accounts or profile contents. */ pick(request, options) { return this.#transport.request({ @@ -730,6 +731,42 @@ export class ContactsClient { }, }); } + /** + * Edit a complete selection in the host's multi-select contact picker. + * + * `selected` preselects existing handles. Confirming none returns `Picked` + * with an empty `handles` list; dismissing never changes the selection. + * Unresolvable initial handles reject the entire request. + */ + pickMany(request, options) { + return this.#transport.request({ + ids: W.CONTACTS_PICK_MANY, + payload: T.VersionedHostContactsPickManyRequest.enc({ tag: "V1", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostContactsPickManyResponse, S.CallError(T.VersionedHostContactsPickManyError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Draw contact names in host-owned rectangles over the product surface. + * + * Labels do not require a shared Profile photo or disclosure. The response + * reveals no name, identity or per-slot availability. Each call replaces + * the previous placement; empty `slots` clears it. + */ + placeLabels(request, options) { + return this.#transport.request({ + ids: W.CONTACTS_PLACE_LABELS, + payload: T.VersionedHostContactsPlaceLabelsRequest.enc({ tag: "V1", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostContactsPlaceLabelsResponse, S.CallError(T.VersionedHostContactsPlaceLabelsError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } } /** Deterministic entropy derivation. */ export class EntropyClient { @@ -1044,6 +1081,158 @@ export class PreimageClient { }); } } +/** + * Profiles shown in host-owned UI. + * + * The product hands over an opaque reference; the host resolves, decrypts and + * renders it. Profile bytes never return to the product. + */ +export class ProfileClient { + #transport; + constructor(transport) { + this.#transport = transport; + } + /** + * Show the referenced profile in host-owned UI. + * + * Resolves once the host has taken the presentation, not when the user + * dismisses it. Loading and fetch failures are shown to the user, not + * returned; a reference this host cannot parse is `InvalidReference`. + */ + present(request, options) { + return this.#transport.request({ + ids: W.PROFILE_PRESENT, + payload: T.VersionedHostProfilePresentRequest.enc({ tag: "V1", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfilePresentResponse, S.CallError(T.VersionedHostProfilePresentError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Store the user's profile and replace its independent delivery audiences. + * + * `ChatApps` shares within every ready Chat App. `App` selects one Chat + * App's audience. `Contacts` shares personally with picked opaque handles; + * those received profiles may render in any App. An empty audience list + * retains the own profile but withdraws all grants. Unknown handles reject + * the whole disclosure. App executions only. The first disclosure asks + * the user once per product; a refusal is `PermissionDenied`. + * v0.1 callers retain the `ChatApps` audience. + */ + disclose(request, options) { + return this.#transport.request({ + ids: W.PROFILE_DISCLOSE, + payload: T.VersionedHostProfileDiscloseRequest.enc({ tag: "V2", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfileDiscloseResponse, S.CallError(T.VersionedHostProfileDiscloseError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Withdraw the reference this product disclosed. Contacts are told to + * drop what they hold. A product that did not disclose it is refused. + */ + retract(options) { + return this.#transport.request({ + ids: W.PROFILE_RETRACT, + payload: T.VersionedHostProfileRetractRequest.enc({ tag: "V1", value: undefined }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfileRetractResponse, S.CallError(T.VersionedHostProfileRetractError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Show a contact's available profile in host-owned UI. + * + * The selector names a Chat peer or a picked opaque handle. App-scoped + * profiles take precedence over personal profiles. References, names, + * resolved accounts and availability never return to the product. Unknown + * handles, absent profiles and host presentation failures return the same + * success. v0.1 callers retain their `NotShared` and presentation errors + * for App-scoped shares only; personal drawers require v0.2 so a legacy + * raw-peer request cannot disclose personal sharing availability. + */ + presentContact(request, options) { + return this.#transport.request({ + ids: W.PROFILE_PRESENT_CONTACT, + payload: T.VersionedHostProfilePresentContactRequest.enc({ tag: "V2", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfilePresentContactResponse, S.CallError(T.VersionedHostProfilePresentContactError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Tell the host where this product draws contacts' avatars, and + * optionally the signed-in user's own, so it can draw each shared photo + * and mood ring over them on its own layer. + * + * Each call replaces the product's placement; an empty `slots` and no + * `own` clears it. The own slot is filled only while the user has + * disclosed a profile, and redrawn when they disclose or retract one. + * The host draws only for contacts who shared a profile with the user, + * and keeps the placement current as they share or withdraw one, until + * the product replaces it or goes away. The answer is the same whoever + * shared: nothing about any slot, and no profile data, returns to the + * product. Taps still reach the product, which opens a profile with + * `presentContact`. + * + * App executions only. Rects are in the units of the surface size the + * product gives: framebuffer pixels for a PolkaVM product, CSS pixels of + * its viewport for a web product. A placement with more than 64 slots, a + * surface side outside 1 to 16384, an avatar that is not square or is + * outside 1 to 1024 a side, or a `slot` repeated across `own` and `slots` + * is `Unknown`. A host that cannot draw over the product is + * `Unsupported`; with no user signed in the call is `NotConnected`. + */ + placeContactAvatars(request, options) { + return this.#transport.request({ + ids: W.PROFILE_PLACE_CONTACT_AVATARS, + payload: T.VersionedHostProfilePlaceContactAvatarsRequest.enc({ tag: "V3", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfilePlaceContactAvatarsResponse, S.CallError(T.VersionedHostProfilePlaceContactAvatarsError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** + * Report whether the signed-in user has configured a profile. + * + * Only the boolean status returns. The profile reference and contents + * remain host-owned. + */ + ownStatus(options) { + return this.#transport.request({ + ids: W.PROFILE_OWN_STATUS, + payload: T.VersionedHostProfileOwnStatusRequest.enc({ tag: "V1", value: undefined }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfileOwnStatusResponse, S.CallError(T.VersionedHostProfileOwnStatusError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } + /** Show the signed-in user's profile in host-owned UI. */ + presentOwn(options) { + return this.#transport.request({ + ids: W.PROFILE_PRESENT_OWN, + payload: T.VersionedHostProfilePresentOwnRequest.enc({ tag: "V1", value: undefined }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProfilePresentOwnResponse, S.CallError(T.VersionedHostProfilePresentOwnError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } +} /** Product-rendered bodies and the actions triggered inside them. */ export class RendererClient { #transport; @@ -1485,6 +1674,7 @@ export function createClient(transport) { permissions: new PermissionsClient(transport), pocket: new PocketClient(transport), preimage: new PreimageClient(transport), + profile: new ProfileClient(transport), renderer: new RendererClient(transport), resourceAllocation: new ResourceAllocationClient(transport), signing: new SigningClient(transport), diff --git a/vendor/truapi/dist/generated/internal-client.d.ts b/vendor/truapi/dist/generated/internal-client.d.ts index e08d1ed14..e611d72f0 100644 --- a/vendor/truapi/dist/generated/internal-client.d.ts +++ b/vendor/truapi/dist/generated/internal-client.d.ts @@ -5,9 +5,9 @@ import type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Obs import * as T from './internal.js'; export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; -export declare const TRUAPI_VERSION: 2; +export declare const TRUAPI_VERSION: 3; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "6bbdd3b23a6400bb"; /** Permission request methods. */ declare class PermissionsClient { #private; diff --git a/vendor/truapi/dist/generated/internal-client.js b/vendor/truapi/dist/generated/internal-client.js index 92dbb8fbd..84562fe29 100644 --- a/vendor/truapi/dist/generated/internal-client.js +++ b/vendor/truapi/dist/generated/internal-client.js @@ -5,9 +5,9 @@ import { SubscriptionError } from '../transport.js'; import * as T from './internal.js'; import * as W from './wire-table.js'; export { ResultAsync, SubscriptionError }; -export const TRUAPI_VERSION = 2; +export const TRUAPI_VERSION = 3; export const TRUAPI_CODEC_VERSION = 3; -export const TRUAPI_WIRE_SCHEMA_HASH = "f7be28c22289b365"; +export const TRUAPI_WIRE_SCHEMA_HASH = "6bbdd3b23a6400bb"; /** Permission request methods. */ class PermissionsClient { #transport; diff --git a/vendor/truapi/dist/generated/types.d.ts b/vendor/truapi/dist/generated/types.d.ts index 66fa61c14..010047b31 100644 --- a/vendor/truapi/dist/generated/types.d.ts +++ b/vendor/truapi/dist/generated/types.d.ts @@ -64,6 +64,18 @@ export declare const AllocationOutcome: S.Codec; /** Main-axis distribution of children. */ export type Arrangement = "Start" | "End" | "Center" | "SpaceBetween" | "SpaceAround" | "SpaceEvenly"; export declare const Arrangement: S.Codec; +/** A rectangle in surface units, relative to the surface's top-left corner. */ +export interface AvatarRect { + /** Left edge. */ + x: number; + /** Top edge. */ + y: number; + /** Width. */ + width: number; + /** Height. */ + height: number; +} +export declare const AvatarRect: S.Codec; /** Background styling. */ export interface Background { /** Background color. */ @@ -371,6 +383,38 @@ export interface ContactHandle { bytes: Bytes32; } export declare const ContactHandle: S.Codec; +/** Geometry for a host-owned contact name, independent of profile sharing. */ +export interface ContactLabelSlot { + /** Product-chosen id, unique within this placement. */ + slot: number; + /** Opaque handle for the contact whose name the host draws. */ + handle: ContactHandle; + /** Name bounds in surface units, with sides from 1 to 16384. */ + rect: AvatarRect; + /** Visible region in surface units; a zero side hides the label. */ + clip: AvatarRect; +} +export declare const ContactLabelSlot: S.Codec; +/** Selection confirmed in the host's multi-contact picker. */ +export type ContactPickManyOutcome = +/** The user confirmed this complete selection, including an empty one. */ +{ + tag: "Picked"; + value: { + handles: Array; + }; +} +/** The user closed the picker without confirming a change. */ + | { + tag: "Dismissed"; + value?: undefined; +} +/** There are no contacts to show. */ + | { + tag: "NoContacts"; + value?: undefined; +}; +export declare const ContactPickManyOutcome: S.Codec; /** * How a contact pick ended. * @@ -1004,6 +1048,30 @@ export type VersionedHostContactsPickError = value: HostContactsPickError; }; export declare const VersionedHostContactsPickError: S.Codec; +/** Versioned envelope for [`HostContactsPickManyError`]. */ +export type VersionedHostContactsPickManyError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyError; +}; +export declare const VersionedHostContactsPickManyError: S.Codec; +/** Versioned envelope for [`HostContactsPickManyRequest`]. */ +export type VersionedHostContactsPickManyRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyRequest; +}; +export declare const VersionedHostContactsPickManyRequest: S.Codec; +/** Versioned envelope for [`HostContactsPickManyResponse`]. */ +export type VersionedHostContactsPickManyResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyResponse; +}; +export declare const VersionedHostContactsPickManyResponse: S.Codec; /** Versioned envelope for [`HostContactsPickRequest`]. */ export type VersionedHostContactsPickRequest = /** Version 1 payload. */ @@ -1020,6 +1088,30 @@ export type VersionedHostContactsPickResponse = value: HostContactsPickResponse; }; export declare const VersionedHostContactsPickResponse: S.Codec; +/** Versioned envelope for [`HostContactsPlaceLabelsError`]. */ +export type VersionedHostContactsPlaceLabelsError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsError; +}; +export declare const VersionedHostContactsPlaceLabelsError: S.Codec; +/** Versioned envelope for [`HostContactsPlaceLabelsRequest`]. */ +export type VersionedHostContactsPlaceLabelsRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsRequest; +}; +export declare const VersionedHostContactsPlaceLabelsRequest: S.Codec; +/** Versioned envelope for [`HostContactsPlaceLabelsResponse`]. */ +export type VersionedHostContactsPlaceLabelsResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsResponse; +}; +export declare const VersionedHostContactsPlaceLabelsResponse: S.Codec; /** Versioned envelope for [`HostCreateTransactionError`]. */ export type VersionedHostCreateTransactionError = /** Version 1 payload. */ @@ -1966,6 +2058,174 @@ export type VersionedHostProductDeviceChatResponse = value: HostProductDeviceChatResponse; }; export declare const VersionedHostProductDeviceChatResponse: S.Codec; +/** Versioned envelope for [`HostProfileDiscloseError`]. */ +export type VersionedHostProfileDiscloseError = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfileDiscloseError; +}; +export declare const VersionedHostProfileDiscloseError: S.Codec; +/** Versioned envelope for [`HostProfileDiscloseRequest`]. */ +export type VersionedHostProfileDiscloseRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfileDiscloseRequest; +}; +export declare const VersionedHostProfileDiscloseRequest: S.Codec; +/** Versioned envelope for [`HostProfileDiscloseResponse`]. */ +export type VersionedHostProfileDiscloseResponse = +/** Version 2 (no payload). */ +{ + tag: "V2"; + value?: undefined; +}; +export declare const VersionedHostProfileDiscloseResponse: S.Codec; +/** Versioned envelope for [`HostProfileOwnStatusError`]. */ +export type VersionedHostProfileOwnStatusError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileOwnStatusError; +}; +export declare const VersionedHostProfileOwnStatusError: S.Codec; +/** Versioned envelope for [`HostProfileOwnStatusRequest`]. */ +export type VersionedHostProfileOwnStatusRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfileOwnStatusRequest: S.Codec; +/** Versioned envelope for [`HostProfileOwnStatusResponse`]. */ +export type VersionedHostProfileOwnStatusResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileOwnStatusResponse; +}; +export declare const VersionedHostProfileOwnStatusResponse: S.Codec; +/** Versioned envelope for [`HostProfilePlaceContactAvatarsError`]. */ +export type VersionedHostProfilePlaceContactAvatarsError = +/** Version 3 payload. */ +{ + tag: "V3"; + value: HostProfilePlaceContactAvatarsError; +}; +export declare const VersionedHostProfilePlaceContactAvatarsError: S.Codec; +/** Versioned envelope for [`HostProfilePlaceContactAvatarsRequest`]. */ +export type VersionedHostProfilePlaceContactAvatarsRequest = +/** Version 3 payload. */ +{ + tag: "V3"; + value: HostProfilePlaceContactAvatarsRequest; +}; +export declare const VersionedHostProfilePlaceContactAvatarsRequest: S.Codec; +/** Versioned envelope for [`HostProfilePlaceContactAvatarsResponse`]. */ +export type VersionedHostProfilePlaceContactAvatarsResponse = +/** Version 3 (no payload). */ +{ + tag: "V3"; + value?: undefined; +}; +export declare const VersionedHostProfilePlaceContactAvatarsResponse: S.Codec; +/** Versioned envelope for [`HostProfilePresentContactError`]. */ +export type VersionedHostProfilePresentContactError = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfilePresentContactError; +}; +export declare const VersionedHostProfilePresentContactError: S.Codec; +/** Versioned envelope for [`HostProfilePresentContactRequest`]. */ +export type VersionedHostProfilePresentContactRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfilePresentContactRequest; +}; +export declare const VersionedHostProfilePresentContactRequest: S.Codec; +/** Versioned envelope for [`HostProfilePresentContactResponse`]. */ +export type VersionedHostProfilePresentContactResponse = +/** Version 2 (no payload). */ +{ + tag: "V2"; + value?: undefined; +}; +export declare const VersionedHostProfilePresentContactResponse: S.Codec; +/** Versioned envelope for [`HostProfilePresentError`]. */ +export type VersionedHostProfilePresentError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentError; +}; +export declare const VersionedHostProfilePresentError: S.Codec; +/** Versioned envelope for [`HostProfilePresentOwnError`]. */ +export type VersionedHostProfilePresentOwnError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentOwnError; +}; +export declare const VersionedHostProfilePresentOwnError: S.Codec; +/** Versioned envelope for [`HostProfilePresentOwnRequest`]. */ +export type VersionedHostProfilePresentOwnRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfilePresentOwnRequest: S.Codec; +/** Versioned envelope for [`HostProfilePresentOwnResponse`]. */ +export type VersionedHostProfilePresentOwnResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfilePresentOwnResponse: S.Codec; +/** Versioned envelope for [`HostProfilePresentRequest`]. */ +export type VersionedHostProfilePresentRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentRequest; +}; +export declare const VersionedHostProfilePresentRequest: S.Codec; +/** Versioned envelope for [`HostProfilePresentResponse`]. */ +export type VersionedHostProfilePresentResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfilePresentResponse: S.Codec; +/** Versioned envelope for [`HostProfileRetractError`]. */ +export type VersionedHostProfileRetractError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileRetractError; +}; +export declare const VersionedHostProfileRetractError: S.Codec; +/** Versioned envelope for [`HostProfileRetractRequest`]. */ +export type VersionedHostProfileRetractRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfileRetractRequest: S.Codec; +/** Versioned envelope for [`HostProfileRetractResponse`]. */ +export type VersionedHostProfileRetractResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export declare const VersionedHostProfileRetractResponse: S.Codec; /** Versioned envelope for [`HostPushNotificationCancelError`]. */ export type VersionedHostPushNotificationCancelError = /** Version 1 payload. */ @@ -2450,6 +2710,16 @@ export type OperationStartedResult = value?: undefined; }; export declare const OperationStartedResult: S.Codec; +/** Where the product draws the signed-in user's own avatar. */ +export interface OwnAvatarSlot { + /** Product-chosen id, unique within this placement. */ + slot: number; + /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */ + rect: AvatarRect; + /** Visible region the avatar is cut to. */ + clip: AvatarRect; +} +export declare const OwnAvatarSlot: S.Codec; /** * Source for a payment top-up operation. * @@ -2596,6 +2866,45 @@ export type VersionedProductRendererRenderRequest = value: ProductRendererRenderRequest; }; export declare const VersionedProductRendererRenderRequest: S.Codec; +/** Recipients of one profile reference. Multiple audiences form a union. */ +export type ProfileAudience = +/** Every ready Chat App, with profiles scoped to that App. */ +{ + tag: "ChatApps"; + value?: undefined; +} +/** Contacts of this Chat App, with profiles scoped to that App. */ + | { + tag: "App"; + value: { + productId: string; + }; +} +/** Selected contacts, with profiles available in any receiving App. */ + | { + tag: "Contacts"; + value: { + handles: Array; + }; +}; +export declare const ProfileAudience: S.Codec; +/** A contact named without exposing a handle's account to the product. */ +export type ProfileContact = +/** An authenticated Chat network identity already known to the product. */ +{ + tag: "Peer"; + value: { + peerIdentity: HexString; + }; +} +/** An opaque host-issued contact selection. */ + | { + tag: "Handle"; + value: { + handle: ContactHandle; + }; +}; +export declare const ProfileContact: S.Codec; /** Raw data to sign -- either binary bytes or a string message. */ export type RawPayload = /** Raw binary data to sign. */ @@ -3545,6 +3854,22 @@ export declare const TxPayloadExtension: S.Codec; /** Typography presets, resolved by the host's design system. */ export type TypographyStyle = "HeadlineLarge" | "TitleMediumRegular" | "BodyLargeRegular" | "BodyMediumRegular" | "BodySmallRegular"; export declare const TypographyStyle: S.Codec; +/** One avatar the product draws for a chat contact. */ +export interface ContactAvatarSlot { + /** + * Product-chosen id, stable for one on-screen avatar (a list row, a + * header). The host uses it only to keep what it draws stable across + * updates. + */ + slot: number; + /** The contact's authenticated root identity, as the chat API names it. */ + peerIdentity: HexString; + /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */ + rect: AvatarRect; + /** Visible region the avatar is cut to, such as the scroll area. */ + clip: AvatarRect; +} +export declare const ContactAvatarSlot: S.Codec; /** User's authentication state. */ export type HostAccountConnectionStatusSubscribeItem = "Disconnected" | "Connected"; export declare const HostAccountConnectionStatusSubscribeItem: S.Codec; @@ -4061,6 +4386,41 @@ export type HostContactsPickError = }; }; export declare const HostContactsPickError: S.Codec; +/** Failure before a complete selection can be confirmed. */ +export type HostContactsPickManyError = +/** No active session, or the session changed while choosing. */ +{ + tag: "NotConnected"; + value?: undefined; +} +/** The selection exceeds the bound or contains an unresolved handle. */ + | { + tag: "InvalidSelection"; + value?: undefined; +} +/** The host could not complete the picker. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostContactsPickManyError: S.Codec; +/** Open the host's picker with the product's current selection. */ +export interface HostContactsPickManyRequest { + /** + * At most 256 handles. Duplicates are ignored; an unresolved handle + * rejects the entire request rather than changing the selected audience. + */ + selected: Array; +} +export declare const HostContactsPickManyRequest: S.Codec; +/** The user's confirmed selection or reason no selection was made. */ +export interface HostContactsPickManyResponse { + /** How the picker ended. */ + outcome: ContactPickManyOutcome; +} +export declare const HostContactsPickManyResponse: S.Codec; /** * Request to open the host's contact picker. * @@ -4076,6 +4436,45 @@ export interface HostContactsPickResponse { outcome: ContactPickOutcome; } export declare const HostContactsPickResponse: S.Codec; +/** Placement failure, never the availability of any individual contact. */ +export type HostContactsPlaceLabelsError = +/** The host cannot draw labels over the product surface. */ +{ + tag: "Unsupported"; + value?: undefined; +} +/** No active session, or it changed while placing labels. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** The surface, slot count, slot ids or rectangles are invalid. */ + | { + tag: "InvalidPlacement"; + value?: undefined; +} +/** The host could not place the labels. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostContactsPlaceLabelsError: S.Codec; +/** Replace the contact names drawn over a product's surface. */ +export interface HostContactsPlaceLabelsRequest { + /** Surface width in framebuffer pixels or web viewport CSS pixels, 1 to 16384. */ + surfaceWidth: number; + /** Surface height in the same units, 1 to 16384. */ + surfaceHeight: number; + /** At most 256 slots. Empty clears the previous placement. */ + slots: Array; +} +export declare const HostContactsPlaceLabelsRequest: S.Codec; +/** Acknowledges placement without revealing any contact's name or availability. */ +export interface HostContactsPlaceLabelsResponse { +} +export declare const HostContactsPlaceLabelsResponse: S.Codec; /** Transaction creation error. */ export type HostCreateTransactionError = /** Payload could not be deserialized. */ @@ -4568,6 +4967,221 @@ export interface HostPocketRemoveCardRequest { cardId: string; } export declare const HostPocketRemoveCardRequest: S.Codec; +/** Profile disclosure failure. */ +export type HostProfileDiscloseError = +/** The reference is empty, too long, or not printable ASCII. */ +{ + tag: "InvalidReference"; + value?: undefined; +} +/** + * The user declined to let this product disclose a profile to their + * chat contacts. + */ + | { + tag: "PermissionDenied"; + value?: undefined; +} +/** No user is signed in, so there are no contacts to disclose to. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfileDiscloseError: S.Codec; +/** + * Request to give the user's chat contacts a profile reference. + * + * The reference is a bearer capability for everyone the host relays it to. + * The host stores it as the user's own and never parses it. + */ +export interface V01HostProfileDiscloseRequest { + /** Opaque profile reference, e.g. a Seity contacts reference. */ + reference: string; +} +export declare const V01HostProfileDiscloseRequest: S.Codec; +/** Failure while querying the signed-in user's profile status. */ +export type HostProfileOwnStatusError = +/** No user is signed in. */ +{ + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfileOwnStatusError: S.Codec; +/** + * Whether the signed-in user currently has a profile disclosed through the + * host. The reference itself never crosses into the product. + */ +export interface HostProfileOwnStatusResponse { + /** `true` when the host holds a current own-profile reference. */ + configured: boolean; +} +export declare const HostProfileOwnStatusResponse: S.Codec; +/** Contact avatar placement failure. Says nothing about any one slot. */ +export type HostProfilePlaceContactAvatarsError = +/** This host cannot draw over the product's surface. */ +{ + tag: "Unsupported"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all, including a malformed placement. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfilePlaceContactAvatarsError: S.Codec; +/** + * Where a chat product draws contact avatars, so the host can draw the + * photo and mood ring each contact shared over them, on its own layer. + * + * The product sends geometry only. The host decides which slots it can fill + * and never says which, so the product cannot learn who shared a profile. + */ +export interface V01HostProfilePlaceContactAvatarsRequest { + /** + * Width of the product's drawing surface, in the units of every rect: + * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport + * for a web product. 1 to 16384. + */ + surfaceWidth: number; + /** Height of the drawing surface, in the same units. 1 to 16384. */ + surfaceHeight: number; + /** + * Replaces the product's previous placement entirely; empty clears it. + * At most 64, each with its own `slot`. + */ + slots: Array; +} +export declare const V01HostProfilePlaceContactAvatarsRequest: S.Codec; +/** Contact profile presentation failure. */ +export type HostProfilePresentContactError = +/** This contact has not shared a profile with the user. */ +{ + tag: "NotShared"; + value?: undefined; +} +/** The host holds a reference it cannot parse. */ + | { + tag: "InvalidReference"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfilePresentContactError: S.Codec; +/** + * Request to show a chat contact's profile in host-owned UI. + * + * The product names the contact, never a reference: the host looks up the + * reference that contact's host sent, so the product cannot read, keep or + * substitute it. + */ +export interface V01HostProfilePresentContactRequest { + /** The contact's authenticated root identity, as the chat API names it. */ + peerIdentity: HexString; +} +export declare const V01HostProfilePresentContactRequest: S.Codec; +/** Profile presentation failure. */ +export type HostProfilePresentError = +/** The reference is malformed or names a format this host cannot open. */ +{ + tag: "InvalidReference"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfilePresentError: S.Codec; +/** Failure while presenting the signed-in user's profile. */ +export type HostProfilePresentOwnError = +/** The signed-in user has not configured a profile. */ +{ + tag: "NotConfigured"; + value?: undefined; +} +/** The host holds a reference it cannot parse. */ + | { + tag: "InvalidReference"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfilePresentOwnError: S.Codec; +/** + * Request to show a profile the calling product references in host-owned UI. + * + * The reference is a bearer capability: whoever holds it can read the profile + * it names. The host resolves and renders it itself, so profile bytes, the + * avatar image included, never reach the product. + */ +export interface HostProfilePresentRequest { + /** Opaque profile reference, e.g. a Seity `#` blob reference. */ + reference: string; +} +export declare const HostProfilePresentRequest: S.Codec; +/** Profile retraction failure. */ +export type HostProfileRetractError = +/** Another product disclosed the reference the host holds. */ +{ + tag: "NotDiscloser"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export declare const HostProfileRetractError: S.Codec; /** Request to cancel a previously scheduled notification. */ export interface HostPushNotificationCancelRequest { /** The notification identifier returned by [`HostPushNotificationResponse`]. */ @@ -5318,6 +5932,72 @@ export interface V02HostProductDeviceChatResponse { richMessages: Array; } export declare const V02HostProductDeviceChatResponse: S.Codec; +/** + * Replace the user's disclosed reference and its complete set of audiences. + * + * An empty audience retains the user's own profile but withdraws all delivery + * grants. A contact handle that no longer resolves rejects the whole request. + */ +export interface HostProfileDiscloseRequest { + /** Opaque bearer reference, retained and relayed only by the host. */ + reference: string; + /** Independent grants for this reference, at most 64. */ + audiences: Array; +} +export declare const HostProfileDiscloseRequest: S.Codec; +/** + * Where a chat product draws avatars the host fills in: its contacts' and, + * optionally, the signed-in user's own. + * + * v0.2 adds `own` to the v0.1 placement. A v0.1 placement is this one with no + * own slot, which is exactly what v0.1 meant. Both kinds live in one + * placement so a product never has two placements replacing each other's + * overlay. + */ +export interface V02HostProfilePlaceContactAvatarsRequest { + /** + * Width of the product's drawing surface, in the units of every rect: + * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport + * for a web product. 1 to 16384. + */ + surfaceWidth: number; + /** Height of the drawing surface, in the same units. 1 to 16384. */ + surfaceHeight: number; + /** + * Where the signed-in user's own avatar is drawn, if the product draws + * one. The host fills it only when the user has disclosed a profile. + */ + own?: OwnAvatarSlot; + /** + * Replaces the product's previous placement entirely; empty clears it. + * At most 64, each with its own `slot`, unique across `own` too. + */ + slots: Array; +} +export declare const V02HostProfilePlaceContactAvatarsRequest: S.Codec; +/** + * Ask the host to present a contact's available profile. + * + * Unknown handles, absent profiles and presentation failures return success, + * without disclosing whether the contact shares a profile. + */ +export interface HostProfilePresentContactRequest { + /** The contact whose profile the host may present. */ + contact: ProfileContact; +} +export declare const HostProfilePresentContactRequest: S.Codec; +/** Geometry and opaque contact selection for one host-rendered avatar. */ +export interface V03ContactAvatarSlot { + /** Product-chosen id, unique across contact and own slots. */ + slot: number; + /** A peer identity or host-issued handle. Unresolved handles remain blank. */ + contact: ProfileContact; + /** Square avatar bounds, from 1 to 1024 units per side. */ + rect: AvatarRect; + /** Visible region to which the avatar is clipped. */ + clip: AvatarRect; +} +export declare const V03ContactAvatarSlot: S.Codec; /** An operation using the calling product's non-exportable Host Chat device. */ export type HostProductDeviceChatRequest = /** Restore public metadata, pending ciphertext, and private file-transfer progress. */ @@ -5447,6 +6127,18 @@ export interface HostProductDeviceChatResponse { coinageCentsUnit?: bigint; } export declare const HostProductDeviceChatResponse: S.Codec; +/** A host-rendered avatar placement using peer identities or opaque handles. */ +export interface HostProfilePlaceContactAvatarsRequest { + /** Width of the drawing surface, from 1 to 16384 units. */ + surfaceWidth: number; + /** Height of the drawing surface, from 1 to 16384 units. */ + surfaceHeight: number; + /** Optional slot for the signed-in user's own disclosed profile. */ + own?: OwnAvatarSlot; + /** Complete replacement of the contact slots, at most 64. */ + slots: Array; +} +export declare const HostProfilePlaceContactAvatarsRequest: S.Codec; /** Cross-axis alignment of `Row` children. */ export type VerticalAlignment = "Top" | "Center" | "Bottom"; export declare const VerticalAlignment: S.Codec; diff --git a/vendor/truapi/dist/generated/types.js b/vendor/truapi/dist/generated/types.js index 4dcc8189f..1c4c6ee4c 100644 --- a/vendor/truapi/dist/generated/types.js +++ b/vendor/truapi/dist/generated/types.js @@ -4,6 +4,7 @@ export const ActionTrigger = S.lazy(() => S.Struct({ messageId: S.str, actionId: export const AllocatableResource = S.lazy(() => S.TaggedUnion({ StatementStoreAllowance: S._void, BulletinAllowance: S._void, SmartContractAllowance: DerivationIndex, AutoSigning: S._void, ProductStatementStoreAllowance: DerivationIndex })); export const AllocationOutcome = S.lazy(() => S.Status("Allocated", "Rejected", "NotAvailable")); export const Arrangement = S.lazy(() => S.Status("Start", "End", "Center", "SpaceBetween", "SpaceAround", "SpaceEvenly")); +export const AvatarRect = S.lazy(() => S.Struct({ x: S.i32, y: S.i32, width: S.u32, height: S.u32 })); export const Background = S.lazy(() => S.Struct({ color: ColorToken, shape: S.Option(Shape) })); export const BlendingMode = S.lazy(() => S.Status("Normal", "Multiply", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", "Hue", "Saturation", "Color", "Luminosity")); export const BorderStyle = S.lazy(() => S.Struct({ width: Size, color: ColorToken, shape: S.Option(Shape) })); @@ -36,6 +37,8 @@ export const CoinPaymentTransmissionChannel = S.lazy(() => S.TaggedUnion({ Stand export const ColorToken = S.lazy(() => S.Status("FgPrimary", "FgSecondary", "FgTertiary", "BgSurfaceMain", "BgSurfaceContainer", "BgSurfaceNested", "FgSuccess", "FgError", "FgWarning")); export const ColumnProps = S.lazy(() => S.Struct({ horizontalAlignment: S.Option(HorizontalAlignment), verticalArrangement: S.Option(Arrangement) })); export const ContactHandle = S.lazy(() => S.Struct({ bytes: Bytes32 })); +export const ContactLabelSlot = S.lazy(() => S.Struct({ slot: S.u32, handle: ContactHandle, rect: AvatarRect, clip: AvatarRect })); +export const ContactPickManyOutcome = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ handles: S.Vector(ContactHandle) }), Dismissed: S._void, NoContacts: S._void })); export const ContactPickOutcome = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ handle: ContactHandle }), Dismissed: S._void, NoContacts: S._void })); export const ContentAlignment = S.lazy(() => S.Status("TopStart", "TopCenter", "TopEnd", "CenterStart", "Center", "CenterEnd", "BottomStart", "BottomCenter", "BottomEnd")); export const ContextualAlias = S.lazy(() => S.Struct({ context: S.Hex(32), alias: S.Hex() })); @@ -112,8 +115,14 @@ export const VersionedHostCoinPaymentRefundError = S.lazy(() => S.indexedTaggedU export const VersionedHostCoinPaymentRefundItem = S.lazy(() => S.indexedTaggedUnion({ V1: [0, CoinPaymentStatus] })); export const VersionedHostCoinPaymentRefundRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostCoinPaymentRefundRequest] })); export const VersionedHostContactsPickError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickError] })); +export const VersionedHostContactsPickManyError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickManyError] })); +export const VersionedHostContactsPickManyRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickManyRequest] })); +export const VersionedHostContactsPickManyResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickManyResponse] })); export const VersionedHostContactsPickRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickRequest] })); export const VersionedHostContactsPickResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPickResponse] })); +export const VersionedHostContactsPlaceLabelsError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPlaceLabelsError] })); +export const VersionedHostContactsPlaceLabelsRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPlaceLabelsRequest] })); +export const VersionedHostContactsPlaceLabelsResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostContactsPlaceLabelsResponse] })); export const VersionedHostCreateTransactionError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostCreateTransactionError] })); export const VersionedHostCreateTransactionRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, ProductAccountTxPayload] })); export const VersionedHostCreateTransactionResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostCreateTransactionResponse] })); @@ -212,6 +221,27 @@ export const VersionedHostPocketRemoveCardResponse = S.lazy(() => S.indexedTagge export const VersionedHostProductDeviceChatError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProductDeviceChatError] })); export const VersionedHostProductDeviceChatRequest = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProductDeviceChatRequest] })); export const VersionedHostProductDeviceChatResponse = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProductDeviceChatResponse] })); +export const VersionedHostProfileDiscloseError = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProfileDiscloseError] })); +export const VersionedHostProfileDiscloseRequest = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProfileDiscloseRequest] })); +export const VersionedHostProfileDiscloseResponse = S.lazy(() => S.indexedTaggedUnion({ V2: [1, S._void] })); +export const VersionedHostProfileOwnStatusError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfileOwnStatusError] })); +export const VersionedHostProfileOwnStatusRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +export const VersionedHostProfileOwnStatusResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfileOwnStatusResponse] })); +export const VersionedHostProfilePlaceContactAvatarsError = S.lazy(() => S.indexedTaggedUnion({ V3: [2, HostProfilePlaceContactAvatarsError] })); +export const VersionedHostProfilePlaceContactAvatarsRequest = S.lazy(() => S.indexedTaggedUnion({ V3: [2, HostProfilePlaceContactAvatarsRequest] })); +export const VersionedHostProfilePlaceContactAvatarsResponse = S.lazy(() => S.indexedTaggedUnion({ V3: [2, S._void] })); +export const VersionedHostProfilePresentContactError = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProfilePresentContactError] })); +export const VersionedHostProfilePresentContactRequest = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostProfilePresentContactRequest] })); +export const VersionedHostProfilePresentContactResponse = S.lazy(() => S.indexedTaggedUnion({ V2: [1, S._void] })); +export const VersionedHostProfilePresentError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfilePresentError] })); +export const VersionedHostProfilePresentOwnError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfilePresentOwnError] })); +export const VersionedHostProfilePresentOwnRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +export const VersionedHostProfilePresentOwnResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +export const VersionedHostProfilePresentRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfilePresentRequest] })); +export const VersionedHostProfilePresentResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +export const VersionedHostProfileRetractError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostProfileRetractError] })); +export const VersionedHostProfileRetractRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +export const VersionedHostProfileRetractResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); export const VersionedHostPushNotificationCancelError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, GenericError] })); export const VersionedHostPushNotificationCancelRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostPushNotificationCancelRequest] })); export const VersionedHostPushNotificationCancelResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); @@ -257,6 +287,7 @@ export const LegacyAccount = S.lazy(() => S.Struct({ publicKey: S.Hex(), name: S export const LegacyAccountTxPayload = S.lazy(() => S.Struct({ signer: S.Hex(32), genesisHash: S.Hex(32), callData: S.Hex(), extensions: S.Vector(TxPayloadExtension), txExtVersion: S.u8 })); export const Modifier = S.lazy(() => S.TaggedUnion({ Margin: Dimensions, Padding: Dimensions, Background: Background, Border: BorderStyle, Height: Size, Width: Size, MinWidth: Size, MinHeight: Size, FillWidth: S.bool, FillHeight: S.bool, Opacity: S.u8, BlendingMode: BlendingMode })); export const OperationStartedResult = S.lazy(() => S.TaggedUnion({ Started: S.Struct({ operationId: S.str }), LimitReached: S._void })); +export const OwnAvatarSlot = S.lazy(() => S.Struct({ slot: S.u32, rect: AvatarRect, clip: AvatarRect })); export const PaymentTopUpSource = S.lazy(() => S.TaggedUnion({ ProductAccount: S.Struct({ derivationIndex: DerivationIndex }), PrivateKey: S.Struct({ sr25519SecretKey: S.Hex(64) }), Coins: S.Struct({ sr25519SecretKeys: S.Vector(S.Hex(64)) }) })); export const PocketCard = S.lazy(() => S.Struct({ cardId: S.str, privileged: S.bool })); export const PreimageSubmitError = S.lazy(() => S.TaggedUnion({ Unknown: S.Struct({ reason: S.str }) })); @@ -267,6 +298,8 @@ export const ProductProofContext = S.lazy(() => S.Struct({ productId: S.str, suf export const VersionedProductRendererRenderError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, GenericError] })); export const VersionedProductRendererRenderItem = S.lazy(() => S.indexedTaggedUnion({ V1: [0, RendererNode] })); export const VersionedProductRendererRenderRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, ProductRendererRenderRequest] })); +export const ProfileAudience = S.lazy(() => S.TaggedUnion({ ChatApps: S._void, App: S.Struct({ productId: S.str }), Contacts: S.Struct({ handles: S.Vector(ContactHandle) }) })); +export const ProfileContact = S.lazy(() => S.TaggedUnion({ Peer: S.Struct({ peerIdentity: S.Hex(32) }), Handle: S.Struct({ handle: ContactHandle }) })); export const RawPayload = S.lazy(() => S.TaggedUnion({ Bytes: S.Struct({ bytes: S.Hex() }), Payload: S.Struct({ payload: S.str }) })); export const RegisteredRingVrfKey = S.lazy(() => S.Struct({ handle: ProductAccountId, rings: S.Vector(RingLocation), publicKey: S.Option(S.Hex(32)) })); export const VersionedRemoteChainHeadBodyError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, GenericError] })); @@ -357,6 +390,7 @@ export const ThemeName = S.lazy(() => S.TaggedUnion({ Custom: S.str, Default: S. export const ThemeVariant = S.lazy(() => S.Status("Light", "Dark")); export const TxPayloadExtension = S.lazy(() => S.Struct({ id: S.str, extra: S.Hex(), additionalSigned: S.Hex() })); export const TypographyStyle = S.lazy(() => S.Status("HeadlineLarge", "TitleMediumRegular", "BodyLargeRegular", "BodyMediumRegular", "BodySmallRegular")); +export const ContactAvatarSlot = S.lazy(() => S.Struct({ slot: S.u32, peerIdentity: S.Hex(32), rect: AvatarRect, clip: AvatarRect })); export const HostAccountConnectionStatusSubscribeItem = S.lazy(() => S.Status("Disconnected", "Connected")); export const HostAccountCreateProofError = S.lazy(() => S.TaggedUnion({ RingNotFound: S._void, NotMember: S._void, KeyNotRegistered: S._void, KeyNotInRing: S._void, NotAllowlisted: S._void, Rejected: S._void, Unknown: S.Struct({ reason: S.str }) })); export const HostAccountCreateProofRequest = S.lazy(() => S.Struct({ keyHandle: ProductAccountId, context: ProductProofContext, ringLocation: RingLocation, message: S.Hex() })); @@ -400,8 +434,14 @@ export const HostCoinPaymentQueryPurseResponse = S.lazy(() => S.Struct({ info: C export const HostCoinPaymentRebalancePurseRequest = S.lazy(() => S.Struct({ from: S.u32, to: S.u32, amount: S.u32 })); export const HostCoinPaymentRefundRequest = S.lazy(() => S.Struct({ receivable: S.Hex(32) })); export const HostContactsPickError = S.lazy(() => S.TaggedUnion({ NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostContactsPickManyError = S.lazy(() => S.TaggedUnion({ NotConnected: S._void, InvalidSelection: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostContactsPickManyRequest = S.lazy(() => S.Struct({ selected: S.Vector(ContactHandle) })); +export const HostContactsPickManyResponse = S.lazy(() => S.Struct({ outcome: ContactPickManyOutcome })); export const HostContactsPickRequest = S.lazy(() => S.Struct({})); export const HostContactsPickResponse = S.lazy(() => S.Struct({ outcome: ContactPickOutcome })); +export const HostContactsPlaceLabelsError = S.lazy(() => S.TaggedUnion({ Unsupported: S._void, NotConnected: S._void, InvalidPlacement: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostContactsPlaceLabelsRequest = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, slots: S.Vector(ContactLabelSlot) })); +export const HostContactsPlaceLabelsResponse = S.lazy(() => S.Struct({})); export const HostCreateTransactionError = S.lazy(() => S.TaggedUnion({ FailedToDecode: S._void, Rejected: S._void, NotSupported: S.Struct({ reason: S.str }), PermissionDenied: S._void, Unknown: S.Struct({ reason: S.str }), UnknownContact: S._void })); export const HostCreateTransactionResponse = S.lazy(() => S.Struct({ transaction: S.Hex() })); export const HostCreateTransactionWithLegacyAccountResponse = S.lazy(() => S.Struct({ transaction: S.Hex() })); @@ -442,6 +482,18 @@ export const HostPaymentTopUpRequest = S.lazy(() => S.Struct({ into: S.Option(S. export const HostPocketListSubscribeItem = S.lazy(() => S.Struct({ cards: S.Vector(PocketCard) })); export const HostPocketRemoveCardError = S.lazy(() => S.TaggedUnion({ Privileged: S._void, Unknown: S.Struct({ reason: S.str }) })); export const HostPocketRemoveCardRequest = S.lazy(() => S.Struct({ cardId: S.str })); +export const HostProfileDiscloseError = S.lazy(() => S.TaggedUnion({ InvalidReference: S._void, PermissionDenied: S._void, NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const V01HostProfileDiscloseRequest = S.lazy(() => S.Struct({ reference: S.str })); +export const HostProfileOwnStatusError = S.lazy(() => S.TaggedUnion({ NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostProfileOwnStatusResponse = S.lazy(() => S.Struct({ configured: S.bool })); +export const HostProfilePlaceContactAvatarsError = S.lazy(() => S.TaggedUnion({ Unsupported: S._void, NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const V01HostProfilePlaceContactAvatarsRequest = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, slots: S.Vector(ContactAvatarSlot) })); +export const HostProfilePresentContactError = S.lazy(() => S.TaggedUnion({ NotShared: S._void, InvalidReference: S._void, NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const V01HostProfilePresentContactRequest = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32) })); +export const HostProfilePresentError = S.lazy(() => S.TaggedUnion({ InvalidReference: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostProfilePresentOwnError = S.lazy(() => S.TaggedUnion({ NotConfigured: S._void, InvalidReference: S._void, NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); +export const HostProfilePresentRequest = S.lazy(() => S.Struct({ reference: S.str })); +export const HostProfileRetractError = S.lazy(() => S.TaggedUnion({ NotDiscloser: S._void, NotConnected: S._void, Unknown: S.Struct({ reason: S.str }) })); export const HostPushNotificationCancelRequest = S.lazy(() => S.Struct({ id: S.u32 })); export const HostPushNotificationError = S.lazy(() => S.TaggedUnion({ ScheduleLimitReached: S._void, Unknown: S.Struct({ reason: S.str }) })); export const HostPushNotificationRequest = S.lazy(() => S.Struct({ text: S.str, deeplink: S.Option(S.str), scheduledAt: S.Option(S.u64) })); @@ -505,8 +557,13 @@ export const HostLocaleSubscribeItem = S.lazy(() => S.Struct({ languageTag: S.st export const HostProductDeviceChatError = S.lazy(() => S.Status("NotConnected", "AccessNotGranted", "UserRejected", "AllowanceRequired", "PeerNotReady", "OperationConflict", "InvalidRequest", "InvalidStatement", "RecipientNotFound", "InsufficientBalance", "StorageUnavailable", "NetworkUnavailable", "OperationNotFound", "AttachmentsUnavailable")); export const V02HostProductDeviceChatRequest = S.lazy(() => S.TaggedUnion({ Initialize: S._void, Invite: S.Struct({ username: S.str, text: S.str }), Receive: S.Struct({ statement: SignedStatement }), AcceptInvitation: S.Struct({ invitationId: S.Hex(32) }), RejectInvitation: S.Struct({ invitationId: S.Hex(32) }), Send: S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, messages: S.Vector(S.Hex()) }), SendPayment: S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, amountCents: S.u64 }), PaymentStatus: S.Struct({ operationId: S.Hex(32) }), Reconcile: S._void, SendAttachments: S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, text: S.Option(S.str) }), OpenAttachment: S.Struct({ attachmentId: S.Hex(32) }) })); export const V02HostProductDeviceChatResponse = S.lazy(() => S.Struct({ device: HostNativeChatDevice, peers: S.Vector(HostNativeChatPeer), invitations: S.Vector(HostNativeChatInvitation), messages: S.Vector(HostNativeChatMessages), acknowledgments: S.Vector(HostNativeChatAcknowledgment), payments: S.Vector(HostNativeChatPayment), richMessages: S.Vector(HostNativeChatRichMessage) })); +export const HostProfileDiscloseRequest = S.lazy(() => S.Struct({ reference: S.str, audiences: S.Vector(ProfileAudience) })); +export const V02HostProfilePlaceContactAvatarsRequest = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, own: S.Option(OwnAvatarSlot), slots: S.Vector(ContactAvatarSlot) })); +export const HostProfilePresentContactRequest = S.lazy(() => S.Struct({ contact: ProfileContact })); +export const V03ContactAvatarSlot = S.lazy(() => S.Struct({ slot: S.u32, contact: ProfileContact, rect: AvatarRect, clip: AvatarRect })); export const HostProductDeviceChatRequest = S.lazy(() => S.TaggedUnion({ Initialize: S._void, Bind: S.Struct({ username: S.str }), Prepare: S.Struct({ peerIdentity: S.Hex(32), route: HostNativeChatRoute, plaintext: S.Hex() }), Open: S.Struct({ statement: SignedStatement }), SendPayment: S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, amountCents: S.u64 }), PaymentStatus: S.Struct({ operationId: S.Hex(32) }), ReconcilePayments: S._void, PrepareAttachments: S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, text: S.Option(S.str) }), OpenAttachment: S.Struct({ attachmentId: S.Hex(32) }), CommitMigration: S.Struct({ migrationId: S.Hex(32) }), ContinueOpen: S.Struct({ openId: S.Hex(32), cursor: S.u32 }), ContinueState: S.Struct({ stateId: S.Hex(32), cursor: S.u32 }), PaymentDenomination: S._void })); export const HostProductDeviceChatResponse = S.lazy(() => S.Struct({ device: HostNativeChatDevice, peers: S.Vector(HostNativeChatPeer), binding: S.Option(HostNativeChatBinding), opened: S.Vector(HostNativeChatOpened), prepared: S.Vector(HostNativeChatPrepared), payments: S.Vector(HostNativeChatPayment), richMessages: S.Vector(HostNativeChatRichMessage), migration: S.Option(V02HostProductDeviceChatResponse), migrationId: S.Option(S.Hex(32)), openPage: S.Option(HostNativeChatOpenPage), migrationInvitations: S.Vector(HostNativeChatMigrationInvitation), statePage: S.Option(HostNativeChatStatePage), coinageCentsUnit: S.Option(S.u128) })); +export const HostProfilePlaceContactAvatarsRequest = S.lazy(() => S.Struct({ surfaceWidth: S.u32, surfaceHeight: S.u32, own: S.Option(OwnAvatarSlot), slots: S.Vector(V03ContactAvatarSlot) })); export const VerticalAlignment = S.lazy(() => S.Status("Top", "Center", "Bottom")); export const VrfSignature = S.lazy(() => S.Struct({ preOutput: S.Hex(32), proof: S.Hex(64) })); export const VrfTranscriptItem = S.lazy(() => S.Struct({ label: S.Hex(), value: S.Hex() })); diff --git a/vendor/truapi/dist/generated/wire-decode.js b/vendor/truapi/dist/generated/wire-decode.js index 7318c27af..11830323b 100644 --- a/vendor/truapi/dist/generated/wire-decode.js +++ b/vendor/truapi/dist/generated/wire-decode.js @@ -384,4 +384,40 @@ export const WIRE_DECODE_TABLE = { 0: (payload) => T.VersionedHostContactsPickRequest.dec(payload), 1: (payload) => S.Result(T.VersionedHostContactsPickResponse, S.CallError(T.VersionedHostContactsPickError)).dec(payload), }, + [W.CONTACTS_PICK_MANY.trait * 256 + W.CONTACTS_PICK_MANY.method]: { + 0: (payload) => T.VersionedHostContactsPickManyRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostContactsPickManyResponse, S.CallError(T.VersionedHostContactsPickManyError)).dec(payload), + }, + [W.CONTACTS_PLACE_LABELS.trait * 256 + W.CONTACTS_PLACE_LABELS.method]: { + 0: (payload) => T.VersionedHostContactsPlaceLabelsRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostContactsPlaceLabelsResponse, S.CallError(T.VersionedHostContactsPlaceLabelsError)).dec(payload), + }, + [W.PROFILE_PRESENT.trait * 256 + W.PROFILE_PRESENT.method]: { + 0: (payload) => T.VersionedHostProfilePresentRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfilePresentResponse, S.CallError(T.VersionedHostProfilePresentError)).dec(payload), + }, + [W.PROFILE_DISCLOSE.trait * 256 + W.PROFILE_DISCLOSE.method]: { + 0: (payload) => T.VersionedHostProfileDiscloseRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfileDiscloseResponse, S.CallError(T.VersionedHostProfileDiscloseError)).dec(payload), + }, + [W.PROFILE_RETRACT.trait * 256 + W.PROFILE_RETRACT.method]: { + 0: (payload) => T.VersionedHostProfileRetractRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfileRetractResponse, S.CallError(T.VersionedHostProfileRetractError)).dec(payload), + }, + [W.PROFILE_PRESENT_CONTACT.trait * 256 + W.PROFILE_PRESENT_CONTACT.method]: { + 0: (payload) => T.VersionedHostProfilePresentContactRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfilePresentContactResponse, S.CallError(T.VersionedHostProfilePresentContactError)).dec(payload), + }, + [W.PROFILE_PLACE_CONTACT_AVATARS.trait * 256 + W.PROFILE_PLACE_CONTACT_AVATARS.method]: { + 0: (payload) => T.VersionedHostProfilePlaceContactAvatarsRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfilePlaceContactAvatarsResponse, S.CallError(T.VersionedHostProfilePlaceContactAvatarsError)).dec(payload), + }, + [W.PROFILE_OWN_STATUS.trait * 256 + W.PROFILE_OWN_STATUS.method]: { + 0: (payload) => T.VersionedHostProfileOwnStatusRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfileOwnStatusResponse, S.CallError(T.VersionedHostProfileOwnStatusError)).dec(payload), + }, + [W.PROFILE_PRESENT_OWN.trait * 256 + W.PROFILE_PRESENT_OWN.method]: { + 0: (payload) => T.VersionedHostProfilePresentOwnRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProfilePresentOwnResponse, S.CallError(T.VersionedHostProfilePresentOwnError)).dec(payload), + }, }; diff --git a/vendor/truapi/dist/generated/wire-table.d.ts b/vendor/truapi/dist/generated/wire-table.d.ts index f3bb2ba4c..53860a624 100644 --- a/vendor/truapi/dist/generated/wire-table.d.ts +++ b/vendor/truapi/dist/generated/wire-table.d.ts @@ -423,3 +423,48 @@ export declare const CONTACTS_PICK: { readonly method: 0; readonly kind: "request"; }; +export declare const CONTACTS_PICK_MANY: { + readonly trait: 20; + readonly method: 1; + readonly kind: "request"; +}; +export declare const CONTACTS_PLACE_LABELS: { + readonly trait: 20; + readonly method: 2; + readonly kind: "request"; +}; +export declare const PROFILE_PRESENT: { + readonly trait: 69; + readonly method: 0; + readonly kind: "request"; +}; +export declare const PROFILE_DISCLOSE: { + readonly trait: 69; + readonly method: 1; + readonly kind: "request"; +}; +export declare const PROFILE_RETRACT: { + readonly trait: 69; + readonly method: 2; + readonly kind: "request"; +}; +export declare const PROFILE_PRESENT_CONTACT: { + readonly trait: 69; + readonly method: 3; + readonly kind: "request"; +}; +export declare const PROFILE_PLACE_CONTACT_AVATARS: { + readonly trait: 69; + readonly method: 4; + readonly kind: "request"; +}; +export declare const PROFILE_OWN_STATUS: { + readonly trait: 69; + readonly method: 5; + readonly kind: "request"; +}; +export declare const PROFILE_PRESENT_OWN: { + readonly trait: 69; + readonly method: 6; + readonly kind: "request"; +}; diff --git a/vendor/truapi/dist/generated/wire-table.js b/vendor/truapi/dist/generated/wire-table.js index 129a15347..9814a03eb 100644 --- a/vendor/truapi/dist/generated/wire-table.js +++ b/vendor/truapi/dist/generated/wire-table.js @@ -434,3 +434,48 @@ export const CONTACTS_PICK = { method: 0, kind: "request", }; +export const CONTACTS_PICK_MANY = { + trait: 20, + method: 1, + kind: "request", +}; +export const CONTACTS_PLACE_LABELS = { + trait: 20, + method: 2, + kind: "request", +}; +export const PROFILE_PRESENT = { + trait: 69, + method: 0, + kind: "request", +}; +export const PROFILE_DISCLOSE = { + trait: 69, + method: 1, + kind: "request", +}; +export const PROFILE_RETRACT = { + trait: 69, + method: 2, + kind: "request", +}; +export const PROFILE_PRESENT_CONTACT = { + trait: 69, + method: 3, + kind: "request", +}; +export const PROFILE_PLACE_CONTACT_AVATARS = { + trait: 69, + method: 4, + kind: "request", +}; +export const PROFILE_OWN_STATUS = { + trait: 69, + method: 5, + kind: "request", +}; +export const PROFILE_PRESENT_OWN = { + trait: 69, + method: 6, + kind: "request", +}; diff --git a/vendor/truapi/dist/playground/codegen/services.js b/vendor/truapi/dist/playground/codegen/services.js index b226b7b29..77429c869 100644 --- a/vendor/truapi/dist/playground/codegen/services.js +++ b/vendor/truapi/dist/playground/codegen/services.js @@ -451,12 +451,34 @@ export const services = [ type: "unary", signature: "pick(request: HostContactsPickRequest): Promise>>", docUrl: "api/contacts/trait.Contacts.html#method.pick", - description: "Ask the host to let the user pick one contact.\n\nResolves with the chosen contact's handle, or with why nothing was\nchosen. A host that serves no picker answers `Unsupported`.\n\nThe handle is not an address and cannot be turned into one. To pay the\nperson it names, put the handle where the recipient goes in the call and\nlist it in `contacts` on the transaction payload: the host replaces it\nwith their account before anything is signed or shown. A handle sent\nanywhere else is 32 bytes that resolve to nobody.", + description: "Ask the host to let the user pick one contact.\n\nResolves with the chosen contact's handle, or with why nothing was\nchosen. A host that serves no picker answers `Unsupported`.\n\nThe handle is not an address and cannot be turned into one by a product.\nTo pay the person, put the handle where the recipient goes in the call\nand list it in `contacts` on the transaction payload: the host replaces\nit with their account before anything is signed or shown. Profile also\naccepts handles as disclosure recipients and as contacts to present or\ndraw avatars for, without returning accounts or profile contents.", requestDescription: "HostContactsPickRequest", exampleSource: 'const result = await truapi.contacts.pick({});\nassert(result.isOk(), "contacts.pick failed:", result);\nconst outcome = result.value.outcome;\nswitch (outcome.tag) {\n case "Picked":\n console.log("picked:", outcome.value.handle);\n break;\n case "Dismissed":\n console.log("the user closed the picker; worth offering again");\n break;\n case "NoContacts":\n console.log("nothing to pick from");\n break;\n}', requestType: "host-contacts-pick-request", responseType: "host-contacts-pick-response", }, + { + name: "pick_many", + type: "unary", + signature: "pickMany(request: HostContactsPickManyRequest): Promise>>", + docUrl: "api/contacts/trait.Contacts.html#method.pick_many", + description: "Edit a complete selection in the host's multi-select contact picker.\n\n`selected` preselects existing handles. Confirming none returns `Picked`\nwith an empty `handles` list; dismissing never changes the selection.\nUnresolvable initial handles reject the entire request.", + requestDescription: "HostContactsPickManyRequest", + exampleSource: 'const result = await truapi.contacts.pickMany({ selected: [] });\nassert(result.isOk(), "contacts.pickMany failed:", result);\nif (result.value.outcome.tag === "Picked") {\n console.log("confirmed handles:", result.value.outcome.value.handles);\n}', + requestType: "host-contacts-pick-many-request", + responseType: "host-contacts-pick-many-response", + }, + { + name: "place_labels", + type: "unary", + signature: "placeLabels(request: HostContactsPlaceLabelsRequest): Promise>>", + docUrl: "api/contacts/trait.Contacts.html#method.place_labels", + description: "Draw contact names in host-owned rectangles over the product surface.\n\nLabels do not require a shared Profile photo or disclosure. The response\nreveals no name, identity or per-slot availability. Each call replaces\nthe previous placement; empty `slots` clears it.", + requestDescription: "HostContactsPlaceLabelsRequest", + exampleSource: '// Empty placement clears this product\'s host-owned labels.\nconst result = await truapi.contacts.placeLabels({\n surfaceWidth: 640,\n surfaceHeight: 480,\n slots: [],\n});\nassert(result.isOk(), "contacts.placeLabels failed:", result);', + requestType: "host-contacts-place-labels-request", + responseType: "host-contacts-place-labels-response", + }, ], }, { @@ -698,6 +720,76 @@ export const services = [ }, ], }, + { + name: "Profile", + methods: [ + { + name: "present", + type: "unary", + signature: "present(request: HostProfilePresentRequest): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.present", + description: "Show the referenced profile in host-owned UI.\n\nResolves once the host has taken the presentation, not when the user\ndismisses it. Loading and fetch failures are shown to the user, not\nreturned; a reference this host cannot parse is `InvalidReference`.", + requestDescription: "HostProfilePresentRequest", + exampleSource: 'const result = await truapi.profile.present({\n reference: "bafkreigh2akiscaildc6ybwhxslp6rx2u4m2vpbhgvzhpsfkyzxiezxcnq#" + "00".repeat(44),\n});\nconsole.log("profile presentation:", result);', + requestType: "host-profile-present-request", + }, + { + name: "disclose", + type: "unary", + signature: "disclose(request: HostProfileDiscloseRequest): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.disclose", + description: "Store the user's profile and replace its independent delivery audiences.\n\n`ChatApps` shares within every ready Chat App. `App` selects one Chat\nApp's audience. `Contacts` shares personally with picked opaque handles;\nthose received profiles may render in any App. An empty audience list\nretains the own profile but withdraws all grants. Unknown handles reject\nthe whole disclosure. App executions only. The first disclosure asks\nthe user once per product; a refusal is `PermissionDenied`.\nv0.1 callers retain the `ChatApps` audience.", + requestDescription: "HostProfileDiscloseRequest", + exampleSource: 'const result = await truapi.profile.disclose({\n reference: "seity-contacts:v1:" + "00".repeat(64),\n audiences: [{ tag: "ChatApps" }],\n});\nconsole.log("profile disclosed:", result);', + requestType: "host-profile-disclose-request", + }, + { + name: "retract", + type: "unary", + signature: "retract(): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.retract", + description: "Withdraw the reference this product disclosed. Contacts are told to\ndrop what they hold. A product that did not disclose it is refused.", + exampleSource: 'const result = await truapi.profile.retract();\nconsole.log("profile retracted:", result);', + }, + { + name: "present_contact", + type: "unary", + signature: "presentContact(request: HostProfilePresentContactRequest): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.present_contact", + description: "Show a contact's available profile in host-owned UI.\n\nThe selector names a Chat peer or a picked opaque handle. App-scoped\nprofiles take precedence over personal profiles. References, names,\nresolved accounts and availability never return to the product. Unknown\nhandles, absent profiles and host presentation failures return the same\nsuccess. v0.1 callers retain their `NotShared` and presentation errors\nfor App-scoped shares only; personal drawers require v0.2 so a legacy\nraw-peer request cannot disclose personal sharing availability.", + requestDescription: "HostProfilePresentContactRequest", + exampleSource: 'const result = await truapi.profile.presentContact({\n contact: { tag: "Peer", value: {\n peerIdentity: "0x0000000000000000000000000000000000000000000000000000000000000000",\n } },\n});\nconsole.log("contact profile presentation:", result);', + requestType: "host-profile-present-contact-request", + }, + { + name: "place_contact_avatars", + type: "unary", + signature: "placeContactAvatars(request: HostProfilePlaceContactAvatarsRequest): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.place_contact_avatars", + description: "Tell the host where this product draws contacts' avatars, and\noptionally the signed-in user's own, so it can draw each shared photo\nand mood ring over them on its own layer.\n\nEach call replaces the product's placement; an empty `slots` and no\n`own` clears it. The own slot is filled only while the user has\ndisclosed a profile, and redrawn when they disclose or retract one.\nThe host draws only for contacts who shared a profile with the user,\nand keeps the placement current as they share or withdraw one, until\nthe product replaces it or goes away. The answer is the same whoever\nshared: nothing about any slot, and no profile data, returns to the\nproduct. Taps still reach the product, which opens a profile with\n`presentContact`.\n\nApp executions only. Rects are in the units of the surface size the\nproduct gives: framebuffer pixels for a PolkaVM product, CSS pixels of\nits viewport for a web product. A placement with more than 64 slots, a\nsurface side outside 1 to 16384, an avatar that is not square or is\noutside 1 to 1024 a side, or a `slot` repeated across `own` and `slots`\nis `Unknown`. A host that cannot draw over the product is\n`Unsupported`; with no user signed in the call is `NotConnected`.", + requestDescription: "HostProfilePlaceContactAvatarsRequest", + exampleSource: 'const result = await truapi.profile.placeContactAvatars({\n surfaceWidth: 360,\n surfaceHeight: 640,\n own: {\n slot: 1,\n rect: { x: 300, y: 16, width: 44, height: 44 },\n clip: { x: 0, y: 0, width: 360, height: 640 },\n },\n slots: [\n {\n slot: 0,\n contact: { tag: "Peer", value: {\n peerIdentity: "0x0000000000000000000000000000000000000000000000000000000000000000",\n } },\n rect: { x: 16, y: 80, width: 44, height: 44 },\n clip: { x: 0, y: 64, width: 360, height: 576 },\n },\n ],\n});\nconsole.log("contact avatars placed:", result);', + requestType: "host-profile-place-contact-avatars-request", + }, + { + name: "own_status", + type: "unary", + signature: "ownStatus(): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.own_status", + description: "Report whether the signed-in user has configured a profile.\n\nOnly the boolean status returns. The profile reference and contents\nremain host-owned.", + exampleSource: 'const result = await truapi.profile.ownStatus();\nconsole.log("own profile configured:", result);', + responseType: "host-profile-own-status-response", + }, + { + name: "present_own", + type: "unary", + signature: "presentOwn(): Promise>>", + docUrl: "api/profile/trait.Profile.html#method.present_own", + description: "Show the signed-in user's profile in host-owned UI.", + exampleSource: 'const result = await truapi.profile.presentOwn();\nconsole.log("own profile presentation:", result);', + }, + ], + }, { name: "Renderer", requiredExecution: "Worker", diff --git a/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts b/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts index 01b7c7553..56958adb6 100644 --- a/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts +++ b/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts @@ -1 +1 @@ -export declare const truapiDts = "// neverthrow (inlined)\n\ninterface ErrorConfig {\n withStackTrace: boolean;\n}\n\ndeclare class ResultAsync implements PromiseLike> {\n private _promise;\n constructor(res: Promise>);\n static fromSafePromise(promise: PromiseLike): ResultAsync;\n static fromPromise(promise: PromiseLike, errorFn: (e: unknown) => E): ResultAsync;\n static fromThrowable(fn: (...args: A) => Promise, errorFn?: (err: unknown) => E): (...args: A) => ResultAsync;\n static combine, ...ResultAsync[]]>(asyncResultList: T): CombineResultAsyncs;\n static combine[]>(asyncResultList: T): CombineResultAsyncs;\n static combineWithAllErrors, ...ResultAsync[]]>(asyncResultList: T): CombineResultsWithAllErrorsArrayAsync;\n static combineWithAllErrors[]>(asyncResultList: T): CombineResultsWithAllErrorsArrayAsync;\n map(f: (t: T) => A | Promise): ResultAsync;\n andThrough(f: (t: T) => Result | ResultAsync): ResultAsync;\n andTee(f: (t: T) => unknown): ResultAsync;\n orTee(f: (t: E) => unknown): ResultAsync;\n mapErr(f: (e: E) => U | Promise): ResultAsync;\n andThen>(f: (t: T) => R): ResultAsync, InferErrTypes | E>;\n andThen>(f: (t: T) => R): ResultAsync, InferAsyncErrTypes | E>;\n andThen(f: (t: T) => Result | ResultAsync): ResultAsync;\n orElse>(f: (e: E) => R): ResultAsync | T, InferErrTypes>;\n orElse>(f: (e: E) => R): ResultAsync | T, InferAsyncErrTypes>;\n orElse(f: (e: E) => Result | ResultAsync): ResultAsync;\n match(ok: (t: T) => A, _err: (e: E) => B): Promise;\n unwrapOr(t: A): Promise;\n /**\n * @deprecated will be removed in 9.0.0.\n *\n * You can use `safeTry` without this method.\n * @example\n * ```typescript\n * safeTry(async function* () {\n * const okValue = yield* yourResult\n * })\n * ```\n * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.\n */\n safeUnwrap(): AsyncGenerator, T>;\n then(successCallback?: (res: Result) => A | PromiseLike, failureCallback?: (reason: unknown) => B | PromiseLike): PromiseLike;\n [Symbol.asyncIterator](): AsyncGenerator, T>;\n}\ndeclare function okAsync(value: T): ResultAsync;\ndeclare function okAsync(value: void): ResultAsync;\ndeclare function errAsync(err: E): ResultAsync;\ndeclare function errAsync(err: void): ResultAsync;\ndeclare const fromPromise: typeof ResultAsync.fromPromise;\ndeclare const fromSafePromise: typeof ResultAsync.fromSafePromise;\ndeclare const fromAsyncThrowable: typeof ResultAsync.fromThrowable;\ndeclare type CombineResultAsyncs[]> = IsLiteralArray extends 1 ? TraverseAsync> : ResultAsync, ExtractErrAsyncTypes[number]>;\ndeclare type CombineResultsWithAllErrorsArrayAsync[]> = IsLiteralArray extends 1 ? TraverseWithAllErrorsAsync> : ResultAsync, ExtractErrAsyncTypes[number][]>;\ndeclare type UnwrapAsync = IsLiteralArray extends 1 ? Writable extends [infer H, ...infer Rest] ? H extends PromiseLike ? HI extends Result ? [Dedup, ...UnwrapAsync] : never : never : [] : T extends Array ? A extends PromiseLike ? HI extends Result ? Ok[] : never : never : never;\ndeclare type TraverseAsync = IsLiteralArray extends 1 ? Combine extends [infer Oks, infer Errs] ? ResultAsync, MembersToUnion> : never : T extends Array ? Combine, Depth> extends [infer Oks, infer Errs] ? Oks extends unknown[] ? Errs extends unknown[] ? ResultAsync, MembersToUnion> : ResultAsync, Errs> : Errs extends unknown[] ? ResultAsync> : ResultAsync : never : never;\ndeclare type TraverseWithAllErrorsAsync = TraverseAsync extends ResultAsync ? ResultAsync : never;\ndeclare type Writable = T extends ReadonlyArray ? [...T] : T;\n\ndeclare type ExtractOkTypes[]> = {\n [idx in keyof T]: T[idx] extends Result ? U : never;\n};\ndeclare type ExtractOkAsyncTypes[]> = {\n [idx in keyof T]: T[idx] extends ResultAsync ? U : never;\n};\ndeclare type ExtractErrTypes[]> = {\n [idx in keyof T]: T[idx] extends Result ? E : never;\n};\ndeclare type ExtractErrAsyncTypes[]> = {\n [idx in keyof T]: T[idx] extends ResultAsync ? E : never;\n};\ndeclare type InferOkTypes = R extends Result ? T : never;\ndeclare type InferErrTypes = R extends Result ? E : never;\ndeclare type InferAsyncOkTypes = R extends ResultAsync ? T : never;\ndeclare type InferAsyncErrTypes = R extends ResultAsync ? E : never;\n\ndeclare namespace Result {\n /**\n * Wraps a function with a try catch, creating a new function with the same\n * arguments but returning `Ok` if successful, `Err` if the function throws\n *\n * @param fn function to wrap with ok on success or err on failure\n * @param errorFn when an error is thrown, this will wrap the error result if provided\n */\n function fromThrowable any, E>(fn: Fn, errorFn?: (e: unknown) => E): (...args: Parameters) => Result, E>;\n function combine, ...Result[]]>(resultList: T): CombineResults;\n function combine[]>(resultList: T): CombineResults;\n function combineWithAllErrors, ...Result[]]>(resultList: T): CombineResultsWithAllErrorsArray;\n function combineWithAllErrors[]>(resultList: T): CombineResultsWithAllErrorsArray;\n}\ndeclare type Result = Ok | Err;\ndeclare function ok(value: T): Ok;\ndeclare function ok(value: void): Ok;\ndeclare function err(err: E): Err;\ndeclare function err(err: E): Err;\ndeclare function err(err: void): Err;\n/**\n * Evaluates the given generator to a Result returned or an Err yielded from it,\n * whichever comes first.\n *\n * This function is intended to emulate Rust's ? operator.\n * See `/tests/safeTry.test.ts` for examples.\n *\n * @param body - What is evaluated. In body, `yield* result` works as\n * Rust's `result?` expression.\n * @returns The first occurrence of either an yielded Err or a returned Result.\n */\ndeclare function safeTry(body: () => Generator, Result>): Result;\ndeclare function safeTry, GeneratorReturnResult extends Result>(body: () => Generator): Result, InferErrTypes | InferErrTypes>;\n/**\n * Evaluates the given generator to a Result returned or an Err yielded from it,\n * whichever comes first.\n *\n * This function is intended to emulate Rust's ? operator.\n * See `/tests/safeTry.test.ts` for examples.\n *\n * @param body - What is evaluated. In body, `yield* result` and\n * `yield* resultAsync` work as Rust's `result?` expression.\n * @returns The first occurrence of either an yielded Err or a returned Result.\n */\ndeclare function safeTry(body: () => AsyncGenerator, Result>): ResultAsync;\ndeclare function safeTry, GeneratorReturnResult extends Result>(body: () => AsyncGenerator): ResultAsync, InferErrTypes | InferErrTypes>;\ninterface IResult {\n /**\n * Used to check if a `Result` is an `OK`\n *\n * @returns `true` if the result is an `OK` variant of Result\n */\n isOk(): this is Ok;\n /**\n * Used to check if a `Result` is an `Err`\n *\n * @returns `true` if the result is an `Err` variant of Result\n */\n isErr(): this is Err;\n /**\n * Maps a `Result` to `Result`\n * by applying a function to a contained `Ok` value, leaving an `Err` value\n * untouched.\n *\n * @param f The function to apply an `OK` value\n * @returns the result of applying `f` or an `Err` untouched\n */\n map(f: (t: T) => A): Result;\n /**\n * Maps a `Result` to `Result` by applying a function to a\n * contained `Err` value, leaving an `Ok` value untouched.\n *\n * This function can be used to pass through a successful result while\n * handling an error.\n *\n * @param f a function to apply to the error `Err` value\n */\n mapErr(f: (e: E) => U): Result;\n /**\n * Similar to `map` Except you must return a new `Result`.\n *\n * This is useful for when you need to do a subsequent computation using the\n * inner `T` value, but that computation might fail.\n * Additionally, `andThen` is really useful as a tool to flatten a\n * `Result, E1>` into a `Result` (see example below).\n *\n * @param f The function to apply to the current value\n */\n andThen>(f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(f: (t: T) => Result): Result;\n /**\n * This \"tee\"s the current value to an passed-in computation such as side\n * effect functions but still returns the same current value as the result.\n *\n * This is useful when you want to pass the current result to your side-track\n * work such as logging but want to continue main-track work after that.\n * This method does not care about the result of the passed in computation.\n *\n * @param f The function to apply to the current value\n */\n andTee(f: (t: T) => unknown): Result;\n /**\n * This \"tee\"s the current `Err` value to an passed-in computation such as side\n * effect functions but still returns the same `Err` value as the result.\n *\n * This is useful when you want to pass the current `Err` value to your side-track\n * work such as logging but want to continue error-track work after that.\n * This method does not care about the result of the passed in computation.\n *\n * @param f The function to apply to the current `Err` value\n */\n orTee(f: (t: E) => unknown): Result;\n /**\n * Similar to `andTee` except error result of the computation will be passed\n * to the downstream in case of an error.\n *\n * This version is useful when you want to make side-effects but in case of an\n * error, you want to pass the error to the downstream.\n *\n * @param f The function to apply to the current value\n */\n andThrough>(f: (t: T) => R): Result | E>;\n andThrough(f: (t: T) => Result): Result;\n /**\n * Takes an `Err` value and maps it to a `Result`.\n *\n * This is useful for error recovery.\n *\n *\n * @param f A function to apply to an `Err` value, leaving `Ok` values\n * untouched.\n */\n orElse>(f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(f: (e: E) => Result): Result;\n /**\n * Similar to `map` Except you must return a new `Result`.\n *\n * This is useful for when you need to do a subsequent async computation using\n * the inner `T` value, but that computation might fail. Must return a ResultAsync\n *\n * @param f The function that returns a `ResultAsync` to apply to the current\n * value\n */\n asyncAndThen(f: (t: T) => ResultAsync): ResultAsync;\n /**\n * Maps a `Result` to `ResultAsync`\n * by applying an async function to a contained `Ok` value, leaving an `Err`\n * value untouched.\n *\n * @param f An async function to apply an `OK` value\n */\n asyncMap(f: (t: T) => Promise): ResultAsync;\n /**\n * Unwrap the `Ok` value, or return the default if there is an `Err`\n *\n * @param v the default value to return if there is an `Err`\n */\n unwrapOr(v: A): T | A;\n /**\n *\n * Given 2 functions (one for the `Ok` variant and one for the `Err` variant)\n * execute the function that matches the `Result` variant.\n *\n * Match callbacks do not necessitate to return a `Result`, however you can\n * return a `Result` if you want to.\n *\n * `match` is like chaining `map` and `mapErr`, with the distinction that\n * with `match` both functions must have the same return type.\n *\n * @param ok\n * @param err\n */\n match(ok: (t: T) => A, err: (e: E) => B): A | B;\n /**\n * @deprecated will be removed in 9.0.0.\n *\n * You can use `safeTry` without this method.\n * @example\n * ```typescript\n * safeTry(function* () {\n * const okValue = yield* yourResult\n * })\n * ```\n * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.\n */\n safeUnwrap(): Generator, T>;\n /**\n * **This method is unsafe, and should only be used in a test environments**\n *\n * Takes a `Result` and returns a `T` when the result is an `Ok`, otherwise it throws a custom object.\n *\n * @param config\n */\n _unsafeUnwrap(config?: ErrorConfig): T;\n /**\n * **This method is unsafe, and should only be used in a test environments**\n *\n * takes a `Result` and returns a `E` when the result is an `Err`,\n * otherwise it throws a custom object.\n *\n * @param config\n */\n _unsafeUnwrapErr(config?: ErrorConfig): E;\n}\ndeclare class Ok implements IResult {\n readonly value: T;\n constructor(value: T);\n isOk(): this is Ok;\n isErr(): this is Err;\n map(f: (t: T) => A): Result;\n mapErr(_f: (e: E) => U): Result;\n andThen>(f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(f: (t: T) => Result): Result;\n andThrough>(f: (t: T) => R): Result | E>;\n andThrough(f: (t: T) => Result): Result;\n andTee(f: (t: T) => unknown): Result;\n orTee(_f: (t: E) => unknown): Result;\n orElse>(_f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(_f: (e: E) => Result): Result;\n asyncAndThen(f: (t: T) => ResultAsync): ResultAsync;\n asyncAndThrough>(f: (t: T) => R): ResultAsync | E>;\n asyncAndThrough(f: (t: T) => ResultAsync): ResultAsync;\n asyncMap(f: (t: T) => Promise): ResultAsync;\n unwrapOr(_v: A): T | A;\n match(ok: (t: T) => A, _err: (e: E) => B): A | B;\n safeUnwrap(): Generator, T>;\n _unsafeUnwrap(_?: ErrorConfig): T;\n _unsafeUnwrapErr(config?: ErrorConfig): E;\n [Symbol.iterator](): Generator, T>;\n}\ndeclare class Err implements IResult {\n readonly error: E;\n constructor(error: E);\n isOk(): this is Ok;\n isErr(): this is Err;\n map(_f: (t: T) => A): Result;\n mapErr(f: (e: E) => U): Result;\n andThrough(_f: (t: T) => Result): Result;\n andTee(_f: (t: T) => unknown): Result;\n orTee(f: (t: E) => unknown): Result;\n andThen>(_f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(_f: (t: T) => Result): Result;\n orElse>(f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(f: (e: E) => Result): Result;\n asyncAndThen(_f: (t: T) => ResultAsync): ResultAsync;\n asyncAndThrough(_f: (t: T) => ResultAsync): ResultAsync;\n asyncMap(_f: (t: T) => Promise): ResultAsync;\n unwrapOr(v: A): T | A;\n match(_ok: (t: T) => A, err: (e: E) => B): A | B;\n safeUnwrap(): Generator, T>;\n _unsafeUnwrap(config?: ErrorConfig): T;\n _unsafeUnwrapErr(_?: ErrorConfig): E;\n [Symbol.iterator](): Generator, T>;\n}\ndeclare const fromThrowable: typeof Result.fromThrowable;\ndeclare type Prev = [\n never,\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 14,\n 15,\n 16,\n 17,\n 18,\n 19,\n 20,\n 21,\n 22,\n 23,\n 24,\n 25,\n 26,\n 27,\n 28,\n 29,\n 30,\n 31,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n ...0[]\n];\ndeclare type CollectResults = [\n Depth\n] extends [never] ? [] : T extends [infer H, ...infer Rest] ? H extends Result ? CollectResults : never : Collected;\ndeclare type Transpose = A extends [infer T, ...infer Rest] ? T extends [infer L, infer R] ? Transposed extends [infer PL, infer PR] ? PL extends unknown[] ? PR extends unknown[] ? Transpose : never : never : Transpose : Transposed : Transposed;\ndeclare type Combine = Transpose, [], Depth> extends [\n infer L,\n infer R\n] ? [UnknownMembersToNever, UnknownMembersToNever] : Transpose, [], Depth> extends [] ? [[], []] : never;\ndeclare type Dedup = T extends Result ? [unknown] extends [RL] ? Err : Ok : T;\ndeclare type MemberListOf = ((T extends unknown ? (t: T) => T : never) extends infer U ? (U extends unknown ? (u: U) => unknown : never) extends (v: infer V) => unknown ? V : never : never) extends (_: unknown) => infer W ? [...MemberListOf>, W] : [];\ndeclare type EmptyArrayToNever = T extends [] ? never : NeverArrayToNever extends 1 ? T extends [never, ...infer Rest] ? [EmptyArrayToNever] extends [never] ? never : T : T : T;\ndeclare type UnknownMembersToNever = T extends [infer H, ...infer R] ? [[unknown] extends [H] ? never : H, ...UnknownMembersToNever] : T;\ndeclare type MembersToUnion = T extends unknown[] ? T[number] : never;\ndeclare type IsLiteralArray = T extends {\n length: infer L;\n} ? L extends number ? number extends L ? 0 : 1 : 0 : 0;\ndeclare type Traverse = Combine extends [infer Oks, infer Errs] ? Result, MembersToUnion> : never;\ndeclare type TraverseWithAllErrors = Traverse extends Result ? Result : never;\ndeclare type CombineResults[]> = IsLiteralArray extends 1 ? Traverse : Result, ExtractErrTypes[number]>;\ndeclare type CombineResultsWithAllErrorsArray[]> = IsLiteralArray extends 1 ? TraverseWithAllErrors : Result, ExtractErrTypes[number][]>;\n\n\n\n// scale.d.ts (module-scope)\n\n/** SCALE codec primitives used by the generated client.\n *\n * Thin wrapper over `scale-ts`: re-exports its primitives and combinators,\n * plus the Polkadot-flavour helpers it does not ship (hex-encoded bytes,\n * lazy recursive codecs, and `V`-indexed tagged unions).\n */\nimport { type Codec, type ResultPayload } from \"scale-ts\";\nexport type { Codec };\nexport type { ResultPayload } from \"scale-ts\";\n/**\n * Bare-named type alias matching generated codegen's naming convention for\n * generic wire types: `Result` is used as both a value (the codec\n * builder re-exported below) and a type (this alias for scale-ts's own\n * `ResultPayload`) in generated `types.ts`.\n */\nexport type Result = ResultPayload;\nexport { Bytes, Enum, Option, Result, Struct, Tuple, Vector, _void, compact, i8, i16, i32, i64, i128, str, u8, u16, u32, u64, u128, } from \"scale-ts\";\n/** SCALE boolean, rejecting byte values Rust cannot decode. */\nexport declare const bool: Codec;\n/**\n * Substrate `OptionBool`: a one-byte `Option`.\n *\n * Canonical SCALE encoding (matches `parity_scale_codec::OptionBool`):\n * `undefined` \u2192 `0`, `true` \u2192 `1`, `false` \u2192 `2`.\n */\nexport declare const OptionBool: Codec;\n/** Hex-encoded byte string, e.g. `\"0xdeadbeef\"`. */\nexport type HexString = `0x${string}`;\n/** Assert that a string is a valid hex string (`0x...`). */\nexport declare function toHexString(value: string): HexString;\n/** Encode a byte array as a lower-case hex string with a `0x` prefix. */\nexport declare function bytesToHex(bytes: Uint8Array): HexString;\n/** Decode a hex string into a byte array. Tolerates a missing `0x` prefix. */\nexport declare function hexToBytes(hex: string): Uint8Array;\n/**\n * SCALE codec for hex-encoded byte strings.\n *\n * Encode accepts a `0x`-prefixed hex string and emits SCALE bytes; decode\n * returns the bytes as a hex string. Pass `length` for fixed-size byte arrays\n * (`[u8; N]`); omit it for variable-length byte vectors (`Vec`).\n */\nexport declare function Hex(length?: number): Codec;\n/**\n * Same wire format as `scale-ts`'s `Enum`, but exposes `value` as optional in\n * the public TS type when the variant codec is `Codec`. Lets unit\n * variants of mixed enums round-trip as `{ tag: \"X\" }` (no `value` key).\n */\nexport declare function TaggedUnion(inner: O): Codec>;\n/** Public TS value for Rust's derived `CallError` enum. */\nexport type CallErrorValue = {\n tag: \"Domain\";\n value: D;\n} | {\n tag: \"Denied\";\n value?: undefined;\n} | {\n tag: \"Unsupported\";\n value?: undefined;\n} | {\n tag: \"MalformedFrame\";\n value: {\n reason: string;\n };\n} | {\n tag: \"HostFailure\";\n value: {\n reason: string;\n };\n} | {\n tag: \"Cancelled\";\n value?: undefined;\n};\n/** SCALE codec for Rust's derived `CallError` enum. */\nexport declare function CallError(domain: Codec): Codec>;\ntype TaggedUnionCodecs = {\n [Sym: symbol]: never;\n [Num: number]: never;\n [Str: string]: Codec;\n};\ntype TaggedUnionValue = {\n [K in keyof O & string]: O[K] extends Codec ? [T] extends [undefined] ? {\n tag: K;\n value?: undefined;\n } : {\n tag: K;\n value: T;\n } : never;\n}[keyof O & string];\n/**\n * Enum without payloads \u2014 maps string labels to SCALE discriminant bytes.\n *\n * `scale-ts` models `Enum({ Foo: _void, Bar: _void })` as tagged objects. For\n * user-facing TrUAPI enums with only unit variants, we keep the public TS shape\n * as a plain string union instead.\n */\nexport declare function Status(...variants: readonly T[]): Codec;\n/**\n * Defers codec construction until first use so recursive generated codecs can\n * reference each other safely.\n */\nexport declare function lazy(factory: () => Codec): Codec;\ntype IndexedVariantCodec = readonly [index: number, codec: Codec];\ntype IndexedVariantValue>, K extends keyof Variants & string> = Variants[K] extends IndexedVariantCodec ? [T] extends [undefined] ? {\n tag: K;\n value?: undefined;\n} : {\n tag: K;\n value: T;\n} : never;\n/**\n * Builds a tagged union codec with explicit SCALE discriminants.\n *\n * `scale-ts` assigns enum indexes by object key order. TrUAPI versioned enums pin\n * `V` to index `N - 1`, including V2-only enums, so generated codecs use this\n * helper for versioned wire wrappers.\n */\nexport declare function indexedTaggedUnion>>(variants: Variants): Codec<{\n [K in keyof Variants & string]: IndexedVariantValue;\n}[keyof Variants & string]>;\n\n\n// generated/types.d.ts (namespace T)\n\ndeclare namespace T {\n/**\n * A press on a button the host draws for a `ChatMessageContent::Actions`\n * message.\n */\nexport interface ActionTrigger {\n /**\n * Message containing the action, as returned by `Chat::post_message` in\n * [`HostChatPostMessageResponse::message_id`].\n */\n messageId: string;\n /** Which action was triggered. */\n actionId: string;\n /** Optional additional data. */\n payload?: HexString;\n}\nexport const ActionTrigger: Codec;\n/**\n * A resource the host can pre-allocate on behalf of the product (RFC 0010).\n *\n * For the slot-table allowances (`StatementStoreAllowance`,\n * `BulletinAllowance`, `SmartContractAllowance`), pre-allocation is\n * opportunistic and the host may also fulfil the allowance implicitly on the\n * first submission. `AutoSigning` must be requested explicitly through this\n * call.\n */\nexport type AllocatableResource = \n/** Statement Store slot allowance for the product's own allowance account. */\n{\n tag: \"StatementStoreAllowance\";\n value?: undefined;\n}\n/** Bulletin chain slot allowance for the product's own allowance account. */\n | {\n tag: \"BulletinAllowance\";\n value?: undefined;\n}\n/**\n * Pre-warmed PGAS balance for the product account selected by this\n * derivation index.\n */\n | {\n tag: \"SmartContractAllowance\";\n value: DerivationIndex;\n}\n/** Permission to sign on the product's behalf without per-call user prompts. */\n | {\n tag: \"AutoSigning\";\n value?: undefined;\n}\n/**\n * Current UTC-day Statement Store allowance whose target is the product\n * account selected by this derivation index.\n */\n | {\n tag: \"ProductStatementStoreAllowance\";\n value: DerivationIndex;\n};\nexport const AllocatableResource: Codec;\n/** Outcome of allocating a single resource (RFC 0010). */\nexport type AllocationOutcome = \"Allocated\" | \"Rejected\" | \"NotAvailable\";\nexport const AllocationOutcome: Codec;\n/** Main-axis distribution of children. */\nexport type Arrangement = \"Start\" | \"End\" | \"Center\" | \"SpaceBetween\" | \"SpaceAround\" | \"SpaceEvenly\";\nexport const Arrangement: Codec;\n/** Background styling. */\nexport interface Background {\n /** Background color. */\n color: ColorToken;\n /** Background shape. */\n shape?: Shape;\n}\nexport const Background: Codec;\n/**\n * How a node composites with what is behind it. The values are those common\n * to CSS `mix-blend-mode`, SwiftUI `BlendMode` and Compose `BlendMode`.\n */\nexport type BlendingMode = \"Normal\" | \"Multiply\" | \"Screen\" | \"Overlay\" | \"Darken\" | \"Lighten\" | \"ColorDodge\" | \"ColorBurn\" | \"HardLight\" | \"SoftLight\" | \"Difference\" | \"Exclusion\" | \"Hue\" | \"Saturation\" | \"Color\" | \"Luminosity\";\nexport const BlendingMode: Codec;\n/** Border styling. */\nexport interface BorderStyle {\n /** Border width. */\n width: Size;\n /** Border color. */\n color: ColorToken;\n /** Border shape. */\n shape?: Shape;\n}\nexport const BorderStyle: Codec;\n/** Properties of a `Box`. */\nexport interface BoxProps {\n /** Placement of content within the box. */\n contentAlignment?: ContentAlignment;\n}\nexport const BoxProps: Codec;\n/** Properties of a `Button`. */\nexport interface ButtonProps {\n /** Button label. */\n text: string;\n /** Button emphasis. */\n variant?: ButtonVariant;\n /** Whether the button accepts presses. Absent leaves the default to the host. */\n enabled?: boolean;\n /**\n * Whether the button shows a loading state. A loading button accepts no\n * presses. Absent leaves the default to the host.\n */\n loading?: boolean;\n /** Action triggered on press. A button without one is inert. */\n clickAction?: string;\n}\nexport const ButtonProps: Codec;\n/** Button emphasis. */\nexport type ButtonVariant = \"Primary\" | \"Secondary\" | \"Text\";\nexport const ButtonVariant: Codec;\n/**\n * A 32-byte value, passed as plain bytes on FFI surfaces. Version-neutral:\n * the FFI conversion below applies to `[u8; 32]` fields in every protocol\n * version.\n */\nexport type Bytes32 = HexString;\nexport const Bytes32: Codec;\n/** Role of a chain within the host's configured environment. */\nexport type ChainIdentifier = \"Relay\" | \"AssetHub\" | \"People\" | \"Bulletin\";\nexport const ChainIdentifier: Codec;\n/** A clickable action button in a chat message. */\nexport interface ChatAction {\n /** Action identifier. */\n actionId: string;\n /** Button label. */\n title: string;\n}\nexport const ChatAction: Codec;\n/** Layout for action buttons. */\nexport type ChatActionLayout = \"Column\" | \"Grid\";\nexport const ChatActionLayout: Codec;\n/** Payload of a received chat action. */\nexport type ChatActionPayload = \n/** A peer posted a message. */\n{\n tag: \"MessagePosted\";\n value: ChatMessageContent;\n}\n/** A user pressed a host-drawn `Actions` button. */\n | {\n tag: \"ActionTriggered\";\n value: ActionTrigger;\n}\n/** A user issued a command. */\n | {\n tag: \"Command\";\n value: ChatCommand;\n};\nexport const ChatActionPayload: Codec;\n/** A set of action buttons with optional text. */\nexport interface ChatActions {\n /** Optional message text. */\n text?: string;\n /** List of action buttons. */\n actions: Array;\n /** `Column` or `Grid` layout. */\n layout: ChatActionLayout;\n}\nexport const ChatActions: Codec;\n/** Whether the bot was newly registered or already existed. */\nexport type ChatBotRegistrationStatus = \"New\" | \"Exists\";\nexport const ChatBotRegistrationStatus: Codec;\n/** A slash command from a chat user. */\nexport interface ChatCommand {\n /** Command name. */\n command: string;\n /** Command arguments. */\n payload: string;\n}\nexport const ChatCommand: Codec;\n/**\n * A custom message with application-defined type and binary payload. The\n * host draws it through `Renderer::render`, with a `ChatMessage` context\n * carrying `message_type` and `payload` as the render payload.\n */\nexport interface ChatCustomMessage {\n /** Application-defined type key. */\n messageType: string;\n /** Binary payload. */\n payload: HexString;\n}\nexport const ChatCustomMessage: Codec;\n/** A file attachment in a chat message. */\nexport interface ChatFile {\n /** File download URL. */\n url: string;\n /** File name. */\n fileName: string;\n /** MIME type. */\n mimeType: string;\n /** File size in bytes. */\n sizeBytes: bigint;\n /** Optional caption text. */\n text?: string;\n}\nexport const ChatFile: Codec;\n/** A media attachment. */\nexport interface ChatMedia {\n /** Media URL. */\n url: string;\n}\nexport const ChatMedia: Codec;\n/** Content of a chat message -- one of several types. */\nexport type ChatMessageContent = \n/** Plain text message. */\n{\n tag: \"Text\";\n value: {\n text: string;\n };\n}\n/** Rich text with media. */\n | {\n tag: \"RichText\";\n value: ChatRichText;\n}\n/** Action button set. */\n | {\n tag: \"Actions\";\n value: ChatActions;\n}\n/** File attachment. */\n | {\n tag: \"File\";\n value: ChatFile;\n}\n/** Emoji reaction. */\n | {\n tag: \"Reaction\";\n value: ChatReaction;\n}\n/** Reaction removal. */\n | {\n tag: \"ReactionRemoved\";\n value: ChatReaction;\n}\n/** Custom message. */\n | {\n tag: \"Custom\";\n value: ChatCustomMessage;\n};\nexport const ChatMessageContent: Codec;\n/** A reaction to a chat message. */\nexport interface ChatReaction {\n /** Message being reacted to. */\n messageId: string;\n /** Emoji reaction. */\n emoji: string;\n}\nexport const ChatReaction: Codec;\n/** Rich text message with optional media. */\nexport interface ChatRichText {\n /** Optional text content. */\n text?: string;\n /** Attached media items. */\n media: Array;\n}\nexport const ChatRichText: Codec;\n/** A chat room the product participates in. */\nexport interface ChatRoom {\n /** Room identifier. */\n roomId: string;\n /** `RoomHost` or `Bot`. */\n participatingAs: ChatRoomParticipation;\n}\nexport const ChatRoom: Codec;\n/** How the product participates in a chat room. */\nexport type ChatRoomParticipation = \"RoomHost\" | \"Bot\";\nexport const ChatRoomParticipation: Codec;\n/** Whether the room was newly created or already existed. */\nexport type ChatRoomRegistrationStatus = \"New\" | \"Exists\";\nexport const ChatRoomRegistrationStatus: Codec;\n/** Standardized encrypted Coinage secret transmission payload. */\nexport interface CoinPaymentCheque {\n /** Receivable public key protecting the cheque contents. */\n id: HexString;\n /** Claimed payment amount. */\n amount: number;\n /** Concatenated coin secrets encrypted to the receivable. */\n encryptedSecrets: HexString;\n}\nexport const CoinPaymentCheque: Codec;\n/** Product-visible clearing reference for reconciliation and receipts. */\nexport interface CoinPaymentClearingReference {\n /** Clearing Merkle root. */\n root: HexString;\n /** Product-visible coin key and transaction hash leaves. */\n leaves: Array<[HexString, HexString]>;\n}\nexport const CoinPaymentClearingReference: Codec;\n/** Errors returned by CoinPayment host operations. */\nexport type CoinPaymentError = \"BalanceLow\" | \"Denied\" | \"BadCoins\" | \"SnipedCoins\" | \"PurseNotFound\" | \"ReceivableNotFound\" | \"UnsupportedChannel\" | \"UserAgentCapabilityUnavailable\" | \"Internal\";\nexport const CoinPaymentError: Codec;\n/** Product-visible metadata and balance state for a CoinPayment purse. */\nexport interface CoinPaymentPurseInfo {\n /** Human-readable purse name supplied by the creating product. */\n name: string;\n /** Creation timestamp. */\n created: bigint;\n /** Product that created the purse. */\n creator: string;\n /** Current product-visible balance. */\n balance: number;\n}\nexport const CoinPaymentPurseInfo: Codec;\n/** Clearing status stream item. */\nexport type CoinPaymentStatus = \n/** More coins have cleared. */\n{\n tag: \"Clearing\";\n value: {\n clearing: number;\n cleared: number;\n };\n}\n/** Some or all coins failed to transfer. */\n | {\n tag: \"Failed\";\n value: {\n error: CoinPaymentError;\n cleared: number;\n reference: CoinPaymentClearingReference;\n };\n}\n/** All coins cleared. */\n | {\n tag: \"Done\";\n value: {\n cleared: number;\n reference: CoinPaymentClearingReference;\n };\n};\nexport const CoinPaymentStatus: Codec;\n/** Standardized cheque transmission channel. */\nexport type CoinPaymentTransmissionChannel = \n/** Statement-store/HOP handoff identified by an SSS topic. */\n{\n tag: \"Standard\";\n value: {\n sssTopic: HexString;\n };\n};\nexport const CoinPaymentTransmissionChannel: Codec;\n/** Semantic color tokens, resolved by the host's theme. */\nexport type ColorToken = \"FgPrimary\" | \"FgSecondary\" | \"FgTertiary\" | \"BgSurfaceMain\" | \"BgSurfaceContainer\" | \"BgSurfaceNested\" | \"FgSuccess\" | \"FgError\" | \"FgWarning\";\nexport const ColorToken: Codec;\n/** Properties of a `Column`. */\nexport interface ColumnProps {\n /** Cross-axis alignment of children. */\n horizontalAlignment?: HorizontalAlignment;\n /** Main-axis distribution of children. */\n verticalArrangement?: Arrangement;\n}\nexport const ColumnProps: Codec;\n/**\n * A contact as a product knows them: 32 bytes and nothing else.\n *\n * Its own type rather than a bare [`Bytes32`], because an account id is also\n * 32 bytes. A product that could pass one where the other is expected would\n * build a valid-looking transfer to an address nobody controls. A handle is\n * not an address, and the type is where that is said.\n */\nexport interface ContactHandle {\n /** The handle's bytes. */\n bytes: Bytes32;\n}\nexport const ContactHandle: Codec;\n/**\n * How a contact pick ended.\n *\n * Distinguishing these matters to a product deciding what to do next: a\n * dismissal is worth retrying, an empty list is not.\n */\nexport type ContactPickOutcome = \n/**\n * The user chose someone.\n *\n * `handle` is the same value for this person in every product, and on every\n * host of this user. It is not an address and cannot be turned into one:\n * the core resolves it when it builds a transaction, so a product can name\n * a recipient it never learns the account of.\n */\n{\n tag: \"Picked\";\n value: {\n handle: ContactHandle;\n };\n}\n/** The user closed the picker without choosing. */\n | {\n tag: \"Dismissed\";\n value?: undefined;\n}\n/** The user has no contacts, so no picker was shown. */\n | {\n tag: \"NoContacts\";\n value?: undefined;\n};\nexport const ContactPickOutcome: Codec;\n/** Placement of content within a `Box`. */\nexport type ContentAlignment = \"TopStart\" | \"TopCenter\" | \"TopEnd\" | \"CenterStart\" | \"Center\" | \"CenterEnd\" | \"BottomStart\" | \"BottomCenter\" | \"BottomEnd\";\nexport const ContentAlignment: Codec;\n/** A privacy-preserving alias derived via ring VRF, bound to a specific context. */\nexport interface ContextualAlias {\n /** 32-byte context identifier the alias is bound to. */\n context: HexString;\n /** Ring VRF alias (variable length). */\n alias: HexString;\n}\nexport const ContextualAlias: Codec;\n/**\n * Account selector within a product subtree. Encodes as\n * `Either` on the wire (`Index` = left, `Raw` = right).\n *\n * `Index` is the primary form \u2014 plain indices keep a product's accounts\n * enumerable. `Raw` carries a raw 32-byte derivation index for cases where\n * bytes are genuinely necessary. Hosts expand `Index(n)` to the internal\n * 32-byte index (`u32` little-endian plus the index magic).\n */\nexport type DerivationIndex = \n/** Plain account index. */\n{\n tag: \"Index\";\n value: number;\n}\n/** Raw 32-byte derivation index. */\n | {\n tag: \"Raw\";\n value: HexString;\n};\nexport const DerivationIndex: Codec;\n/** Edge dimensions. `bottom` defaults to `top` and `start` to `end` when absent. */\nexport interface Dimensions {\n /** Top edge. */\n top: Size;\n /** End edge. */\n end: Size;\n /** Bottom edge; defaults to `top`. */\n bottom?: Size;\n /** Start edge; defaults to `end`. */\n start?: Size;\n}\nexport const Dimensions: Codec;\n/** A visual effect. Each variant names one effect and carries its parameters. */\nexport type Effect = \"Rainbow\";\nexport const Effect: Codec;\n/** Properties of an `Effect`. */\nexport interface EffectProps {\n /** The effect applied to the children. */\n effect: Effect;\n}\nexport const EffectProps: Codec;\n/**\n * Generic error payload carrying a human-readable reason string. Used by many\n * methods as a catch-all error type.\n */\nexport interface GenericError {\n /** Human-readable failure reason. */\n reason: string;\n}\nexport const GenericError: Codec;\n/** Cross-axis alignment of `Column` children. */\nexport type HorizontalAlignment = \"Start\" | \"Center\" | \"End\";\nexport const HorizontalAlignment: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeError`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeError: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeItem`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountConnectionStatusSubscribeItem;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeItem: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeRequest`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeRequest: Codec;\n/** Versioned envelope for [`HostAccountCreateProofError`]. */\nexport type VersionedHostAccountCreateProofError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofError;\n};\nexport const VersionedHostAccountCreateProofError: Codec;\n/** Versioned envelope for [`HostAccountCreateProofRequest`]. */\nexport type VersionedHostAccountCreateProofRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofRequest;\n};\nexport const VersionedHostAccountCreateProofRequest: Codec;\n/** Versioned envelope for [`HostAccountCreateProofResponse`]. */\nexport type VersionedHostAccountCreateProofResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofResponse;\n};\nexport const VersionedHostAccountCreateProofResponse: Codec;\n/** Versioned envelope for [`HostAccountGetAliasError`]. */\nexport type VersionedHostAccountGetAliasError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetAliasError;\n};\nexport const VersionedHostAccountGetAliasError: Codec;\n/** Versioned envelope for [`HostAccountGetAliasRequest`]. */\nexport type VersionedHostAccountGetAliasRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetAliasRequest;\n};\nexport const VersionedHostAccountGetAliasRequest: Codec;\n/** Versioned envelope for [`HostAccountGetAliasResponse`]. */\nexport type VersionedHostAccountGetAliasResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ContextualAlias;\n};\nexport const VersionedHostAccountGetAliasResponse: Codec;\n/** Versioned envelope for [`HostAccountGetError`]. */\nexport type VersionedHostAccountGetError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetError;\n};\nexport const VersionedHostAccountGetError: Codec;\n/** Versioned envelope for [`HostAccountGetRequest`]. */\nexport type VersionedHostAccountGetRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetRequest;\n};\nexport const VersionedHostAccountGetRequest: Codec;\n/** Versioned envelope for [`HostAccountGetResponse`]. */\nexport type VersionedHostAccountGetResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetResponse;\n};\nexport const VersionedHostAccountGetResponse: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysError`]. */\nexport type VersionedHostAccountListRingVrfKeysError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountListRingVrfKeysError;\n};\nexport const VersionedHostAccountListRingVrfKeysError: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysRequest`]. */\nexport type VersionedHostAccountListRingVrfKeysRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountListRingVrfKeysRequest;\n};\nexport const VersionedHostAccountListRingVrfKeysRequest: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysResponse`]. */\nexport type VersionedHostAccountListRingVrfKeysResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: Array;\n};\nexport const VersionedHostAccountListRingVrfKeysResponse: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyError`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRegisterRingVrfKeyError;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyError: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyRequest`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRegisterRingVrfKeyRequest;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyRequest: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyResponse`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyResponse: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignError`]. */\nexport type VersionedHostAccountRingVrfSignError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRingVrfSignError;\n};\nexport const VersionedHostAccountRingVrfSignError: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignRequest`]. */\nexport type VersionedHostAccountRingVrfSignRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRingVrfSignRequest;\n};\nexport const VersionedHostAccountRingVrfSignRequest: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignResponse`]. */\nexport type VersionedHostAccountRingVrfSignResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedHostAccountRingVrfSignResponse: Codec;\n/** Versioned envelope for [`HostAccountSignVrfError`]. */\nexport type VersionedHostAccountSignVrfError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountSignVrfError;\n};\nexport const VersionedHostAccountSignVrfError: Codec;\n/** Versioned envelope for [`HostAccountSignVrfRequest`]. */\nexport type VersionedHostAccountSignVrfRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountSignVrfRequest;\n};\nexport const VersionedHostAccountSignVrfRequest: Codec;\n/** Versioned envelope for [`HostAccountSignVrfResponse`]. */\nexport type VersionedHostAccountSignVrfResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: VrfSignature;\n};\nexport const VersionedHostAccountSignVrfResponse: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeError`]. */\nexport type VersionedHostChatActionSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostChatActionSubscribeError: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeItem`]. */\nexport type VersionedHostChatActionSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatActionSubscribeItem;\n};\nexport const VersionedHostChatActionSubscribeItem: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeRequest`]. */\nexport type VersionedHostChatActionSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostChatActionSubscribeRequest: Codec;\n/** Versioned envelope for [`HostChatCreateRoomError`]. */\nexport type VersionedHostChatCreateRoomError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomError;\n};\nexport const VersionedHostChatCreateRoomError: Codec;\n/** Versioned envelope for [`HostChatCreateRoomRequest`]. */\nexport type VersionedHostChatCreateRoomRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomRequest;\n};\nexport const VersionedHostChatCreateRoomRequest: Codec;\n/** Versioned envelope for [`HostChatCreateRoomResponse`]. */\nexport type VersionedHostChatCreateRoomResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomResponse;\n};\nexport const VersionedHostChatCreateRoomResponse: Codec;\n/** Versioned envelope for [`HostChatListSubscribeError`]. */\nexport type VersionedHostChatListSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostChatListSubscribeError: Codec;\n/** Versioned envelope for [`HostChatListSubscribeItem`]. */\nexport type VersionedHostChatListSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatListSubscribeItem;\n};\nexport const VersionedHostChatListSubscribeItem: Codec;\n/** Versioned envelope for [`HostChatListSubscribeRequest`]. */\nexport type VersionedHostChatListSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostChatListSubscribeRequest: Codec;\n/** Versioned envelope for [`HostChatPostMessageError`]. */\nexport type VersionedHostChatPostMessageError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageError;\n};\nexport const VersionedHostChatPostMessageError: Codec;\n/** Versioned envelope for [`HostChatPostMessageRequest`]. */\nexport type VersionedHostChatPostMessageRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageRequest;\n};\nexport const VersionedHostChatPostMessageRequest: Codec;\n/** Versioned envelope for [`HostChatPostMessageResponse`]. */\nexport type VersionedHostChatPostMessageResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageResponse;\n};\nexport const VersionedHostChatPostMessageResponse: Codec;\n/** Versioned envelope for [`HostChatRegisterBotError`]. */\nexport type VersionedHostChatRegisterBotError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotError;\n};\nexport const VersionedHostChatRegisterBotError: Codec;\n/** Versioned envelope for [`HostChatRegisterBotRequest`]. */\nexport type VersionedHostChatRegisterBotRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotRequest;\n};\nexport const VersionedHostChatRegisterBotRequest: Codec;\n/** Versioned envelope for [`HostChatRegisterBotResponse`]. */\nexport type VersionedHostChatRegisterBotResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotResponse;\n};\nexport const VersionedHostChatRegisterBotResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeError`]. */\nexport type VersionedHostCoinPaymentCreateChequeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreateChequeError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeRequest`]. */\nexport type VersionedHostCoinPaymentCreateChequeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateChequeRequest;\n};\nexport const VersionedHostCoinPaymentCreateChequeRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeResponse`]. */\nexport type VersionedHostCoinPaymentCreateChequeResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateChequeResponse;\n};\nexport const VersionedHostCoinPaymentCreateChequeResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseError`]. */\nexport type VersionedHostCoinPaymentCreatePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreatePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseRequest`]. */\nexport type VersionedHostCoinPaymentCreatePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreatePurseRequest;\n};\nexport const VersionedHostCoinPaymentCreatePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseResponse`]. */\nexport type VersionedHostCoinPaymentCreatePurseResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreatePurseResponse;\n};\nexport const VersionedHostCoinPaymentCreatePurseResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableError`]. */\nexport type VersionedHostCoinPaymentCreateReceivableError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreateReceivableError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableRequest`]. */\nexport type VersionedHostCoinPaymentCreateReceivableRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateReceivableRequest;\n};\nexport const VersionedHostCoinPaymentCreateReceivableRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableResponse`]. */\nexport type VersionedHostCoinPaymentCreateReceivableResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateReceivableResponse;\n};\nexport const VersionedHostCoinPaymentCreateReceivableResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseError`]. */\nexport type VersionedHostCoinPaymentDeletePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentDeletePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseItem`]. */\nexport type VersionedHostCoinPaymentDeletePurseItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentDeletePurseItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseRequest`]. */\nexport type VersionedHostCoinPaymentDeletePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentDeletePurseRequest;\n};\nexport const VersionedHostCoinPaymentDeletePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositError`]. */\nexport type VersionedHostCoinPaymentDepositError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentDepositError: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositItem`]. */\nexport type VersionedHostCoinPaymentDepositItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentDepositItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositRequest`]. */\nexport type VersionedHostCoinPaymentDepositRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentDepositRequest;\n};\nexport const VersionedHostCoinPaymentDepositRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForError`]. */\nexport type VersionedHostCoinPaymentListenForError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentListenForError: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForItem`]. */\nexport type VersionedHostCoinPaymentListenForItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentListenForItem;\n};\nexport const VersionedHostCoinPaymentListenForItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForRequest`]. */\nexport type VersionedHostCoinPaymentListenForRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentListenForRequest;\n};\nexport const VersionedHostCoinPaymentListenForRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseError`]. */\nexport type VersionedHostCoinPaymentQueryPurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentQueryPurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseRequest`]. */\nexport type VersionedHostCoinPaymentQueryPurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentQueryPurseRequest;\n};\nexport const VersionedHostCoinPaymentQueryPurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseResponse`]. */\nexport type VersionedHostCoinPaymentQueryPurseResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentQueryPurseResponse;\n};\nexport const VersionedHostCoinPaymentQueryPurseResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseError`]. */\nexport type VersionedHostCoinPaymentRebalancePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentRebalancePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseItem`]. */\nexport type VersionedHostCoinPaymentRebalancePurseItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentRebalancePurseItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseRequest`]. */\nexport type VersionedHostCoinPaymentRebalancePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentRebalancePurseRequest;\n};\nexport const VersionedHostCoinPaymentRebalancePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundError`]. */\nexport type VersionedHostCoinPaymentRefundError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentRefundError: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundItem`]. */\nexport type VersionedHostCoinPaymentRefundItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentRefundItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundRequest`]. */\nexport type VersionedHostCoinPaymentRefundRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentRefundRequest;\n};\nexport const VersionedHostCoinPaymentRefundRequest: Codec;\n/** Versioned envelope for [`HostContactsPickError`]. */\nexport type VersionedHostContactsPickError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickError;\n};\nexport const VersionedHostContactsPickError: Codec;\n/** Versioned envelope for [`HostContactsPickRequest`]. */\nexport type VersionedHostContactsPickRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickRequest;\n};\nexport const VersionedHostContactsPickRequest: Codec;\n/** Versioned envelope for [`HostContactsPickResponse`]. */\nexport type VersionedHostContactsPickResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickResponse;\n};\nexport const VersionedHostContactsPickResponse: Codec;\n/** Versioned envelope for [`HostCreateTransactionError`]. */\nexport type VersionedHostCreateTransactionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionError;\n};\nexport const VersionedHostCreateTransactionError: Codec;\n/** Versioned envelope for [`HostCreateTransactionRequest`]. */\nexport type VersionedHostCreateTransactionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ProductAccountTxPayload;\n};\nexport const VersionedHostCreateTransactionRequest: Codec;\n/** Versioned envelope for [`HostCreateTransactionResponse`]. */\nexport type VersionedHostCreateTransactionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionResponse;\n};\nexport const VersionedHostCreateTransactionResponse: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountError`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionError;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountRequest`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: LegacyAccountTxPayload;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountResponse`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionWithLegacyAccountResponse;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostDeriveEntropyError`]. */\nexport type VersionedHostDeriveEntropyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyError;\n};\nexport const VersionedHostDeriveEntropyError: Codec;\n/** Versioned envelope for [`HostDeriveEntropyRequest`]. */\nexport type VersionedHostDeriveEntropyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyRequest;\n};\nexport const VersionedHostDeriveEntropyRequest: Codec;\n/** Versioned envelope for [`HostDeriveEntropyResponse`]. */\nexport type VersionedHostDeriveEntropyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyResponse;\n};\nexport const VersionedHostDeriveEntropyResponse: Codec;\n/** Versioned envelope for [`HostDevicePermissionError`]. */\nexport type VersionedHostDevicePermissionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostDevicePermissionError: Codec;\n/** Versioned envelope for [`HostDevicePermissionRequest`]. */\nexport type VersionedHostDevicePermissionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDevicePermissionRequest;\n};\nexport const VersionedHostDevicePermissionRequest: Codec;\n/** Versioned envelope for [`HostDevicePermissionResponse`]. */\nexport type VersionedHostDevicePermissionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDevicePermissionResponse;\n};\nexport const VersionedHostDevicePermissionResponse: Codec;\n/** Versioned envelope for [`HostFeatureSupportedError`]. */\nexport type VersionedHostFeatureSupportedError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostFeatureSupportedError: Codec;\n/** Versioned envelope for [`HostFeatureSupportedRequest`]. */\nexport type VersionedHostFeatureSupportedRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostFeatureSupportedRequest;\n};\nexport const VersionedHostFeatureSupportedRequest: Codec;\n/** Versioned envelope for [`HostFeatureSupportedResponse`]. */\nexport type VersionedHostFeatureSupportedResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostFeatureSupportedResponse;\n};\nexport const VersionedHostFeatureSupportedResponse: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsError`]. */\nexport type VersionedHostGetLegacyAccountsError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetError;\n};\nexport const VersionedHostGetLegacyAccountsError: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsRequest`]. */\nexport type VersionedHostGetLegacyAccountsRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetLegacyAccountsRequest: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsResponse`]. */\nexport type VersionedHostGetLegacyAccountsResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetLegacyAccountsResponse;\n};\nexport const VersionedHostGetLegacyAccountsResponse: Codec;\n/** Versioned envelope for [`HostGetProductContextError`]. */\nexport type VersionedHostGetProductContextError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostGetProductContextError: Codec;\n/** Versioned envelope for [`HostGetProductContextRequest`]. */\nexport type VersionedHostGetProductContextRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetProductContextRequest: Codec;\n/** Versioned envelope for [`HostGetProductContextResponse`]. */\nexport type VersionedHostGetProductContextResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetProductContextResponse;\n};\nexport const VersionedHostGetProductContextResponse: Codec;\n/** Versioned envelope for [`HostGetUserIdError`]. */\nexport type VersionedHostGetUserIdError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetUserIdError;\n};\nexport const VersionedHostGetUserIdError: Codec;\n/** Versioned envelope for [`HostGetUserIdRequest`]. */\nexport type VersionedHostGetUserIdRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetUserIdRequest: Codec;\n/** Versioned envelope for [`HostGetUserIdResponse`]. */\nexport type VersionedHostGetUserIdResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetUserIdResponse;\n};\nexport const VersionedHostGetUserIdResponse: Codec;\n/** Versioned envelope for [`HostHandshakeError`]. */\nexport type VersionedHostHandshakeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostHandshakeError;\n};\nexport const VersionedHostHandshakeError: Codec;\n/** Versioned envelope for [`HostHandshakeRequest`]. */\nexport type VersionedHostHandshakeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostHandshakeRequest;\n};\nexport const VersionedHostHandshakeRequest: Codec;\n/** Versioned envelope for [`HostHandshakeResponse`]. */\nexport type VersionedHostHandshakeResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostHandshakeResponse: Codec;\n/**\n * Identity and version of the host currently running the product.\n *\n * Reported by [`crate::api::System::host_info`] so a product knows which host\n * (and which build of it) is running it \u2014 for adapting to the host,\n * telemetry, and attributing behaviour to a concrete build in diagnostics and\n * bug reports.\n */\nexport interface HostInfo {\n /** Platform category the host runs on. */\n platform: HostPlatform;\n /**\n * Human-readable name of the host implementation, e.g. `\"Polkadot\n * Desktop\"`, `\"Polkadot Mobile\"`, or `\"dotli\"`. Hosts should report a\n * stable, non-empty name.\n */\n name: string;\n /**\n * Host-native version string, e.g. a semver such as `\"1.2.3\"`. Hosts\n * should report a non-empty value; the format is the host's own.\n */\n version: string;\n}\nexport const HostInfo: Codec;\n/** Versioned envelope for [`HostInfoError`]. */\nexport type VersionedHostInfoError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostInfoError: Codec;\n/** Versioned envelope for [`HostInfoRequest`]. */\nexport type VersionedHostInfoRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostInfoRequest: Codec;\n/** Versioned envelope for [`HostInfoResponse`]. */\nexport type VersionedHostInfoResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostInfo;\n};\nexport const VersionedHostInfoResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageChangeItem`]. */\nexport type VersionedHostLocalStorageChangeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageChangeItem;\n};\nexport const VersionedHostLocalStorageChangeItem: Codec;\n/** Versioned envelope for [`HostLocalStorageClearError`]. */\nexport type VersionedHostLocalStorageClearError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: V01HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageClearError: Codec;\n/** Versioned envelope for [`HostLocalStorageClearRequest`]. */\nexport type VersionedHostLocalStorageClearRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageClearRequest;\n};\nexport const VersionedHostLocalStorageClearRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageClearResponse`]. */\nexport type VersionedHostLocalStorageClearResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostLocalStorageClearResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageReadError`]. */\nexport type VersionedHostLocalStorageReadError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageReadError: Codec;\n/** Versioned envelope for [`HostLocalStorageReadRequest`]. */\nexport type VersionedHostLocalStorageReadRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadRequest;\n};\nexport const VersionedHostLocalStorageReadRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageReadResponse`]. */\nexport type VersionedHostLocalStorageReadResponse = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadResponse;\n};\nexport const VersionedHostLocalStorageReadResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageSubscribeError`]. */\nexport type VersionedHostLocalStorageSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostLocalStorageSubscribeError: Codec;\n/** Versioned envelope for [`HostLocalStorageSubscribeRequest`]. */\nexport type VersionedHostLocalStorageSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageSubscribeRequest;\n};\nexport const VersionedHostLocalStorageSubscribeRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteError`]. */\nexport type VersionedHostLocalStorageWriteError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: V01HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageWriteError: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteRequest`]. */\nexport type VersionedHostLocalStorageWriteRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageWriteRequest;\n};\nexport const VersionedHostLocalStorageWriteRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteResponse`]. */\nexport type VersionedHostLocalStorageWriteResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostLocalStorageWriteResponse: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsError`]. */\nexport type VersionedHostLocaleLocalizeTimestampsError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostLocaleLocalizeTimestampsError: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsRequest`]. */\nexport type VersionedHostLocaleLocalizeTimestampsRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocaleLocalizeTimestampsRequest;\n};\nexport const VersionedHostLocaleLocalizeTimestampsRequest: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsResponse`]. */\nexport type VersionedHostLocaleLocalizeTimestampsResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocaleLocalizeTimestampsResponse;\n};\nexport const VersionedHostLocaleLocalizeTimestampsResponse: Codec;\n/** One timestamp's calendar identity and presentation in the requested context. */\nexport interface HostLocaleLocalizedTimestamp {\n /** Gregorian YYYY-MM-DD local date, independent of display language/calendar. */\n localDate: string;\n /** Localized short time, including the host language's hour-cycle convention. */\n time: string;\n /** Localized date label. */\n date: string;\n /** Localized date and time with a time-zone indication for detail views. */\n dateTime: string;\n}\nexport const HostLocaleLocalizedTimestamp: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeError`]. */\nexport type VersionedHostLocaleSubscribeError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: GenericError;\n};\nexport const VersionedHostLocaleSubscribeError: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeItem`]. */\nexport type VersionedHostLocaleSubscribeItem = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocaleSubscribeItem;\n};\nexport const VersionedHostLocaleSubscribeItem: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeRequest`]. */\nexport type VersionedHostLocaleSubscribeRequest = \n/** Version 2 (no payload). */\n{\n tag: \"V2\";\n value?: undefined;\n};\nexport const VersionedHostLocaleSubscribeRequest: Codec;\n/** A peer's native delivery acknowledgment, not a payment-clearing receipt. */\nexport interface HostNativeChatAcknowledgment {\n /** Authenticated acknowledging identity. */\n peerIdentity: HexString;\n /** Acknowledged native request identifier. */\n requestId: string;\n /** Native response code; zero denotes successful delivery processing. */\n responseCode: number;\n}\nexport const HostNativeChatAcknowledgment: Codec;\n/** Public attachment handle; only the Host can resolve its private backing. */\nexport interface HostNativeChatAttachment {\n /** Opaque handle scoped to the current wallet, network and calling product. */\n attachmentId: HexString;\n /** Non-secret native metadata. */\n metadata: HostNativeChatAttachmentMetadata;\n /** Current durable transfer progress. */\n state: HostNativeChatAttachmentState;\n}\nexport const HostNativeChatAttachment: Codec;\n/** Public native media metadata; thumbnails are BlurHash text, not executable images. */\nexport type HostNativeChatAttachmentKind = \n/** A general document or other opaque file. */\n{\n tag: \"File\";\n value?: undefined;\n}\n/** An image with native dimensions and an optional UTF-8 BlurHash. */\n | {\n tag: \"Image\";\n value: {\n width: number;\n height: number;\n thumbnail?: HexString;\n };\n}\n/** A video with native duration and an optional UTF-8 BlurHash. */\n | {\n tag: \"Video\";\n value: {\n durationSeconds: number;\n thumbnail?: HexString;\n };\n};\nexport const HostNativeChatAttachmentKind: Codec;\n/** Safe attachment description, independent of private transfer credentials. */\nexport interface HostNativeChatAttachmentMetadata {\n /** Validated media type; it does not authorize execution or network loading. */\n mimeType: string;\n /** Exact native file size, verified against the downloaded root and chunks. */\n sizeBytes: number;\n /** General file, image or video metadata. */\n kind: HostNativeChatAttachmentKind;\n}\nexport const HostNativeChatAttachmentMetadata: Codec;\n/** Durable transfer progress, distinct from message delivery acknowledgment. */\nexport type HostNativeChatAttachmentState = \n/** The Host is securing an immutable selected source. */\n{\n tag: \"Preparing\";\n value?: undefined;\n}\n/** Native HOP entries are being uploaded. */\n | {\n tag: \"Uploading\";\n value: {\n uploadedBytes: number;\n };\n}\n/** Verified file bytes are being committed to private local storage. */\n | {\n tag: \"Downloading\";\n value: {\n downloadedBytes: number;\n };\n}\n/** Complete verified bytes are available through trusted Host presentation. */\n | {\n tag: \"Ready\";\n value?: undefined;\n}\n/** An interrupted transfer retains its exact credentials and progress for retry. */\n | {\n tag: \"Recovering\";\n value?: undefined;\n};\nexport const HostNativeChatAttachmentState: Codec;\n/** Peer cryptographic identity independently resolved and bound by the Host. */\nexport interface HostNativeChatBinding {\n /** Authenticated peer root identity. */\n peerIdentity: HexString;\n /** Peer identity-level native Chat encryption key. */\n peerChatPublicKey: HexString;\n /** Identity proof used in the native invitation handshake. */\n identityProof: HexString;\n}\nexport const HostNativeChatBinding: Codec;\n/** The Host-owned device's public identity and statement-signing account. */\nexport interface HostNativeChatDevice {\n /** Wallet identity on the configured People chain. */\n identityAccountId: HexString;\n /** Wallet identity's public X25519 key. */\n identityChatPublicKey: HexString;\n /** Product account used to obtain a statement-store allowance for this device. */\n productAccount: ProductAccountId;\n /** Public statement signer for the Host-owned device. */\n accountId: HexString;\n /** Public X25519 key; its secret never leaves the Host. */\n chatPublicKey: HexString;\n}\nexport const HostNativeChatDevice: Codec;\n/** An authenticated invitation awaiting the user's Chat decision. */\nexport interface HostNativeChatInvitation {\n /** Host-generated stable invitation identifier. */\n invitationId: HexString;\n /** Authenticated sender identity. */\n peerIdentity: HexString;\n /** Host-resolved sender username, when available. */\n username?: string;\n /** Authenticated native invitation timestamp in milliseconds. */\n timestamp: bigint;\n /** Ordinary initial text, never an embedded payment or control message. */\n text: string;\n}\nexport const HostNativeChatInvitation: Codec;\n/** Safe ordinary messages from one authenticated native request. */\nexport interface HostNativeChatMessages {\n /** Authenticated counterparty identity. */\n peerIdentity: HexString;\n /** Whether the peer sent these messages; false also covers our welcome text. */\n incoming: boolean;\n /** Native request identifier, retained for message-delivery correlation. */\n requestId: string;\n /** Native message encodings after custody-sensitive content is removed. */\n messages: Array;\n}\nexport const HostNativeChatMessages: Codec;\n/** Native request identity needed to answer a migrated legacy invitation. */\nexport interface HostNativeChatMigrationInvitation {\n /** Invitation handle in the accompanying legacy public view. */\n invitationId: HexString;\n /** Original native request identity to acknowledge when answering. */\n requestId: string;\n}\nexport const HostNativeChatMigrationInvitation: Codec;\n/** Continuation metadata for a bounded page of authenticated incoming plaintext. */\nexport interface HostNativeChatOpenPage {\n /** Opaque identifier of the authenticated opening operation. */\n openId: HexString;\n /** Cursor identifying this page. */\n cursor: number;\n /** Cursor to request next; absent when the authenticated batch is complete. */\n nextCursor?: number;\n}\nexport const HostNativeChatOpenPage: Codec;\n/** Authenticated incoming native plaintext, potentially containing incoming coin keys. */\nexport interface HostNativeChatOpened {\n /** Authenticated peer root identity, never the local wallet's own identity. */\n peerIdentity: HexString;\n /** Account that signed the accepted native statement. */\n senderAccountId: HexString;\n /** Authenticated native context of the incoming statement. */\n route: HostNativeChatRoute;\n /** Native invitation or tagged request/response plaintext; never outgoing payment memos. */\n plaintext: HexString;\n}\nexport const HostNativeChatOpened: Codec;\n/** A product-visible payment card; it contains no spendable memo material. */\nexport interface HostNativeChatPayment {\n /** Durable, product-scoped operation identifier. */\n operationId: HexString;\n /** Caller request id for outgoing payments; native request id for incoming ones. */\n requestId: string;\n /** Native message id used to place the payment in conversation history. */\n messageId: string;\n /** Native message timestamp in milliseconds. */\n timestamp: bigint;\n /** Counterparty identity authenticated by the Host. */\n peerIdentity: HexString;\n /** Incoming or outgoing relative to the current wallet. */\n direction: HostNativeChatPaymentDirection;\n /** Exact requested/received value in cents. */\n amountCents: bigint;\n /** Durable transport/clearing state. */\n state: HostNativeChatPaymentState;\n}\nexport const HostNativeChatPayment: Codec;\n/** Payment direction relative to the current wallet. */\nexport type HostNativeChatPaymentDirection = \"Outgoing\" | \"Incoming\";\nexport const HostNativeChatPaymentDirection: Codec;\n/** Public, non-secret payment failure categories. */\nexport type HostNativeChatPaymentFailure = \"Cancelled\" | \"InsufficientBalance\" | \"AlreadySpent\" | \"InvalidMemo\" | \"ChainRejected\";\nexport const HostNativeChatPaymentFailure: Codec;\n/** Durable payment state. Delivery and on-chain clearing are deliberately distinct. */\nexport type HostNativeChatPaymentState = \n/** Approved inputs are reserved; required split/unload work is in progress. */\n{\n tag: \"Preparing\";\n value?: undefined;\n}\n/** The encrypted memo is durable and transport delivery is being retried. */\n | {\n tag: \"Delivering\";\n value?: undefined;\n}\n/** The peer acknowledged the memo; settlement has not yet been established. */\n | {\n tag: \"Delivered\";\n value?: undefined;\n}\n/** Received secrets are durably held while their claim is in progress. */\n | {\n tag: \"Claiming\";\n value?: undefined;\n}\n/** Some, but not all, of the payment has been observed clearing on chain. */\n | {\n tag: \"PartiallyCleared\";\n value: {\n clearedCents: bigint;\n };\n}\n/** The complete payment has been verified at chain finality. */\n | {\n tag: \"Cleared\";\n value?: undefined;\n}\n/** An ambiguous effect is retained for reconciliation; inputs remain reserved. */\n | {\n tag: \"Recovering\";\n value?: undefined;\n}\n/** A definitive failure; the Host has reconciled any possible prior effects. */\n | {\n tag: \"Failed\";\n value: {\n reason: HostNativeChatPaymentFailure;\n };\n};\nexport const HostNativeChatPaymentState: Codec;\n/** Public conversation state; products cannot write this roster back to the Host. */\nexport interface HostNativeChatPeer {\n /** Recipient wallet identity. */\n identityAccountId: HexString;\n /** Username resolved by the Host, if currently available. */\n username?: string;\n /** Devices admitted by authenticated native invitation/control messages. */\n devices: Array;\n /** Native session topics for subscriptions, not request/response channel hashes. */\n incomingChannels: Array;\n /** Whether establishment and legacy-device revocation have been acknowledged. */\n readyForPayments: boolean;\n}\nexport const HostNativeChatPeer: Codec;\n/** Public metadata for one authenticated remote device. */\nexport interface HostNativeChatPeerDevice {\n /** Remote device's statement signer. */\n accountId: HexString;\n /** Remote device's authenticated public X25519 key. */\n chatPublicKey: HexString;\n}\nexport const HostNativeChatPeerDevice: Codec;\n/** Signed ciphertext with the native identity required for durable product delivery. */\nexport interface HostNativeChatPrepared {\n /** Exact signed ciphertext to submit again when retrying delivery. */\n statement: SignedStatement;\n /** Authenticated recipient root identity. */\n peerIdentity: HexString;\n /** Native request identity used to correlate delivery acknowledgments. */\n requestId: string;\n /** Whether delivery remains pending until a native peer acknowledgment arrives. */\n requiresAck: boolean;\n /** Original product intent id for correlating migrated pending UI, when retained. */\n clientRequestId?: string;\n}\nexport const HostNativeChatPrepared: Codec;\n/** Authenticated rich content after private file capabilities have been removed. */\nexport interface HostNativeChatRichMessage {\n /** Authenticated conversation identity. */\n peerIdentity: HexString;\n /** Whether the remote peer authored this content. */\n incoming: boolean;\n /** Native request id used for delivery acknowledgment. */\n requestId: string;\n /** Native id of this message or edit event. */\n messageId: string;\n /** Native timestamp in milliseconds. */\n timestamp: bigint;\n /** New message, reply or edit; authorship checks still apply to edits. */\n kind: HostNativeChatRichMessageKind;\n /** Ordinary optional text. */\n text?: string;\n /** Opaque file handles and safe metadata, never native file references. */\n attachments: Array;\n}\nexport const HostNativeChatRichMessage: Codec;\n/** Native rich-content timeline operation. */\nexport type HostNativeChatRichMessageKind = \n/** A new ordinary rich message. */\n{\n tag: \"Message\";\n value?: undefined;\n}\n/** A new rich message replying to an earlier message. */\n | {\n tag: \"Reply\";\n value: {\n messageId: string;\n };\n}\n/** A replacement of the same author's earlier rich content. */\n | {\n tag: \"Edited\";\n value: {\n messageId: string;\n };\n};\nexport const HostNativeChatRichMessageKind: Codec;\n/** The authenticated native encryption and statement-routing context. */\nexport type HostNativeChatRoute = \"Invitation\" | \"Identity\" | \"Device\";\nexport const HostNativeChatRoute: Codec;\n/** Continuation metadata for a bounded page of a stable public state snapshot. */\nexport interface HostNativeChatStatePage {\n /** Opaque identifier of the Host-retained public state snapshot. */\n stateId: HexString;\n /** Cursor identifying this page. */\n cursor: number;\n /** Cursor to request next; absent when the snapshot is complete. */\n nextCursor?: number;\n}\nexport const HostNativeChatStatePage: Codec;\n/** Versioned envelope for [`HostNavigateToError`]. */\nexport type VersionedHostNavigateToError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostNavigateToError;\n};\nexport const VersionedHostNavigateToError: Codec;\n/** Versioned envelope for [`HostNavigateToRequest`]. */\nexport type VersionedHostNavigateToRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostNavigateToRequest;\n};\nexport const VersionedHostNavigateToRequest: Codec;\n/** Versioned envelope for [`HostNavigateToResponse`]. */\nexport type VersionedHostNavigateToResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostNavigateToResponse: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeError`]. */\nexport type VersionedHostPaymentBalanceSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeError;\n};\nexport const VersionedHostPaymentBalanceSubscribeError: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeItem`]. */\nexport type VersionedHostPaymentBalanceSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeItem;\n};\nexport const VersionedHostPaymentBalanceSubscribeItem: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeRequest`]. */\nexport type VersionedHostPaymentBalanceSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeRequest;\n};\nexport const VersionedHostPaymentBalanceSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPaymentError`]. */\nexport type VersionedHostPaymentError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentError;\n};\nexport const VersionedHostPaymentError: Codec;\n/** Versioned envelope for [`HostPaymentRequest`]. */\nexport type VersionedHostPaymentRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentRequest;\n};\nexport const VersionedHostPaymentRequest: Codec;\n/** Versioned envelope for [`HostPaymentResponse`]. */\nexport type VersionedHostPaymentResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentResponse;\n};\nexport const VersionedHostPaymentResponse: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeError`]. */\nexport type VersionedHostPaymentStatusSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeError;\n};\nexport const VersionedHostPaymentStatusSubscribeError: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeItem`]. */\nexport type VersionedHostPaymentStatusSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeItem;\n};\nexport const VersionedHostPaymentStatusSubscribeItem: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeRequest`]. */\nexport type VersionedHostPaymentStatusSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeRequest;\n};\nexport const VersionedHostPaymentStatusSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPaymentTopUpError`]. */\nexport type VersionedHostPaymentTopUpError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentTopUpError;\n};\nexport const VersionedHostPaymentTopUpError: Codec;\n/** Versioned envelope for [`HostPaymentTopUpRequest`]. */\nexport type VersionedHostPaymentTopUpRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentTopUpRequest;\n};\nexport const VersionedHostPaymentTopUpRequest: Codec;\n/** Versioned envelope for [`HostPaymentTopUpResponse`]. */\nexport type VersionedHostPaymentTopUpResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPaymentTopUpResponse: Codec;\n/** Platform category a host runs on. */\nexport type HostPlatform = \"Web\" | \"Android\" | \"Ios\" | \"Desktop\" | \"Cli\" | \"Unknown\";\nexport const HostPlatform: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeError`]. */\nexport type VersionedHostPocketListSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostPocketListSubscribeError: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeItem`]. */\nexport type VersionedHostPocketListSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketListSubscribeItem;\n};\nexport const VersionedHostPocketListSubscribeItem: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeRequest`]. */\nexport type VersionedHostPocketListSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPocketListSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardError`]. */\nexport type VersionedHostPocketRemoveCardError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketRemoveCardError;\n};\nexport const VersionedHostPocketRemoveCardError: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardRequest`]. */\nexport type VersionedHostPocketRemoveCardRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketRemoveCardRequest;\n};\nexport const VersionedHostPocketRemoveCardRequest: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardResponse`]. */\nexport type VersionedHostPocketRemoveCardResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPocketRemoveCardResponse: Codec;\n/** Versioned envelope for [`HostProductDeviceChatError`]. */\nexport type VersionedHostProductDeviceChatError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProductDeviceChatError;\n};\nexport const VersionedHostProductDeviceChatError: Codec;\n/** Versioned envelope for [`HostProductDeviceChatRequest`]. */\nexport type VersionedHostProductDeviceChatRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProductDeviceChatRequest;\n};\nexport const VersionedHostProductDeviceChatRequest: Codec;\n/** Versioned envelope for [`HostProductDeviceChatResponse`]. */\nexport type VersionedHostProductDeviceChatResponse = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProductDeviceChatResponse;\n};\nexport const VersionedHostProductDeviceChatResponse: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelError`]. */\nexport type VersionedHostPushNotificationCancelError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostPushNotificationCancelError: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelRequest`]. */\nexport type VersionedHostPushNotificationCancelRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationCancelRequest;\n};\nexport const VersionedHostPushNotificationCancelRequest: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelResponse`]. */\nexport type VersionedHostPushNotificationCancelResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPushNotificationCancelResponse: Codec;\n/** Versioned envelope for [`HostPushNotificationError`]. */\nexport type VersionedHostPushNotificationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationError;\n};\nexport const VersionedHostPushNotificationError: Codec;\n/** Versioned envelope for [`HostPushNotificationRequest`]. */\nexport type VersionedHostPushNotificationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationRequest;\n};\nexport const VersionedHostPushNotificationRequest: Codec;\n/** Versioned envelope for [`HostPushNotificationResponse`]. */\nexport type VersionedHostPushNotificationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationResponse;\n};\nexport const VersionedHostPushNotificationResponse: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeError`]. */\nexport type VersionedHostRendererActionSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostRendererActionSubscribeError: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeItem`]. */\nexport type VersionedHostRendererActionSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRendererActionSubscribeItem;\n};\nexport const VersionedHostRendererActionSubscribeItem: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeRequest`]. */\nexport type VersionedHostRendererActionSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostRendererActionSubscribeRequest: Codec;\n/** Versioned envelope for [`HostRequestLoginError`]. */\nexport type VersionedHostRequestLoginError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginError;\n};\nexport const VersionedHostRequestLoginError: Codec;\n/** Versioned envelope for [`HostRequestLoginRequest`]. */\nexport type VersionedHostRequestLoginRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginRequest;\n};\nexport const VersionedHostRequestLoginRequest: Codec;\n/** Versioned envelope for [`HostRequestLoginResponse`]. */\nexport type VersionedHostRequestLoginResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginResponse;\n};\nexport const VersionedHostRequestLoginResponse: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationError`]. */\nexport type VersionedHostRequestResourceAllocationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ResourceAllocationError;\n};\nexport const VersionedHostRequestResourceAllocationError: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationRequest`]. */\nexport type VersionedHostRequestResourceAllocationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestResourceAllocationRequest;\n};\nexport const VersionedHostRequestResourceAllocationRequest: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationResponse`]. */\nexport type VersionedHostRequestResourceAllocationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestResourceAllocationResponse;\n};\nexport const VersionedHostRequestResourceAllocationResponse: Codec;\n/**\n * Full Substrate extrinsic signing payload with all fields needed for signature\n * generation.\n */\nexport interface HostSignPayloadData {\n /** Reference block hash. */\n blockHash: HexString;\n /** Reference block number. */\n blockNumber: HexString;\n /** Mortality era encoding. */\n era: HexString;\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** SCALE-encoded call data. */\n method: HexString;\n /** Account nonce. */\n nonce: HexString;\n /** Runtime spec version. */\n specVersion: HexString;\n /** Transaction tip. */\n tip: HexString;\n /** Transaction format version. */\n transactionVersion: HexString;\n /** Extension identifiers. */\n signedExtensions: Array;\n /** Extrinsic version. */\n version: number;\n /** For multi-asset tips. */\n assetId?: HexString;\n /** CheckMetadataHash extension. */\n metadataHash?: HexString;\n /** Metadata mode. */\n mode?: number;\n /** Request signed transaction back, encoded as one byte: absent, true, or false. */\n withSignedTransaction?: boolean;\n}\nexport const HostSignPayloadData: Codec;\n/** Versioned envelope for [`HostSignPayloadError`]. */\nexport type VersionedHostSignPayloadError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignPayloadError: Codec;\n/** Versioned envelope for [`HostSignPayloadRequest`]. */\nexport type VersionedHostSignPayloadRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadRequest;\n};\nexport const VersionedHostSignPayloadRequest: Codec;\n/** Versioned envelope for [`HostSignPayloadResponse`]. */\nexport type VersionedHostSignPayloadResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignPayloadResponse: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountError`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountRequest`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadWithLegacyAccountRequest;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountResponse`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostSignRawError`]. */\nexport type VersionedHostSignRawError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignRawError: Codec;\n/** Versioned envelope for [`HostSignRawRequest`]. */\nexport type VersionedHostSignRawRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignRawRequest;\n};\nexport const VersionedHostSignRawRequest: Codec;\n/** Versioned envelope for [`HostSignRawResponse`]. */\nexport type VersionedHostSignRawResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignRawResponse: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountError`]. */\nexport type VersionedHostSignRawWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignRawWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountRequest`]. */\nexport type VersionedHostSignRawWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignRawWithLegacyAccountRequest;\n};\nexport const VersionedHostSignRawWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountResponse`]. */\nexport type VersionedHostSignRawWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignRawWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostThemeSubscribeError`]. */\nexport type VersionedHostThemeSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostThemeSubscribeError: Codec;\n/** Versioned envelope for [`HostThemeSubscribeItem`]. */\nexport type VersionedHostThemeSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostThemeSubscribeItem;\n};\nexport const VersionedHostThemeSubscribeItem: Codec;\n/** Versioned envelope for [`HostThemeSubscribeRequest`]. */\nexport type VersionedHostThemeSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostThemeSubscribeRequest: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationError`]. */\nexport type VersionedHostWorkerBeginOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerOperationError;\n};\nexport const VersionedHostWorkerBeginOperationError: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationRequest`]. */\nexport type VersionedHostWorkerBeginOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerBeginOperationRequest;\n};\nexport const VersionedHostWorkerBeginOperationRequest: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationResponse`]. */\nexport type VersionedHostWorkerBeginOperationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerBeginOperationResponse;\n};\nexport const VersionedHostWorkerBeginOperationResponse: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationError`]. */\nexport type VersionedHostWorkerEndOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerOperationError;\n};\nexport const VersionedHostWorkerEndOperationError: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationRequest`]. */\nexport type VersionedHostWorkerEndOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerEndOperationRequest;\n};\nexport const VersionedHostWorkerEndOperationRequest: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationResponse`]. */\nexport type VersionedHostWorkerEndOperationResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostWorkerEndOperationResponse: Codec;\n/** Pending-operation error. */\nexport type HostWorkerOperationError = \n/**\n * The product is already at the host's per-product limit of open\n * operations.\n */\n{\n tag: \"TooManyOpen\";\n value?: undefined;\n}\n/** Catch-all host failure. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostWorkerOperationError: Codec;\n/** How an image meets the box its modifiers size. */\nexport type ImageFit = \"None\" | \"Fill\" | \"Cover\" | \"Contain\" | \"ScaleDown\";\nexport const ImageFit: Codec;\n/** Properties of an `Image`. */\nexport interface ImageProps {\n /** Where the image bytes come from. */\n source: ImageSource;\n /** Defaults to `Fill`. */\n fit?: ImageFit;\n}\nexport const ImageProps: Codec;\n/** Where image bytes come from. The host fetches them; the tree carries no URL. */\nexport type ImageSource = \n/** A Bulletin chain blob, addressed by its CID. */\n{\n tag: \"Bulletin\";\n value: string;\n}\n/**\n * A file inside the product's executable archive, as a path relative to\n * the archive root.\n */\n | {\n tag: \"Archive\";\n value: string;\n};\nexport const ImageSource: Codec;\n/**\n * A user-imported (legacy) account: public key plus an optional user-chosen\n * display name.\n *\n * Returned by [`HostGetLegacyAccountsResponse`]. Distinct from\n * [`ProductAccount`], which is protocol-derived and never carries a label.\n */\nexport interface LegacyAccount {\n /** The account public key (variable-length bytes). */\n publicKey: HexString;\n /** Optional user-chosen display name. */\n name?: string;\n}\nexport const LegacyAccount: Codec;\n/**\n * Transaction payload for a legacy (non-product) account.\n *\n * Identical to [`ProductAccountTxPayload`] except the signer is a raw\n * 32-byte account identifier.\n */\nexport interface LegacyAccountTxPayload {\n /** Raw 32-byte public key of the legacy account. */\n signer: HexString;\n /** Chain where the transaction will execute. */\n genesisHash: HexString;\n /** SCALE-encoded Call data. */\n callData: HexString;\n /** Transaction extensions supplied by the caller. */\n extensions: Array;\n /**\n * Version of the transaction extensions in `extensions`, as the runtime\n * numbers them.\n */\n txExtVersion: number;\n}\nexport const LegacyAccountTxPayload: Codec;\n/** Layout and styling applied to one node. */\nexport type Modifier = \n/** Outer spacing. */\n{\n tag: \"Margin\";\n value: Dimensions;\n}\n/** Inner spacing. */\n | {\n tag: \"Padding\";\n value: Dimensions;\n}\n/** Background fill. */\n | {\n tag: \"Background\";\n value: Background;\n}\n/** Border. */\n | {\n tag: \"Border\";\n value: BorderStyle;\n}\n/** Fixed height. */\n | {\n tag: \"Height\";\n value: Size;\n}\n/** Fixed width. */\n | {\n tag: \"Width\";\n value: Size;\n}\n/** Minimum width. */\n | {\n tag: \"MinWidth\";\n value: Size;\n}\n/** Minimum height. */\n | {\n tag: \"MinHeight\";\n value: Size;\n}\n/** Fill the available width. */\n | {\n tag: \"FillWidth\";\n value: boolean;\n}\n/** Fill the available height. */\n | {\n tag: \"FillHeight\";\n value: boolean;\n}\n/** 0 is transparent, 255 is opaque. */\n | {\n tag: \"Opacity\";\n value: number;\n}\n/** Compositing mode against what is behind the node. */\n | {\n tag: \"BlendingMode\";\n value: BlendingMode;\n};\nexport const Modifier: Codec;\n/** Outcome of starting a chain-head operation. */\nexport type OperationStartedResult = \n/** The operation was accepted; results arrive as follow events. */\n{\n tag: \"Started\";\n value: {\n operationId: string;\n };\n}\n/** Too many operations are in progress; retry after some complete. */\n | {\n tag: \"LimitReached\";\n value?: undefined;\n};\nexport const OperationStartedResult: Codec;\n/**\n * Source for a payment top-up operation.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type PaymentTopUpSource = \n/** Fund from one of the calling product's scoped accounts. */\n{\n tag: \"ProductAccount\";\n value: {\n derivationIndex: DerivationIndex;\n };\n}\n/**\n * Fund from a one-time account represented by its private key. This is a\n * standard account holding public funds, not a coin key.\n */\n | {\n tag: \"PrivateKey\";\n value: {\n sr25519SecretKey: HexString;\n };\n}\n/**\n * Fund directly from coin secret keys. Each key is an sr25519 secret\n * controlling a single coin.\n */\n | {\n tag: \"Coins\";\n value: {\n sr25519SecretKeys: Array;\n };\n};\nexport const PaymentTopUpSource: Codec;\n/** One of the calling product's Pocket cards. */\nexport interface PocketCard {\n /** Card label declared by the product, unique within the product. */\n cardId: string;\n /** Placed by the host itself; removable by neither the user nor the product. */\n privileged: boolean;\n}\nexport const PocketCard: Codec;\n/** Preimage submission error. */\nexport type PreimageSubmitError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const PreimageSubmitError: Codec;\n/** A product account: public key only, no display name. */\nexport interface ProductAccount {\n /** The account public key (variable-length bytes). */\n publicKey: HexString;\n}\nexport const ProductAccount: Codec;\n/**\n * Identifies a product-specific account by combining a dotNS domain name with a\n * derivation index.\n */\nexport interface ProductAccountId {\n /** A dotNS domain name identifier (e.g., `\"my-product.dot\"`). */\n dotNsIdentifier: string;\n /** Account selector within the product subtree. */\n derivationIndex: DerivationIndex;\n}\nexport const ProductAccountId: Codec;\n/**\n * Transaction payload for a product account.\n *\n * Contains everything the host needs to construct a signed extrinsic.\n * The signer is a [`ProductAccountId`]; the host resolves the\n * corresponding key pair through its account management layer.\n */\nexport interface ProductAccountTxPayload {\n /** Product account that will sign the transaction. */\n signer: ProductAccountId;\n /** Chain where the transaction will execute. */\n genesisHash: HexString;\n /** SCALE-encoded Call data. */\n callData: HexString;\n /** Transaction extensions supplied by the caller. */\n extensions: Array;\n /**\n * Version of the transaction extensions in `extensions`, as the runtime\n * numbers them.\n */\n txExtVersion: number;\n /**\n * Contact handles `call_data` names, which the host replaces with the\n * accounts they resolve to before anything is signed or shown.\n *\n * A product declares them rather than passing offsets: an offset is a\n * number it computes about its own encoding and gets wrong silently,\n * while a declared handle is either in the call or it is not, and a host\n * that cannot find one refuses rather than signing a call that names\n * somebody else. A call naming nobody leaves this empty.\n */\n contacts: Array;\n}\nexport const ProductAccountTxPayload: Codec;\n/**\n * A product-scoped proof context: a product and a context within it.\n *\n * Hashed (with a `product//` prefix) into the 32-byte context bound\n * to a ring VRF proof, so contexts cannot collide across products and the same\n * member key under different contexts yields unlinkable aliases.\n */\nexport interface ProductProofContext {\n /** dotNS product identifier (e.g. `\"my-product.dot\"`) scoping the context. */\n productId: string;\n /**\n * Selector distinguishing contexts within the product; expands to the\n * same 32-byte derivation index as [`ProductAccountId::derivation_index`].\n */\n suffix: DerivationIndex;\n}\nexport const ProductProofContext: Codec;\n/** Versioned envelope for [`ProductRendererRenderError`]. */\nexport type VersionedProductRendererRenderError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedProductRendererRenderError: Codec;\n/** Versioned envelope for [`ProductRendererRenderItem`]. */\nexport type VersionedProductRendererRenderItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RendererNode;\n};\nexport const VersionedProductRendererRenderItem: Codec;\n/** Versioned envelope for [`ProductRendererRenderRequest`]. */\nexport type VersionedProductRendererRenderRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ProductRendererRenderRequest;\n};\nexport const VersionedProductRendererRenderRequest: Codec;\n/** Raw data to sign -- either binary bytes or a string message. */\nexport type RawPayload = \n/** Raw binary data to sign. */\n{\n tag: \"Bytes\";\n value: {\n bytes: HexString;\n };\n}\n/** String message to sign. */\n | {\n tag: \"Payload\";\n value: {\n payload: string;\n };\n};\nexport const RawPayload: Codec;\n/** A registered ring-VRF key entry. */\nexport interface RegisteredRingVrfKey {\n /** Stable public name of the key. */\n handle: ProductAccountId;\n /** Rings the owning product declared this key for. */\n rings: Array;\n /** Present when the caller owns the key or requested/granted disclosure. */\n publicKey?: HexString;\n}\nexport const RegisteredRingVrfKey: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyError`]. */\nexport type VersionedRemoteChainHeadBodyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadBodyError: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyRequest`]. */\nexport type VersionedRemoteChainHeadBodyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadBodyRequest;\n};\nexport const VersionedRemoteChainHeadBodyRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyResponse`]. */\nexport type VersionedRemoteChainHeadBodyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadBodyResponse;\n};\nexport const VersionedRemoteChainHeadBodyResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallError`]. */\nexport type VersionedRemoteChainHeadCallError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadCallError: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallRequest`]. */\nexport type VersionedRemoteChainHeadCallRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadCallRequest;\n};\nexport const VersionedRemoteChainHeadCallRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallResponse`]. */\nexport type VersionedRemoteChainHeadCallResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadCallResponse;\n};\nexport const VersionedRemoteChainHeadCallResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueError`]. */\nexport type VersionedRemoteChainHeadContinueError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadContinueError: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueRequest`]. */\nexport type VersionedRemoteChainHeadContinueRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadContinueRequest;\n};\nexport const VersionedRemoteChainHeadContinueRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueResponse`]. */\nexport type VersionedRemoteChainHeadContinueResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadContinueResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowError`]. */\nexport type VersionedRemoteChainHeadFollowError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadFollowError: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowItem`]. */\nexport type VersionedRemoteChainHeadFollowItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadFollowItem;\n};\nexport const VersionedRemoteChainHeadFollowItem: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowRequest`]. */\nexport type VersionedRemoteChainHeadFollowRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadFollowRequest;\n};\nexport const VersionedRemoteChainHeadFollowRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderError`]. */\nexport type VersionedRemoteChainHeadHeaderError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadHeaderError: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderRequest`]. */\nexport type VersionedRemoteChainHeadHeaderRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadHeaderRequest;\n};\nexport const VersionedRemoteChainHeadHeaderRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderResponse`]. */\nexport type VersionedRemoteChainHeadHeaderResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadHeaderResponse;\n};\nexport const VersionedRemoteChainHeadHeaderResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationError`]. */\nexport type VersionedRemoteChainHeadStopOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadStopOperationError: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationRequest`]. */\nexport type VersionedRemoteChainHeadStopOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStopOperationRequest;\n};\nexport const VersionedRemoteChainHeadStopOperationRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationResponse`]. */\nexport type VersionedRemoteChainHeadStopOperationResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadStopOperationResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageError`]. */\nexport type VersionedRemoteChainHeadStorageError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadStorageError: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageRequest`]. */\nexport type VersionedRemoteChainHeadStorageRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStorageRequest;\n};\nexport const VersionedRemoteChainHeadStorageRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageResponse`]. */\nexport type VersionedRemoteChainHeadStorageResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStorageResponse;\n};\nexport const VersionedRemoteChainHeadStorageResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinError`]. */\nexport type VersionedRemoteChainHeadUnpinError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadUnpinError: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinRequest`]. */\nexport type VersionedRemoteChainHeadUnpinRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadUnpinRequest;\n};\nexport const VersionedRemoteChainHeadUnpinRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinResponse`]. */\nexport type VersionedRemoteChainHeadUnpinResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadUnpinResponse: Codec;\n/** Versioned envelope for [`RemoteChainInfoError`]. */\nexport type VersionedRemoteChainInfoError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoError;\n};\nexport const VersionedRemoteChainInfoError: Codec;\n/** Versioned envelope for [`RemoteChainInfoRequest`]. */\nexport type VersionedRemoteChainInfoRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoRequest;\n};\nexport const VersionedRemoteChainInfoRequest: Codec;\n/** Versioned envelope for [`RemoteChainInfoResponse`]. */\nexport type VersionedRemoteChainInfoResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoResponse;\n};\nexport const VersionedRemoteChainInfoResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameError`]. */\nexport type VersionedRemoteChainSpecChainNameError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecChainNameError: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameRequest`]. */\nexport type VersionedRemoteChainSpecChainNameRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecChainNameRequest;\n};\nexport const VersionedRemoteChainSpecChainNameRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameResponse`]. */\nexport type VersionedRemoteChainSpecChainNameResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecChainNameResponse;\n};\nexport const VersionedRemoteChainSpecChainNameResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashError`]. */\nexport type VersionedRemoteChainSpecGenesisHashError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecGenesisHashError: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashRequest`]. */\nexport type VersionedRemoteChainSpecGenesisHashRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecGenesisHashRequest;\n};\nexport const VersionedRemoteChainSpecGenesisHashRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashResponse`]. */\nexport type VersionedRemoteChainSpecGenesisHashResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecGenesisHashResponse;\n};\nexport const VersionedRemoteChainSpecGenesisHashResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesError`]. */\nexport type VersionedRemoteChainSpecPropertiesError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecPropertiesError: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesRequest`]. */\nexport type VersionedRemoteChainSpecPropertiesRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecPropertiesRequest;\n};\nexport const VersionedRemoteChainSpecPropertiesRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesResponse`]. */\nexport type VersionedRemoteChainSpecPropertiesResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecPropertiesResponse;\n};\nexport const VersionedRemoteChainSpecPropertiesResponse: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastError`]. */\nexport type VersionedRemoteChainTransactionBroadcastError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainTransactionBroadcastError: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastRequest`]. */\nexport type VersionedRemoteChainTransactionBroadcastRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionBroadcastRequest;\n};\nexport const VersionedRemoteChainTransactionBroadcastRequest: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastResponse`]. */\nexport type VersionedRemoteChainTransactionBroadcastResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionBroadcastResponse;\n};\nexport const VersionedRemoteChainTransactionBroadcastResponse: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopError`]. */\nexport type VersionedRemoteChainTransactionStopError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainTransactionStopError: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopRequest`]. */\nexport type VersionedRemoteChainTransactionStopRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionStopRequest;\n};\nexport const VersionedRemoteChainTransactionStopRequest: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopResponse`]. */\nexport type VersionedRemoteChainTransactionStopResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainTransactionStopResponse: Codec;\n/**\n * One remote-operation permission requested by the product (RFC 0002).\n *\n * `ChainSubmit`, `PreimageSubmit`, and `StatementSubmit` are also triggered\n * implicitly by the corresponding business calls when not yet granted.\n */\nexport type RemotePermission = \n/**\n * Outbound HTTP/WebSocket access to a set of domains. External navigation\n * uses [`HostDevicePermissionRequest::OpenUrl`] instead.\n */\n{\n tag: \"Remote\";\n value: {\n domains: Array;\n };\n}\n/**\n * WebRTC access.\n *\n * The container authorizes each peer connection through Rust before its\n * first network method. Later methods on that connection share the same\n * decision, so a one-use grant permits one connection. New connections\n * check current permissions without requiring a page reload.\n *\n * Camera and microphone capture is gated by the OS permission prompts and\n * [`HostDevicePermissionRequest`], not by this permission.\n */\n | {\n tag: \"WebRtc\";\n value?: undefined;\n}\n/** Submitting transactions on behalf of the user via `remote_chain_transaction_broadcast`. */\n | {\n tag: \"ChainSubmit\";\n value?: undefined;\n}\n/** Submitting preimages on behalf of the user via `remote_preimage_submit`. */\n | {\n tag: \"PreimageSubmit\";\n value?: undefined;\n}\n/** Submitting statements on behalf of the user via `remote_statement_store_submit`. */\n | {\n tag: \"StatementSubmit\";\n value?: undefined;\n};\nexport const RemotePermission: Codec;\n/** Versioned envelope for [`RemotePermissionError`]. */\nexport type VersionedRemotePermissionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemotePermissionError: Codec;\n/** Versioned envelope for [`RemotePermissionRequest`]. */\nexport type VersionedRemotePermissionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePermissionRequest;\n};\nexport const VersionedRemotePermissionRequest: Codec;\n/** Versioned envelope for [`RemotePermissionResponse`]. */\nexport type VersionedRemotePermissionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePermissionResponse;\n};\nexport const VersionedRemotePermissionResponse: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeError`]. */\nexport type VersionedRemotePreimageLookupSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemotePreimageLookupSubscribeError: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeItem`]. */\nexport type VersionedRemotePreimageLookupSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePreimageLookupSubscribeItem;\n};\nexport const VersionedRemotePreimageLookupSubscribeItem: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeRequest`]. */\nexport type VersionedRemotePreimageLookupSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePreimageLookupSubscribeRequest;\n};\nexport const VersionedRemotePreimageLookupSubscribeRequest: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitError`]. */\nexport type VersionedRemotePreimageSubmitError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: PreimageSubmitError;\n};\nexport const VersionedRemotePreimageSubmitError: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitRequest`]. */\nexport type VersionedRemotePreimageSubmitRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedRemotePreimageSubmitRequest: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitResponse`]. */\nexport type VersionedRemotePreimageSubmitResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedRemotePreimageSubmitResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedError`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofError;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedRequest`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: Statement;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedResponse`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofResponse;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofError`]. */\nexport type VersionedRemoteStatementStoreCreateProofError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofError;\n};\nexport const VersionedRemoteStatementStoreCreateProofError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofRequest`]. */\nexport type VersionedRemoteStatementStoreCreateProofRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofRequest;\n};\nexport const VersionedRemoteStatementStoreCreateProofRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofResponse`]. */\nexport type VersionedRemoteStatementStoreCreateProofResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofResponse;\n};\nexport const VersionedRemoteStatementStoreCreateProofResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitError`]. */\nexport type VersionedRemoteStatementStoreSubmitError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteStatementStoreSubmitError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitRequest`]. */\nexport type VersionedRemoteStatementStoreSubmitRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: SignedStatement;\n};\nexport const VersionedRemoteStatementStoreSubmitRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitResponse`]. */\nexport type VersionedRemoteStatementStoreSubmitResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteStatementStoreSubmitResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeError`]. */\nexport type VersionedRemoteStatementStoreSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteStatementStoreSubscribeError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeItem`]. */\nexport type VersionedRemoteStatementStoreSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreSubscribeItem;\n};\nexport const VersionedRemoteStatementStoreSubscribeItem: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeRequest`]. */\nexport type VersionedRemoteStatementStoreSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreSubscribeRequest;\n};\nexport const VersionedRemoteStatementStoreSubscribeRequest: Codec;\n/** Where a product-rendered body lives, and the id that names it there. */\nexport type RenderContext = \n/** A message in a chat room. */\n{\n tag: \"ChatMessage\";\n value: {\n roomId: string;\n messageId: string;\n messageType: string;\n };\n}\n/** A candidate answered to an input query. */\n | {\n tag: \"InputWidget\";\n value: {\n candidateId: string;\n };\n}\n/** A card face in the host's Pocket collection. */\n | {\n tag: \"PocketCard\";\n value: {\n cardId: string;\n };\n};\nexport const RenderContext: Codec;\n/**\n * A node in a product-rendered tree. Container variants recurse through\n * `children`.\n */\nexport type RendererNode = \n/** Draws nothing. */\n{\n tag: \"Nil\";\n value?: undefined;\n}\n/** A text run. */\n | {\n tag: \"String\";\n value: {\n text: string;\n };\n}\n/** Generic container. */\n | {\n tag: \"Box\";\n value: {\n modifiers: Array;\n props: BoxProps;\n children: Array;\n };\n}\n/** Vertical layout. */\n | {\n tag: \"Column\";\n value: {\n modifiers: Array;\n props: ColumnProps;\n children: Array;\n };\n}\n/** Horizontal layout. */\n | {\n tag: \"Row\";\n value: {\n modifiers: Array;\n props: RowProps;\n children: Array;\n };\n}\n/** Flexible space. */\n | {\n tag: \"Spacer\";\n value: {\n modifiers: Array;\n };\n}\n/** Styled text. */\n | {\n tag: \"Text\";\n value: {\n modifiers: Array;\n props: TextProps;\n children: Array;\n };\n}\n/** Interactive button. */\n | {\n tag: \"Button\";\n value: {\n modifiers: Array;\n props: ButtonProps;\n children: Array;\n };\n}\n/** Single-line text input. */\n | {\n tag: \"TextField\";\n value: {\n modifiers: Array;\n props: TextFieldProps;\n };\n}\n/** Image, sized by modifiers. */\n | {\n tag: \"Image\";\n value: {\n modifiers: Array;\n props: ImageProps;\n };\n}\n/** Applies its effect to its children. */\n | {\n tag: \"Effect\";\n value: {\n props: EffectProps;\n children: Array;\n };\n};\nexport const RendererNode: Codec;\n/** Error from [`crate::api::ResourceAllocation::request`]. */\nexport type ResourceAllocationError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const ResourceAllocationError: Codec;\n/**\n * Locates a ring for ring VRF operations using only identifiers that are\n * stable across membership changes.\n */\nexport interface RingLocation {\n /** Genesis hash of the chain hosting the ring. */\n chainId: HexString;\n /** Path addressing the ring within the chain. */\n junctions: Array;\n}\nexport const RingLocation: Codec;\n/** A single step in a [`RingLocation`] path, addressing a ring within a chain. */\nexport type RingLocationJunction = \n/** Pallet instance hosting the ring collection. */\n{\n tag: \"PalletInstance\";\n value: number;\n}\n/** Ring collection identifier within the pallet. */\n | {\n tag: \"CollectionId\";\n value: HexString;\n};\nexport const RingLocationJunction: Codec;\n/** How much of a registry entry the caller asks for. */\nexport type RingVrfKeyDisclosure = \"Anonymized\" | \"PublicKey\";\nexport const RingVrfKeyDisclosure: Codec;\n/** Properties of a `Row`. */\nexport interface RowProps {\n /** Cross-axis alignment of children. */\n verticalAlignment?: VerticalAlignment;\n /** Main-axis distribution of children. */\n horizontalArrangement?: Arrangement;\n}\nexport const RowProps: Codec;\n/** One entry of a runtime's supported API list. */\nexport interface RuntimeApi {\n /** Runtime API name. */\n name: string;\n /** Runtime API version. */\n version: number;\n}\nexport const RuntimeApi: Codec;\n/** Runtime version information for a block's runtime. */\nexport interface RuntimeSpec {\n /** Specification name. */\n specName: string;\n /** Implementation name. */\n implName: string;\n /** Spec version number. */\n specVersion: number;\n /** Implementation version. */\n implVersion: number;\n /** Transaction format version. */\n transactionVersion?: number;\n /** Supported runtime APIs. */\n apis: Array;\n}\nexport const RuntimeSpec: Codec;\n/** Runtime attached to follow events, either a decoded spec or a decode error. */\nexport type RuntimeType = \n/** Runtime spec decoded successfully. */\n{\n tag: \"Valid\";\n value: RuntimeSpec;\n}\n/** The runtime could not be decoded. */\n | {\n tag: \"Invalid\";\n value: {\n error: string;\n };\n};\nexport const RuntimeType: Codec;\n/** Outline of a background or border. */\nexport type Shape = \n/** Rounded corners with the given radius. */\n{\n tag: \"Rounded\";\n value: Size;\n}\n/** Circular shape. */\n | {\n tag: \"Circle\";\n value?: undefined;\n}\n/** Square corners. */\n | {\n tag: \"Square\";\n value?: undefined;\n};\nexport const Shape: Codec;\n/** A statement with a required (not optional) proof. */\nexport interface SignedStatement {\n /** Required cryptographic proof. */\n proof: StatementProof;\n /** Optional decryption key. */\n decryptionKey?: HexString;\n /** Optional Unix timestamp expiry. */\n expiry?: bigint;\n /** Optional channel. */\n channel?: HexString;\n /** [u8; 32] tags. */\n topics: Array;\n /** Optional data payload. */\n data?: HexString;\n}\nexport const SignedStatement: Codec;\n/** A size in logical pixels, SCALE-encoded as `Compact`. */\nexport type Size = number | bigint;\nexport const Size: Codec;\n/** A statement with optional proof and metadata. */\nexport interface Statement {\n /** Optional cryptographic proof. */\n proof?: StatementProof;\n /** Optional decryption key. */\n decryptionKey?: HexString;\n /** Optional Unix timestamp expiry. */\n expiry?: bigint;\n /** Optional channel. */\n channel?: HexString;\n /** [u8; 32] tags. */\n topics: Array;\n /** Optional data payload. */\n data?: HexString;\n}\nexport const Statement: Codec;\n/** Cryptographic proof for a statement. */\nexport type StatementProof = \n/** Sr25519 signature proof. */\n{\n tag: \"Sr25519\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** Ed25519 signature proof. */\n | {\n tag: \"Ed25519\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** ECDSA signature proof. */\n | {\n tag: \"Ecdsa\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** On-chain event proof. */\n | {\n tag: \"OnChain\";\n value: {\n who: HexString;\n blockHash: HexString;\n event: bigint;\n };\n};\nexport const StatementProof: Codec;\n/** A single key query within a chain-head storage request. */\nexport interface StorageQueryItem {\n /** Storage key to query. */\n key: HexString;\n /** What to return. */\n queryType: StorageQueryType;\n}\nexport const StorageQueryItem: Codec;\n/** What a chain-head storage query returns for a key. */\nexport type StorageQueryType = \"Value\" | \"Hash\" | \"ClosestDescendantMerkleValue\" | \"DescendantsValues\" | \"DescendantsHashes\";\nexport const StorageQueryType: Codec;\n/** Result for one queried storage key. */\nexport interface StorageResultItem {\n /** The queried key. */\n key: HexString;\n /** Value, if requested. */\n value?: HexString;\n /** Hash, if requested. */\n hash?: HexString;\n /** Merkle value, if requested. */\n closestDescendantMerkleValue?: HexString;\n}\nexport const StorageResultItem: Codec;\n/** Properties of a `TextField`. */\nexport interface TextFieldProps {\n /** Current value. */\n text: string;\n /** Shown when the value is empty. */\n placeholder?: string;\n /** Field label. */\n label?: string;\n /** Whether the field accepts input. Absent leaves the default to the host. */\n enabled?: boolean;\n /**\n * Action triggered on every value change. The action carries the new\n * value as UTF-8 bytes, with no length prefix.\n */\n valueChangeAction?: string;\n}\nexport const TextFieldProps: Codec;\n/** Properties of a `Text`. */\nexport interface TextProps {\n /** Typography preset. */\n style?: TypographyStyle;\n /** Text color. */\n color?: ColorToken;\n}\nexport const TextProps: Codec;\n/** Identifies a named theme. */\nexport type ThemeName = \n/** A custom named theme. */\n{\n tag: \"Custom\";\n value: string;\n}\n/** The host's default theme. */\n | {\n tag: \"Default\";\n value?: undefined;\n};\nexport const ThemeName: Codec;\n/** Light or dark variant. */\nexport type ThemeVariant = \"Light\" | \"Dark\";\nexport const ThemeVariant: Codec;\n/** A signed extension for a transaction payload. */\nexport interface TxPayloadExtension {\n /** Extension name (e.g., `\"CheckSpecVersion\"`). */\n id: string;\n /** SCALE-encoded extra data (in extrinsic body). */\n extra: HexString;\n /** SCALE-encoded implicit data (signed, not in body). */\n additionalSigned: HexString;\n}\nexport const TxPayloadExtension: Codec;\n/** Typography presets, resolved by the host's design system. */\nexport type TypographyStyle = \"HeadlineLarge\" | \"TitleMediumRegular\" | \"BodyLargeRegular\" | \"BodyMediumRegular\" | \"BodySmallRegular\";\nexport const TypographyStyle: Codec;\n/** User's authentication state. */\nexport type HostAccountConnectionStatusSubscribeItem = \"Disconnected\" | \"Connected\";\nexport const HostAccountConnectionStatusSubscribeItem: Codec;\n/** Error returned when ring VRF proof creation fails. */\nexport type HostAccountCreateProofError = \n/** Ring not available at the specified location. */\n{\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** The registered member key is not a member of the requested ring. */\n | {\n tag: \"NotMember\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The key handle is not registered for the requested ring. */\n | {\n tag: \"KeyNotInRing\";\n value?: undefined;\n}\n/** The foreign key owner has not allowlisted the caller. */\n | {\n tag: \"NotAllowlisted\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountCreateProofError: Codec;\n/** Request to create a ring VRF proof. */\nexport interface HostAccountCreateProofRequest {\n /** Ring-VRF key handle naming the member key to use. */\n keyHandle: ProductAccountId;\n /** Product-scoped context the derived alias is bound to. */\n context: ProductProofContext;\n /** Ring to generate the proof against. */\n ringLocation: RingLocation;\n /** Opaque message bound into the proof. */\n message: HexString;\n}\nexport const HostAccountCreateProofRequest: Codec;\n/**\n * Response containing a ring VRF proof and the values needed to verify it\n * against a downstream precompile.\n */\nexport interface HostAccountCreateProofResponse {\n /** Variable-length ring VRF proof bytes. */\n proof: HexString;\n /** Alias derived for the request's context. */\n contextualAlias: ContextualAlias;\n /** Index of the selected member key within the ring. */\n ringIndex: number;\n /** Ring revision the proof was generated against. */\n ringRevision: number;\n}\nexport const HostAccountCreateProofResponse: Codec;\n/** Error returned when contextual alias derivation fails. */\nexport type HostAccountGetAliasError = \n/** Ring not available at the specified location. */\n{\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** The registered member key is not a member of the requested ring. */\n | {\n tag: \"NotMember\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The key handle is not registered for the requested ring. */\n | {\n tag: \"KeyNotInRing\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountGetAliasError: Codec;\n/** Request to retrieve the contextual alias for a context and ring. */\nexport interface HostAccountGetAliasRequest {\n /** Ring-VRF key handle naming the member key to use. */\n keyHandle: ProductAccountId;\n /** Product-scoped context to derive the alias for. */\n context: ProductProofContext;\n /** Ring whose member key the host should use; matches `create_proof`. */\n ringLocation: RingLocation;\n}\nexport const HostAccountGetAliasRequest: Codec;\n/** Error returned when credential/account requests fail. */\nexport type HostAccountGetError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected the request. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Domain identifier is invalid. */\n | {\n tag: \"DomainNotValid\";\n value?: undefined;\n}\n/** Catch-all error with reason. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountGetError: Codec;\n/** Request to retrieve a product-scoped account. */\nexport interface HostAccountGetRequest {\n /** Product account to retrieve. */\n productAccountId: ProductAccountId;\n}\nexport const HostAccountGetRequest: Codec;\n/** Response containing a product-scoped account. */\nexport interface HostAccountGetResponse {\n /** Retrieved product account. */\n account: ProductAccount;\n}\nexport const HostAccountGetResponse: Codec;\n/** Error returned when listing ring-VRF keys fails. */\nexport type HostAccountListRingVrfKeysError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountListRingVrfKeysError: Codec;\n/** Request to list registered ring-VRF keys for an owner product. */\nexport interface HostAccountListRingVrfKeysRequest {\n /** Product whose registry entries should be listed. */\n owner: string;\n /** Disclosure level requested by the caller. */\n disclosure: RingVrfKeyDisclosure;\n}\nexport const HostAccountListRingVrfKeysRequest: Codec;\n/** Error returned when ring-VRF key registration fails. */\nexport type HostAccountRegisterRingVrfKeyError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Ring not available at the specified location. */\n | {\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountRegisterRingVrfKeyError: Codec;\n/** Request to register a ring-VRF key owned by the calling product. */\nexport interface HostAccountRegisterRingVrfKeyRequest {\n /** Key derivation index within the caller's ring-VRF domain. */\n index: DerivationIndex;\n /** Ring this key is declared for. */\n ring: RingLocation;\n}\nexport const HostAccountRegisterRingVrfKeyRequest: Codec;\n/** Error returned when direct ring-VRF key signing fails. */\nexport type HostAccountRingVrfSignError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The foreign key owner has not allowlisted the caller. */\n | {\n tag: \"NotAllowlisted\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountRingVrfSignError: Codec;\n/** Request to sign bytes with a registered ring-VRF key. */\nexport interface HostAccountRingVrfSignRequest {\n /** Registered key handle. */\n keyHandle: ProductAccountId;\n /** Opaque message to sign. */\n message: HexString;\n}\nexport const HostAccountRingVrfSignRequest: Codec;\n/** Error returned when VRF signing fails. */\nexport type HostAccountSignVrfError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected the signing confirmation. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountSignVrfError: Codec;\n/**\n * Request to produce an sr25519 VRF signature from a product account over a\n * caller-supplied Merlin transcript.\n */\nexport interface HostAccountSignVrfRequest {\n /** Account whose key signs the VRF. */\n account: ProductAccountId;\n /** Root domain-separation label: `Transcript::new(transcript_label)`. */\n transcriptLabel: HexString;\n /** Transcript items replayed in order as `append_message(label, value)`. */\n items: Array;\n}\nexport const HostAccountSignVrfRequest: Codec;\n/** A chat action received from the host. */\nexport interface HostChatActionSubscribeItem {\n /** Room where the action occurred. */\n roomId: string;\n /** Peer who initiated the action. */\n peer: string;\n /** The action payload. */\n payload: ChatActionPayload;\n}\nexport const HostChatActionSubscribeItem: Codec;\n/** Chat room registration error. */\nexport type HostChatCreateRoomError = \n/** Not allowed. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatCreateRoomError: Codec;\n/** Request to create a chat room. */\nexport interface HostChatCreateRoomRequest {\n /** Unique room identifier. */\n roomId: string;\n /** Room display name. */\n name: string;\n /** URL or base64 image. */\n icon: string;\n}\nexport const HostChatCreateRoomRequest: Codec;\n/** Result of a room registration. */\nexport interface HostChatCreateRoomResponse {\n /** `New` or `Exists`. */\n status: ChatRoomRegistrationStatus;\n}\nexport const HostChatCreateRoomResponse: Codec;\n/** Item containing the current chat rooms. */\nexport interface HostChatListSubscribeItem {\n /** Chat rooms the product participates in. */\n rooms: Array;\n}\nexport const HostChatListSubscribeItem: Codec;\n/** Chat message posting error. */\nexport type HostChatPostMessageError = \n/** Message exceeded size limit. */\n{\n tag: \"MessageTooLarge\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatPostMessageError: Codec;\n/** Request to post a message to a chat room. */\nexport interface HostChatPostMessageRequest {\n /** Room to post to. */\n roomId: string;\n /** Message content. */\n payload: ChatMessageContent;\n}\nexport const HostChatPostMessageRequest: Codec;\n/** Result of posting a message. */\nexport interface HostChatPostMessageResponse {\n /**\n * Host-assigned message id, and the correlation key for any action the\n * message carries: a trigger names it in [`ActionTrigger::message_id`].\n */\n messageId: string;\n}\nexport const HostChatPostMessageResponse: Codec;\n/** Chat bot registration error. */\nexport type HostChatRegisterBotError = \n/** Not allowed. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatRegisterBotError: Codec;\n/** Request to register a chat bot. */\nexport interface HostChatRegisterBotRequest {\n /** Unique bot identifier. */\n botId: string;\n /** Bot display name. */\n name: string;\n /** URL or base64 image. */\n icon: string;\n}\nexport const HostChatRegisterBotRequest: Codec;\n/** Result of a bot registration. */\nexport interface HostChatRegisterBotResponse {\n /** `New` or `Exists`. */\n status: ChatBotRegistrationStatus;\n}\nexport const HostChatRegisterBotResponse: Codec;\n/** Request to create a cheque from a local purse to a receivable. */\nexport interface HostCoinPaymentCreateChequeRequest {\n /** Source purse. */\n from: number;\n /** Destination receivable. */\n to: HexString;\n /** Payment amount. */\n amount: number;\n}\nexport const HostCoinPaymentCreateChequeRequest: Codec;\n/** Created cheque response. */\nexport interface HostCoinPaymentCreateChequeResponse {\n /** Encrypted cheque. */\n cheque: CoinPaymentCheque;\n}\nexport const HostCoinPaymentCreateChequeResponse: Codec;\n/** Request to create a new firewalled CoinPayment purse. */\nexport interface HostCoinPaymentCreatePurseRequest {\n /** Human-readable purse name. */\n name: string;\n}\nexport const HostCoinPaymentCreatePurseRequest: Codec;\n/** Created purse identifier. */\nexport interface HostCoinPaymentCreatePurseResponse {\n /** Assigned purse identifier. */\n purse: number;\n}\nexport const HostCoinPaymentCreatePurseResponse: Codec;\n/** Request to create a fresh receivable for a purse. */\nexport interface HostCoinPaymentCreateReceivableRequest {\n /** Target purse for future deposits. */\n into: number;\n}\nexport const HostCoinPaymentCreateReceivableRequest: Codec;\n/** Created receivable response. */\nexport interface HostCoinPaymentCreateReceivableResponse {\n /** Receivable public key. */\n receivable: HexString;\n}\nexport const HostCoinPaymentCreateReceivableResponse: Codec;\n/** Request to delete a purse after draining its balance. */\nexport interface HostCoinPaymentDeletePurseRequest {\n /** Purse to delete. */\n target: number;\n /** Purse that receives drained funds. */\n drainInto: number;\n}\nexport const HostCoinPaymentDeletePurseRequest: Codec;\n/** Request to deposit a cheque into the purse associated with its receivable. */\nexport interface HostCoinPaymentDepositRequest {\n /** Cheque to deposit. */\n cheque: CoinPaymentCheque;\n}\nexport const HostCoinPaymentDepositRequest: Codec;\n/** Stream item for `host_coin_payment_listen_for`. */\nexport type HostCoinPaymentListenForItem = \n/** Handoff channel suitable for inclusion in an invoice. */\n{\n tag: \"Channel\";\n value: CoinPaymentTransmissionChannel;\n}\n/** Cheque received through the handoff channel. */\n | {\n tag: \"Cheque\";\n value: CoinPaymentCheque;\n};\nexport const HostCoinPaymentListenForItem: Codec;\n/** Request to listen for a cheque delivered to a receivable. */\nexport interface HostCoinPaymentListenForRequest {\n /** Receivable to listen for. */\n receivable: HexString;\n}\nexport const HostCoinPaymentListenForRequest: Codec;\n/** Request to query product-visible purse metadata. */\nexport interface HostCoinPaymentQueryPurseRequest {\n /** Purse to query. */\n purse: number;\n}\nexport const HostCoinPaymentQueryPurseRequest: Codec;\n/** Product-visible purse metadata response. */\nexport interface HostCoinPaymentQueryPurseResponse {\n /** Purse information. */\n info: CoinPaymentPurseInfo;\n}\nexport const HostCoinPaymentQueryPurseResponse: Codec;\n/** Request to transfer balance between local purses. */\nexport interface HostCoinPaymentRebalancePurseRequest {\n /** Source purse. */\n from: number;\n /** Destination purse. */\n to: number;\n /** Amount to move. */\n amount: number;\n}\nexport const HostCoinPaymentRebalancePurseRequest: Codec;\n/** Request to refund coins associated with a receivable. */\nexport interface HostCoinPaymentRefundRequest {\n /** Receivable to refund. */\n receivable: HexString;\n}\nexport const HostCoinPaymentRefundRequest: Codec;\n/**\n * Error returned by the contact picker.\n *\n * Neither a dismissal nor an empty contact list is an error; both are outcomes.\n * A host that serves no picker at all answers `Unsupported` at the framework\n * level rather than through this enum.\n */\nexport type HostContactsPickError = \n/** No active session. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostContactsPickError: Codec;\n/**\n * Request to open the host's contact picker.\n *\n * Carries no arguments: the host owns the overlay, draws it from its own chat\n * contacts, and nothing the product supplies appears in it.\n */\nexport interface HostContactsPickRequest {\n}\nexport const HostContactsPickRequest: Codec;\n/** Outcome of a pick. */\nexport interface HostContactsPickResponse {\n /** How the pick ended. */\n outcome: ContactPickOutcome;\n}\nexport const HostContactsPickResponse: Codec;\n/** Transaction creation error. */\nexport type HostCreateTransactionError = \n/** Payload could not be deserialized. */\n{\n tag: \"FailedToDecode\";\n value?: undefined;\n}\n/** User rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Unsupported payload version or extension. */\n | {\n tag: \"NotSupported\";\n value: {\n reason: string;\n };\n}\n/** Not authenticated. */\n | {\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n}\n/**\n * A declared contact handle names nobody this host has a contact for, or\n * does not appear in the call it was declared for, or a handle appears in\n * the call without being declared. One refusal for all three, because\n * telling them apart would say whether a handle is current.\n */\n | {\n tag: \"UnknownContact\";\n value?: undefined;\n};\nexport const HostCreateTransactionError: Codec;\n/** Response containing a created transaction. */\nexport interface HostCreateTransactionResponse {\n /**\n * SCALE-encoded transaction, signed unless the request supplied its own\n * V5 `VerifyMultiSignature` extension.\n */\n transaction: HexString;\n}\nexport const HostCreateTransactionResponse: Codec;\n/** Response containing a transaction created with a non-product account. */\nexport interface HostCreateTransactionWithLegacyAccountResponse {\n /**\n * SCALE-encoded transaction, signed unless the request supplied its own\n * V5 `VerifyMultiSignature` extension.\n */\n transaction: HexString;\n}\nexport const HostCreateTransactionWithLegacyAccountResponse: Codec;\n/** Error from [`crate::api::Entropy::derive`] (RFC 0007). */\nexport type HostDeriveEntropyError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostDeriveEntropyError: Codec;\n/**\n * Request to derive deterministic per-product entropy (RFC 0007).\n *\n * The host derives 32 bytes from product-scoped seed material and `context`.\n * Repeated calls with the same `context` for the same product yield the same\n * entropy.\n */\nexport interface HostDeriveEntropyRequest {\n /** Domain-separated derivation context. */\n context: HexString;\n}\nexport const HostDeriveEntropyRequest: Codec;\n/** Response carrying 32 bytes of deterministically derived entropy. */\nexport interface HostDeriveEntropyResponse {\n /** 32 bytes of derived entropy. */\n entropy: HexString;\n}\nexport const HostDeriveEntropyResponse: Codec;\n/**\n * Device-capability permission requested from the host (RFC 0002).\n *\n * Lasting grants and denials survive app restarts. A host may also offer a\n * one-use grant, held in memory until a permission-gated operation consumes it.\n *\n * That decision is about this product. The OS grant behind it belongs to the\n * host application and can move independently, so a host that can read OS\n * state has the capability resolve only while both allow it: a stored grant\n * whose OS grant was revoked answers `granted: false` without a prompt. An OS\n * grant that is merely undetermined does not change the answer, because the OS\n * resolves its own gate when the capability is used.\n */\nexport type HostDevicePermissionRequest = \"Notifications\" | \"Camera\" | \"Microphone\" | \"Bluetooth\" | \"NFC\" | \"Location\" | \"Clipboard\" | \"OpenUrl\" | \"Biometrics\";\nexport const HostDevicePermissionRequest: Codec;\n/** Outcome of a device-permission request. */\nexport interface HostDevicePermissionResponse {\n /** Whether the permission was granted. */\n granted: boolean;\n}\nexport const HostDevicePermissionResponse: Codec;\n/** Request to query whether a feature is supported by the host. */\nexport type HostFeatureSupportedRequest = \n/** Ask whether the host can interact with the chain identified by genesis hash. */\n{\n tag: \"Chain\";\n value: {\n genesisHash: HexString;\n };\n};\nexport const HostFeatureSupportedRequest: Codec;\n/** Response to a feature-support query. */\nexport interface HostFeatureSupportedResponse {\n /** Whether the feature is supported. */\n supported: boolean;\n}\nexport const HostFeatureSupportedResponse: Codec;\n/** Response containing all legacy (user-imported) accounts owned by the user. */\nexport interface HostGetLegacyAccountsResponse {\n /** Legacy accounts. */\n accounts: Array;\n}\nexport const HostGetLegacyAccountsResponse: Codec;\n/** Response containing the product context bound to the current host runtime. */\nexport interface HostGetProductContextResponse {\n /** Full canonical identifier used for authorization and account derivation. */\n productId: string;\n}\nexport const HostGetProductContextResponse: Codec;\n/** Error from [`crate::api::Account::get_user_id`]. */\nexport type HostGetUserIdError = \n/** User denied the identity disclosure request. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** User is not logged in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostGetUserIdError: Codec;\n/** The user's primary DotNS account identity. */\nexport interface HostGetUserIdResponse {\n /** The user's primary DotNS username. */\n primaryUsername: string;\n}\nexport const HostGetUserIdResponse: Codec;\n/**\n * Error from [`crate::api::System::handshake`] (RFC 0009).\n *\n * The handshake is the first call on a fresh connection; it does not require\n * user authentication and is used to negotiate the wire codec version.\n */\nexport type HostHandshakeError = \n/** Host did not complete the handshake in time. */\n{\n tag: \"Timeout\";\n value?: undefined;\n}\n/** Host does not speak the codec version requested by the product. */\n | {\n tag: \"UnsupportedProtocolVersion\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: GenericError;\n};\nexport const HostHandshakeError: Codec;\n/** Wire-codec negotiation payload sent by the product (RFC 0009). */\nexport interface HostHandshakeRequest {\n /** Wire codec version requested by the product. */\n codecVersion: number;\n}\nexport const HostHandshakeRequest: Codec;\n/** A change to a subscribed storage key, pushed to the subscriber. */\nexport interface HostLocalStorageChangeItem {\n /** Value after the change. `Some` on write, `None` after clear. */\n value?: HexString;\n}\nexport const HostLocalStorageChangeItem: Codec;\n/** Request to clear a local storage key. */\nexport interface HostLocalStorageClearRequest {\n /** Storage key to clear. */\n key: string;\n}\nexport const HostLocalStorageClearRequest: Codec;\n/** Local storage operation error. */\nexport type V01HostLocalStorageReadError = \n/** Storage quota exceeded. */\n{\n tag: \"Full\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const V01HostLocalStorageReadError: Codec;\n/** Request to read a local storage value. */\nexport interface V01HostLocalStorageReadRequest {\n /** Storage key to read. */\n key: string;\n}\nexport const V01HostLocalStorageReadRequest: Codec;\n/** Response containing an optional local storage value. */\nexport interface HostLocalStorageReadResponse {\n /** Stored value, if present. */\n value?: HexString;\n}\nexport const HostLocalStorageReadResponse: Codec;\n/** Request to subscribe to changes of one local storage key. */\nexport interface HostLocalStorageSubscribeRequest {\n /** Storage key to observe. */\n key: string;\n}\nexport const HostLocalStorageSubscribeRequest: Codec;\n/** Request to write a value into local storage. */\nexport interface HostLocalStorageWriteRequest {\n /** Storage key to write. */\n key: string;\n /** Value to store at the key. */\n value: HexString;\n}\nexport const HostLocalStorageWriteRequest: Codec;\n/** Locale the host currently presents its interface in, pushed to subscribers. */\nexport interface V01HostLocaleSubscribeItem {\n /**\n * BCP 47 language tag, such as `en`, `pt-BR` or `zh-Hans`. The set is\n * open: a product that does not ship the tag chooses its own fallback.\n */\n languageTag: string;\n}\nexport const V01HostLocaleSubscribeItem: Codec;\n/** Error from [`crate::api::System::navigate_to`]. */\nexport type HostNavigateToError = \n/**\n * The target host is not authorized for outbound access: the user answered\n * no to the prompt, a stored decision already refused it, or no prompt\n * could be put to the user.\n */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostNavigateToError: Codec;\n/** Request to navigate the host to an external URL. */\nexport interface HostNavigateToRequest {\n /** URL to open. */\n url: string;\n}\nexport const HostNavigateToRequest: Codec;\n/**\n * Error from [`crate::api::Payment::balance_subscribe`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentBalanceSubscribeError = \n/** User denied the balance disclosure request. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentBalanceSubscribeError: Codec;\n/**\n * Current payment balance state pushed to subscribers.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport interface HostPaymentBalanceSubscribeItem {\n /** Balance that can be spent right now. */\n available: bigint;\n}\nexport const HostPaymentBalanceSubscribeItem: Codec;\n/** Request to subscribe to payment balance updates. */\nexport interface HostPaymentBalanceSubscribeRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n purse?: number;\n}\nexport const HostPaymentBalanceSubscribeRequest: Codec;\n/**\n * Error from [`crate::api::Payment::request`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentError = \n/** User rejected the payment request. */\n{\n tag: \"Rejected\";\n value?: undefined;\n}\n/** User's available balance is not sufficient for the requested amount. */\n | {\n tag: \"InsufficientBalance\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentError: Codec;\n/** Request to initiate a payment to another account. */\nexport interface HostPaymentRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n from?: number;\n /** Amount to pay. */\n amount: bigint;\n /** Destination account. */\n destination: HexString;\n}\nexport const HostPaymentRequest: Codec;\n/**\n * Receipt returned after a successful payment request.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport interface HostPaymentResponse {\n /** The assigned payment identifier. */\n id: string;\n}\nexport const HostPaymentResponse: Codec;\n/**\n * Error from [`crate::api::Payment::status_subscribe`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentStatusSubscribeError = \n/** Payment ID was not found or does not belong to the current product. */\n{\n tag: \"PaymentNotFound\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentStatusSubscribeError: Codec;\n/**\n * Payment lifecycle status pushed to subscribers.\n *\n * Once a terminal state (`Completed` or `Failed`) is reached, the host\n * delivers it and may close the subscription.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentStatusSubscribeItem = \n/** Payment is being processed. */\n{\n tag: \"Processing\";\n value?: undefined;\n}\n/** Payment has been settled successfully. */\n | {\n tag: \"Completed\";\n value?: undefined;\n}\n/** Payment has failed. */\n | {\n tag: \"Failed\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentStatusSubscribeItem: Codec;\n/** Request to subscribe to a payment status. */\nexport interface HostPaymentStatusSubscribeRequest {\n /** Payment identifier to watch. */\n paymentId: string;\n}\nexport const HostPaymentStatusSubscribeRequest: Codec;\n/**\n * Error from [`crate::api::Payment::top_up`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentTopUpError = \n/** The source account does not hold sufficient funds. */\n{\n tag: \"InsufficientFunds\";\n value?: undefined;\n}\n/** The source account was not found or is invalid. */\n | {\n tag: \"InvalidSource\";\n value?: undefined;\n}\n/** Some coins were claimed but the total fell short of the requested amount. */\n | {\n tag: \"PartialPayment\";\n value: {\n credited: bigint;\n };\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentTopUpError: Codec;\n/** Request to top up the product payment balance. */\nexport interface HostPaymentTopUpRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n into?: number;\n /** Amount to top up. */\n amount: bigint;\n /** Funding source for the top-up. */\n source: PaymentTopUpSource;\n}\nexport const HostPaymentTopUpRequest: Codec;\n/** The calling product's cards: the whole set on subscribe and after every change. */\nexport interface HostPocketListSubscribeItem {\n /** Cards currently in Pocket for the calling product. */\n cards: Array;\n}\nexport const HostPocketListSubscribeItem: Codec;\n/** Card removal failure. */\nexport type HostPocketRemoveCardError = \n/** The card is privileged and stays in Pocket. */\n{\n tag: \"Privileged\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPocketRemoveCardError: Codec;\n/** Request to remove one of the calling product's cards. */\nexport interface HostPocketRemoveCardRequest {\n /** Card to remove. A card that is not present is already removed. */\n cardId: string;\n}\nexport const HostPocketRemoveCardRequest: Codec;\n/** Request to cancel a previously scheduled notification. */\nexport interface HostPushNotificationCancelRequest {\n /** The notification identifier returned by [`HostPushNotificationResponse`]. */\n id: number;\n}\nexport const HostPushNotificationCancelRequest: Codec;\n/** Push notification error. */\nexport type HostPushNotificationError = \n/** The host-wide queue of pending scheduled notifications is full. */\n{\n tag: \"ScheduleLimitReached\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPushNotificationError: Codec;\n/**\n * Push notification payload.\n *\n * When `scheduled_at` is `Some`, the notification is deferred to the given\n * wall-clock instant (Unix milliseconds UTC). `None` fires immediately,\n * preserving prior behaviour. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\nexport interface HostPushNotificationRequest {\n /** Notification text. */\n text: string;\n /** Optional URL to open on tap. */\n deeplink?: string;\n /**\n * Optional Unix timestamp in milliseconds (UTC) at which the notification\n * should fire. `None` fires immediately.\n */\n scheduledAt?: bigint;\n}\nexport const HostPushNotificationRequest: Codec;\n/** Successful push notification response carrying the assigned id. */\nexport interface HostPushNotificationResponse {\n /** Host-assigned notification identifier. */\n id: number;\n}\nexport const HostPushNotificationResponse: Codec;\n/** An action triggered inside a product-rendered body. */\nexport interface HostRendererActionSubscribeItem {\n /** Where the body lives. */\n context: RenderContext;\n /** Which action was triggered, as named in the renderer tree. */\n actionId: string;\n /**\n * Data the node attached to the action. A `Button` press carries an\n * empty payload; a `TextField` value change carries the UTF-8 bytes of\n * the new value, with no length prefix.\n */\n payload: HexString;\n}\nexport const HostRendererActionSubscribeItem: Codec;\n/** Login request error. */\nexport type HostRequestLoginError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostRequestLoginError: Codec;\n/** Request to present the host login flow. */\nexport interface HostRequestLoginRequest {\n /** Optional human-readable reason shown in the login UI. */\n reason?: string;\n}\nexport const HostRequestLoginRequest: Codec;\n/** Result of a login request. */\nexport type HostRequestLoginResponse = \"Success\" | \"AlreadyConnected\" | \"Rejected\";\nexport const HostRequestLoginResponse: Codec;\n/** Batched resource pre-allocation request (RFC 0010). */\nexport interface HostRequestResourceAllocationRequest {\n /** Resources to allocate. */\n resources: Array;\n}\nexport const HostRequestResourceAllocationRequest: Codec;\n/** Per-resource outcomes for a batched allocation request (RFC 0010). */\nexport interface HostRequestResourceAllocationResponse {\n /** Per-resource allocation outcomes, in the same order as the request. */\n outcomes: Array;\n}\nexport const HostRequestResourceAllocationResponse: Codec;\n/** Signing operation error. */\nexport type HostSignPayloadError = \n/** Payload could not be deserialized. */\n{\n tag: \"FailedToDecode\";\n value?: undefined;\n}\n/** User rejected signing. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Not authenticated. */\n | {\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostSignPayloadError: Codec;\n/** Request to sign an extrinsic payload with a product account. */\nexport interface HostSignPayloadRequest {\n /** Product account that will sign this payload. */\n account: ProductAccountId;\n /** The extrinsic payload to sign. */\n payload: HostSignPayloadData;\n}\nexport const HostSignPayloadRequest: Codec;\n/** Result of a signing operation. */\nexport interface HostSignPayloadResponse {\n /** The cryptographic signature. */\n signature: HexString;\n /** Full signed transaction, if requested. */\n signedTransaction?: HexString;\n}\nexport const HostSignPayloadResponse: Codec;\n/**\n * Sign a Substrate extrinsic payload with a non-product (legacy) account.\n * Contains the same fields as [`HostSignPayloadRequest`] minus `address`\n * (replaced by `signer`).\n */\nexport interface HostSignPayloadWithLegacyAccountRequest {\n /** Signer address (SS58 or hex) of the legacy account. */\n signer: string;\n /** The extrinsic payload to sign. */\n payload: HostSignPayloadData;\n}\nexport const HostSignPayloadWithLegacyAccountRequest: Codec;\n/** A raw signing request pairing an account with the payload to sign. */\nexport interface HostSignRawRequest {\n /** Product account that will sign this payload. */\n account: ProductAccountId;\n /** The payload to sign. */\n payload: RawPayload;\n}\nexport const HostSignRawRequest: Codec;\n/**\n * Sign raw bytes with a non-product (legacy) account. The signer field\n * identifies which legacy account to use.\n */\nexport interface HostSignRawWithLegacyAccountRequest {\n /** Signer address (SS58 or hex) of the legacy account. */\n signer: string;\n /** The data to sign. */\n payload: RawPayload;\n}\nexport const HostSignRawWithLegacyAccountRequest: Codec;\n/** Current theme state pushed to subscribers. */\nexport interface HostThemeSubscribeItem {\n /** Theme name. */\n name: ThemeName;\n /** Light or dark variant. */\n variant: ThemeVariant;\n}\nexport const HostThemeSubscribeItem: Codec;\n/** Request to begin a pending operation. */\nexport interface HostWorkerBeginOperationRequest {\n /** Optional label for host logs and UI. */\n label?: string;\n}\nexport const HostWorkerBeginOperationRequest: Codec;\n/** Response carrying the id of a newly begun operation. */\nexport interface HostWorkerBeginOperationResponse {\n /** Id to pass to `end_operation`. */\n id: number;\n}\nexport const HostWorkerBeginOperationResponse: Codec;\n/** Request to end a pending operation. */\nexport interface HostWorkerEndOperationRequest {\n /** Id returned by `begin_operation`. */\n id: number;\n}\nexport const HostWorkerEndOperationRequest: Codec;\n/** A body the host needs drawn. */\nexport interface ProductRendererRenderRequest {\n /** Where the body lives. */\n context: RenderContext;\n /** Product-defined payload, opaque to the host. */\n payload: HexString;\n}\nexport const ProductRendererRenderRequest: Codec;\n/** Request to fetch the body of a pinned block. */\nexport interface RemoteChainHeadBodyRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n}\nexport const RemoteChainHeadBodyRequest: Codec;\n/** Response to a body request; results arrive as follow events. */\nexport interface RemoteChainHeadBodyResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadBodyResponse: Codec;\n/** Request to invoke a runtime call at a pinned block. */\nexport interface RemoteChainHeadCallRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n /** Runtime API function name. */\n function: string;\n /** SCALE-encoded call parameters. */\n callParameters: HexString;\n}\nexport const RemoteChainHeadCallRequest: Codec;\n/** Response to a runtime call request; the output arrives as a follow event. */\nexport interface RemoteChainHeadCallResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadCallResponse: Codec;\n/** Request to continue a paused chain-head operation. */\nexport interface RemoteChainHeadContinueRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Operation identifier. */\n operationId: string;\n}\nexport const RemoteChainHeadContinueRequest: Codec;\n/** Event emitted on a chain-head follow subscription. */\nexport type RemoteChainHeadFollowItem = \n/** First event of the subscription, describing the current finalized blocks. */\n{\n tag: \"Initialized\";\n value: {\n finalizedBlockHashes: Array;\n finalizedBlockRuntime?: RuntimeType;\n };\n}\n/** A new non-finalized block was announced. */\n | {\n tag: \"NewBlock\";\n value: {\n blockHash: HexString;\n parentBlockHash: HexString;\n newRuntime?: RuntimeType;\n };\n}\n/** The best block has changed. */\n | {\n tag: \"BestBlockChanged\";\n value: {\n bestBlockHash: HexString;\n };\n}\n/** One or more blocks were finalized. */\n | {\n tag: \"Finalized\";\n value: {\n finalizedBlockHashes: Array;\n prunedBlockHashes: Array;\n };\n}\n/** A body operation completed. */\n | {\n tag: \"OperationBodyDone\";\n value: {\n operationId: string;\n value: Array;\n };\n}\n/** A runtime call operation completed. */\n | {\n tag: \"OperationCallDone\";\n value: {\n operationId: string;\n output: HexString;\n };\n}\n/** A storage operation produced a batch of results. */\n | {\n tag: \"OperationStorageItems\";\n value: {\n operationId: string;\n items: Array;\n };\n}\n/** A storage operation finished emitting results. */\n | {\n tag: \"OperationStorageDone\";\n value: {\n operationId: string;\n };\n}\n/** A storage operation is paused until the product requests continuation. */\n | {\n tag: \"OperationWaitingForContinue\";\n value: {\n operationId: string;\n };\n}\n/** The operation failed because the required data was not accessible; it can be retried. */\n | {\n tag: \"OperationInaccessible\";\n value: {\n operationId: string;\n };\n}\n/** The operation failed with an error. */\n | {\n tag: \"OperationError\";\n value: {\n operationId: string;\n error: string;\n };\n}\n/** The subscription was stopped by the host and is no longer valid. */\n | {\n tag: \"Stop\";\n value?: undefined;\n};\nexport const RemoteChainHeadFollowItem: Codec;\n/** Request to start a chain-head follow subscription. */\nexport interface RemoteChainHeadFollowRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Whether to include runtime information in events. */\n withRuntime: boolean;\n}\nexport const RemoteChainHeadFollowRequest: Codec;\n/** Request to fetch the header of a pinned block. */\nexport interface RemoteChainHeadHeaderRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n}\nexport const RemoteChainHeadHeaderRequest: Codec;\n/** Response containing the requested block header. */\nexport interface RemoteChainHeadHeaderResponse {\n /** SCALE-encoded block header. */\n header?: HexString;\n}\nexport const RemoteChainHeadHeaderResponse: Codec;\n/** Request to stop an in-progress chain-head operation. */\nexport interface RemoteChainHeadStopOperationRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Operation identifier. */\n operationId: string;\n}\nexport const RemoteChainHeadStopOperationRequest: Codec;\n/** Request to query storage at a pinned block. */\nexport interface RemoteChainHeadStorageRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n /** Storage items to query. */\n items: Array;\n /** Optional child trie. */\n childTrie?: HexString;\n}\nexport const RemoteChainHeadStorageRequest: Codec;\n/** Response to a storage request; results arrive as follow events. */\nexport interface RemoteChainHeadStorageResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadStorageResponse: Codec;\n/** Request to release pinned blocks. */\nexport interface RemoteChainHeadUnpinRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hashes to unpin. */\n hashes: Array;\n}\nexport const RemoteChainHeadUnpinRequest: Codec;\n/** Error from [`crate::api::Chain::get_chain_info`]. */\nexport type RemoteChainInfoError = \n/** The host does not serve the requested chain. */\n{\n tag: \"NotSupported\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: GenericError;\n};\nexport const RemoteChainInfoError: Codec;\n/** Request to resolve one chain identifier against the host's environment. */\nexport interface RemoteChainInfoRequest {\n /** Chain to resolve. */\n chain: ChainIdentifier;\n}\nexport const RemoteChainInfoRequest: Codec;\n/** Response carrying the resolved chain data. */\nexport interface RemoteChainInfoResponse {\n /** Ecosystem the host is configured for, e.g. \"polkadot\", \"kusama\", \"paseo\". */\n network: string;\n /** Chain this response resolves, echoed from the request. */\n chain: ChainIdentifier;\n /** Genesis hash identifying the chain in all chain-scoped calls. */\n genesisHash: HexString;\n}\nexport const RemoteChainInfoResponse: Codec;\n/** Request for the display name of a chain. */\nexport interface RemoteChainSpecChainNameRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecChainNameRequest: Codec;\n/** Response containing the chain display name. */\nexport interface RemoteChainSpecChainNameResponse {\n /** Chain display name. */\n chainName: string;\n}\nexport const RemoteChainSpecChainNameResponse: Codec;\n/** Request for the canonical genesis hash of a chain. */\nexport interface RemoteChainSpecGenesisHashRequest {\n /** Chain genesis hash requested by the product. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecGenesisHashRequest: Codec;\n/** Response containing the canonical genesis hash. */\nexport interface RemoteChainSpecGenesisHashResponse {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecGenesisHashResponse: Codec;\n/** Request for the JSON-encoded properties of a chain. */\nexport interface RemoteChainSpecPropertiesRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecPropertiesRequest: Codec;\n/** Response containing the chain properties. */\nexport interface RemoteChainSpecPropertiesResponse {\n /** JSON-encoded properties. */\n properties: string;\n}\nexport const RemoteChainSpecPropertiesResponse: Codec;\n/** Request to broadcast a signed transaction. */\nexport interface RemoteChainTransactionBroadcastRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Signed transaction bytes. */\n transaction: HexString;\n}\nexport const RemoteChainTransactionBroadcastRequest: Codec;\n/** Response to a transaction broadcast request. */\nexport interface RemoteChainTransactionBroadcastResponse {\n /** Broadcast operation identifier, if available. */\n operationId?: string;\n}\nexport const RemoteChainTransactionBroadcastResponse: Codec;\n/** Request to stop broadcasting a transaction. */\nexport interface RemoteChainTransactionStopRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Operation identifier of the broadcast to stop. */\n operationId: string;\n}\nexport const RemoteChainTransactionStopRequest: Codec;\n/** remote-permission request (RFC 0002). */\nexport interface RemotePermissionRequest {\n /** Permission requested by the product. */\n permission: RemotePermission;\n}\nexport const RemotePermissionRequest: Codec;\n/** Outcome of a remote-permission request. */\nexport interface RemotePermissionResponse {\n /** Whether the permission was granted. */\n granted: boolean;\n}\nexport const RemotePermissionResponse: Codec;\n/** Item containing an optional preimage lookup result. */\nexport interface RemotePreimageLookupSubscribeItem {\n /** Preimage data, if found. */\n value?: HexString;\n}\nexport const RemotePreimageLookupSubscribeItem: Codec;\n/** Request to subscribe to preimage lookup results. */\nexport interface RemotePreimageLookupSubscribeRequest {\n /** Hash of the preimage. */\n key: HexString;\n}\nexport const RemotePreimageLookupSubscribeRequest: Codec;\n/** Statement proof creation error. */\nexport type RemoteStatementStoreCreateProofError = \n/** Signing operation failed. */\n{\n tag: \"UnableToSign\";\n value?: undefined;\n}\n/** Account not recognized. */\n | {\n tag: \"UnknownAccount\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const RemoteStatementStoreCreateProofError: Codec;\n/** Request to create a cryptographic proof for a statement. */\nexport interface RemoteStatementStoreCreateProofRequest {\n /** Product account that should create the proof. */\n productAccountId: ProductAccountId;\n /** Statement to prove. */\n statement: Statement;\n}\nexport const RemoteStatementStoreCreateProofRequest: Codec;\n/** Response containing a statement proof. */\nexport interface RemoteStatementStoreCreateProofResponse {\n /** Created statement proof. */\n proof: StatementProof;\n}\nexport const RemoteStatementStoreCreateProofResponse: Codec;\n/**\n * Page of signed statements delivered by the statement store subscription\n * (RFC 0008). The `is_complete` flag distinguishes the historical-dump phase\n * (`false`) from the live-update phase (`true`).\n */\nexport interface RemoteStatementStoreSubscribeItem {\n /** Signed statements matching the subscription. */\n statements: Array;\n /**\n * `false` while the host is still streaming the historical dump (more\n * pages to follow). `true` once the dump is complete; all subsequent\n * pages are also `true` and carry only newly-arrived statements.\n */\n isComplete: boolean;\n}\nexport const RemoteStatementStoreSubscribeItem: Codec;\n/** Request to subscribe to statements via a topic filter (RFC 0008). */\nexport type RemoteStatementStoreSubscribeRequest = \n/** AND: statement must contain every listed topic. */\n{\n tag: \"MatchAll\";\n value: Array;\n}\n/** OR: statement must contain at least one listed topic. */\n | {\n tag: \"MatchAny\";\n value: Array;\n};\nexport const RemoteStatementStoreSubscribeRequest: Codec;\n/** Local storage read failure. */\nexport type HostLocalStorageReadError = \n/** Storage quota exceeded. */\n{\n tag: \"Full\";\n value?: undefined;\n}\n/**\n * The addressed storage belongs to another product that has not granted\n * this caller the `storage` scope.\n *\n * One variant answers every reason: the product does not resolve, it\n * published no manifest, or its manifest grants this caller nothing.\n * Distinguishing them would make the call a probe for which products exist\n * and which hold data.\n */\n | {\n tag: \"AccessNotGranted\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostLocalStorageReadError: Codec;\n/**\n * Request to read a local storage value.\n *\n * Storage is private by default: `product: None` addresses the caller's own\n * storage, which is what every v0.1 read resolved to. Naming another product\n * reads that product's storage instead, and succeeds only if that product's\n * manifest grants this caller the `storage` scope.\n */\nexport interface HostLocalStorageReadRequest {\n /**\n * Product whose storage is read. `None`, or the caller's own id, means the\n * caller, and consults no grant.\n */\n product?: string;\n /** Storage key to read. */\n key: string;\n}\nexport const HostLocalStorageReadRequest: Codec;\n/** Convert UTC instants using a snapshot of the host's locale subscription. */\nexport interface HostLocaleLocalizeTimestampsRequest {\n /** At most 128 Unix millisecond instants, no later than year 9999. */\n timestampsMs: Array;\n /** Language tag from the locale subscription, not a guessed language. */\n languageTag: string;\n /** Time zone from the locale subscription; evaluated separately at each instant. */\n timeZone: string;\n}\nexport const HostLocaleLocalizeTimestampsRequest: Codec;\n/** Local timestamps in exactly the request's order. */\nexport interface HostLocaleLocalizeTimestampsResponse {\n /** One result per requested timestamp; partial success is not returned. */\n timestamps: Array;\n}\nexport const HostLocaleLocalizeTimestampsResponse: Codec;\n/** Host language and local time zone, replaced together when either changes. */\nexport interface HostLocaleSubscribeItem {\n /** BCP 47 language tag selected by the host. */\n languageTag: string;\n /** IANA time zone, or absent when the host cannot supply local time. */\n timeZone?: string;\n}\nexport const HostLocaleSubscribeItem: Codec;\n/** Failure of a Host-owned Chat operation before a public update is available. */\nexport type HostProductDeviceChatError = \"NotConnected\" | \"AccessNotGranted\" | \"UserRejected\" | \"AllowanceRequired\" | \"PeerNotReady\" | \"OperationConflict\" | \"InvalidRequest\" | \"InvalidStatement\" | \"RecipientNotFound\" | \"InsufficientBalance\" | \"StorageUnavailable\" | \"NetworkUnavailable\" | \"OperationNotFound\" | \"AttachmentsUnavailable\";\nexport const HostProductDeviceChatError: Codec;\n/** An operation on the calling product's Host-owned native Chat device. */\nexport type V02HostProductDeviceChatRequest = \n/** Restore the installation's public device and durable conversation state. */\n{\n tag: \"Initialize\";\n value?: undefined;\n}\n/** Resolve a username in the configured network and send a fresh invitation. */\n | {\n tag: \"Invite\";\n value: {\n username: string;\n text: string;\n };\n}\n/** Authenticate, decrypt and durably process a native statement. */\n | {\n tag: \"Receive\";\n value: {\n statement: SignedStatement;\n };\n}\n/** Accept an invitation previously authenticated and retained by the Host. */\n | {\n tag: \"AcceptInvitation\";\n value: {\n invitationId: HexString;\n };\n}\n/** Reject an invitation previously authenticated and retained by the Host. */\n | {\n tag: \"RejectInvitation\";\n value: {\n invitationId: HexString;\n };\n}\n/** Send ordinary messages to an established, Host-authenticated peer roster. */\n | {\n tag: \"Send\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n messages: Array;\n };\n}\n/** Propose one main-purse payment; this operation always requires Host review. */\n | {\n tag: \"SendPayment\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n amountCents: bigint;\n };\n}\n/** Read a payment's durable status without authorizing another spend. */\n | {\n tag: \"PaymentStatus\";\n value: {\n operationId: HexString;\n };\n}\n/** Resume durable transport work and return newly available public views. */\n | {\n tag: \"Reconcile\";\n value?: undefined;\n}\n/** Select immutable files in trusted Host UI and send native rich content. */\n | {\n tag: \"SendAttachments\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n text?: string;\n };\n}\n/** Resume a private download and present or export through trusted Host UI. */\n | {\n tag: \"OpenAttachment\";\n value: {\n attachmentId: HexString;\n };\n};\nexport const V02HostProductDeviceChatRequest: Codec;\n/** Public updates from a Host-owned Chat operation. */\nexport interface V02HostProductDeviceChatResponse {\n /** Public local device metadata, including its allowance account. */\n device: HostNativeChatDevice;\n /** Current authenticated peers and subscription channels. */\n peers: Array;\n /** Invitations still awaiting a user decision. */\n invitations: Array;\n /** Newly processed safe ordinary messages. */\n messages: Array;\n /** Newly processed native delivery acknowledgments. */\n acknowledgments: Array;\n /** Current public payment statuses belonging to the calling product. */\n payments: Array;\n /** Safe rich-content views and their current private-transfer progress. */\n richMessages: Array;\n}\nexport const V02HostProductDeviceChatResponse: Codec;\n/** An operation using the calling product's non-exportable Host Chat device. */\nexport type HostProductDeviceChatRequest = \n/** Restore public metadata, pending ciphertext, and private file-transfer progress. */\n{\n tag: \"Initialize\";\n value?: undefined;\n}\n/** Independently resolve and bind a peer on the trusted network. */\n | {\n tag: \"Bind\";\n value: {\n username: string;\n };\n}\n/** Validate native plaintext and return signed ciphertext for product delivery. */\n | {\n tag: \"Prepare\";\n value: {\n peerIdentity: HexString;\n route: HostNativeChatRoute;\n plaintext: HexString;\n };\n}\n/** Authenticate and decrypt a complete external native statement, never own output. */\n | {\n tag: \"Open\";\n value: {\n statement: SignedStatement;\n };\n}\n/** Propose one main-purse payment; this operation requires trusted Host review. */\n | {\n tag: \"SendPayment\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n amountCents: bigint;\n };\n}\n/** Read durable payment status without authorizing another spend. */\n | {\n tag: \"PaymentStatus\";\n value: {\n operationId: HexString;\n };\n}\n/** Reconcile payment custody and return opaque statements for product delivery. */\n | {\n tag: \"ReconcilePayments\";\n value?: undefined;\n}\n/** Select files in trusted Host UI and prepare native rich content without delivery. */\n | {\n tag: \"PrepareAttachments\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n text?: string;\n };\n}\n/** Resume a private download and present or export through trusted Host UI. */\n | {\n tag: \"OpenAttachment\";\n value: {\n attachmentId: HexString;\n };\n}\n/** Acknowledge durable product storage of the legacy view and ordinary ciphertext. */\n | {\n tag: \"CommitMigration\";\n value: {\n migrationId: HexString;\n };\n}\n/** Continue a Host-authenticated incoming batch without supplying new ciphertext. */\n | {\n tag: \"ContinueOpen\";\n value: {\n openId: HexString;\n cursor: number;\n };\n}\n/** Continue a bounded snapshot of custody metadata and pending prepared statements. */\n | {\n tag: \"ContinueState\";\n value: {\n stateId: HexString;\n cursor: number;\n };\n}\n/** Read configured raw chain units per native Coinage cent, without spending. */\n | {\n tag: \"PaymentDenomination\";\n value?: undefined;\n};\nexport const HostProductDeviceChatRequest: Codec;\n/** Cryptographic results and custody metadata; products drive delivery and import. */\nexport interface HostProductDeviceChatResponse {\n /** Public local device metadata, including its allowance account. */\n device: HostNativeChatDevice;\n /** Host-authenticated peer and device metadata. */\n peers: Array;\n /** Newly resolved peer binding, when requested. */\n binding?: HostNativeChatBinding;\n /** Authenticated incoming plaintext; incoming payment import is product-owned. */\n opened: Array;\n /** Signed ciphertext for product submission and exact-identity retries. */\n prepared: Array;\n /** Durable public payment status, never outgoing bearer secrets. */\n payments: Array;\n /** Rich-content metadata and trusted private-transfer progress. */\n richMessages: Array;\n /** Legacy public view retained until the product durably commits migration. */\n migration?: V02HostProductDeviceChatResponse;\n /** Snapshot identifier to acknowledge only after persisting its view and ciphertext. */\n migrationId?: HexString;\n /** Continuation of an authenticated incoming batch, when opening is paginated. */\n openPage?: HostNativeChatOpenPage;\n /** Native request identities for invitations in the legacy migration view. */\n migrationInvitations: Array;\n /** Continuation of a bounded public state snapshot, when metadata is paginated. */\n statePage?: HostNativeChatStatePage;\n /**\n * Configured raw chain units per native Coinage cent, only when requested.\n * This is positive denomination metadata, never a balance or fiat price.\n */\n coinageCentsUnit?: bigint;\n}\nexport const HostProductDeviceChatResponse: Codec;\n/** Cross-axis alignment of `Row` children. */\nexport type VerticalAlignment = \"Top\" | \"Center\" | \"Bottom\";\nexport const VerticalAlignment: Codec;\n/** An sr25519 (schnorrkel) VRF signature: the VRF pre-output and its proof. */\nexport interface VrfSignature {\n /** schnorrkel `VRFPreOut` \u2014 the 32-byte VRF output point. */\n preOutput: HexString;\n /** schnorrkel `VRFProof` \u2014 the 64-byte DLEQ proof. */\n proof: HexString;\n}\nexport const VrfSignature: Codec;\n/** One `append_message` call replayed against the signing transcript. */\nexport interface VrfTranscriptItem {\n /** Merlin `append_message` label. */\n label: HexString;\n /** Merlin `append_message` value. */\n value: HexString;\n}\nexport const VrfTranscriptItem: Codec;\n\n}\n\n\n// re-export namespace T at module top level (mirrors index.d.ts `export *`)\n\nexport import ActionTrigger = T.ActionTrigger;\nexport import AllocatableResource = T.AllocatableResource;\nexport import AllocationOutcome = T.AllocationOutcome;\nexport import Arrangement = T.Arrangement;\nexport import Background = T.Background;\nexport import BlendingMode = T.BlendingMode;\nexport import BorderStyle = T.BorderStyle;\nexport import BoxProps = T.BoxProps;\nexport import ButtonProps = T.ButtonProps;\nexport import ButtonVariant = T.ButtonVariant;\nexport import Bytes32 = T.Bytes32;\nexport import ChainIdentifier = T.ChainIdentifier;\nexport import ChatAction = T.ChatAction;\nexport import ChatActionLayout = T.ChatActionLayout;\nexport import ChatActionPayload = T.ChatActionPayload;\nexport import ChatActions = T.ChatActions;\nexport import ChatBotRegistrationStatus = T.ChatBotRegistrationStatus;\nexport import ChatCommand = T.ChatCommand;\nexport import ChatCustomMessage = T.ChatCustomMessage;\nexport import ChatFile = T.ChatFile;\nexport import ChatMedia = T.ChatMedia;\nexport import ChatMessageContent = T.ChatMessageContent;\nexport import ChatReaction = T.ChatReaction;\nexport import ChatRichText = T.ChatRichText;\nexport import ChatRoom = T.ChatRoom;\nexport import ChatRoomParticipation = T.ChatRoomParticipation;\nexport import ChatRoomRegistrationStatus = T.ChatRoomRegistrationStatus;\nexport import CoinPaymentCheque = T.CoinPaymentCheque;\nexport import CoinPaymentClearingReference = T.CoinPaymentClearingReference;\nexport import CoinPaymentError = T.CoinPaymentError;\nexport import CoinPaymentPurseInfo = T.CoinPaymentPurseInfo;\nexport import CoinPaymentStatus = T.CoinPaymentStatus;\nexport import CoinPaymentTransmissionChannel = T.CoinPaymentTransmissionChannel;\nexport import ColorToken = T.ColorToken;\nexport import ColumnProps = T.ColumnProps;\nexport import ContactHandle = T.ContactHandle;\nexport import ContactPickOutcome = T.ContactPickOutcome;\nexport import ContentAlignment = T.ContentAlignment;\nexport import ContextualAlias = T.ContextualAlias;\nexport import DerivationIndex = T.DerivationIndex;\nexport import Dimensions = T.Dimensions;\nexport import Effect = T.Effect;\nexport import EffectProps = T.EffectProps;\nexport import GenericError = T.GenericError;\nexport import HorizontalAlignment = T.HorizontalAlignment;\nexport import VersionedHostAccountConnectionStatusSubscribeError = T.VersionedHostAccountConnectionStatusSubscribeError;\nexport import VersionedHostAccountConnectionStatusSubscribeItem = T.VersionedHostAccountConnectionStatusSubscribeItem;\nexport import VersionedHostAccountConnectionStatusSubscribeRequest = T.VersionedHostAccountConnectionStatusSubscribeRequest;\nexport import VersionedHostAccountCreateProofError = T.VersionedHostAccountCreateProofError;\nexport import VersionedHostAccountCreateProofRequest = T.VersionedHostAccountCreateProofRequest;\nexport import VersionedHostAccountCreateProofResponse = T.VersionedHostAccountCreateProofResponse;\nexport import VersionedHostAccountGetAliasError = T.VersionedHostAccountGetAliasError;\nexport import VersionedHostAccountGetAliasRequest = T.VersionedHostAccountGetAliasRequest;\nexport import VersionedHostAccountGetAliasResponse = T.VersionedHostAccountGetAliasResponse;\nexport import VersionedHostAccountGetError = T.VersionedHostAccountGetError;\nexport import VersionedHostAccountGetRequest = T.VersionedHostAccountGetRequest;\nexport import VersionedHostAccountGetResponse = T.VersionedHostAccountGetResponse;\nexport import VersionedHostAccountListRingVrfKeysError = T.VersionedHostAccountListRingVrfKeysError;\nexport import VersionedHostAccountListRingVrfKeysRequest = T.VersionedHostAccountListRingVrfKeysRequest;\nexport import VersionedHostAccountListRingVrfKeysResponse = T.VersionedHostAccountListRingVrfKeysResponse;\nexport import VersionedHostAccountRegisterRingVrfKeyError = T.VersionedHostAccountRegisterRingVrfKeyError;\nexport import VersionedHostAccountRegisterRingVrfKeyRequest = T.VersionedHostAccountRegisterRingVrfKeyRequest;\nexport import VersionedHostAccountRegisterRingVrfKeyResponse = T.VersionedHostAccountRegisterRingVrfKeyResponse;\nexport import VersionedHostAccountRingVrfSignError = T.VersionedHostAccountRingVrfSignError;\nexport import VersionedHostAccountRingVrfSignRequest = T.VersionedHostAccountRingVrfSignRequest;\nexport import VersionedHostAccountRingVrfSignResponse = T.VersionedHostAccountRingVrfSignResponse;\nexport import VersionedHostAccountSignVrfError = T.VersionedHostAccountSignVrfError;\nexport import VersionedHostAccountSignVrfRequest = T.VersionedHostAccountSignVrfRequest;\nexport import VersionedHostAccountSignVrfResponse = T.VersionedHostAccountSignVrfResponse;\nexport import VersionedHostChatActionSubscribeError = T.VersionedHostChatActionSubscribeError;\nexport import VersionedHostChatActionSubscribeItem = T.VersionedHostChatActionSubscribeItem;\nexport import VersionedHostChatActionSubscribeRequest = T.VersionedHostChatActionSubscribeRequest;\nexport import VersionedHostChatCreateRoomError = T.VersionedHostChatCreateRoomError;\nexport import VersionedHostChatCreateRoomRequest = T.VersionedHostChatCreateRoomRequest;\nexport import VersionedHostChatCreateRoomResponse = T.VersionedHostChatCreateRoomResponse;\nexport import VersionedHostChatListSubscribeError = T.VersionedHostChatListSubscribeError;\nexport import VersionedHostChatListSubscribeItem = T.VersionedHostChatListSubscribeItem;\nexport import VersionedHostChatListSubscribeRequest = T.VersionedHostChatListSubscribeRequest;\nexport import VersionedHostChatPostMessageError = T.VersionedHostChatPostMessageError;\nexport import VersionedHostChatPostMessageRequest = T.VersionedHostChatPostMessageRequest;\nexport import VersionedHostChatPostMessageResponse = T.VersionedHostChatPostMessageResponse;\nexport import VersionedHostChatRegisterBotError = T.VersionedHostChatRegisterBotError;\nexport import VersionedHostChatRegisterBotRequest = T.VersionedHostChatRegisterBotRequest;\nexport import VersionedHostChatRegisterBotResponse = T.VersionedHostChatRegisterBotResponse;\nexport import VersionedHostCoinPaymentCreateChequeError = T.VersionedHostCoinPaymentCreateChequeError;\nexport import VersionedHostCoinPaymentCreateChequeRequest = T.VersionedHostCoinPaymentCreateChequeRequest;\nexport import VersionedHostCoinPaymentCreateChequeResponse = T.VersionedHostCoinPaymentCreateChequeResponse;\nexport import VersionedHostCoinPaymentCreatePurseError = T.VersionedHostCoinPaymentCreatePurseError;\nexport import VersionedHostCoinPaymentCreatePurseRequest = T.VersionedHostCoinPaymentCreatePurseRequest;\nexport import VersionedHostCoinPaymentCreatePurseResponse = T.VersionedHostCoinPaymentCreatePurseResponse;\nexport import VersionedHostCoinPaymentCreateReceivableError = T.VersionedHostCoinPaymentCreateReceivableError;\nexport import VersionedHostCoinPaymentCreateReceivableRequest = T.VersionedHostCoinPaymentCreateReceivableRequest;\nexport import VersionedHostCoinPaymentCreateReceivableResponse = T.VersionedHostCoinPaymentCreateReceivableResponse;\nexport import VersionedHostCoinPaymentDeletePurseError = T.VersionedHostCoinPaymentDeletePurseError;\nexport import VersionedHostCoinPaymentDeletePurseItem = T.VersionedHostCoinPaymentDeletePurseItem;\nexport import VersionedHostCoinPaymentDeletePurseRequest = T.VersionedHostCoinPaymentDeletePurseRequest;\nexport import VersionedHostCoinPaymentDepositError = T.VersionedHostCoinPaymentDepositError;\nexport import VersionedHostCoinPaymentDepositItem = T.VersionedHostCoinPaymentDepositItem;\nexport import VersionedHostCoinPaymentDepositRequest = T.VersionedHostCoinPaymentDepositRequest;\nexport import VersionedHostCoinPaymentListenForError = T.VersionedHostCoinPaymentListenForError;\nexport import VersionedHostCoinPaymentListenForItem = T.VersionedHostCoinPaymentListenForItem;\nexport import VersionedHostCoinPaymentListenForRequest = T.VersionedHostCoinPaymentListenForRequest;\nexport import VersionedHostCoinPaymentQueryPurseError = T.VersionedHostCoinPaymentQueryPurseError;\nexport import VersionedHostCoinPaymentQueryPurseRequest = T.VersionedHostCoinPaymentQueryPurseRequest;\nexport import VersionedHostCoinPaymentQueryPurseResponse = T.VersionedHostCoinPaymentQueryPurseResponse;\nexport import VersionedHostCoinPaymentRebalancePurseError = T.VersionedHostCoinPaymentRebalancePurseError;\nexport import VersionedHostCoinPaymentRebalancePurseItem = T.VersionedHostCoinPaymentRebalancePurseItem;\nexport import VersionedHostCoinPaymentRebalancePurseRequest = T.VersionedHostCoinPaymentRebalancePurseRequest;\nexport import VersionedHostCoinPaymentRefundError = T.VersionedHostCoinPaymentRefundError;\nexport import VersionedHostCoinPaymentRefundItem = T.VersionedHostCoinPaymentRefundItem;\nexport import VersionedHostCoinPaymentRefundRequest = T.VersionedHostCoinPaymentRefundRequest;\nexport import VersionedHostContactsPickError = T.VersionedHostContactsPickError;\nexport import VersionedHostContactsPickRequest = T.VersionedHostContactsPickRequest;\nexport import VersionedHostContactsPickResponse = T.VersionedHostContactsPickResponse;\nexport import VersionedHostCreateTransactionError = T.VersionedHostCreateTransactionError;\nexport import VersionedHostCreateTransactionRequest = T.VersionedHostCreateTransactionRequest;\nexport import VersionedHostCreateTransactionResponse = T.VersionedHostCreateTransactionResponse;\nexport import VersionedHostCreateTransactionWithLegacyAccountError = T.VersionedHostCreateTransactionWithLegacyAccountError;\nexport import VersionedHostCreateTransactionWithLegacyAccountRequest = T.VersionedHostCreateTransactionWithLegacyAccountRequest;\nexport import VersionedHostCreateTransactionWithLegacyAccountResponse = T.VersionedHostCreateTransactionWithLegacyAccountResponse;\nexport import VersionedHostDeriveEntropyError = T.VersionedHostDeriveEntropyError;\nexport import VersionedHostDeriveEntropyRequest = T.VersionedHostDeriveEntropyRequest;\nexport import VersionedHostDeriveEntropyResponse = T.VersionedHostDeriveEntropyResponse;\nexport import VersionedHostDevicePermissionError = T.VersionedHostDevicePermissionError;\nexport import VersionedHostDevicePermissionRequest = T.VersionedHostDevicePermissionRequest;\nexport import VersionedHostDevicePermissionResponse = T.VersionedHostDevicePermissionResponse;\nexport import VersionedHostFeatureSupportedError = T.VersionedHostFeatureSupportedError;\nexport import VersionedHostFeatureSupportedRequest = T.VersionedHostFeatureSupportedRequest;\nexport import VersionedHostFeatureSupportedResponse = T.VersionedHostFeatureSupportedResponse;\nexport import VersionedHostGetLegacyAccountsError = T.VersionedHostGetLegacyAccountsError;\nexport import VersionedHostGetLegacyAccountsRequest = T.VersionedHostGetLegacyAccountsRequest;\nexport import VersionedHostGetLegacyAccountsResponse = T.VersionedHostGetLegacyAccountsResponse;\nexport import VersionedHostGetProductContextError = T.VersionedHostGetProductContextError;\nexport import VersionedHostGetProductContextRequest = T.VersionedHostGetProductContextRequest;\nexport import VersionedHostGetProductContextResponse = T.VersionedHostGetProductContextResponse;\nexport import VersionedHostGetUserIdError = T.VersionedHostGetUserIdError;\nexport import VersionedHostGetUserIdRequest = T.VersionedHostGetUserIdRequest;\nexport import VersionedHostGetUserIdResponse = T.VersionedHostGetUserIdResponse;\nexport import VersionedHostHandshakeError = T.VersionedHostHandshakeError;\nexport import VersionedHostHandshakeRequest = T.VersionedHostHandshakeRequest;\nexport import VersionedHostHandshakeResponse = T.VersionedHostHandshakeResponse;\nexport import HostInfo = T.HostInfo;\nexport import VersionedHostInfoError = T.VersionedHostInfoError;\nexport import VersionedHostInfoRequest = T.VersionedHostInfoRequest;\nexport import VersionedHostInfoResponse = T.VersionedHostInfoResponse;\nexport import VersionedHostLocalStorageChangeItem = T.VersionedHostLocalStorageChangeItem;\nexport import VersionedHostLocalStorageClearError = T.VersionedHostLocalStorageClearError;\nexport import VersionedHostLocalStorageClearRequest = T.VersionedHostLocalStorageClearRequest;\nexport import VersionedHostLocalStorageClearResponse = T.VersionedHostLocalStorageClearResponse;\nexport import VersionedHostLocalStorageReadError = T.VersionedHostLocalStorageReadError;\nexport import VersionedHostLocalStorageReadRequest = T.VersionedHostLocalStorageReadRequest;\nexport import VersionedHostLocalStorageReadResponse = T.VersionedHostLocalStorageReadResponse;\nexport import VersionedHostLocalStorageSubscribeError = T.VersionedHostLocalStorageSubscribeError;\nexport import VersionedHostLocalStorageSubscribeRequest = T.VersionedHostLocalStorageSubscribeRequest;\nexport import VersionedHostLocalStorageWriteError = T.VersionedHostLocalStorageWriteError;\nexport import VersionedHostLocalStorageWriteRequest = T.VersionedHostLocalStorageWriteRequest;\nexport import VersionedHostLocalStorageWriteResponse = T.VersionedHostLocalStorageWriteResponse;\nexport import VersionedHostLocaleLocalizeTimestampsError = T.VersionedHostLocaleLocalizeTimestampsError;\nexport import VersionedHostLocaleLocalizeTimestampsRequest = T.VersionedHostLocaleLocalizeTimestampsRequest;\nexport import VersionedHostLocaleLocalizeTimestampsResponse = T.VersionedHostLocaleLocalizeTimestampsResponse;\nexport import HostLocaleLocalizedTimestamp = T.HostLocaleLocalizedTimestamp;\nexport import VersionedHostLocaleSubscribeError = T.VersionedHostLocaleSubscribeError;\nexport import VersionedHostLocaleSubscribeItem = T.VersionedHostLocaleSubscribeItem;\nexport import VersionedHostLocaleSubscribeRequest = T.VersionedHostLocaleSubscribeRequest;\nexport import HostNativeChatAcknowledgment = T.HostNativeChatAcknowledgment;\nexport import HostNativeChatAttachment = T.HostNativeChatAttachment;\nexport import HostNativeChatAttachmentKind = T.HostNativeChatAttachmentKind;\nexport import HostNativeChatAttachmentMetadata = T.HostNativeChatAttachmentMetadata;\nexport import HostNativeChatAttachmentState = T.HostNativeChatAttachmentState;\nexport import HostNativeChatBinding = T.HostNativeChatBinding;\nexport import HostNativeChatDevice = T.HostNativeChatDevice;\nexport import HostNativeChatInvitation = T.HostNativeChatInvitation;\nexport import HostNativeChatMessages = T.HostNativeChatMessages;\nexport import HostNativeChatMigrationInvitation = T.HostNativeChatMigrationInvitation;\nexport import HostNativeChatOpenPage = T.HostNativeChatOpenPage;\nexport import HostNativeChatOpened = T.HostNativeChatOpened;\nexport import HostNativeChatPayment = T.HostNativeChatPayment;\nexport import HostNativeChatPaymentDirection = T.HostNativeChatPaymentDirection;\nexport import HostNativeChatPaymentFailure = T.HostNativeChatPaymentFailure;\nexport import HostNativeChatPaymentState = T.HostNativeChatPaymentState;\nexport import HostNativeChatPeer = T.HostNativeChatPeer;\nexport import HostNativeChatPeerDevice = T.HostNativeChatPeerDevice;\nexport import HostNativeChatPrepared = T.HostNativeChatPrepared;\nexport import HostNativeChatRichMessage = T.HostNativeChatRichMessage;\nexport import HostNativeChatRichMessageKind = T.HostNativeChatRichMessageKind;\nexport import HostNativeChatRoute = T.HostNativeChatRoute;\nexport import HostNativeChatStatePage = T.HostNativeChatStatePage;\nexport import VersionedHostNavigateToError = T.VersionedHostNavigateToError;\nexport import VersionedHostNavigateToRequest = T.VersionedHostNavigateToRequest;\nexport import VersionedHostNavigateToResponse = T.VersionedHostNavigateToResponse;\nexport import VersionedHostPaymentBalanceSubscribeError = T.VersionedHostPaymentBalanceSubscribeError;\nexport import VersionedHostPaymentBalanceSubscribeItem = T.VersionedHostPaymentBalanceSubscribeItem;\nexport import VersionedHostPaymentBalanceSubscribeRequest = T.VersionedHostPaymentBalanceSubscribeRequest;\nexport import VersionedHostPaymentError = T.VersionedHostPaymentError;\nexport import VersionedHostPaymentRequest = T.VersionedHostPaymentRequest;\nexport import VersionedHostPaymentResponse = T.VersionedHostPaymentResponse;\nexport import VersionedHostPaymentStatusSubscribeError = T.VersionedHostPaymentStatusSubscribeError;\nexport import VersionedHostPaymentStatusSubscribeItem = T.VersionedHostPaymentStatusSubscribeItem;\nexport import VersionedHostPaymentStatusSubscribeRequest = T.VersionedHostPaymentStatusSubscribeRequest;\nexport import VersionedHostPaymentTopUpError = T.VersionedHostPaymentTopUpError;\nexport import VersionedHostPaymentTopUpRequest = T.VersionedHostPaymentTopUpRequest;\nexport import VersionedHostPaymentTopUpResponse = T.VersionedHostPaymentTopUpResponse;\nexport import HostPlatform = T.HostPlatform;\nexport import VersionedHostPocketListSubscribeError = T.VersionedHostPocketListSubscribeError;\nexport import VersionedHostPocketListSubscribeItem = T.VersionedHostPocketListSubscribeItem;\nexport import VersionedHostPocketListSubscribeRequest = T.VersionedHostPocketListSubscribeRequest;\nexport import VersionedHostPocketRemoveCardError = T.VersionedHostPocketRemoveCardError;\nexport import VersionedHostPocketRemoveCardRequest = T.VersionedHostPocketRemoveCardRequest;\nexport import VersionedHostPocketRemoveCardResponse = T.VersionedHostPocketRemoveCardResponse;\nexport import VersionedHostProductDeviceChatError = T.VersionedHostProductDeviceChatError;\nexport import VersionedHostProductDeviceChatRequest = T.VersionedHostProductDeviceChatRequest;\nexport import VersionedHostProductDeviceChatResponse = T.VersionedHostProductDeviceChatResponse;\nexport import VersionedHostPushNotificationCancelError = T.VersionedHostPushNotificationCancelError;\nexport import VersionedHostPushNotificationCancelRequest = T.VersionedHostPushNotificationCancelRequest;\nexport import VersionedHostPushNotificationCancelResponse = T.VersionedHostPushNotificationCancelResponse;\nexport import VersionedHostPushNotificationError = T.VersionedHostPushNotificationError;\nexport import VersionedHostPushNotificationRequest = T.VersionedHostPushNotificationRequest;\nexport import VersionedHostPushNotificationResponse = T.VersionedHostPushNotificationResponse;\nexport import VersionedHostRendererActionSubscribeError = T.VersionedHostRendererActionSubscribeError;\nexport import VersionedHostRendererActionSubscribeItem = T.VersionedHostRendererActionSubscribeItem;\nexport import VersionedHostRendererActionSubscribeRequest = T.VersionedHostRendererActionSubscribeRequest;\nexport import VersionedHostRequestLoginError = T.VersionedHostRequestLoginError;\nexport import VersionedHostRequestLoginRequest = T.VersionedHostRequestLoginRequest;\nexport import VersionedHostRequestLoginResponse = T.VersionedHostRequestLoginResponse;\nexport import VersionedHostRequestResourceAllocationError = T.VersionedHostRequestResourceAllocationError;\nexport import VersionedHostRequestResourceAllocationRequest = T.VersionedHostRequestResourceAllocationRequest;\nexport import VersionedHostRequestResourceAllocationResponse = T.VersionedHostRequestResourceAllocationResponse;\nexport import HostSignPayloadData = T.HostSignPayloadData;\nexport import VersionedHostSignPayloadError = T.VersionedHostSignPayloadError;\nexport import VersionedHostSignPayloadRequest = T.VersionedHostSignPayloadRequest;\nexport import VersionedHostSignPayloadResponse = T.VersionedHostSignPayloadResponse;\nexport import VersionedHostSignPayloadWithLegacyAccountError = T.VersionedHostSignPayloadWithLegacyAccountError;\nexport import VersionedHostSignPayloadWithLegacyAccountRequest = T.VersionedHostSignPayloadWithLegacyAccountRequest;\nexport import VersionedHostSignPayloadWithLegacyAccountResponse = T.VersionedHostSignPayloadWithLegacyAccountResponse;\nexport import VersionedHostSignRawError = T.VersionedHostSignRawError;\nexport import VersionedHostSignRawRequest = T.VersionedHostSignRawRequest;\nexport import VersionedHostSignRawResponse = T.VersionedHostSignRawResponse;\nexport import VersionedHostSignRawWithLegacyAccountError = T.VersionedHostSignRawWithLegacyAccountError;\nexport import VersionedHostSignRawWithLegacyAccountRequest = T.VersionedHostSignRawWithLegacyAccountRequest;\nexport import VersionedHostSignRawWithLegacyAccountResponse = T.VersionedHostSignRawWithLegacyAccountResponse;\nexport import VersionedHostThemeSubscribeError = T.VersionedHostThemeSubscribeError;\nexport import VersionedHostThemeSubscribeItem = T.VersionedHostThemeSubscribeItem;\nexport import VersionedHostThemeSubscribeRequest = T.VersionedHostThemeSubscribeRequest;\nexport import VersionedHostWorkerBeginOperationError = T.VersionedHostWorkerBeginOperationError;\nexport import VersionedHostWorkerBeginOperationRequest = T.VersionedHostWorkerBeginOperationRequest;\nexport import VersionedHostWorkerBeginOperationResponse = T.VersionedHostWorkerBeginOperationResponse;\nexport import VersionedHostWorkerEndOperationError = T.VersionedHostWorkerEndOperationError;\nexport import VersionedHostWorkerEndOperationRequest = T.VersionedHostWorkerEndOperationRequest;\nexport import VersionedHostWorkerEndOperationResponse = T.VersionedHostWorkerEndOperationResponse;\nexport import HostWorkerOperationError = T.HostWorkerOperationError;\nexport import ImageFit = T.ImageFit;\nexport import ImageProps = T.ImageProps;\nexport import ImageSource = T.ImageSource;\nexport import LegacyAccount = T.LegacyAccount;\nexport import LegacyAccountTxPayload = T.LegacyAccountTxPayload;\nexport import Modifier = T.Modifier;\nexport import OperationStartedResult = T.OperationStartedResult;\nexport import PaymentTopUpSource = T.PaymentTopUpSource;\nexport import PocketCard = T.PocketCard;\nexport import PreimageSubmitError = T.PreimageSubmitError;\nexport import ProductAccount = T.ProductAccount;\nexport import ProductAccountId = T.ProductAccountId;\nexport import ProductAccountTxPayload = T.ProductAccountTxPayload;\nexport import ProductProofContext = T.ProductProofContext;\nexport import VersionedProductRendererRenderError = T.VersionedProductRendererRenderError;\nexport import VersionedProductRendererRenderItem = T.VersionedProductRendererRenderItem;\nexport import VersionedProductRendererRenderRequest = T.VersionedProductRendererRenderRequest;\nexport import RawPayload = T.RawPayload;\nexport import RegisteredRingVrfKey = T.RegisteredRingVrfKey;\nexport import VersionedRemoteChainHeadBodyError = T.VersionedRemoteChainHeadBodyError;\nexport import VersionedRemoteChainHeadBodyRequest = T.VersionedRemoteChainHeadBodyRequest;\nexport import VersionedRemoteChainHeadBodyResponse = T.VersionedRemoteChainHeadBodyResponse;\nexport import VersionedRemoteChainHeadCallError = T.VersionedRemoteChainHeadCallError;\nexport import VersionedRemoteChainHeadCallRequest = T.VersionedRemoteChainHeadCallRequest;\nexport import VersionedRemoteChainHeadCallResponse = T.VersionedRemoteChainHeadCallResponse;\nexport import VersionedRemoteChainHeadContinueError = T.VersionedRemoteChainHeadContinueError;\nexport import VersionedRemoteChainHeadContinueRequest = T.VersionedRemoteChainHeadContinueRequest;\nexport import VersionedRemoteChainHeadContinueResponse = T.VersionedRemoteChainHeadContinueResponse;\nexport import VersionedRemoteChainHeadFollowError = T.VersionedRemoteChainHeadFollowError;\nexport import VersionedRemoteChainHeadFollowItem = T.VersionedRemoteChainHeadFollowItem;\nexport import VersionedRemoteChainHeadFollowRequest = T.VersionedRemoteChainHeadFollowRequest;\nexport import VersionedRemoteChainHeadHeaderError = T.VersionedRemoteChainHeadHeaderError;\nexport import VersionedRemoteChainHeadHeaderRequest = T.VersionedRemoteChainHeadHeaderRequest;\nexport import VersionedRemoteChainHeadHeaderResponse = T.VersionedRemoteChainHeadHeaderResponse;\nexport import VersionedRemoteChainHeadStopOperationError = T.VersionedRemoteChainHeadStopOperationError;\nexport import VersionedRemoteChainHeadStopOperationRequest = T.VersionedRemoteChainHeadStopOperationRequest;\nexport import VersionedRemoteChainHeadStopOperationResponse = T.VersionedRemoteChainHeadStopOperationResponse;\nexport import VersionedRemoteChainHeadStorageError = T.VersionedRemoteChainHeadStorageError;\nexport import VersionedRemoteChainHeadStorageRequest = T.VersionedRemoteChainHeadStorageRequest;\nexport import VersionedRemoteChainHeadStorageResponse = T.VersionedRemoteChainHeadStorageResponse;\nexport import VersionedRemoteChainHeadUnpinError = T.VersionedRemoteChainHeadUnpinError;\nexport import VersionedRemoteChainHeadUnpinRequest = T.VersionedRemoteChainHeadUnpinRequest;\nexport import VersionedRemoteChainHeadUnpinResponse = T.VersionedRemoteChainHeadUnpinResponse;\nexport import VersionedRemoteChainInfoError = T.VersionedRemoteChainInfoError;\nexport import VersionedRemoteChainInfoRequest = T.VersionedRemoteChainInfoRequest;\nexport import VersionedRemoteChainInfoResponse = T.VersionedRemoteChainInfoResponse;\nexport import VersionedRemoteChainSpecChainNameError = T.VersionedRemoteChainSpecChainNameError;\nexport import VersionedRemoteChainSpecChainNameRequest = T.VersionedRemoteChainSpecChainNameRequest;\nexport import VersionedRemoteChainSpecChainNameResponse = T.VersionedRemoteChainSpecChainNameResponse;\nexport import VersionedRemoteChainSpecGenesisHashError = T.VersionedRemoteChainSpecGenesisHashError;\nexport import VersionedRemoteChainSpecGenesisHashRequest = T.VersionedRemoteChainSpecGenesisHashRequest;\nexport import VersionedRemoteChainSpecGenesisHashResponse = T.VersionedRemoteChainSpecGenesisHashResponse;\nexport import VersionedRemoteChainSpecPropertiesError = T.VersionedRemoteChainSpecPropertiesError;\nexport import VersionedRemoteChainSpecPropertiesRequest = T.VersionedRemoteChainSpecPropertiesRequest;\nexport import VersionedRemoteChainSpecPropertiesResponse = T.VersionedRemoteChainSpecPropertiesResponse;\nexport import VersionedRemoteChainTransactionBroadcastError = T.VersionedRemoteChainTransactionBroadcastError;\nexport import VersionedRemoteChainTransactionBroadcastRequest = T.VersionedRemoteChainTransactionBroadcastRequest;\nexport import VersionedRemoteChainTransactionBroadcastResponse = T.VersionedRemoteChainTransactionBroadcastResponse;\nexport import VersionedRemoteChainTransactionStopError = T.VersionedRemoteChainTransactionStopError;\nexport import VersionedRemoteChainTransactionStopRequest = T.VersionedRemoteChainTransactionStopRequest;\nexport import VersionedRemoteChainTransactionStopResponse = T.VersionedRemoteChainTransactionStopResponse;\nexport import RemotePermission = T.RemotePermission;\nexport import VersionedRemotePermissionError = T.VersionedRemotePermissionError;\nexport import VersionedRemotePermissionRequest = T.VersionedRemotePermissionRequest;\nexport import VersionedRemotePermissionResponse = T.VersionedRemotePermissionResponse;\nexport import VersionedRemotePreimageLookupSubscribeError = T.VersionedRemotePreimageLookupSubscribeError;\nexport import VersionedRemotePreimageLookupSubscribeItem = T.VersionedRemotePreimageLookupSubscribeItem;\nexport import VersionedRemotePreimageLookupSubscribeRequest = T.VersionedRemotePreimageLookupSubscribeRequest;\nexport import VersionedRemotePreimageSubmitError = T.VersionedRemotePreimageSubmitError;\nexport import VersionedRemotePreimageSubmitRequest = T.VersionedRemotePreimageSubmitRequest;\nexport import VersionedRemotePreimageSubmitResponse = T.VersionedRemotePreimageSubmitResponse;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedError = T.VersionedRemoteStatementStoreCreateProofAuthorizedError;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedRequest = T.VersionedRemoteStatementStoreCreateProofAuthorizedRequest;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedResponse = T.VersionedRemoteStatementStoreCreateProofAuthorizedResponse;\nexport import VersionedRemoteStatementStoreCreateProofError = T.VersionedRemoteStatementStoreCreateProofError;\nexport import VersionedRemoteStatementStoreCreateProofRequest = T.VersionedRemoteStatementStoreCreateProofRequest;\nexport import VersionedRemoteStatementStoreCreateProofResponse = T.VersionedRemoteStatementStoreCreateProofResponse;\nexport import VersionedRemoteStatementStoreSubmitError = T.VersionedRemoteStatementStoreSubmitError;\nexport import VersionedRemoteStatementStoreSubmitRequest = T.VersionedRemoteStatementStoreSubmitRequest;\nexport import VersionedRemoteStatementStoreSubmitResponse = T.VersionedRemoteStatementStoreSubmitResponse;\nexport import VersionedRemoteStatementStoreSubscribeError = T.VersionedRemoteStatementStoreSubscribeError;\nexport import VersionedRemoteStatementStoreSubscribeItem = T.VersionedRemoteStatementStoreSubscribeItem;\nexport import VersionedRemoteStatementStoreSubscribeRequest = T.VersionedRemoteStatementStoreSubscribeRequest;\nexport import RenderContext = T.RenderContext;\nexport import RendererNode = T.RendererNode;\nexport import ResourceAllocationError = T.ResourceAllocationError;\nexport import RingLocation = T.RingLocation;\nexport import RingLocationJunction = T.RingLocationJunction;\nexport import RingVrfKeyDisclosure = T.RingVrfKeyDisclosure;\nexport import RowProps = T.RowProps;\nexport import RuntimeApi = T.RuntimeApi;\nexport import RuntimeSpec = T.RuntimeSpec;\nexport import RuntimeType = T.RuntimeType;\nexport import Shape = T.Shape;\nexport import SignedStatement = T.SignedStatement;\nexport import Size = T.Size;\nexport import Statement = T.Statement;\nexport import StatementProof = T.StatementProof;\nexport import StorageQueryItem = T.StorageQueryItem;\nexport import StorageQueryType = T.StorageQueryType;\nexport import StorageResultItem = T.StorageResultItem;\nexport import TextFieldProps = T.TextFieldProps;\nexport import TextProps = T.TextProps;\nexport import ThemeName = T.ThemeName;\nexport import ThemeVariant = T.ThemeVariant;\nexport import TxPayloadExtension = T.TxPayloadExtension;\nexport import TypographyStyle = T.TypographyStyle;\nexport import HostAccountConnectionStatusSubscribeItem = T.HostAccountConnectionStatusSubscribeItem;\nexport import HostAccountCreateProofError = T.HostAccountCreateProofError;\nexport import HostAccountCreateProofRequest = T.HostAccountCreateProofRequest;\nexport import HostAccountCreateProofResponse = T.HostAccountCreateProofResponse;\nexport import HostAccountGetAliasError = T.HostAccountGetAliasError;\nexport import HostAccountGetAliasRequest = T.HostAccountGetAliasRequest;\nexport import HostAccountGetError = T.HostAccountGetError;\nexport import HostAccountGetRequest = T.HostAccountGetRequest;\nexport import HostAccountGetResponse = T.HostAccountGetResponse;\nexport import HostAccountListRingVrfKeysError = T.HostAccountListRingVrfKeysError;\nexport import HostAccountListRingVrfKeysRequest = T.HostAccountListRingVrfKeysRequest;\nexport import HostAccountRegisterRingVrfKeyError = T.HostAccountRegisterRingVrfKeyError;\nexport import HostAccountRegisterRingVrfKeyRequest = T.HostAccountRegisterRingVrfKeyRequest;\nexport import HostAccountRingVrfSignError = T.HostAccountRingVrfSignError;\nexport import HostAccountRingVrfSignRequest = T.HostAccountRingVrfSignRequest;\nexport import HostAccountSignVrfError = T.HostAccountSignVrfError;\nexport import HostAccountSignVrfRequest = T.HostAccountSignVrfRequest;\nexport import HostChatActionSubscribeItem = T.HostChatActionSubscribeItem;\nexport import HostChatCreateRoomError = T.HostChatCreateRoomError;\nexport import HostChatCreateRoomRequest = T.HostChatCreateRoomRequest;\nexport import HostChatCreateRoomResponse = T.HostChatCreateRoomResponse;\nexport import HostChatListSubscribeItem = T.HostChatListSubscribeItem;\nexport import HostChatPostMessageError = T.HostChatPostMessageError;\nexport import HostChatPostMessageRequest = T.HostChatPostMessageRequest;\nexport import HostChatPostMessageResponse = T.HostChatPostMessageResponse;\nexport import HostChatRegisterBotError = T.HostChatRegisterBotError;\nexport import HostChatRegisterBotRequest = T.HostChatRegisterBotRequest;\nexport import HostChatRegisterBotResponse = T.HostChatRegisterBotResponse;\nexport import HostCoinPaymentCreateChequeRequest = T.HostCoinPaymentCreateChequeRequest;\nexport import HostCoinPaymentCreateChequeResponse = T.HostCoinPaymentCreateChequeResponse;\nexport import HostCoinPaymentCreatePurseRequest = T.HostCoinPaymentCreatePurseRequest;\nexport import HostCoinPaymentCreatePurseResponse = T.HostCoinPaymentCreatePurseResponse;\nexport import HostCoinPaymentCreateReceivableRequest = T.HostCoinPaymentCreateReceivableRequest;\nexport import HostCoinPaymentCreateReceivableResponse = T.HostCoinPaymentCreateReceivableResponse;\nexport import HostCoinPaymentDeletePurseRequest = T.HostCoinPaymentDeletePurseRequest;\nexport import HostCoinPaymentDepositRequest = T.HostCoinPaymentDepositRequest;\nexport import HostCoinPaymentListenForItem = T.HostCoinPaymentListenForItem;\nexport import HostCoinPaymentListenForRequest = T.HostCoinPaymentListenForRequest;\nexport import HostCoinPaymentQueryPurseRequest = T.HostCoinPaymentQueryPurseRequest;\nexport import HostCoinPaymentQueryPurseResponse = T.HostCoinPaymentQueryPurseResponse;\nexport import HostCoinPaymentRebalancePurseRequest = T.HostCoinPaymentRebalancePurseRequest;\nexport import HostCoinPaymentRefundRequest = T.HostCoinPaymentRefundRequest;\nexport import HostContactsPickError = T.HostContactsPickError;\nexport import HostContactsPickRequest = T.HostContactsPickRequest;\nexport import HostContactsPickResponse = T.HostContactsPickResponse;\nexport import HostCreateTransactionError = T.HostCreateTransactionError;\nexport import HostCreateTransactionResponse = T.HostCreateTransactionResponse;\nexport import HostCreateTransactionWithLegacyAccountResponse = T.HostCreateTransactionWithLegacyAccountResponse;\nexport import HostDeriveEntropyError = T.HostDeriveEntropyError;\nexport import HostDeriveEntropyRequest = T.HostDeriveEntropyRequest;\nexport import HostDeriveEntropyResponse = T.HostDeriveEntropyResponse;\nexport import HostDevicePermissionRequest = T.HostDevicePermissionRequest;\nexport import HostDevicePermissionResponse = T.HostDevicePermissionResponse;\nexport import HostFeatureSupportedRequest = T.HostFeatureSupportedRequest;\nexport import HostFeatureSupportedResponse = T.HostFeatureSupportedResponse;\nexport import HostGetLegacyAccountsResponse = T.HostGetLegacyAccountsResponse;\nexport import HostGetProductContextResponse = T.HostGetProductContextResponse;\nexport import HostGetUserIdError = T.HostGetUserIdError;\nexport import HostGetUserIdResponse = T.HostGetUserIdResponse;\nexport import HostHandshakeError = T.HostHandshakeError;\nexport import HostHandshakeRequest = T.HostHandshakeRequest;\nexport import HostLocalStorageChangeItem = T.HostLocalStorageChangeItem;\nexport import HostLocalStorageClearRequest = T.HostLocalStorageClearRequest;\nexport import V01HostLocalStorageReadError = T.V01HostLocalStorageReadError;\nexport import V01HostLocalStorageReadRequest = T.V01HostLocalStorageReadRequest;\nexport import HostLocalStorageReadResponse = T.HostLocalStorageReadResponse;\nexport import HostLocalStorageSubscribeRequest = T.HostLocalStorageSubscribeRequest;\nexport import HostLocalStorageWriteRequest = T.HostLocalStorageWriteRequest;\nexport import V01HostLocaleSubscribeItem = T.V01HostLocaleSubscribeItem;\nexport import HostNavigateToError = T.HostNavigateToError;\nexport import HostNavigateToRequest = T.HostNavigateToRequest;\nexport import HostPaymentBalanceSubscribeError = T.HostPaymentBalanceSubscribeError;\nexport import HostPaymentBalanceSubscribeItem = T.HostPaymentBalanceSubscribeItem;\nexport import HostPaymentBalanceSubscribeRequest = T.HostPaymentBalanceSubscribeRequest;\nexport import HostPaymentError = T.HostPaymentError;\nexport import HostPaymentRequest = T.HostPaymentRequest;\nexport import HostPaymentResponse = T.HostPaymentResponse;\nexport import HostPaymentStatusSubscribeError = T.HostPaymentStatusSubscribeError;\nexport import HostPaymentStatusSubscribeItem = T.HostPaymentStatusSubscribeItem;\nexport import HostPaymentStatusSubscribeRequest = T.HostPaymentStatusSubscribeRequest;\nexport import HostPaymentTopUpError = T.HostPaymentTopUpError;\nexport import HostPaymentTopUpRequest = T.HostPaymentTopUpRequest;\nexport import HostPocketListSubscribeItem = T.HostPocketListSubscribeItem;\nexport import HostPocketRemoveCardError = T.HostPocketRemoveCardError;\nexport import HostPocketRemoveCardRequest = T.HostPocketRemoveCardRequest;\nexport import HostPushNotificationCancelRequest = T.HostPushNotificationCancelRequest;\nexport import HostPushNotificationError = T.HostPushNotificationError;\nexport import HostPushNotificationRequest = T.HostPushNotificationRequest;\nexport import HostPushNotificationResponse = T.HostPushNotificationResponse;\nexport import HostRendererActionSubscribeItem = T.HostRendererActionSubscribeItem;\nexport import HostRequestLoginError = T.HostRequestLoginError;\nexport import HostRequestLoginRequest = T.HostRequestLoginRequest;\nexport import HostRequestLoginResponse = T.HostRequestLoginResponse;\nexport import HostRequestResourceAllocationRequest = T.HostRequestResourceAllocationRequest;\nexport import HostRequestResourceAllocationResponse = T.HostRequestResourceAllocationResponse;\nexport import HostSignPayloadError = T.HostSignPayloadError;\nexport import HostSignPayloadRequest = T.HostSignPayloadRequest;\nexport import HostSignPayloadResponse = T.HostSignPayloadResponse;\nexport import HostSignPayloadWithLegacyAccountRequest = T.HostSignPayloadWithLegacyAccountRequest;\nexport import HostSignRawRequest = T.HostSignRawRequest;\nexport import HostSignRawWithLegacyAccountRequest = T.HostSignRawWithLegacyAccountRequest;\nexport import HostThemeSubscribeItem = T.HostThemeSubscribeItem;\nexport import HostWorkerBeginOperationRequest = T.HostWorkerBeginOperationRequest;\nexport import HostWorkerBeginOperationResponse = T.HostWorkerBeginOperationResponse;\nexport import HostWorkerEndOperationRequest = T.HostWorkerEndOperationRequest;\nexport import ProductRendererRenderRequest = T.ProductRendererRenderRequest;\nexport import RemoteChainHeadBodyRequest = T.RemoteChainHeadBodyRequest;\nexport import RemoteChainHeadBodyResponse = T.RemoteChainHeadBodyResponse;\nexport import RemoteChainHeadCallRequest = T.RemoteChainHeadCallRequest;\nexport import RemoteChainHeadCallResponse = T.RemoteChainHeadCallResponse;\nexport import RemoteChainHeadContinueRequest = T.RemoteChainHeadContinueRequest;\nexport import RemoteChainHeadFollowItem = T.RemoteChainHeadFollowItem;\nexport import RemoteChainHeadFollowRequest = T.RemoteChainHeadFollowRequest;\nexport import RemoteChainHeadHeaderRequest = T.RemoteChainHeadHeaderRequest;\nexport import RemoteChainHeadHeaderResponse = T.RemoteChainHeadHeaderResponse;\nexport import RemoteChainHeadStopOperationRequest = T.RemoteChainHeadStopOperationRequest;\nexport import RemoteChainHeadStorageRequest = T.RemoteChainHeadStorageRequest;\nexport import RemoteChainHeadStorageResponse = T.RemoteChainHeadStorageResponse;\nexport import RemoteChainHeadUnpinRequest = T.RemoteChainHeadUnpinRequest;\nexport import RemoteChainInfoError = T.RemoteChainInfoError;\nexport import RemoteChainInfoRequest = T.RemoteChainInfoRequest;\nexport import RemoteChainInfoResponse = T.RemoteChainInfoResponse;\nexport import RemoteChainSpecChainNameRequest = T.RemoteChainSpecChainNameRequest;\nexport import RemoteChainSpecChainNameResponse = T.RemoteChainSpecChainNameResponse;\nexport import RemoteChainSpecGenesisHashRequest = T.RemoteChainSpecGenesisHashRequest;\nexport import RemoteChainSpecGenesisHashResponse = T.RemoteChainSpecGenesisHashResponse;\nexport import RemoteChainSpecPropertiesRequest = T.RemoteChainSpecPropertiesRequest;\nexport import RemoteChainSpecPropertiesResponse = T.RemoteChainSpecPropertiesResponse;\nexport import RemoteChainTransactionBroadcastRequest = T.RemoteChainTransactionBroadcastRequest;\nexport import RemoteChainTransactionBroadcastResponse = T.RemoteChainTransactionBroadcastResponse;\nexport import RemoteChainTransactionStopRequest = T.RemoteChainTransactionStopRequest;\nexport import RemotePermissionRequest = T.RemotePermissionRequest;\nexport import RemotePermissionResponse = T.RemotePermissionResponse;\nexport import RemotePreimageLookupSubscribeItem = T.RemotePreimageLookupSubscribeItem;\nexport import RemotePreimageLookupSubscribeRequest = T.RemotePreimageLookupSubscribeRequest;\nexport import RemoteStatementStoreCreateProofError = T.RemoteStatementStoreCreateProofError;\nexport import RemoteStatementStoreCreateProofRequest = T.RemoteStatementStoreCreateProofRequest;\nexport import RemoteStatementStoreCreateProofResponse = T.RemoteStatementStoreCreateProofResponse;\nexport import RemoteStatementStoreSubscribeItem = T.RemoteStatementStoreSubscribeItem;\nexport import RemoteStatementStoreSubscribeRequest = T.RemoteStatementStoreSubscribeRequest;\nexport import HostLocalStorageReadError = T.HostLocalStorageReadError;\nexport import HostLocalStorageReadRequest = T.HostLocalStorageReadRequest;\nexport import HostLocaleLocalizeTimestampsRequest = T.HostLocaleLocalizeTimestampsRequest;\nexport import HostLocaleLocalizeTimestampsResponse = T.HostLocaleLocalizeTimestampsResponse;\nexport import HostLocaleSubscribeItem = T.HostLocaleSubscribeItem;\nexport import HostProductDeviceChatError = T.HostProductDeviceChatError;\nexport import V02HostProductDeviceChatRequest = T.V02HostProductDeviceChatRequest;\nexport import V02HostProductDeviceChatResponse = T.V02HostProductDeviceChatResponse;\nexport import HostProductDeviceChatRequest = T.HostProductDeviceChatRequest;\nexport import HostProductDeviceChatResponse = T.HostProductDeviceChatResponse;\nexport import VerticalAlignment = T.VerticalAlignment;\nexport import VrfSignature = T.VrfSignature;\nexport import VrfTranscriptItem = T.VrfTranscriptItem;\n\n// index.d.ts\n\n\n// transport.d.ts\n/**\n * Wire trait discriminant reserved for method-independent protocol errors. No\n * API trait may declare it, so no method is ever addressed here.\n **/\nexport declare const PROTOCOL_ERROR_TRAIT_ID: 255;\n/** Wire method discriminant reserved for method-independent protocol errors. **/\nexport declare const PROTOCOL_ERROR_METHOD_ID: 255;\n/** The peer rejected an outbound frame because it does not support its API. **/\nexport declare class UnsupportedMessageError extends Error {\n /** Trait discriminant of the unsupported outbound frame. **/\n readonly traitId: number;\n /** Method discriminant of the unsupported outbound frame. **/\n readonly methodId: number;\n constructor(traitId: number, methodId: number);\n}\n/** The host connection ended; interrupted operations are not retried. */\nexport declare class ConnectionResetError extends Error {\n constructor(options?: ErrorOptions);\n}\n/** Call result returned when the peer does not recognize a request frame. **/\nexport type UnsupportedCallError = Extract, {\n tag: \"Unsupported\";\n}>;\n/**\n * Handle returned by TrUAPI subscription APIs.\n **/\nexport interface Subscription {\n /**\n * Stop the subscription. Calling this more than once has no additional effect.\n **/\n unsubscribe: () => void;\n /**\n * Transport-assigned request id for the subscription start frame.\n *\n * Methods that accept a `followSubscriptionId` use this value to scope\n * follow-up requests to a specific active subscription.\n **/\n subscriptionId: string;\n}\n/**\n * Terminal error delivered through `Observer.error` for every non-normal\n * subscription end. When the peer interrupted the stream with a typed payload,\n * `reason` carries the decoded `Reason`; otherwise `reason` is `undefined` and\n * the underlying transport/decode error is preserved on `cause`.\n *\n * Discriminate with `error.reason !== undefined` (or `'reason' in error`).\n **/\nexport declare class SubscriptionError extends Error {\n /**\n * Typed payload supplied by the peer when it interrupted the subscription.\n * `undefined` when the stream ended for any other reason (transport close,\n * decode failure, malformed interrupt payload).\n **/\n readonly reason?: Reason;\n constructor(message: string, options?: {\n reason?: Reason;\n cause?: unknown;\n });\n}\n/**\n * Minimal Observable-compatible observer shape used by generated subscription\n * APIs without depending on RxJS.\n *\n * `Reason` is the typed interrupt payload for the originating subscription.\n * Methods without a typed interrupt resolve `Reason` to `never`, leaving\n * `error.reason` typed as `undefined`.\n **/\nexport interface Observer {\n /**\n * Called with each successfully decoded subscription item.\n **/\n next(value: Item): void;\n /**\n * Called once when the stream terminates with an error. Inspect\n * `error.reason` to distinguish a typed peer interrupt from a transport or\n * decode failure (`error.cause` carries the underlying failure in the\n * latter case).\n **/\n error(error: SubscriptionError): void;\n /**\n * Called once when the peer normally completes the stream.\n **/\n complete(): void;\n}\ndeclare global {\n interface SymbolConstructor {\n readonly observable: unique symbol;\n }\n}\n/**\n * Minimal Observable-compatible object returned by generated subscription APIs.\n *\n * Implements the ES Observable interop protocol so that consumers can pass\n * an instance straight to `rxjs.from(...)`.\n **/\nexport interface ObservableLike {\n /**\n * Start the stream and receive `next`, `error`, and `complete` callbacks.\n **/\n subscribe(observer?: Partial>): Subscription;\n /**\n * Observable interop hook. Returns `this`.\n **/\n [Symbol.observable](): ObservableLike;\n}\n/**\n * Product-side handler for a subscription the native host initiates.\n *\n * It receives the decoded request and two callbacks: `send` delivers one item\n * to the host, and `interrupt` ends the stream, cleanly when called with no\n * argument and with the method's interrupt value otherwise. The returned\n * teardown, if any, runs once the stream ends: on the host's stop frame, on\n * `interrupt`, when the transport closes, or when the host restarts the same\n * request id.\n **/\nexport type HostInitiatedSubscriptionHandler = (request: Request, send: (item: Item) => void, interrupt: (reason?: Reason) => void) => (() => void) | void;\n/**\n * Wire discriminant pair addressing a method. One id addresses a method\n * regardless of shape (request/response, or a subscription's four phases):\n * which leg of the exchange a frame carries is the wire's own `messageType`\n * byte, not a separate id per leg.\n **/\nexport interface MethodIds {\n /**\n * Wire trait discriminant.\n **/\n trait: number;\n /**\n * Wire method discriminant within the trait.\n **/\n method: number;\n /**\n * Whether this method's legs follow the request/response shape or the\n * subscription shape (`\"subscription\"` covers both plain and result\n * subscriptions, which share the same four-leg wire shape). The one piece\n * of shape a payload-blind reader needs to interpret a frame's own\n * `messageType` byte without decoding the payload.\n **/\n kind: \"request\" | \"subscription\";\n}\n/**\n * Per-call options every generated request method accepts as its last\n * argument.\n **/\nexport interface CallOptions {\n /** See {@link RequestParams.signal}. **/\n signal?: AbortSignal;\n}\n/**\n * Options accepted by `TrUApiTransport.request`.\n **/\nexport interface RequestParams {\n /**\n * Wire discriminants for this request method.\n **/\n ids: MethodIds;\n /**\n * SCALE-encoded request wrapper payload bytes (its own `V` tag is the\n * wire's only version signal), constructed by the generated caller.\n **/\n payload: Uint8Array;\n /**\n * Decode a `Response`-leg frame's raw payload bytes into the typed Ok/Err\n * outcome. Implementations decode `Result<{Method}Response,\n * CallError<{Method}Error>>` directly. The transport unwraps the result\n * into `ResultAsync`.\n **/\n decodeResponse: (payload: Uint8Array) => ResultPayload;\n /**\n * Withdraw the call. Aborting sends a `Cancel` frame on this method's own\n * address; the promise still settles on the response the host sends, which\n * for a call the host stopped is `CallError::Cancelled`. A signal already\n * aborted when the call is made sends nothing and rejects immediately.\n *\n * A host that predates the `Cancel` leg drops the frame, so an aborted call\n * against one settles on its deadline instead. There is no way to detect that\n * first: `system.featureSupported` answers only about chains, so an abort\n * against an older host is indistinguishable from one it honoured.\n **/\n signal?: AbortSignal;\n}\n/**\n * Options accepted by `TrUApiTransport.subscribeRaw`.\n **/\nexport interface SubscribeRawParams {\n /**\n * Wire discriminants for this subscription method.\n **/\n ids: MethodIds;\n /**\n * SCALE-encoded `Start`-leg payload bytes: the request wrapper's own\n * encoding, or empty bytes for a method with no request at all,\n * constructed by the generated caller.\n **/\n payload: Uint8Array;\n /**\n * Called with a `Receive`-leg frame's raw payload bytes.\n **/\n onReceive: (payload: Uint8Array) => void;\n /**\n * Called with an `Interrupt`-leg frame's raw payload bytes.\n **/\n onInterrupt?: (payload: Uint8Array) => void;\n /**\n * Called when a transport-level error or unsupported start frame terminates\n * the subscription.\n **/\n onClose?: (error: Error) => void;\n}\n/** Product-side registration for one host-initiated subscription method. **/\nexport interface HostInitiatedSubscriptionRegistration {\n /** Install or replace the handler used for future start frames. **/\n setHandler(handler: HostInitiatedSubscriptionHandler): {\n unsubscribe(): void;\n };\n}\n/** Options used to register a host-initiated subscription method. **/\nexport interface RegisterHostInitiatedSubscriptionParams {\n /** Wire discriminants for the host-initiated subscription. **/\n ids: MethodIds;\n /**\n * Decode a `Start`-leg frame's raw payload bytes into the typed request.\n **/\n decodeRequest(payload: Uint8Array): Request;\n /**\n * Encode one product emission as a `Receive`-leg frame's raw payload bytes.\n **/\n encodeItem(item: Item): Uint8Array;\n /**\n * Encode an `Interrupt`-leg frame's raw payload bytes: the stream's clean\n * end when `reason` is omitted, and the method's interrupt value otherwise.\n **/\n encodeInterrupt(reason?: Reason): Uint8Array;\n /**\n * Exact payload used when the transport ends a stream the product's handler\n * never got to serve.\n **/\n declinePayload: Uint8Array;\n /** Number of starts retained before a handler is installed. **/\n bufferCapacity: number;\n}\n/**\n * Byte-level transport used by generated client stubs.\n **/\nexport interface TrUApiTransport {\n /**\n * Send a one-shot request and resolve with the typed Ok/Err outcome.\n **/\n request(params: RequestParams): ResultAsync;\n /**\n * Start a subscription and return a handle that can stop it.\n **/\n subscribeRaw(params: SubscribeRawParams): Subscription;\n /** Register product-side handling for a host-initiated subscription. **/\n registerHostInitiatedSubscription(params: RegisterHostInitiatedSubscriptionParams): HostInitiatedSubscriptionRegistration;\n /**\n * Tear down the transport and release the listeners it registered on the\n * underlying `WireProvider`. Pending requests reject and live subscriptions\n * receive `onClose`. Idempotent.\n *\n * The provider itself is left alone; the caller decides whether to also\n * call `provider.dispose()` (long-lived hosts that swap providers will\n * typically dispose the transport but keep the provider).\n **/\n dispose(): void;\n}\n/**\n * Tagged payload inside a TrUAPI wire frame.\n **/\nexport interface Payload {\n /**\n * Wire-table trait discriminant: first byte of the `(trait, method)` pair.\n **/\n traitId: number;\n /**\n * Wire-table method discriminant within the trait: second byte of the pair.\n **/\n methodId: number;\n /**\n * Which leg of the method's exchange this frame carries: `Request`/`Start`\n * = 0, `Response`/`Receive` = 1, `Interrupt` = 2, `Stop` = 3. Third byte of\n * the wire frame \u2014 readable generically, without decoding `value`.\n **/\n messageType: number;\n /**\n * SCALE-encoded payload body: that leg's own versioned wrapper, with no\n * further tag identifying direction or version beyond the wrapper's own.\n **/\n value: Uint8Array;\n}\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_REQUEST = 0;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_START = 0;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_RESPONSE = 1;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_RECEIVE = 1;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_INTERRUPT = 2;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_STOP = 3;\n/**\n * A request's withdrawal, correlated by the same `requestId` and carrying no\n * payload. The call still settles with exactly one response; this only fires\n * the handler's cancellation token on the far side.\n **/\nexport declare const MESSAGE_TYPE_CANCEL = 4;\n/**\n * Top-level TrUAPI wire message.\n **/\nexport interface ProtocolMessage {\n /**\n * Request id used to correlate request/response and subscription frames.\n **/\n requestId: string;\n /**\n * Tagged SCALE payload carried by this frame.\n **/\n payload: Payload;\n}\n/**\n * Raw SCALE-wire-frame pipe abstraction used by the transport. A `WireProvider`\n * is the low-level channel (a `MessagePort` or iframe `postMessage` link) that\n * carries encoded frames between the product and the host.\n **/\nexport interface WireProvider {\n /**\n * Send a complete SCALE-encoded wire frame to the peer.\n **/\n postMessage(message: Uint8Array): void;\n /**\n * Register a callback for inbound SCALE-encoded wire frames.\n **/\n subscribe(callback: (message: Uint8Array) => void): () => void;\n /**\n * Register a callback for provider-level close or failure events.\n *\n * Providers keep a terminal close reason. The callback fires at most once\n * for an active subscription, and fires immediately when registered after\n * the provider has already closed.\n **/\n subscribeClose?(callback: (error: Error) => void): () => void;\n /** End current operations while keeping the provider available for new work. */\n subscribeReset?(callback: (error: Error) => void): () => void;\n /**\n * Release provider resources and close the underlying pipe.\n **/\n dispose(): void;\n}\n/**\n * A {@link WireProvider} backed by a WebSocket, which reports when its socket\n * is up. Awaiting {@link WebSocketWireProvider.opened} is optional: frames\n * posted earlier are queued and flushed on open.\n **/\nexport interface WebSocketWireProvider extends WireProvider {\n /** Resolves once the socket is open, rejects if it never connects. */\n opened: Promise;\n}\n/**\n * Encode a `ProtocolMessage` into a SCALE wire frame.\n **/\nexport declare function encodeWireMessage(message: ProtocolMessage): Result;\n/**\n * Decode a SCALE wire frame into a `ProtocolMessage`.\n **/\nexport declare function decodeWireMessage(message: Uint8Array): Result;\n/**\n * Create a provider for the child side of an iframe `postMessage` channel.\n *\n * `target` is the `Window` the provider posts to (typically `window.parent`);\n * `hostOrigin` is the pinned `targetOrigin` for outbound frames and the\n * required `event.origin` of inbound frames. The provider only delivers\n * frames whose `event.source === target` and `event.origin === hostOrigin`,\n * so it cannot be coerced by an unrelated frame parent.\n **/\nexport declare function createIframeProvider(options: {\n target: Window;\n hostOrigin: string;\n}): WireProvider;\n/**\n * Create a provider from a web or Electron `MessagePort`.\n **/\nexport declare function createMessagePortProvider(port: MessagePort | Promise): WireProvider;\n/**\n * Wire provider over a binary WebSocket, one message per SCALE frame.\n *\n * This is the transport a host exposes on a loopback socket: the Rust core's\n * `ws-bridge`, and `truapi-host signing-host --frame-listen`. The frame bytes\n * are identical to what the {@link createMessagePortProvider} path carries, so\n * this is a pipe and nothing more.\n *\n * Frames posted before the socket opens are queued and flushed on open, so a\n * caller never has to await {@link WebSocketWireProvider.opened} first.\n **/\nexport declare function createWebSocketProvider(url: string): WebSocketWireProvider;\n/** Capture native socket APIs before product code installs network gates. */\nexport declare function createWebSocketProviderFactory(): (url: string) => WebSocketWireProvider;\n\n\n// client.d.ts\nexport type { Subscription, TrUApiTransport };\n/** A request received no matching response before its transport deadline. */\nexport declare class RequestTimeoutError extends Error {\n /** Transport-assigned request identifier. */\n readonly requestId: string;\n /** Trait discriminant of the unanswered request. */\n readonly traitId: number;\n /** Method discriminant of the unanswered request. */\n readonly methodId: number;\n /** Deadline that elapsed, in milliseconds. */\n readonly timeoutMs: number;\n constructor(requestId: string, traitId: number, methodId: number, timeoutMs: number);\n}\n/**\n * Options accepted when constructing a transport.\n */\nexport interface CreateTransportOptions {\n /** Request ID namespace when multiple transports share a connection. Defaults to `p:`. */\n requestIdPrefix?: string;\n /** Wait for connection readiness before sending a request or starting a subscription. */\n prepare?: (ids: MethodIds) => Promise;\n /** Replace a failed connection after a malformed frame; otherwise the transport closes permanently. */\n onProtocolError?: (error: Error) => void;\n /**\n * Maximum time to wait for a matching response before rejecting the request.\n *\n * Defaults to 120 seconds. This bounds dead hosts and missed transport\n * handshakes while leaving interactive approval flows enough time to finish.\n * The handshake keeps its own shorter deadline, since a codec mismatch means\n * no answer is ever coming.\n */\n requestTimeoutMs?: number;\n}\n/**\n * Build a `TrUApiTransport` on top of a `WireProvider`, adding request/response\n * correlation and subscription start/receive/stop lifecycle handling.\n */\nexport declare function createTransport(provider: WireProvider, options?: CreateTransportOptions): TrUApiTransport;\n\n\n// generated/index.d.ts\n\n\n// generated/client.d.ts\nexport { ResultAsync, SubscriptionError };\nexport type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport };\nexport declare const TRUAPI_VERSION: 2;\nexport declare const TRUAPI_CODEC_VERSION: 3;\nexport declare const TRUAPI_WIRE_SCHEMA_HASH: \"f7be28c22289b365\";\n/** Account lookup, aliasing, and proof generation. */\nexport declare class AccountClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to account connection status changes. */\n connectionStatusSubscribe(): ObservableLike>;\n /** Retrieve a product-scoped account. */\n getAccount(request: T.HostAccountGetRequest, options?: CallOptions): ResultAsync>;\n /** Retrieve the contextual alias for a context and ring. */\n getAccountAlias(request: T.HostAccountGetAliasRequest, options?: CallOptions): ResultAsync>;\n /** Generate a ring VRF proof with an explicitly registered member key. */\n createAccountProof(request: T.HostAccountCreateProofRequest, options?: CallOptions): ResultAsync>;\n /**\n * Produce an sr25519 (schnorrkel) VRF signature from a product account.\n *\n * The host builds a Merlin transcript from `transcriptLabel` and `items`\n * and signs it with the account's key, returning the VRF pre-output and\n * proof. Authorized like signing: local when `AutoSigning` covers the\n * account, otherwise a per-call user confirmation.\n */\n signVrf(request: T.HostAccountSignVrfRequest, options?: CallOptions): ResultAsync>;\n /** Register a ring-VRF key owned by the calling product. */\n registerRingVrfKey(request: T.HostAccountRegisterRingVrfKeyRequest, options?: CallOptions): ResultAsync>;\n /** List registered ring-VRF keys owned by a product. */\n listRingVrfKeys(request: T.HostAccountListRingVrfKeysRequest, options?: CallOptions): ResultAsync, S.CallErrorValue>;\n /** Sign bytes directly with a registered ring-VRF member key. */\n ringVrfSign(request: T.HostAccountRingVrfSignRequest, options?: CallOptions): ResultAsync>;\n /**\n * Use a non-exportable Host Chat device for native cryptographic operations\n * and reviewed main-purse payments. The product owns native lifecycle frames,\n * subscriptions, delivery, retries, history, and acknowledgments.\n *\n * `Bind` resolves the peer independently. `Prepare` validates native plaintext\n * and returns signed ciphertext for product submission. `Open` authenticates\n * complete external statements and rejects reflected local output; it is not\n * an arbitrary decryption primitive. Incoming plaintext can contain incoming\n * bearer coin keys: persist the import intent securely and use generic payment\n * top-up before acknowledging. Wallet/device keys and outgoing main-purse\n * coin secrets never leave the Host.\n *\n * `Initialize` also advances private file transfers. Persist any legacy\n * migration view and ordinary prepared statements before `CommitMigration`.\n * `ContinueOpen` retrieves the next bounded page of an authenticated batch.\n * `ContinueState` retrieves remaining pages of a stable public state snapshot;\n * persist every page before committing its migration.\n *\n * Method 11 (the former raw-crypto interface) and method 12's former V1 actor\n * operations are retired, not forwarded. This boundary uses V2 payloads.\n */\n deviceChat(request: T.HostProductDeviceChatRequest, options?: CallOptions): ResultAsync>;\n /**\n * List non-product accounts the user owns.\n *\n * Current hosts do not expose non-product accounts, so the list is empty.\n */\n getLegacyAccounts(options?: CallOptions): ResultAsync>;\n /** Fetch the user's primary identity. */\n getUserId(options?: CallOptions): ResultAsync>;\n /**\n * Request the host to present the login flow to the user.\n *\n * Products should call this in response to a user action (e.g. tapping a\n * \"Sign in\" button), not automatically on load.\n */\n requestLogin(request: T.HostRequestLoginRequest, options?: CallOptions): ResultAsync>;\n}\n/** Chain interaction methods. */\nexport declare class ChainClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Follow the chain head and receive block events. */\n followHeadSubscribe({ request }: {\n request: T.RemoteChainHeadFollowRequest;\n }): ObservableLike>;\n /** Fetch a block header. */\n getHeadHeader(request: T.RemoteChainHeadHeaderRequest, options?: CallOptions): ResultAsync>;\n /** Fetch a block body. */\n getHeadBody(request: T.RemoteChainHeadBodyRequest, options?: CallOptions): ResultAsync>;\n /** Query runtime storage at a specific block. */\n getHeadStorage(request: T.RemoteChainHeadStorageRequest, options?: CallOptions): ResultAsync>;\n /** Invoke a runtime call at a specific block. */\n callHead(request: T.RemoteChainHeadCallRequest, options?: CallOptions): ResultAsync>;\n /** Release pinned blocks. */\n unpinHead(request: T.RemoteChainHeadUnpinRequest, options?: CallOptions): ResultAsync>;\n /** Continue a paused chain-head operation. */\n continueHead(request: T.RemoteChainHeadContinueRequest, options?: CallOptions): ResultAsync>;\n /** Stop a chain-head operation. */\n stopHeadOperation(request: T.RemoteChainHeadStopOperationRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the canonical genesis hash for a chain. */\n getSpecGenesisHash(request: T.RemoteChainSpecGenesisHashRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the display name of a chain. */\n getSpecChainName(request: T.RemoteChainSpecChainNameRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the JSON-encoded properties of a chain. */\n getSpecProperties(request: T.RemoteChainSpecPropertiesRequest, options?: CallOptions): ResultAsync>;\n /** Broadcast a signed transaction. */\n broadcastTransaction(request: T.RemoteChainTransactionBroadcastRequest, options?: CallOptions): ResultAsync>;\n /** Stop a transaction broadcast. */\n stopTransaction(request: T.RemoteChainTransactionStopRequest, options?: CallOptions): ResultAsync>;\n /**\n * Resolve a chain identifier to its genesis hash against the host's\n * configured environment (RFC 0026).\n */\n getChainInfo(request: T.RemoteChainInfoRequest, options?: CallOptions): ResultAsync>;\n}\n/** Chat room, bot, and message APIs. */\nexport declare class ChatClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Create a chat room. */\n createRoom(request: T.HostChatCreateRoomRequest, options?: CallOptions): ResultAsync>;\n /** Register a chat bot. */\n registerBot(request: T.HostChatRegisterBotRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to the list of chat rooms. */\n listSubscribe(): ObservableLike>;\n /**\n * Post a message to a chat room.\n *\n * The host bounds and screens what it forwards. Message text is capped at\n * 16 KiB and keeps line breaks and tabs, but is rejected for other\n * control characters and for bidirectional overrides. Identifiers and\n * display names are normalized and screened. A message carries at most 32\n * actions and 32 media items, a custom payload at most 256 KiB, and a URL\n * at most 2 KiB which must be `https` or an inline raster image. A\n * rejection reports `MessageTooLarge` when the body or custom payload is\n * over budget, and `Unknown` with a reason naming the field otherwise.\n *\n * The returned `messageId` is the correlation key for any action the\n * message carries: a later `actionSubscribe` trigger names it.\n */\n postMessage(request: T.HostChatPostMessageRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to received chat actions. */\n actionSubscribe(): ObservableLike>;\n}\n/**\n * CoinPayment operations.\n *\n * RFC 0017 describes `Resolvable` values for long-running operations.\n * TrUAPI represents those as subscriptions whose items are the RFC status\n * updates.\n */\nexport declare class CoinPaymentClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Create a new firewalled CoinPayment purse. */\n createPurse(request: T.HostCoinPaymentCreatePurseRequest, options?: CallOptions): ResultAsync>;\n /** Query product-visible purse metadata and balance. */\n queryPurse(request: T.HostCoinPaymentQueryPurseRequest, options?: CallOptions): ResultAsync>;\n /** Transfer balance between local purses. */\n rebalancePurse({ request }: {\n request: T.HostCoinPaymentRebalancePurseRequest;\n }): ObservableLike>;\n /** Delete a purse after draining its balance into another local purse. */\n deletePurse({ request }: {\n request: T.HostCoinPaymentDeletePurseRequest;\n }): ObservableLike>;\n /** Create a receivable public key for depositing into a purse. */\n createReceivable(request: T.HostCoinPaymentCreateReceivableRequest, options?: CallOptions): ResultAsync>;\n /** Create a cheque paying from a local purse to a receivable. */\n createCheque(request: T.HostCoinPaymentCreateChequeRequest, options?: CallOptions): ResultAsync>;\n /** Claim coins from a cheque into the receivable's purse. */\n deposit({ request }: {\n request: T.HostCoinPaymentDepositRequest;\n }): ObservableLike>;\n /** Attempt to return coins associated with a receivable. */\n refund({ request }: {\n request: T.HostCoinPaymentRefundRequest;\n }): ObservableLike>;\n /** Listen for a cheque delivered through a standard transmission channel. */\n listenForPayment({ request }: {\n request: T.HostCoinPaymentListenForRequest;\n }): ObservableLike>;\n}\n/**\n * User-mediated access to the user's contacts.\n *\n * A product never reads the contact list. It opens the host's picker; the host\n * renders an overlay from the chat lists its chat extensions hold, and\n * returns only the person the user selected. Names, accounts, and every other\n * contact the user did not pick stay host-side.\n *\n * That is also why there is no permission to request: the user choosing a\n * contact in host UI is the consent, and a product that is never handed the\n * list has nothing to be granted.\n */\nexport declare class ContactsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Ask the host to let the user pick one contact.\n *\n * Resolves with the chosen contact's handle, or with why nothing was\n * chosen. A host that serves no picker answers `Unsupported`.\n *\n * The handle is not an address and cannot be turned into one. To pay the\n * person it names, put the handle where the recipient goes in the call and\n * list it in `contacts` on the transaction payload: the host replaces it\n * with their account before anything is signed or shown. A handle sent\n * anywhere else is 32 bytes that resolve to nobody.\n */\n pick(request: T.HostContactsPickRequest, options?: CallOptions): ResultAsync>;\n}\n/** Deterministic entropy derivation. */\nexport declare class EntropyClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Derive deterministic entropy. */\n derive(request: T.HostDeriveEntropyRequest, options?: CallOptions): ResultAsync>;\n}\n/** Local key/value storage scoped to the calling product. */\nexport declare class LocalStorageClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Read a value by key. */\n read(request: T.HostLocalStorageReadRequest, options?: CallOptions): ResultAsync>;\n /** Write a value to a key. */\n write(request: T.HostLocalStorageWriteRequest, options?: CallOptions): ResultAsync>;\n /** Clear a value by key. */\n clear(request: T.HostLocalStorageClearRequest, options?: CallOptions): ResultAsync>;\n /**\n * Subscribe to changes of one key in the product's own storage namespace.\n *\n * Emits the current value immediately, then one item per later write or\n * clear of the key by any of the product's runtimes. A write that leaves\n * the stored bytes unchanged emits nothing.\n */\n subscribe({ request }: {\n request: T.HostLocalStorageSubscribeRequest;\n }): ObservableLike>;\n}\n/** Host locale subscription. */\nexport declare class LocaleClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to the host's selected locale. */\n subscribe(): ObservableLike>;\n /** Localize a bounded batch of UTC instants in a host locale snapshot. */\n localizeTimestamps(request: T.HostLocaleLocalizeTimestampsRequest, options?: CallOptions): ResultAsync>;\n}\n/** Notification methods for locally-rendered push notifications. */\nexport declare class NotificationsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Send a push notification to the user.\n *\n * Returns a notification id that can be\n * passed to [`cancel_push_notification`](Self::cancel_push_notification)\n * to retract a scheduled notification. When `scheduled_at` is set the host\n * persists the notification across restarts and fires it through the\n * platform-native scheduler. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\n sendPushNotification(request: T.HostPushNotificationRequest, options?: CallOptions): ResultAsync>;\n /**\n * Cancels a previously issued push notification.\n *\n * Cancellation is idempotent: returns `Ok(())` whether the notification is\n * still pending, already fired, or was never issued. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\n cancelPushNotification(request: T.HostPushNotificationCancelRequest, options?: CallOptions): ResultAsync>;\n}\n/** Payment request and balance/status subscription methods. */\nexport declare class PaymentClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to payment balance updates. */\n balanceSubscribe({ request }: {\n request: T.HostPaymentBalanceSubscribeRequest;\n }): ObservableLike>;\n /** Request a payment from the user. */\n request(request: T.HostPaymentRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to payment lifecycle updates for a specific payment. */\n statusSubscribe({ request }: {\n request: T.HostPaymentStatusSubscribeRequest;\n }): ObservableLike>;\n /** Top up the user's payment balance. */\n topUp(request: T.HostPaymentTopUpRequest, options?: CallOptions): ResultAsync>;\n}\n/** Permission request methods. */\nexport declare class PermissionsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Request a device-capability permission from the user. */\n requestDevicePermission(request: T.HostDevicePermissionRequest, options?: CallOptions): ResultAsync>;\n /**\n * Request a remote-operation permission.\n *\n * This example makes live requests to Frankfurter after permission is granted.\n */\n requestRemotePermission(request: T.RemotePermissionRequest, options?: CallOptions): ResultAsync>;\n}\n/**\n * Pocket cards backed by the calling product.\n *\n * The host owns the collection: a product observes its own cards and may\n * remove them, but cannot add one.\n */\nexport declare class PocketClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Subscribe to the calling product's cards.\n *\n * Emits the whole set on subscribe and again after every change.\n */\n listSubscribe(): ObservableLike>;\n /**\n * Remove one of the calling product's cards.\n *\n * Removing a card that is not present succeeds. A privileged card is\n * refused with `Privileged`.\n */\n removeCard(request: T.HostPocketRemoveCardRequest, options?: CallOptions): ResultAsync>;\n}\n/** Preimage lookup and submission methods. */\nexport declare class PreimageClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to preimage lookups for a given key. */\n lookupSubscribe({ request }: {\n request: T.RemotePreimageLookupSubscribeRequest;\n }): ObservableLike>;\n /** Submit a preimage. Returns the preimage key (hash) on success. */\n submit(request: HexString, options?: CallOptions): ResultAsync>;\n}\n/** Product-rendered bodies and the actions triggered inside them. */\nexport declare class RendererClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Streams renderer trees for one product-rendered body. Each item\n * replaces the previous tree. The stream stays open while the body is\n * displayed so the product can redraw in place.\n */\n onRender(handler: HostInitiatedSubscriptionHandler>): {\n unsubscribe(): void;\n };\n /** Subscribe to actions triggered inside this product's rendered bodies. */\n actionSubscribe(): ObservableLike>;\n}\n/** Resource pre-allocation (allowance management). */\nexport declare class ResourceAllocationClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Request the host to pre-allocate one or more resources. */\n request(request: T.HostRequestResourceAllocationRequest, options?: CallOptions): ResultAsync>;\n}\n/** Signing operations. */\nexport declare class SigningClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Construct a transaction for a product account.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n *\n * Under Extrinsic V5, omitting `VerifyMultiSignature` from `extensions`\n * lets the host sign with the signer's key. Listing it \u2014 as `Disabled`,\n * with a proof in a later extension \u2014 encodes the given bytes verbatim and\n * returns an unsigned transaction.\n *\n * `txExtVersion` is the version of the transaction extensions in\n * `extensions`, as the runtime numbers them. The host picks the extrinsic\n * format from it. V4 always uses version 0, so a non-zero version builds a\n * V5 general transaction. Version 0 builds V5 when it includes\n * `VerifyMultiSignature`, and a signed V4 transaction otherwise.\n *\n * `contacts` lists the contact handles `callData` names, and the host\n * replaces each with the account it resolves to before the call is shown\n * or signed. A declared handle the call does not contain, or one no\n * contact matches, refuses the whole call as `UnknownContact` rather than\n * signing something that names somebody else. A call paying nobody from\n * the picker leaves it empty.\n */\n createTransaction(request: T.ProductAccountTxPayload, options?: CallOptions): ResultAsync>;\n /**\n * Construct a transaction for a non-product (legacy) account.\n *\n * The V5 `VerifyMultiSignature` rule is the same as\n * [`Signing::create_transaction`]: omit it and the host signs, list it and\n * the given bytes are used with no host signature.\n */\n createTransactionWithLegacyAccount(request: T.LegacyAccountTxPayload, options?: CallOptions): ResultAsync>;\n /** Sign raw bytes with a non-product account. */\n signRawWithLegacyAccount(request: T.HostSignRawWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n /** Sign an extrinsic payload with a non-product account. */\n signPayloadWithLegacyAccount(request: T.HostSignPayloadWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign raw bytes or a message.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n */\n signRaw(request: T.HostSignRawRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign an extrinsic payload.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n */\n signPayload(request: T.HostSignPayloadRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign the supplied data without adding or removing a watermark.\n *\n * Temporary compatibility API for runtime ownership proofs, including the\n * 32-byte Resources alias used by Humanity. Payload decoding matches\n * watermarked signing, but the decoded bytes are signed exactly as supplied.\n * This permits transaction-shaped data and requires signing authorization\n * and explicit user confirmation.\n *\n * @deprecated Temporary unwatermarked signing; migrate to watermarked signing when the runtime supports it. This API will be removed. See \n */\n signRawUnwatermarkedDeprecated(request: T.HostSignRawRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign the supplied data without adding or removing a watermark.\n *\n * Temporary compatibility API for runtime ownership proofs, including the\n * 32-byte Resources alias used by Humanity. Payload decoding matches\n * watermarked signing, but the decoded bytes are signed exactly as supplied.\n * This permits transaction-shaped data and requires signing authorization\n * and explicit user confirmation.\n *\n * @deprecated Temporary unwatermarked signing; migrate to watermarked signing when the runtime supports it. This API will be removed. See \n */\n signRawUnwatermarkedDeprecatedWithLegacyAccount(request: T.HostSignRawWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n}\n/** Statement store methods. */\nexport declare class StatementStoreClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to statements matching a topic filter. */\n subscribe({ request }: {\n request: T.RemoteStatementStoreSubscribeRequest;\n }): ObservableLike>;\n /**\n * Create a proof for a statement.\n *\n * **Deprecated:** use [`create_proof_authorized`](Self::create_proof_authorized)\n * instead, which uses a pre-allocated allowance account and does not\n * require a per-call signing prompt. Pairing hosts may reject this method\n * when their signing channel cannot sign statement proof payloads exactly.\n */\n createProof(request: T.RemoteStatementStoreCreateProofRequest, options?: CallOptions): ResultAsync>;\n /**\n * Create a proof for a statement using a pre-allocated allowance account,\n * bypassing the per-call signing prompt.\n */\n createProofAuthorized(request: T.Statement, options?: CallOptions): ResultAsync>;\n /**\n * Submit a signed statement to the network. The request body is the\n * [`SignedStatement`](crate::v01::SignedStatement) directly (no wrapping\n * struct), matching upstream `triangle-js-sdks`.\n */\n submit(request: T.SignedStatement, options?: CallOptions): ResultAsync>;\n}\n/**\n * General-purpose TrUAPI methods for handshake, feature detection,\n * navigation, and runtime information.\n */\nexport declare class SystemClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Negotiate the wire codec version with the product. */\n handshake(options?: CallOptions): ResultAsync>;\n /** Query whether the host supports a specific feature. */\n featureSupported(request: T.HostFeatureSupportedRequest, options?: CallOptions): ResultAsync>;\n /**\n * Request the host to open a URL.\n *\n * An `http` or `https` URL outside the ecosystem needs a\n * `RemotePermission::Remote` grant for the target host, and prompts for one\n * on first use. dotNS names, `localhost`, and the app-handoff schemes\n * (`mailto:`, `tel:`, `polkadot:`, `dot:`) consume no grant. The grant is\n * per host and shared with outbound data access to that host, so approving\n * one covers the other.\n */\n navigateTo(request: T.HostNavigateToRequest, options?: CallOptions): ResultAsync>;\n /**\n * Report the host's identity and version.\n *\n * Returns the host's platform, name, and version so a product knows\n * exactly which host \u2014 and which build of it \u2014 is running it: for\n * adapting to the host, telemetry, and attributing behaviour to a\n * concrete build in diagnostics and bug reports.\n */\n info(options?: CallOptions): ResultAsync>;\n /** Return the product context bound to the current host runtime. */\n getProductContext(options?: CallOptions): ResultAsync>;\n}\n/** Host theme subscription. */\nexport declare class ThemeClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to host theme changes. */\n subscribe(): ObservableLike>;\n}\n/**\n * Worker background-operation APIs.\n *\n * The host keeps a product's worker running while it holds at least one open\n * operation, which is how a worker outlives the surface that started it.\n */\nexport declare class WorkerClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Begin a pending operation. */\n beginOperation(request: T.HostWorkerBeginOperationRequest, options?: CallOptions): ResultAsync>;\n /**\n * End a pending operation. Idempotent: an unknown or already-ended id\n * succeeds, so a retry after an ambiguous failure is safe.\n */\n endOperation(request: T.HostWorkerEndOperationRequest, options?: CallOptions): ResultAsync>;\n}\nexport interface TrUApiClient {\n readonly account: AccountClient;\n readonly chain: ChainClient;\n readonly chat: ChatClient;\n readonly coinPayment: CoinPaymentClient;\n readonly contacts: ContactsClient;\n readonly entropy: EntropyClient;\n readonly localStorage: LocalStorageClient;\n readonly locale: LocaleClient;\n readonly notifications: NotificationsClient;\n readonly payment: PaymentClient;\n readonly permissions: PermissionsClient;\n readonly pocket: PocketClient;\n readonly preimage: PreimageClient;\n readonly renderer: RendererClient;\n readonly resourceAllocation: ResourceAllocationClient;\n readonly signing: SigningClient;\n readonly statementStore: StatementStoreClient;\n readonly system: SystemClient;\n readonly theme: ThemeClient;\n readonly worker: WorkerClient;\n}\nexport type Client = TrUApiClient;\n/** Creates the generated client facade by binding each service namespace to the\n * shared transport instance. */\nexport declare function createClient(transport: TrUApiTransport): TrUApiClient;\n\n\n// development.d.ts\n/** Same as `HostAccountCreateProofRequest`, with the 32-byte context given raw. */\nexport interface DevelopmentCreateProofRequest extends Omit {\n /** The exact 32 bytes the proof is bound to, as `0x`-prefixed hex. */\n context: HexString;\n}\n/**\n * `account.createAccountProof` with a verbatim 32-byte proof context instead of\n * a product-namespaced one.\n *\n */\nexport declare function development_createAccountProof(client: Pick, request: DevelopmentCreateProofRequest): ResultAsync>;\n"; +export declare const truapiDts = "// neverthrow (inlined)\n\ninterface ErrorConfig {\n withStackTrace: boolean;\n}\n\ndeclare class ResultAsync implements PromiseLike> {\n private _promise;\n constructor(res: Promise>);\n static fromSafePromise(promise: PromiseLike): ResultAsync;\n static fromPromise(promise: PromiseLike, errorFn: (e: unknown) => E): ResultAsync;\n static fromThrowable(fn: (...args: A) => Promise, errorFn?: (err: unknown) => E): (...args: A) => ResultAsync;\n static combine, ...ResultAsync[]]>(asyncResultList: T): CombineResultAsyncs;\n static combine[]>(asyncResultList: T): CombineResultAsyncs;\n static combineWithAllErrors, ...ResultAsync[]]>(asyncResultList: T): CombineResultsWithAllErrorsArrayAsync;\n static combineWithAllErrors[]>(asyncResultList: T): CombineResultsWithAllErrorsArrayAsync;\n map(f: (t: T) => A | Promise): ResultAsync;\n andThrough(f: (t: T) => Result | ResultAsync): ResultAsync;\n andTee(f: (t: T) => unknown): ResultAsync;\n orTee(f: (t: E) => unknown): ResultAsync;\n mapErr(f: (e: E) => U | Promise): ResultAsync;\n andThen>(f: (t: T) => R): ResultAsync, InferErrTypes | E>;\n andThen>(f: (t: T) => R): ResultAsync, InferAsyncErrTypes | E>;\n andThen(f: (t: T) => Result | ResultAsync): ResultAsync;\n orElse>(f: (e: E) => R): ResultAsync | T, InferErrTypes>;\n orElse>(f: (e: E) => R): ResultAsync | T, InferAsyncErrTypes>;\n orElse(f: (e: E) => Result | ResultAsync): ResultAsync;\n match(ok: (t: T) => A, _err: (e: E) => B): Promise;\n unwrapOr(t: A): Promise;\n /**\n * @deprecated will be removed in 9.0.0.\n *\n * You can use `safeTry` without this method.\n * @example\n * ```typescript\n * safeTry(async function* () {\n * const okValue = yield* yourResult\n * })\n * ```\n * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.\n */\n safeUnwrap(): AsyncGenerator, T>;\n then(successCallback?: (res: Result) => A | PromiseLike, failureCallback?: (reason: unknown) => B | PromiseLike): PromiseLike;\n [Symbol.asyncIterator](): AsyncGenerator, T>;\n}\ndeclare function okAsync(value: T): ResultAsync;\ndeclare function okAsync(value: void): ResultAsync;\ndeclare function errAsync(err: E): ResultAsync;\ndeclare function errAsync(err: void): ResultAsync;\ndeclare const fromPromise: typeof ResultAsync.fromPromise;\ndeclare const fromSafePromise: typeof ResultAsync.fromSafePromise;\ndeclare const fromAsyncThrowable: typeof ResultAsync.fromThrowable;\ndeclare type CombineResultAsyncs[]> = IsLiteralArray extends 1 ? TraverseAsync> : ResultAsync, ExtractErrAsyncTypes[number]>;\ndeclare type CombineResultsWithAllErrorsArrayAsync[]> = IsLiteralArray extends 1 ? TraverseWithAllErrorsAsync> : ResultAsync, ExtractErrAsyncTypes[number][]>;\ndeclare type UnwrapAsync = IsLiteralArray extends 1 ? Writable extends [infer H, ...infer Rest] ? H extends PromiseLike ? HI extends Result ? [Dedup, ...UnwrapAsync] : never : never : [] : T extends Array ? A extends PromiseLike ? HI extends Result ? Ok[] : never : never : never;\ndeclare type TraverseAsync = IsLiteralArray extends 1 ? Combine extends [infer Oks, infer Errs] ? ResultAsync, MembersToUnion> : never : T extends Array ? Combine, Depth> extends [infer Oks, infer Errs] ? Oks extends unknown[] ? Errs extends unknown[] ? ResultAsync, MembersToUnion> : ResultAsync, Errs> : Errs extends unknown[] ? ResultAsync> : ResultAsync : never : never;\ndeclare type TraverseWithAllErrorsAsync = TraverseAsync extends ResultAsync ? ResultAsync : never;\ndeclare type Writable = T extends ReadonlyArray ? [...T] : T;\n\ndeclare type ExtractOkTypes[]> = {\n [idx in keyof T]: T[idx] extends Result ? U : never;\n};\ndeclare type ExtractOkAsyncTypes[]> = {\n [idx in keyof T]: T[idx] extends ResultAsync ? U : never;\n};\ndeclare type ExtractErrTypes[]> = {\n [idx in keyof T]: T[idx] extends Result ? E : never;\n};\ndeclare type ExtractErrAsyncTypes[]> = {\n [idx in keyof T]: T[idx] extends ResultAsync ? E : never;\n};\ndeclare type InferOkTypes = R extends Result ? T : never;\ndeclare type InferErrTypes = R extends Result ? E : never;\ndeclare type InferAsyncOkTypes = R extends ResultAsync ? T : never;\ndeclare type InferAsyncErrTypes = R extends ResultAsync ? E : never;\n\ndeclare namespace Result {\n /**\n * Wraps a function with a try catch, creating a new function with the same\n * arguments but returning `Ok` if successful, `Err` if the function throws\n *\n * @param fn function to wrap with ok on success or err on failure\n * @param errorFn when an error is thrown, this will wrap the error result if provided\n */\n function fromThrowable any, E>(fn: Fn, errorFn?: (e: unknown) => E): (...args: Parameters) => Result, E>;\n function combine, ...Result[]]>(resultList: T): CombineResults;\n function combine[]>(resultList: T): CombineResults;\n function combineWithAllErrors, ...Result[]]>(resultList: T): CombineResultsWithAllErrorsArray;\n function combineWithAllErrors[]>(resultList: T): CombineResultsWithAllErrorsArray;\n}\ndeclare type Result = Ok | Err;\ndeclare function ok(value: T): Ok;\ndeclare function ok(value: void): Ok;\ndeclare function err(err: E): Err;\ndeclare function err(err: E): Err;\ndeclare function err(err: void): Err;\n/**\n * Evaluates the given generator to a Result returned or an Err yielded from it,\n * whichever comes first.\n *\n * This function is intended to emulate Rust's ? operator.\n * See `/tests/safeTry.test.ts` for examples.\n *\n * @param body - What is evaluated. In body, `yield* result` works as\n * Rust's `result?` expression.\n * @returns The first occurrence of either an yielded Err or a returned Result.\n */\ndeclare function safeTry(body: () => Generator, Result>): Result;\ndeclare function safeTry, GeneratorReturnResult extends Result>(body: () => Generator): Result, InferErrTypes | InferErrTypes>;\n/**\n * Evaluates the given generator to a Result returned or an Err yielded from it,\n * whichever comes first.\n *\n * This function is intended to emulate Rust's ? operator.\n * See `/tests/safeTry.test.ts` for examples.\n *\n * @param body - What is evaluated. In body, `yield* result` and\n * `yield* resultAsync` work as Rust's `result?` expression.\n * @returns The first occurrence of either an yielded Err or a returned Result.\n */\ndeclare function safeTry(body: () => AsyncGenerator, Result>): ResultAsync;\ndeclare function safeTry, GeneratorReturnResult extends Result>(body: () => AsyncGenerator): ResultAsync, InferErrTypes | InferErrTypes>;\ninterface IResult {\n /**\n * Used to check if a `Result` is an `OK`\n *\n * @returns `true` if the result is an `OK` variant of Result\n */\n isOk(): this is Ok;\n /**\n * Used to check if a `Result` is an `Err`\n *\n * @returns `true` if the result is an `Err` variant of Result\n */\n isErr(): this is Err;\n /**\n * Maps a `Result` to `Result`\n * by applying a function to a contained `Ok` value, leaving an `Err` value\n * untouched.\n *\n * @param f The function to apply an `OK` value\n * @returns the result of applying `f` or an `Err` untouched\n */\n map(f: (t: T) => A): Result;\n /**\n * Maps a `Result` to `Result` by applying a function to a\n * contained `Err` value, leaving an `Ok` value untouched.\n *\n * This function can be used to pass through a successful result while\n * handling an error.\n *\n * @param f a function to apply to the error `Err` value\n */\n mapErr(f: (e: E) => U): Result;\n /**\n * Similar to `map` Except you must return a new `Result`.\n *\n * This is useful for when you need to do a subsequent computation using the\n * inner `T` value, but that computation might fail.\n * Additionally, `andThen` is really useful as a tool to flatten a\n * `Result, E1>` into a `Result` (see example below).\n *\n * @param f The function to apply to the current value\n */\n andThen>(f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(f: (t: T) => Result): Result;\n /**\n * This \"tee\"s the current value to an passed-in computation such as side\n * effect functions but still returns the same current value as the result.\n *\n * This is useful when you want to pass the current result to your side-track\n * work such as logging but want to continue main-track work after that.\n * This method does not care about the result of the passed in computation.\n *\n * @param f The function to apply to the current value\n */\n andTee(f: (t: T) => unknown): Result;\n /**\n * This \"tee\"s the current `Err` value to an passed-in computation such as side\n * effect functions but still returns the same `Err` value as the result.\n *\n * This is useful when you want to pass the current `Err` value to your side-track\n * work such as logging but want to continue error-track work after that.\n * This method does not care about the result of the passed in computation.\n *\n * @param f The function to apply to the current `Err` value\n */\n orTee(f: (t: E) => unknown): Result;\n /**\n * Similar to `andTee` except error result of the computation will be passed\n * to the downstream in case of an error.\n *\n * This version is useful when you want to make side-effects but in case of an\n * error, you want to pass the error to the downstream.\n *\n * @param f The function to apply to the current value\n */\n andThrough>(f: (t: T) => R): Result | E>;\n andThrough(f: (t: T) => Result): Result;\n /**\n * Takes an `Err` value and maps it to a `Result`.\n *\n * This is useful for error recovery.\n *\n *\n * @param f A function to apply to an `Err` value, leaving `Ok` values\n * untouched.\n */\n orElse>(f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(f: (e: E) => Result): Result;\n /**\n * Similar to `map` Except you must return a new `Result`.\n *\n * This is useful for when you need to do a subsequent async computation using\n * the inner `T` value, but that computation might fail. Must return a ResultAsync\n *\n * @param f The function that returns a `ResultAsync` to apply to the current\n * value\n */\n asyncAndThen(f: (t: T) => ResultAsync): ResultAsync;\n /**\n * Maps a `Result` to `ResultAsync`\n * by applying an async function to a contained `Ok` value, leaving an `Err`\n * value untouched.\n *\n * @param f An async function to apply an `OK` value\n */\n asyncMap(f: (t: T) => Promise): ResultAsync;\n /**\n * Unwrap the `Ok` value, or return the default if there is an `Err`\n *\n * @param v the default value to return if there is an `Err`\n */\n unwrapOr(v: A): T | A;\n /**\n *\n * Given 2 functions (one for the `Ok` variant and one for the `Err` variant)\n * execute the function that matches the `Result` variant.\n *\n * Match callbacks do not necessitate to return a `Result`, however you can\n * return a `Result` if you want to.\n *\n * `match` is like chaining `map` and `mapErr`, with the distinction that\n * with `match` both functions must have the same return type.\n *\n * @param ok\n * @param err\n */\n match(ok: (t: T) => A, err: (e: E) => B): A | B;\n /**\n * @deprecated will be removed in 9.0.0.\n *\n * You can use `safeTry` without this method.\n * @example\n * ```typescript\n * safeTry(function* () {\n * const okValue = yield* yourResult\n * })\n * ```\n * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.\n */\n safeUnwrap(): Generator, T>;\n /**\n * **This method is unsafe, and should only be used in a test environments**\n *\n * Takes a `Result` and returns a `T` when the result is an `Ok`, otherwise it throws a custom object.\n *\n * @param config\n */\n _unsafeUnwrap(config?: ErrorConfig): T;\n /**\n * **This method is unsafe, and should only be used in a test environments**\n *\n * takes a `Result` and returns a `E` when the result is an `Err`,\n * otherwise it throws a custom object.\n *\n * @param config\n */\n _unsafeUnwrapErr(config?: ErrorConfig): E;\n}\ndeclare class Ok implements IResult {\n readonly value: T;\n constructor(value: T);\n isOk(): this is Ok;\n isErr(): this is Err;\n map(f: (t: T) => A): Result;\n mapErr(_f: (e: E) => U): Result;\n andThen>(f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(f: (t: T) => Result): Result;\n andThrough>(f: (t: T) => R): Result | E>;\n andThrough(f: (t: T) => Result): Result;\n andTee(f: (t: T) => unknown): Result;\n orTee(_f: (t: E) => unknown): Result;\n orElse>(_f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(_f: (e: E) => Result): Result;\n asyncAndThen(f: (t: T) => ResultAsync): ResultAsync;\n asyncAndThrough>(f: (t: T) => R): ResultAsync | E>;\n asyncAndThrough(f: (t: T) => ResultAsync): ResultAsync;\n asyncMap(f: (t: T) => Promise): ResultAsync;\n unwrapOr(_v: A): T | A;\n match(ok: (t: T) => A, _err: (e: E) => B): A | B;\n safeUnwrap(): Generator, T>;\n _unsafeUnwrap(_?: ErrorConfig): T;\n _unsafeUnwrapErr(config?: ErrorConfig): E;\n [Symbol.iterator](): Generator, T>;\n}\ndeclare class Err implements IResult {\n readonly error: E;\n constructor(error: E);\n isOk(): this is Ok;\n isErr(): this is Err;\n map(_f: (t: T) => A): Result;\n mapErr(f: (e: E) => U): Result;\n andThrough(_f: (t: T) => Result): Result;\n andTee(_f: (t: T) => unknown): Result;\n orTee(f: (t: E) => unknown): Result;\n andThen>(_f: (t: T) => R): Result, InferErrTypes | E>;\n andThen(_f: (t: T) => Result): Result;\n orElse>(f: (e: E) => R): Result | T, InferErrTypes>;\n orElse(f: (e: E) => Result): Result;\n asyncAndThen(_f: (t: T) => ResultAsync): ResultAsync;\n asyncAndThrough(_f: (t: T) => ResultAsync): ResultAsync;\n asyncMap(_f: (t: T) => Promise): ResultAsync;\n unwrapOr(v: A): T | A;\n match(_ok: (t: T) => A, err: (e: E) => B): A | B;\n safeUnwrap(): Generator, T>;\n _unsafeUnwrap(config?: ErrorConfig): T;\n _unsafeUnwrapErr(_?: ErrorConfig): E;\n [Symbol.iterator](): Generator, T>;\n}\ndeclare const fromThrowable: typeof Result.fromThrowable;\ndeclare type Prev = [\n never,\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13,\n 14,\n 15,\n 16,\n 17,\n 18,\n 19,\n 20,\n 21,\n 22,\n 23,\n 24,\n 25,\n 26,\n 27,\n 28,\n 29,\n 30,\n 31,\n 32,\n 33,\n 34,\n 35,\n 36,\n 37,\n 38,\n 39,\n 40,\n 41,\n 42,\n 43,\n 44,\n 45,\n 46,\n 47,\n 48,\n 49,\n ...0[]\n];\ndeclare type CollectResults = [\n Depth\n] extends [never] ? [] : T extends [infer H, ...infer Rest] ? H extends Result ? CollectResults : never : Collected;\ndeclare type Transpose = A extends [infer T, ...infer Rest] ? T extends [infer L, infer R] ? Transposed extends [infer PL, infer PR] ? PL extends unknown[] ? PR extends unknown[] ? Transpose : never : never : Transpose : Transposed : Transposed;\ndeclare type Combine = Transpose, [], Depth> extends [\n infer L,\n infer R\n] ? [UnknownMembersToNever, UnknownMembersToNever] : Transpose, [], Depth> extends [] ? [[], []] : never;\ndeclare type Dedup = T extends Result ? [unknown] extends [RL] ? Err : Ok : T;\ndeclare type MemberListOf = ((T extends unknown ? (t: T) => T : never) extends infer U ? (U extends unknown ? (u: U) => unknown : never) extends (v: infer V) => unknown ? V : never : never) extends (_: unknown) => infer W ? [...MemberListOf>, W] : [];\ndeclare type EmptyArrayToNever = T extends [] ? never : NeverArrayToNever extends 1 ? T extends [never, ...infer Rest] ? [EmptyArrayToNever] extends [never] ? never : T : T : T;\ndeclare type UnknownMembersToNever = T extends [infer H, ...infer R] ? [[unknown] extends [H] ? never : H, ...UnknownMembersToNever] : T;\ndeclare type MembersToUnion = T extends unknown[] ? T[number] : never;\ndeclare type IsLiteralArray = T extends {\n length: infer L;\n} ? L extends number ? number extends L ? 0 : 1 : 0 : 0;\ndeclare type Traverse = Combine extends [infer Oks, infer Errs] ? Result, MembersToUnion> : never;\ndeclare type TraverseWithAllErrors = Traverse extends Result ? Result : never;\ndeclare type CombineResults[]> = IsLiteralArray extends 1 ? Traverse : Result, ExtractErrTypes[number]>;\ndeclare type CombineResultsWithAllErrorsArray[]> = IsLiteralArray extends 1 ? TraverseWithAllErrors : Result, ExtractErrTypes[number][]>;\n\n\n\n// scale.d.ts (module-scope)\n\n/** SCALE codec primitives used by the generated client.\n *\n * Thin wrapper over `scale-ts`: re-exports its primitives and combinators,\n * plus the Polkadot-flavour helpers it does not ship (hex-encoded bytes,\n * lazy recursive codecs, and `V`-indexed tagged unions).\n */\nimport { type Codec, type ResultPayload } from \"scale-ts\";\nexport type { Codec };\nexport type { ResultPayload } from \"scale-ts\";\n/**\n * Bare-named type alias matching generated codegen's naming convention for\n * generic wire types: `Result` is used as both a value (the codec\n * builder re-exported below) and a type (this alias for scale-ts's own\n * `ResultPayload`) in generated `types.ts`.\n */\nexport type Result = ResultPayload;\nexport { Bytes, Enum, Option, Result, Struct, Tuple, Vector, _void, compact, i8, i16, i32, i64, i128, str, u8, u16, u32, u64, u128, } from \"scale-ts\";\n/** SCALE boolean, rejecting byte values Rust cannot decode. */\nexport declare const bool: Codec;\n/**\n * Substrate `OptionBool`: a one-byte `Option`.\n *\n * Canonical SCALE encoding (matches `parity_scale_codec::OptionBool`):\n * `undefined` \u2192 `0`, `true` \u2192 `1`, `false` \u2192 `2`.\n */\nexport declare const OptionBool: Codec;\n/** Hex-encoded byte string, e.g. `\"0xdeadbeef\"`. */\nexport type HexString = `0x${string}`;\n/** Assert that a string is a valid hex string (`0x...`). */\nexport declare function toHexString(value: string): HexString;\n/** Encode a byte array as a lower-case hex string with a `0x` prefix. */\nexport declare function bytesToHex(bytes: Uint8Array): HexString;\n/** Decode a hex string into a byte array. Tolerates a missing `0x` prefix. */\nexport declare function hexToBytes(hex: string): Uint8Array;\n/**\n * SCALE codec for hex-encoded byte strings.\n *\n * Encode accepts a `0x`-prefixed hex string and emits SCALE bytes; decode\n * returns the bytes as a hex string. Pass `length` for fixed-size byte arrays\n * (`[u8; N]`); omit it for variable-length byte vectors (`Vec`).\n */\nexport declare function Hex(length?: number): Codec;\n/**\n * Same wire format as `scale-ts`'s `Enum`, but exposes `value` as optional in\n * the public TS type when the variant codec is `Codec`. Lets unit\n * variants of mixed enums round-trip as `{ tag: \"X\" }` (no `value` key).\n */\nexport declare function TaggedUnion(inner: O): Codec>;\n/** Public TS value for Rust's derived `CallError` enum. */\nexport type CallErrorValue = {\n tag: \"Domain\";\n value: D;\n} | {\n tag: \"Denied\";\n value?: undefined;\n} | {\n tag: \"Unsupported\";\n value?: undefined;\n} | {\n tag: \"MalformedFrame\";\n value: {\n reason: string;\n };\n} | {\n tag: \"HostFailure\";\n value: {\n reason: string;\n };\n} | {\n tag: \"Cancelled\";\n value?: undefined;\n};\n/** SCALE codec for Rust's derived `CallError` enum. */\nexport declare function CallError(domain: Codec): Codec>;\ntype TaggedUnionCodecs = {\n [Sym: symbol]: never;\n [Num: number]: never;\n [Str: string]: Codec;\n};\ntype TaggedUnionValue = {\n [K in keyof O & string]: O[K] extends Codec ? [T] extends [undefined] ? {\n tag: K;\n value?: undefined;\n } : {\n tag: K;\n value: T;\n } : never;\n}[keyof O & string];\n/**\n * Enum without payloads \u2014 maps string labels to SCALE discriminant bytes.\n *\n * `scale-ts` models `Enum({ Foo: _void, Bar: _void })` as tagged objects. For\n * user-facing TrUAPI enums with only unit variants, we keep the public TS shape\n * as a plain string union instead.\n */\nexport declare function Status(...variants: readonly T[]): Codec;\n/**\n * Defers codec construction until first use so recursive generated codecs can\n * reference each other safely.\n */\nexport declare function lazy(factory: () => Codec): Codec;\ntype IndexedVariantCodec = readonly [index: number, codec: Codec];\ntype IndexedVariantValue>, K extends keyof Variants & string> = Variants[K] extends IndexedVariantCodec ? [T] extends [undefined] ? {\n tag: K;\n value?: undefined;\n} : {\n tag: K;\n value: T;\n} : never;\n/**\n * Builds a tagged union codec with explicit SCALE discriminants.\n *\n * `scale-ts` assigns enum indexes by object key order. TrUAPI versioned enums pin\n * `V` to index `N - 1`, including V2-only enums, so generated codecs use this\n * helper for versioned wire wrappers.\n */\nexport declare function indexedTaggedUnion>>(variants: Variants): Codec<{\n [K in keyof Variants & string]: IndexedVariantValue;\n}[keyof Variants & string]>;\n\n\n// generated/types.d.ts (namespace T)\n\ndeclare namespace T {\n/**\n * A press on a button the host draws for a `ChatMessageContent::Actions`\n * message.\n */\nexport interface ActionTrigger {\n /**\n * Message containing the action, as returned by `Chat::post_message` in\n * [`HostChatPostMessageResponse::message_id`].\n */\n messageId: string;\n /** Which action was triggered. */\n actionId: string;\n /** Optional additional data. */\n payload?: HexString;\n}\nexport const ActionTrigger: Codec;\n/**\n * A resource the host can pre-allocate on behalf of the product (RFC 0010).\n *\n * For the slot-table allowances (`StatementStoreAllowance`,\n * `BulletinAllowance`, `SmartContractAllowance`), pre-allocation is\n * opportunistic and the host may also fulfil the allowance implicitly on the\n * first submission. `AutoSigning` must be requested explicitly through this\n * call.\n */\nexport type AllocatableResource = \n/** Statement Store slot allowance for the product's own allowance account. */\n{\n tag: \"StatementStoreAllowance\";\n value?: undefined;\n}\n/** Bulletin chain slot allowance for the product's own allowance account. */\n | {\n tag: \"BulletinAllowance\";\n value?: undefined;\n}\n/**\n * Pre-warmed PGAS balance for the product account selected by this\n * derivation index.\n */\n | {\n tag: \"SmartContractAllowance\";\n value: DerivationIndex;\n}\n/** Permission to sign on the product's behalf without per-call user prompts. */\n | {\n tag: \"AutoSigning\";\n value?: undefined;\n}\n/**\n * Current UTC-day Statement Store allowance whose target is the product\n * account selected by this derivation index.\n */\n | {\n tag: \"ProductStatementStoreAllowance\";\n value: DerivationIndex;\n};\nexport const AllocatableResource: Codec;\n/** Outcome of allocating a single resource (RFC 0010). */\nexport type AllocationOutcome = \"Allocated\" | \"Rejected\" | \"NotAvailable\";\nexport const AllocationOutcome: Codec;\n/** Main-axis distribution of children. */\nexport type Arrangement = \"Start\" | \"End\" | \"Center\" | \"SpaceBetween\" | \"SpaceAround\" | \"SpaceEvenly\";\nexport const Arrangement: Codec;\n/** A rectangle in surface units, relative to the surface's top-left corner. */\nexport interface AvatarRect {\n /** Left edge. */\n x: number;\n /** Top edge. */\n y: number;\n /** Width. */\n width: number;\n /** Height. */\n height: number;\n}\nexport const AvatarRect: Codec;\n/** Background styling. */\nexport interface Background {\n /** Background color. */\n color: ColorToken;\n /** Background shape. */\n shape?: Shape;\n}\nexport const Background: Codec;\n/**\n * How a node composites with what is behind it. The values are those common\n * to CSS `mix-blend-mode`, SwiftUI `BlendMode` and Compose `BlendMode`.\n */\nexport type BlendingMode = \"Normal\" | \"Multiply\" | \"Screen\" | \"Overlay\" | \"Darken\" | \"Lighten\" | \"ColorDodge\" | \"ColorBurn\" | \"HardLight\" | \"SoftLight\" | \"Difference\" | \"Exclusion\" | \"Hue\" | \"Saturation\" | \"Color\" | \"Luminosity\";\nexport const BlendingMode: Codec;\n/** Border styling. */\nexport interface BorderStyle {\n /** Border width. */\n width: Size;\n /** Border color. */\n color: ColorToken;\n /** Border shape. */\n shape?: Shape;\n}\nexport const BorderStyle: Codec;\n/** Properties of a `Box`. */\nexport interface BoxProps {\n /** Placement of content within the box. */\n contentAlignment?: ContentAlignment;\n}\nexport const BoxProps: Codec;\n/** Properties of a `Button`. */\nexport interface ButtonProps {\n /** Button label. */\n text: string;\n /** Button emphasis. */\n variant?: ButtonVariant;\n /** Whether the button accepts presses. Absent leaves the default to the host. */\n enabled?: boolean;\n /**\n * Whether the button shows a loading state. A loading button accepts no\n * presses. Absent leaves the default to the host.\n */\n loading?: boolean;\n /** Action triggered on press. A button without one is inert. */\n clickAction?: string;\n}\nexport const ButtonProps: Codec;\n/** Button emphasis. */\nexport type ButtonVariant = \"Primary\" | \"Secondary\" | \"Text\";\nexport const ButtonVariant: Codec;\n/**\n * A 32-byte value, passed as plain bytes on FFI surfaces. Version-neutral:\n * the FFI conversion below applies to `[u8; 32]` fields in every protocol\n * version.\n */\nexport type Bytes32 = HexString;\nexport const Bytes32: Codec;\n/** Role of a chain within the host's configured environment. */\nexport type ChainIdentifier = \"Relay\" | \"AssetHub\" | \"People\" | \"Bulletin\";\nexport const ChainIdentifier: Codec;\n/** A clickable action button in a chat message. */\nexport interface ChatAction {\n /** Action identifier. */\n actionId: string;\n /** Button label. */\n title: string;\n}\nexport const ChatAction: Codec;\n/** Layout for action buttons. */\nexport type ChatActionLayout = \"Column\" | \"Grid\";\nexport const ChatActionLayout: Codec;\n/** Payload of a received chat action. */\nexport type ChatActionPayload = \n/** A peer posted a message. */\n{\n tag: \"MessagePosted\";\n value: ChatMessageContent;\n}\n/** A user pressed a host-drawn `Actions` button. */\n | {\n tag: \"ActionTriggered\";\n value: ActionTrigger;\n}\n/** A user issued a command. */\n | {\n tag: \"Command\";\n value: ChatCommand;\n};\nexport const ChatActionPayload: Codec;\n/** A set of action buttons with optional text. */\nexport interface ChatActions {\n /** Optional message text. */\n text?: string;\n /** List of action buttons. */\n actions: Array;\n /** `Column` or `Grid` layout. */\n layout: ChatActionLayout;\n}\nexport const ChatActions: Codec;\n/** Whether the bot was newly registered or already existed. */\nexport type ChatBotRegistrationStatus = \"New\" | \"Exists\";\nexport const ChatBotRegistrationStatus: Codec;\n/** A slash command from a chat user. */\nexport interface ChatCommand {\n /** Command name. */\n command: string;\n /** Command arguments. */\n payload: string;\n}\nexport const ChatCommand: Codec;\n/**\n * A custom message with application-defined type and binary payload. The\n * host draws it through `Renderer::render`, with a `ChatMessage` context\n * carrying `message_type` and `payload` as the render payload.\n */\nexport interface ChatCustomMessage {\n /** Application-defined type key. */\n messageType: string;\n /** Binary payload. */\n payload: HexString;\n}\nexport const ChatCustomMessage: Codec;\n/** A file attachment in a chat message. */\nexport interface ChatFile {\n /** File download URL. */\n url: string;\n /** File name. */\n fileName: string;\n /** MIME type. */\n mimeType: string;\n /** File size in bytes. */\n sizeBytes: bigint;\n /** Optional caption text. */\n text?: string;\n}\nexport const ChatFile: Codec;\n/** A media attachment. */\nexport interface ChatMedia {\n /** Media URL. */\n url: string;\n}\nexport const ChatMedia: Codec;\n/** Content of a chat message -- one of several types. */\nexport type ChatMessageContent = \n/** Plain text message. */\n{\n tag: \"Text\";\n value: {\n text: string;\n };\n}\n/** Rich text with media. */\n | {\n tag: \"RichText\";\n value: ChatRichText;\n}\n/** Action button set. */\n | {\n tag: \"Actions\";\n value: ChatActions;\n}\n/** File attachment. */\n | {\n tag: \"File\";\n value: ChatFile;\n}\n/** Emoji reaction. */\n | {\n tag: \"Reaction\";\n value: ChatReaction;\n}\n/** Reaction removal. */\n | {\n tag: \"ReactionRemoved\";\n value: ChatReaction;\n}\n/** Custom message. */\n | {\n tag: \"Custom\";\n value: ChatCustomMessage;\n};\nexport const ChatMessageContent: Codec;\n/** A reaction to a chat message. */\nexport interface ChatReaction {\n /** Message being reacted to. */\n messageId: string;\n /** Emoji reaction. */\n emoji: string;\n}\nexport const ChatReaction: Codec;\n/** Rich text message with optional media. */\nexport interface ChatRichText {\n /** Optional text content. */\n text?: string;\n /** Attached media items. */\n media: Array;\n}\nexport const ChatRichText: Codec;\n/** A chat room the product participates in. */\nexport interface ChatRoom {\n /** Room identifier. */\n roomId: string;\n /** `RoomHost` or `Bot`. */\n participatingAs: ChatRoomParticipation;\n}\nexport const ChatRoom: Codec;\n/** How the product participates in a chat room. */\nexport type ChatRoomParticipation = \"RoomHost\" | \"Bot\";\nexport const ChatRoomParticipation: Codec;\n/** Whether the room was newly created or already existed. */\nexport type ChatRoomRegistrationStatus = \"New\" | \"Exists\";\nexport const ChatRoomRegistrationStatus: Codec;\n/** Standardized encrypted Coinage secret transmission payload. */\nexport interface CoinPaymentCheque {\n /** Receivable public key protecting the cheque contents. */\n id: HexString;\n /** Claimed payment amount. */\n amount: number;\n /** Concatenated coin secrets encrypted to the receivable. */\n encryptedSecrets: HexString;\n}\nexport const CoinPaymentCheque: Codec;\n/** Product-visible clearing reference for reconciliation and receipts. */\nexport interface CoinPaymentClearingReference {\n /** Clearing Merkle root. */\n root: HexString;\n /** Product-visible coin key and transaction hash leaves. */\n leaves: Array<[HexString, HexString]>;\n}\nexport const CoinPaymentClearingReference: Codec;\n/** Errors returned by CoinPayment host operations. */\nexport type CoinPaymentError = \"BalanceLow\" | \"Denied\" | \"BadCoins\" | \"SnipedCoins\" | \"PurseNotFound\" | \"ReceivableNotFound\" | \"UnsupportedChannel\" | \"UserAgentCapabilityUnavailable\" | \"Internal\";\nexport const CoinPaymentError: Codec;\n/** Product-visible metadata and balance state for a CoinPayment purse. */\nexport interface CoinPaymentPurseInfo {\n /** Human-readable purse name supplied by the creating product. */\n name: string;\n /** Creation timestamp. */\n created: bigint;\n /** Product that created the purse. */\n creator: string;\n /** Current product-visible balance. */\n balance: number;\n}\nexport const CoinPaymentPurseInfo: Codec;\n/** Clearing status stream item. */\nexport type CoinPaymentStatus = \n/** More coins have cleared. */\n{\n tag: \"Clearing\";\n value: {\n clearing: number;\n cleared: number;\n };\n}\n/** Some or all coins failed to transfer. */\n | {\n tag: \"Failed\";\n value: {\n error: CoinPaymentError;\n cleared: number;\n reference: CoinPaymentClearingReference;\n };\n}\n/** All coins cleared. */\n | {\n tag: \"Done\";\n value: {\n cleared: number;\n reference: CoinPaymentClearingReference;\n };\n};\nexport const CoinPaymentStatus: Codec;\n/** Standardized cheque transmission channel. */\nexport type CoinPaymentTransmissionChannel = \n/** Statement-store/HOP handoff identified by an SSS topic. */\n{\n tag: \"Standard\";\n value: {\n sssTopic: HexString;\n };\n};\nexport const CoinPaymentTransmissionChannel: Codec;\n/** Semantic color tokens, resolved by the host's theme. */\nexport type ColorToken = \"FgPrimary\" | \"FgSecondary\" | \"FgTertiary\" | \"BgSurfaceMain\" | \"BgSurfaceContainer\" | \"BgSurfaceNested\" | \"FgSuccess\" | \"FgError\" | \"FgWarning\";\nexport const ColorToken: Codec;\n/** Properties of a `Column`. */\nexport interface ColumnProps {\n /** Cross-axis alignment of children. */\n horizontalAlignment?: HorizontalAlignment;\n /** Main-axis distribution of children. */\n verticalArrangement?: Arrangement;\n}\nexport const ColumnProps: Codec;\n/**\n * A contact as a product knows them: 32 bytes and nothing else.\n *\n * Its own type rather than a bare [`Bytes32`], because an account id is also\n * 32 bytes. A product that could pass one where the other is expected would\n * build a valid-looking transfer to an address nobody controls. A handle is\n * not an address, and the type is where that is said.\n */\nexport interface ContactHandle {\n /** The handle's bytes. */\n bytes: Bytes32;\n}\nexport const ContactHandle: Codec;\n/** Geometry for a host-owned contact name, independent of profile sharing. */\nexport interface ContactLabelSlot {\n /** Product-chosen id, unique within this placement. */\n slot: number;\n /** Opaque handle for the contact whose name the host draws. */\n handle: ContactHandle;\n /** Name bounds in surface units, with sides from 1 to 16384. */\n rect: AvatarRect;\n /** Visible region in surface units; a zero side hides the label. */\n clip: AvatarRect;\n}\nexport const ContactLabelSlot: Codec;\n/** Selection confirmed in the host's multi-contact picker. */\nexport type ContactPickManyOutcome = \n/** The user confirmed this complete selection, including an empty one. */\n{\n tag: \"Picked\";\n value: {\n handles: Array;\n };\n}\n/** The user closed the picker without confirming a change. */\n | {\n tag: \"Dismissed\";\n value?: undefined;\n}\n/** There are no contacts to show. */\n | {\n tag: \"NoContacts\";\n value?: undefined;\n};\nexport const ContactPickManyOutcome: Codec;\n/**\n * How a contact pick ended.\n *\n * Distinguishing these matters to a product deciding what to do next: a\n * dismissal is worth retrying, an empty list is not.\n */\nexport type ContactPickOutcome = \n/**\n * The user chose someone.\n *\n * `handle` is the same value for this person in every product, and on every\n * host of this user. It is not an address and cannot be turned into one:\n * the core resolves it when it builds a transaction, so a product can name\n * a recipient it never learns the account of.\n */\n{\n tag: \"Picked\";\n value: {\n handle: ContactHandle;\n };\n}\n/** The user closed the picker without choosing. */\n | {\n tag: \"Dismissed\";\n value?: undefined;\n}\n/** The user has no contacts, so no picker was shown. */\n | {\n tag: \"NoContacts\";\n value?: undefined;\n};\nexport const ContactPickOutcome: Codec;\n/** Placement of content within a `Box`. */\nexport type ContentAlignment = \"TopStart\" | \"TopCenter\" | \"TopEnd\" | \"CenterStart\" | \"Center\" | \"CenterEnd\" | \"BottomStart\" | \"BottomCenter\" | \"BottomEnd\";\nexport const ContentAlignment: Codec;\n/** A privacy-preserving alias derived via ring VRF, bound to a specific context. */\nexport interface ContextualAlias {\n /** 32-byte context identifier the alias is bound to. */\n context: HexString;\n /** Ring VRF alias (variable length). */\n alias: HexString;\n}\nexport const ContextualAlias: Codec;\n/**\n * Account selector within a product subtree. Encodes as\n * `Either` on the wire (`Index` = left, `Raw` = right).\n *\n * `Index` is the primary form \u2014 plain indices keep a product's accounts\n * enumerable. `Raw` carries a raw 32-byte derivation index for cases where\n * bytes are genuinely necessary. Hosts expand `Index(n)` to the internal\n * 32-byte index (`u32` little-endian plus the index magic).\n */\nexport type DerivationIndex = \n/** Plain account index. */\n{\n tag: \"Index\";\n value: number;\n}\n/** Raw 32-byte derivation index. */\n | {\n tag: \"Raw\";\n value: HexString;\n};\nexport const DerivationIndex: Codec;\n/** Edge dimensions. `bottom` defaults to `top` and `start` to `end` when absent. */\nexport interface Dimensions {\n /** Top edge. */\n top: Size;\n /** End edge. */\n end: Size;\n /** Bottom edge; defaults to `top`. */\n bottom?: Size;\n /** Start edge; defaults to `end`. */\n start?: Size;\n}\nexport const Dimensions: Codec;\n/** A visual effect. Each variant names one effect and carries its parameters. */\nexport type Effect = \"Rainbow\";\nexport const Effect: Codec;\n/** Properties of an `Effect`. */\nexport interface EffectProps {\n /** The effect applied to the children. */\n effect: Effect;\n}\nexport const EffectProps: Codec;\n/**\n * Generic error payload carrying a human-readable reason string. Used by many\n * methods as a catch-all error type.\n */\nexport interface GenericError {\n /** Human-readable failure reason. */\n reason: string;\n}\nexport const GenericError: Codec;\n/** Cross-axis alignment of `Column` children. */\nexport type HorizontalAlignment = \"Start\" | \"Center\" | \"End\";\nexport const HorizontalAlignment: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeError`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeError: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeItem`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountConnectionStatusSubscribeItem;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeItem: Codec;\n/** Versioned envelope for [`HostAccountConnectionStatusSubscribeRequest`]. */\nexport type VersionedHostAccountConnectionStatusSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostAccountConnectionStatusSubscribeRequest: Codec;\n/** Versioned envelope for [`HostAccountCreateProofError`]. */\nexport type VersionedHostAccountCreateProofError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofError;\n};\nexport const VersionedHostAccountCreateProofError: Codec;\n/** Versioned envelope for [`HostAccountCreateProofRequest`]. */\nexport type VersionedHostAccountCreateProofRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofRequest;\n};\nexport const VersionedHostAccountCreateProofRequest: Codec;\n/** Versioned envelope for [`HostAccountCreateProofResponse`]. */\nexport type VersionedHostAccountCreateProofResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountCreateProofResponse;\n};\nexport const VersionedHostAccountCreateProofResponse: Codec;\n/** Versioned envelope for [`HostAccountGetAliasError`]. */\nexport type VersionedHostAccountGetAliasError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetAliasError;\n};\nexport const VersionedHostAccountGetAliasError: Codec;\n/** Versioned envelope for [`HostAccountGetAliasRequest`]. */\nexport type VersionedHostAccountGetAliasRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetAliasRequest;\n};\nexport const VersionedHostAccountGetAliasRequest: Codec;\n/** Versioned envelope for [`HostAccountGetAliasResponse`]. */\nexport type VersionedHostAccountGetAliasResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ContextualAlias;\n};\nexport const VersionedHostAccountGetAliasResponse: Codec;\n/** Versioned envelope for [`HostAccountGetError`]. */\nexport type VersionedHostAccountGetError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetError;\n};\nexport const VersionedHostAccountGetError: Codec;\n/** Versioned envelope for [`HostAccountGetRequest`]. */\nexport type VersionedHostAccountGetRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetRequest;\n};\nexport const VersionedHostAccountGetRequest: Codec;\n/** Versioned envelope for [`HostAccountGetResponse`]. */\nexport type VersionedHostAccountGetResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetResponse;\n};\nexport const VersionedHostAccountGetResponse: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysError`]. */\nexport type VersionedHostAccountListRingVrfKeysError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountListRingVrfKeysError;\n};\nexport const VersionedHostAccountListRingVrfKeysError: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysRequest`]. */\nexport type VersionedHostAccountListRingVrfKeysRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountListRingVrfKeysRequest;\n};\nexport const VersionedHostAccountListRingVrfKeysRequest: Codec;\n/** Versioned envelope for [`HostAccountListRingVrfKeysResponse`]. */\nexport type VersionedHostAccountListRingVrfKeysResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: Array;\n};\nexport const VersionedHostAccountListRingVrfKeysResponse: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyError`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRegisterRingVrfKeyError;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyError: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyRequest`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRegisterRingVrfKeyRequest;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyRequest: Codec;\n/** Versioned envelope for [`HostAccountRegisterRingVrfKeyResponse`]. */\nexport type VersionedHostAccountRegisterRingVrfKeyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedHostAccountRegisterRingVrfKeyResponse: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignError`]. */\nexport type VersionedHostAccountRingVrfSignError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRingVrfSignError;\n};\nexport const VersionedHostAccountRingVrfSignError: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignRequest`]. */\nexport type VersionedHostAccountRingVrfSignRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountRingVrfSignRequest;\n};\nexport const VersionedHostAccountRingVrfSignRequest: Codec;\n/** Versioned envelope for [`HostAccountRingVrfSignResponse`]. */\nexport type VersionedHostAccountRingVrfSignResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedHostAccountRingVrfSignResponse: Codec;\n/** Versioned envelope for [`HostAccountSignVrfError`]. */\nexport type VersionedHostAccountSignVrfError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountSignVrfError;\n};\nexport const VersionedHostAccountSignVrfError: Codec;\n/** Versioned envelope for [`HostAccountSignVrfRequest`]. */\nexport type VersionedHostAccountSignVrfRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountSignVrfRequest;\n};\nexport const VersionedHostAccountSignVrfRequest: Codec;\n/** Versioned envelope for [`HostAccountSignVrfResponse`]. */\nexport type VersionedHostAccountSignVrfResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: VrfSignature;\n};\nexport const VersionedHostAccountSignVrfResponse: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeError`]. */\nexport type VersionedHostChatActionSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostChatActionSubscribeError: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeItem`]. */\nexport type VersionedHostChatActionSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatActionSubscribeItem;\n};\nexport const VersionedHostChatActionSubscribeItem: Codec;\n/** Versioned envelope for [`HostChatActionSubscribeRequest`]. */\nexport type VersionedHostChatActionSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostChatActionSubscribeRequest: Codec;\n/** Versioned envelope for [`HostChatCreateRoomError`]. */\nexport type VersionedHostChatCreateRoomError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomError;\n};\nexport const VersionedHostChatCreateRoomError: Codec;\n/** Versioned envelope for [`HostChatCreateRoomRequest`]. */\nexport type VersionedHostChatCreateRoomRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomRequest;\n};\nexport const VersionedHostChatCreateRoomRequest: Codec;\n/** Versioned envelope for [`HostChatCreateRoomResponse`]. */\nexport type VersionedHostChatCreateRoomResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatCreateRoomResponse;\n};\nexport const VersionedHostChatCreateRoomResponse: Codec;\n/** Versioned envelope for [`HostChatListSubscribeError`]. */\nexport type VersionedHostChatListSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostChatListSubscribeError: Codec;\n/** Versioned envelope for [`HostChatListSubscribeItem`]. */\nexport type VersionedHostChatListSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatListSubscribeItem;\n};\nexport const VersionedHostChatListSubscribeItem: Codec;\n/** Versioned envelope for [`HostChatListSubscribeRequest`]. */\nexport type VersionedHostChatListSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostChatListSubscribeRequest: Codec;\n/** Versioned envelope for [`HostChatPostMessageError`]. */\nexport type VersionedHostChatPostMessageError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageError;\n};\nexport const VersionedHostChatPostMessageError: Codec;\n/** Versioned envelope for [`HostChatPostMessageRequest`]. */\nexport type VersionedHostChatPostMessageRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageRequest;\n};\nexport const VersionedHostChatPostMessageRequest: Codec;\n/** Versioned envelope for [`HostChatPostMessageResponse`]. */\nexport type VersionedHostChatPostMessageResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatPostMessageResponse;\n};\nexport const VersionedHostChatPostMessageResponse: Codec;\n/** Versioned envelope for [`HostChatRegisterBotError`]. */\nexport type VersionedHostChatRegisterBotError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotError;\n};\nexport const VersionedHostChatRegisterBotError: Codec;\n/** Versioned envelope for [`HostChatRegisterBotRequest`]. */\nexport type VersionedHostChatRegisterBotRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotRequest;\n};\nexport const VersionedHostChatRegisterBotRequest: Codec;\n/** Versioned envelope for [`HostChatRegisterBotResponse`]. */\nexport type VersionedHostChatRegisterBotResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostChatRegisterBotResponse;\n};\nexport const VersionedHostChatRegisterBotResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeError`]. */\nexport type VersionedHostCoinPaymentCreateChequeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreateChequeError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeRequest`]. */\nexport type VersionedHostCoinPaymentCreateChequeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateChequeRequest;\n};\nexport const VersionedHostCoinPaymentCreateChequeRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateChequeResponse`]. */\nexport type VersionedHostCoinPaymentCreateChequeResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateChequeResponse;\n};\nexport const VersionedHostCoinPaymentCreateChequeResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseError`]. */\nexport type VersionedHostCoinPaymentCreatePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreatePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseRequest`]. */\nexport type VersionedHostCoinPaymentCreatePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreatePurseRequest;\n};\nexport const VersionedHostCoinPaymentCreatePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreatePurseResponse`]. */\nexport type VersionedHostCoinPaymentCreatePurseResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreatePurseResponse;\n};\nexport const VersionedHostCoinPaymentCreatePurseResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableError`]. */\nexport type VersionedHostCoinPaymentCreateReceivableError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentCreateReceivableError: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableRequest`]. */\nexport type VersionedHostCoinPaymentCreateReceivableRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateReceivableRequest;\n};\nexport const VersionedHostCoinPaymentCreateReceivableRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentCreateReceivableResponse`]. */\nexport type VersionedHostCoinPaymentCreateReceivableResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentCreateReceivableResponse;\n};\nexport const VersionedHostCoinPaymentCreateReceivableResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseError`]. */\nexport type VersionedHostCoinPaymentDeletePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentDeletePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseItem`]. */\nexport type VersionedHostCoinPaymentDeletePurseItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentDeletePurseItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentDeletePurseRequest`]. */\nexport type VersionedHostCoinPaymentDeletePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentDeletePurseRequest;\n};\nexport const VersionedHostCoinPaymentDeletePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositError`]. */\nexport type VersionedHostCoinPaymentDepositError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentDepositError: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositItem`]. */\nexport type VersionedHostCoinPaymentDepositItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentDepositItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentDepositRequest`]. */\nexport type VersionedHostCoinPaymentDepositRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentDepositRequest;\n};\nexport const VersionedHostCoinPaymentDepositRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForError`]. */\nexport type VersionedHostCoinPaymentListenForError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentListenForError: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForItem`]. */\nexport type VersionedHostCoinPaymentListenForItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentListenForItem;\n};\nexport const VersionedHostCoinPaymentListenForItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentListenForRequest`]. */\nexport type VersionedHostCoinPaymentListenForRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentListenForRequest;\n};\nexport const VersionedHostCoinPaymentListenForRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseError`]. */\nexport type VersionedHostCoinPaymentQueryPurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentQueryPurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseRequest`]. */\nexport type VersionedHostCoinPaymentQueryPurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentQueryPurseRequest;\n};\nexport const VersionedHostCoinPaymentQueryPurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentQueryPurseResponse`]. */\nexport type VersionedHostCoinPaymentQueryPurseResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentQueryPurseResponse;\n};\nexport const VersionedHostCoinPaymentQueryPurseResponse: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseError`]. */\nexport type VersionedHostCoinPaymentRebalancePurseError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentRebalancePurseError: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseItem`]. */\nexport type VersionedHostCoinPaymentRebalancePurseItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentRebalancePurseItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentRebalancePurseRequest`]. */\nexport type VersionedHostCoinPaymentRebalancePurseRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentRebalancePurseRequest;\n};\nexport const VersionedHostCoinPaymentRebalancePurseRequest: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundError`]. */\nexport type VersionedHostCoinPaymentRefundError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentError;\n};\nexport const VersionedHostCoinPaymentRefundError: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundItem`]. */\nexport type VersionedHostCoinPaymentRefundItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: CoinPaymentStatus;\n};\nexport const VersionedHostCoinPaymentRefundItem: Codec;\n/** Versioned envelope for [`HostCoinPaymentRefundRequest`]. */\nexport type VersionedHostCoinPaymentRefundRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCoinPaymentRefundRequest;\n};\nexport const VersionedHostCoinPaymentRefundRequest: Codec;\n/** Versioned envelope for [`HostContactsPickError`]. */\nexport type VersionedHostContactsPickError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickError;\n};\nexport const VersionedHostContactsPickError: Codec;\n/** Versioned envelope for [`HostContactsPickManyError`]. */\nexport type VersionedHostContactsPickManyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickManyError;\n};\nexport const VersionedHostContactsPickManyError: Codec;\n/** Versioned envelope for [`HostContactsPickManyRequest`]. */\nexport type VersionedHostContactsPickManyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickManyRequest;\n};\nexport const VersionedHostContactsPickManyRequest: Codec;\n/** Versioned envelope for [`HostContactsPickManyResponse`]. */\nexport type VersionedHostContactsPickManyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickManyResponse;\n};\nexport const VersionedHostContactsPickManyResponse: Codec;\n/** Versioned envelope for [`HostContactsPickRequest`]. */\nexport type VersionedHostContactsPickRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickRequest;\n};\nexport const VersionedHostContactsPickRequest: Codec;\n/** Versioned envelope for [`HostContactsPickResponse`]. */\nexport type VersionedHostContactsPickResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPickResponse;\n};\nexport const VersionedHostContactsPickResponse: Codec;\n/** Versioned envelope for [`HostContactsPlaceLabelsError`]. */\nexport type VersionedHostContactsPlaceLabelsError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPlaceLabelsError;\n};\nexport const VersionedHostContactsPlaceLabelsError: Codec;\n/** Versioned envelope for [`HostContactsPlaceLabelsRequest`]. */\nexport type VersionedHostContactsPlaceLabelsRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPlaceLabelsRequest;\n};\nexport const VersionedHostContactsPlaceLabelsRequest: Codec;\n/** Versioned envelope for [`HostContactsPlaceLabelsResponse`]. */\nexport type VersionedHostContactsPlaceLabelsResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostContactsPlaceLabelsResponse;\n};\nexport const VersionedHostContactsPlaceLabelsResponse: Codec;\n/** Versioned envelope for [`HostCreateTransactionError`]. */\nexport type VersionedHostCreateTransactionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionError;\n};\nexport const VersionedHostCreateTransactionError: Codec;\n/** Versioned envelope for [`HostCreateTransactionRequest`]. */\nexport type VersionedHostCreateTransactionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ProductAccountTxPayload;\n};\nexport const VersionedHostCreateTransactionRequest: Codec;\n/** Versioned envelope for [`HostCreateTransactionResponse`]. */\nexport type VersionedHostCreateTransactionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionResponse;\n};\nexport const VersionedHostCreateTransactionResponse: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountError`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionError;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountRequest`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: LegacyAccountTxPayload;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostCreateTransactionWithLegacyAccountResponse`]. */\nexport type VersionedHostCreateTransactionWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostCreateTransactionWithLegacyAccountResponse;\n};\nexport const VersionedHostCreateTransactionWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostDeriveEntropyError`]. */\nexport type VersionedHostDeriveEntropyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyError;\n};\nexport const VersionedHostDeriveEntropyError: Codec;\n/** Versioned envelope for [`HostDeriveEntropyRequest`]. */\nexport type VersionedHostDeriveEntropyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyRequest;\n};\nexport const VersionedHostDeriveEntropyRequest: Codec;\n/** Versioned envelope for [`HostDeriveEntropyResponse`]. */\nexport type VersionedHostDeriveEntropyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDeriveEntropyResponse;\n};\nexport const VersionedHostDeriveEntropyResponse: Codec;\n/** Versioned envelope for [`HostDevicePermissionError`]. */\nexport type VersionedHostDevicePermissionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostDevicePermissionError: Codec;\n/** Versioned envelope for [`HostDevicePermissionRequest`]. */\nexport type VersionedHostDevicePermissionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDevicePermissionRequest;\n};\nexport const VersionedHostDevicePermissionRequest: Codec;\n/** Versioned envelope for [`HostDevicePermissionResponse`]. */\nexport type VersionedHostDevicePermissionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostDevicePermissionResponse;\n};\nexport const VersionedHostDevicePermissionResponse: Codec;\n/** Versioned envelope for [`HostFeatureSupportedError`]. */\nexport type VersionedHostFeatureSupportedError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostFeatureSupportedError: Codec;\n/** Versioned envelope for [`HostFeatureSupportedRequest`]. */\nexport type VersionedHostFeatureSupportedRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostFeatureSupportedRequest;\n};\nexport const VersionedHostFeatureSupportedRequest: Codec;\n/** Versioned envelope for [`HostFeatureSupportedResponse`]. */\nexport type VersionedHostFeatureSupportedResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostFeatureSupportedResponse;\n};\nexport const VersionedHostFeatureSupportedResponse: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsError`]. */\nexport type VersionedHostGetLegacyAccountsError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostAccountGetError;\n};\nexport const VersionedHostGetLegacyAccountsError: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsRequest`]. */\nexport type VersionedHostGetLegacyAccountsRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetLegacyAccountsRequest: Codec;\n/** Versioned envelope for [`HostGetLegacyAccountsResponse`]. */\nexport type VersionedHostGetLegacyAccountsResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetLegacyAccountsResponse;\n};\nexport const VersionedHostGetLegacyAccountsResponse: Codec;\n/** Versioned envelope for [`HostGetProductContextError`]. */\nexport type VersionedHostGetProductContextError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostGetProductContextError: Codec;\n/** Versioned envelope for [`HostGetProductContextRequest`]. */\nexport type VersionedHostGetProductContextRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetProductContextRequest: Codec;\n/** Versioned envelope for [`HostGetProductContextResponse`]. */\nexport type VersionedHostGetProductContextResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetProductContextResponse;\n};\nexport const VersionedHostGetProductContextResponse: Codec;\n/** Versioned envelope for [`HostGetUserIdError`]. */\nexport type VersionedHostGetUserIdError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetUserIdError;\n};\nexport const VersionedHostGetUserIdError: Codec;\n/** Versioned envelope for [`HostGetUserIdRequest`]. */\nexport type VersionedHostGetUserIdRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostGetUserIdRequest: Codec;\n/** Versioned envelope for [`HostGetUserIdResponse`]. */\nexport type VersionedHostGetUserIdResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostGetUserIdResponse;\n};\nexport const VersionedHostGetUserIdResponse: Codec;\n/** Versioned envelope for [`HostHandshakeError`]. */\nexport type VersionedHostHandshakeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostHandshakeError;\n};\nexport const VersionedHostHandshakeError: Codec;\n/** Versioned envelope for [`HostHandshakeRequest`]. */\nexport type VersionedHostHandshakeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostHandshakeRequest;\n};\nexport const VersionedHostHandshakeRequest: Codec;\n/** Versioned envelope for [`HostHandshakeResponse`]. */\nexport type VersionedHostHandshakeResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostHandshakeResponse: Codec;\n/**\n * Identity and version of the host currently running the product.\n *\n * Reported by [`crate::api::System::host_info`] so a product knows which host\n * (and which build of it) is running it \u2014 for adapting to the host,\n * telemetry, and attributing behaviour to a concrete build in diagnostics and\n * bug reports.\n */\nexport interface HostInfo {\n /** Platform category the host runs on. */\n platform: HostPlatform;\n /**\n * Human-readable name of the host implementation, e.g. `\"Polkadot\n * Desktop\"`, `\"Polkadot Mobile\"`, or `\"dotli\"`. Hosts should report a\n * stable, non-empty name.\n */\n name: string;\n /**\n * Host-native version string, e.g. a semver such as `\"1.2.3\"`. Hosts\n * should report a non-empty value; the format is the host's own.\n */\n version: string;\n}\nexport const HostInfo: Codec;\n/** Versioned envelope for [`HostInfoError`]. */\nexport type VersionedHostInfoError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostInfoError: Codec;\n/** Versioned envelope for [`HostInfoRequest`]. */\nexport type VersionedHostInfoRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostInfoRequest: Codec;\n/** Versioned envelope for [`HostInfoResponse`]. */\nexport type VersionedHostInfoResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostInfo;\n};\nexport const VersionedHostInfoResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageChangeItem`]. */\nexport type VersionedHostLocalStorageChangeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageChangeItem;\n};\nexport const VersionedHostLocalStorageChangeItem: Codec;\n/** Versioned envelope for [`HostLocalStorageClearError`]. */\nexport type VersionedHostLocalStorageClearError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: V01HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageClearError: Codec;\n/** Versioned envelope for [`HostLocalStorageClearRequest`]. */\nexport type VersionedHostLocalStorageClearRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageClearRequest;\n};\nexport const VersionedHostLocalStorageClearRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageClearResponse`]. */\nexport type VersionedHostLocalStorageClearResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostLocalStorageClearResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageReadError`]. */\nexport type VersionedHostLocalStorageReadError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageReadError: Codec;\n/** Versioned envelope for [`HostLocalStorageReadRequest`]. */\nexport type VersionedHostLocalStorageReadRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadRequest;\n};\nexport const VersionedHostLocalStorageReadRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageReadResponse`]. */\nexport type VersionedHostLocalStorageReadResponse = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocalStorageReadResponse;\n};\nexport const VersionedHostLocalStorageReadResponse: Codec;\n/** Versioned envelope for [`HostLocalStorageSubscribeError`]. */\nexport type VersionedHostLocalStorageSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostLocalStorageSubscribeError: Codec;\n/** Versioned envelope for [`HostLocalStorageSubscribeRequest`]. */\nexport type VersionedHostLocalStorageSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageSubscribeRequest;\n};\nexport const VersionedHostLocalStorageSubscribeRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteError`]. */\nexport type VersionedHostLocalStorageWriteError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: V01HostLocalStorageReadError;\n};\nexport const VersionedHostLocalStorageWriteError: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteRequest`]. */\nexport type VersionedHostLocalStorageWriteRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocalStorageWriteRequest;\n};\nexport const VersionedHostLocalStorageWriteRequest: Codec;\n/** Versioned envelope for [`HostLocalStorageWriteResponse`]. */\nexport type VersionedHostLocalStorageWriteResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostLocalStorageWriteResponse: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsError`]. */\nexport type VersionedHostLocaleLocalizeTimestampsError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostLocaleLocalizeTimestampsError: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsRequest`]. */\nexport type VersionedHostLocaleLocalizeTimestampsRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocaleLocalizeTimestampsRequest;\n};\nexport const VersionedHostLocaleLocalizeTimestampsRequest: Codec;\n/** Versioned envelope for [`HostLocaleLocalizeTimestampsResponse`]. */\nexport type VersionedHostLocaleLocalizeTimestampsResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostLocaleLocalizeTimestampsResponse;\n};\nexport const VersionedHostLocaleLocalizeTimestampsResponse: Codec;\n/** One timestamp's calendar identity and presentation in the requested context. */\nexport interface HostLocaleLocalizedTimestamp {\n /** Gregorian YYYY-MM-DD local date, independent of display language/calendar. */\n localDate: string;\n /** Localized short time, including the host language's hour-cycle convention. */\n time: string;\n /** Localized date label. */\n date: string;\n /** Localized date and time with a time-zone indication for detail views. */\n dateTime: string;\n}\nexport const HostLocaleLocalizedTimestamp: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeError`]. */\nexport type VersionedHostLocaleSubscribeError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: GenericError;\n};\nexport const VersionedHostLocaleSubscribeError: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeItem`]. */\nexport type VersionedHostLocaleSubscribeItem = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostLocaleSubscribeItem;\n};\nexport const VersionedHostLocaleSubscribeItem: Codec;\n/** Versioned envelope for [`HostLocaleSubscribeRequest`]. */\nexport type VersionedHostLocaleSubscribeRequest = \n/** Version 2 (no payload). */\n{\n tag: \"V2\";\n value?: undefined;\n};\nexport const VersionedHostLocaleSubscribeRequest: Codec;\n/** A peer's native delivery acknowledgment, not a payment-clearing receipt. */\nexport interface HostNativeChatAcknowledgment {\n /** Authenticated acknowledging identity. */\n peerIdentity: HexString;\n /** Acknowledged native request identifier. */\n requestId: string;\n /** Native response code; zero denotes successful delivery processing. */\n responseCode: number;\n}\nexport const HostNativeChatAcknowledgment: Codec;\n/** Public attachment handle; only the Host can resolve its private backing. */\nexport interface HostNativeChatAttachment {\n /** Opaque handle scoped to the current wallet, network and calling product. */\n attachmentId: HexString;\n /** Non-secret native metadata. */\n metadata: HostNativeChatAttachmentMetadata;\n /** Current durable transfer progress. */\n state: HostNativeChatAttachmentState;\n}\nexport const HostNativeChatAttachment: Codec;\n/** Public native media metadata; thumbnails are BlurHash text, not executable images. */\nexport type HostNativeChatAttachmentKind = \n/** A general document or other opaque file. */\n{\n tag: \"File\";\n value?: undefined;\n}\n/** An image with native dimensions and an optional UTF-8 BlurHash. */\n | {\n tag: \"Image\";\n value: {\n width: number;\n height: number;\n thumbnail?: HexString;\n };\n}\n/** A video with native duration and an optional UTF-8 BlurHash. */\n | {\n tag: \"Video\";\n value: {\n durationSeconds: number;\n thumbnail?: HexString;\n };\n};\nexport const HostNativeChatAttachmentKind: Codec;\n/** Safe attachment description, independent of private transfer credentials. */\nexport interface HostNativeChatAttachmentMetadata {\n /** Validated media type; it does not authorize execution or network loading. */\n mimeType: string;\n /** Exact native file size, verified against the downloaded root and chunks. */\n sizeBytes: number;\n /** General file, image or video metadata. */\n kind: HostNativeChatAttachmentKind;\n}\nexport const HostNativeChatAttachmentMetadata: Codec;\n/** Durable transfer progress, distinct from message delivery acknowledgment. */\nexport type HostNativeChatAttachmentState = \n/** The Host is securing an immutable selected source. */\n{\n tag: \"Preparing\";\n value?: undefined;\n}\n/** Native HOP entries are being uploaded. */\n | {\n tag: \"Uploading\";\n value: {\n uploadedBytes: number;\n };\n}\n/** Verified file bytes are being committed to private local storage. */\n | {\n tag: \"Downloading\";\n value: {\n downloadedBytes: number;\n };\n}\n/** Complete verified bytes are available through trusted Host presentation. */\n | {\n tag: \"Ready\";\n value?: undefined;\n}\n/** An interrupted transfer retains its exact credentials and progress for retry. */\n | {\n tag: \"Recovering\";\n value?: undefined;\n};\nexport const HostNativeChatAttachmentState: Codec;\n/** Peer cryptographic identity independently resolved and bound by the Host. */\nexport interface HostNativeChatBinding {\n /** Authenticated peer root identity. */\n peerIdentity: HexString;\n /** Peer identity-level native Chat encryption key. */\n peerChatPublicKey: HexString;\n /** Identity proof used in the native invitation handshake. */\n identityProof: HexString;\n}\nexport const HostNativeChatBinding: Codec;\n/** The Host-owned device's public identity and statement-signing account. */\nexport interface HostNativeChatDevice {\n /** Wallet identity on the configured People chain. */\n identityAccountId: HexString;\n /** Wallet identity's public X25519 key. */\n identityChatPublicKey: HexString;\n /** Product account used to obtain a statement-store allowance for this device. */\n productAccount: ProductAccountId;\n /** Public statement signer for the Host-owned device. */\n accountId: HexString;\n /** Public X25519 key; its secret never leaves the Host. */\n chatPublicKey: HexString;\n}\nexport const HostNativeChatDevice: Codec;\n/** An authenticated invitation awaiting the user's Chat decision. */\nexport interface HostNativeChatInvitation {\n /** Host-generated stable invitation identifier. */\n invitationId: HexString;\n /** Authenticated sender identity. */\n peerIdentity: HexString;\n /** Host-resolved sender username, when available. */\n username?: string;\n /** Authenticated native invitation timestamp in milliseconds. */\n timestamp: bigint;\n /** Ordinary initial text, never an embedded payment or control message. */\n text: string;\n}\nexport const HostNativeChatInvitation: Codec;\n/** Safe ordinary messages from one authenticated native request. */\nexport interface HostNativeChatMessages {\n /** Authenticated counterparty identity. */\n peerIdentity: HexString;\n /** Whether the peer sent these messages; false also covers our welcome text. */\n incoming: boolean;\n /** Native request identifier, retained for message-delivery correlation. */\n requestId: string;\n /** Native message encodings after custody-sensitive content is removed. */\n messages: Array;\n}\nexport const HostNativeChatMessages: Codec;\n/** Native request identity needed to answer a migrated legacy invitation. */\nexport interface HostNativeChatMigrationInvitation {\n /** Invitation handle in the accompanying legacy public view. */\n invitationId: HexString;\n /** Original native request identity to acknowledge when answering. */\n requestId: string;\n}\nexport const HostNativeChatMigrationInvitation: Codec;\n/** Continuation metadata for a bounded page of authenticated incoming plaintext. */\nexport interface HostNativeChatOpenPage {\n /** Opaque identifier of the authenticated opening operation. */\n openId: HexString;\n /** Cursor identifying this page. */\n cursor: number;\n /** Cursor to request next; absent when the authenticated batch is complete. */\n nextCursor?: number;\n}\nexport const HostNativeChatOpenPage: Codec;\n/** Authenticated incoming native plaintext, potentially containing incoming coin keys. */\nexport interface HostNativeChatOpened {\n /** Authenticated peer root identity, never the local wallet's own identity. */\n peerIdentity: HexString;\n /** Account that signed the accepted native statement. */\n senderAccountId: HexString;\n /** Authenticated native context of the incoming statement. */\n route: HostNativeChatRoute;\n /** Native invitation or tagged request/response plaintext; never outgoing payment memos. */\n plaintext: HexString;\n}\nexport const HostNativeChatOpened: Codec;\n/** A product-visible payment card; it contains no spendable memo material. */\nexport interface HostNativeChatPayment {\n /** Durable, product-scoped operation identifier. */\n operationId: HexString;\n /** Caller request id for outgoing payments; native request id for incoming ones. */\n requestId: string;\n /** Native message id used to place the payment in conversation history. */\n messageId: string;\n /** Native message timestamp in milliseconds. */\n timestamp: bigint;\n /** Counterparty identity authenticated by the Host. */\n peerIdentity: HexString;\n /** Incoming or outgoing relative to the current wallet. */\n direction: HostNativeChatPaymentDirection;\n /** Exact requested/received value in cents. */\n amountCents: bigint;\n /** Durable transport/clearing state. */\n state: HostNativeChatPaymentState;\n}\nexport const HostNativeChatPayment: Codec;\n/** Payment direction relative to the current wallet. */\nexport type HostNativeChatPaymentDirection = \"Outgoing\" | \"Incoming\";\nexport const HostNativeChatPaymentDirection: Codec;\n/** Public, non-secret payment failure categories. */\nexport type HostNativeChatPaymentFailure = \"Cancelled\" | \"InsufficientBalance\" | \"AlreadySpent\" | \"InvalidMemo\" | \"ChainRejected\";\nexport const HostNativeChatPaymentFailure: Codec;\n/** Durable payment state. Delivery and on-chain clearing are deliberately distinct. */\nexport type HostNativeChatPaymentState = \n/** Approved inputs are reserved; required split/unload work is in progress. */\n{\n tag: \"Preparing\";\n value?: undefined;\n}\n/** The encrypted memo is durable and transport delivery is being retried. */\n | {\n tag: \"Delivering\";\n value?: undefined;\n}\n/** The peer acknowledged the memo; settlement has not yet been established. */\n | {\n tag: \"Delivered\";\n value?: undefined;\n}\n/** Received secrets are durably held while their claim is in progress. */\n | {\n tag: \"Claiming\";\n value?: undefined;\n}\n/** Some, but not all, of the payment has been observed clearing on chain. */\n | {\n tag: \"PartiallyCleared\";\n value: {\n clearedCents: bigint;\n };\n}\n/** The complete payment has been verified at chain finality. */\n | {\n tag: \"Cleared\";\n value?: undefined;\n}\n/** An ambiguous effect is retained for reconciliation; inputs remain reserved. */\n | {\n tag: \"Recovering\";\n value?: undefined;\n}\n/** A definitive failure; the Host has reconciled any possible prior effects. */\n | {\n tag: \"Failed\";\n value: {\n reason: HostNativeChatPaymentFailure;\n };\n};\nexport const HostNativeChatPaymentState: Codec;\n/** Public conversation state; products cannot write this roster back to the Host. */\nexport interface HostNativeChatPeer {\n /** Recipient wallet identity. */\n identityAccountId: HexString;\n /** Username resolved by the Host, if currently available. */\n username?: string;\n /** Devices admitted by authenticated native invitation/control messages. */\n devices: Array;\n /** Native session topics for subscriptions, not request/response channel hashes. */\n incomingChannels: Array;\n /** Whether establishment and legacy-device revocation have been acknowledged. */\n readyForPayments: boolean;\n}\nexport const HostNativeChatPeer: Codec;\n/** Public metadata for one authenticated remote device. */\nexport interface HostNativeChatPeerDevice {\n /** Remote device's statement signer. */\n accountId: HexString;\n /** Remote device's authenticated public X25519 key. */\n chatPublicKey: HexString;\n}\nexport const HostNativeChatPeerDevice: Codec;\n/** Signed ciphertext with the native identity required for durable product delivery. */\nexport interface HostNativeChatPrepared {\n /** Exact signed ciphertext to submit again when retrying delivery. */\n statement: SignedStatement;\n /** Authenticated recipient root identity. */\n peerIdentity: HexString;\n /** Native request identity used to correlate delivery acknowledgments. */\n requestId: string;\n /** Whether delivery remains pending until a native peer acknowledgment arrives. */\n requiresAck: boolean;\n /** Original product intent id for correlating migrated pending UI, when retained. */\n clientRequestId?: string;\n}\nexport const HostNativeChatPrepared: Codec;\n/** Authenticated rich content after private file capabilities have been removed. */\nexport interface HostNativeChatRichMessage {\n /** Authenticated conversation identity. */\n peerIdentity: HexString;\n /** Whether the remote peer authored this content. */\n incoming: boolean;\n /** Native request id used for delivery acknowledgment. */\n requestId: string;\n /** Native id of this message or edit event. */\n messageId: string;\n /** Native timestamp in milliseconds. */\n timestamp: bigint;\n /** New message, reply or edit; authorship checks still apply to edits. */\n kind: HostNativeChatRichMessageKind;\n /** Ordinary optional text. */\n text?: string;\n /** Opaque file handles and safe metadata, never native file references. */\n attachments: Array;\n}\nexport const HostNativeChatRichMessage: Codec;\n/** Native rich-content timeline operation. */\nexport type HostNativeChatRichMessageKind = \n/** A new ordinary rich message. */\n{\n tag: \"Message\";\n value?: undefined;\n}\n/** A new rich message replying to an earlier message. */\n | {\n tag: \"Reply\";\n value: {\n messageId: string;\n };\n}\n/** A replacement of the same author's earlier rich content. */\n | {\n tag: \"Edited\";\n value: {\n messageId: string;\n };\n};\nexport const HostNativeChatRichMessageKind: Codec;\n/** The authenticated native encryption and statement-routing context. */\nexport type HostNativeChatRoute = \"Invitation\" | \"Identity\" | \"Device\";\nexport const HostNativeChatRoute: Codec;\n/** Continuation metadata for a bounded page of a stable public state snapshot. */\nexport interface HostNativeChatStatePage {\n /** Opaque identifier of the Host-retained public state snapshot. */\n stateId: HexString;\n /** Cursor identifying this page. */\n cursor: number;\n /** Cursor to request next; absent when the snapshot is complete. */\n nextCursor?: number;\n}\nexport const HostNativeChatStatePage: Codec;\n/** Versioned envelope for [`HostNavigateToError`]. */\nexport type VersionedHostNavigateToError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostNavigateToError;\n};\nexport const VersionedHostNavigateToError: Codec;\n/** Versioned envelope for [`HostNavigateToRequest`]. */\nexport type VersionedHostNavigateToRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostNavigateToRequest;\n};\nexport const VersionedHostNavigateToRequest: Codec;\n/** Versioned envelope for [`HostNavigateToResponse`]. */\nexport type VersionedHostNavigateToResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostNavigateToResponse: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeError`]. */\nexport type VersionedHostPaymentBalanceSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeError;\n};\nexport const VersionedHostPaymentBalanceSubscribeError: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeItem`]. */\nexport type VersionedHostPaymentBalanceSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeItem;\n};\nexport const VersionedHostPaymentBalanceSubscribeItem: Codec;\n/** Versioned envelope for [`HostPaymentBalanceSubscribeRequest`]. */\nexport type VersionedHostPaymentBalanceSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentBalanceSubscribeRequest;\n};\nexport const VersionedHostPaymentBalanceSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPaymentError`]. */\nexport type VersionedHostPaymentError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentError;\n};\nexport const VersionedHostPaymentError: Codec;\n/** Versioned envelope for [`HostPaymentRequest`]. */\nexport type VersionedHostPaymentRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentRequest;\n};\nexport const VersionedHostPaymentRequest: Codec;\n/** Versioned envelope for [`HostPaymentResponse`]. */\nexport type VersionedHostPaymentResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentResponse;\n};\nexport const VersionedHostPaymentResponse: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeError`]. */\nexport type VersionedHostPaymentStatusSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeError;\n};\nexport const VersionedHostPaymentStatusSubscribeError: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeItem`]. */\nexport type VersionedHostPaymentStatusSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeItem;\n};\nexport const VersionedHostPaymentStatusSubscribeItem: Codec;\n/** Versioned envelope for [`HostPaymentStatusSubscribeRequest`]. */\nexport type VersionedHostPaymentStatusSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentStatusSubscribeRequest;\n};\nexport const VersionedHostPaymentStatusSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPaymentTopUpError`]. */\nexport type VersionedHostPaymentTopUpError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentTopUpError;\n};\nexport const VersionedHostPaymentTopUpError: Codec;\n/** Versioned envelope for [`HostPaymentTopUpRequest`]. */\nexport type VersionedHostPaymentTopUpRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPaymentTopUpRequest;\n};\nexport const VersionedHostPaymentTopUpRequest: Codec;\n/** Versioned envelope for [`HostPaymentTopUpResponse`]. */\nexport type VersionedHostPaymentTopUpResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPaymentTopUpResponse: Codec;\n/** Platform category a host runs on. */\nexport type HostPlatform = \"Web\" | \"Android\" | \"Ios\" | \"Desktop\" | \"Cli\" | \"Unknown\";\nexport const HostPlatform: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeError`]. */\nexport type VersionedHostPocketListSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostPocketListSubscribeError: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeItem`]. */\nexport type VersionedHostPocketListSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketListSubscribeItem;\n};\nexport const VersionedHostPocketListSubscribeItem: Codec;\n/** Versioned envelope for [`HostPocketListSubscribeRequest`]. */\nexport type VersionedHostPocketListSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPocketListSubscribeRequest: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardError`]. */\nexport type VersionedHostPocketRemoveCardError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketRemoveCardError;\n};\nexport const VersionedHostPocketRemoveCardError: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardRequest`]. */\nexport type VersionedHostPocketRemoveCardRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPocketRemoveCardRequest;\n};\nexport const VersionedHostPocketRemoveCardRequest: Codec;\n/** Versioned envelope for [`HostPocketRemoveCardResponse`]. */\nexport type VersionedHostPocketRemoveCardResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPocketRemoveCardResponse: Codec;\n/** Versioned envelope for [`HostProductDeviceChatError`]. */\nexport type VersionedHostProductDeviceChatError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProductDeviceChatError;\n};\nexport const VersionedHostProductDeviceChatError: Codec;\n/** Versioned envelope for [`HostProductDeviceChatRequest`]. */\nexport type VersionedHostProductDeviceChatRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProductDeviceChatRequest;\n};\nexport const VersionedHostProductDeviceChatRequest: Codec;\n/** Versioned envelope for [`HostProductDeviceChatResponse`]. */\nexport type VersionedHostProductDeviceChatResponse = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProductDeviceChatResponse;\n};\nexport const VersionedHostProductDeviceChatResponse: Codec;\n/** Versioned envelope for [`HostProfileDiscloseError`]. */\nexport type VersionedHostProfileDiscloseError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProfileDiscloseError;\n};\nexport const VersionedHostProfileDiscloseError: Codec;\n/** Versioned envelope for [`HostProfileDiscloseRequest`]. */\nexport type VersionedHostProfileDiscloseRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProfileDiscloseRequest;\n};\nexport const VersionedHostProfileDiscloseRequest: Codec;\n/** Versioned envelope for [`HostProfileDiscloseResponse`]. */\nexport type VersionedHostProfileDiscloseResponse = \n/** Version 2 (no payload). */\n{\n tag: \"V2\";\n value?: undefined;\n};\nexport const VersionedHostProfileDiscloseResponse: Codec;\n/** Versioned envelope for [`HostProfileOwnStatusError`]. */\nexport type VersionedHostProfileOwnStatusError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfileOwnStatusError;\n};\nexport const VersionedHostProfileOwnStatusError: Codec;\n/** Versioned envelope for [`HostProfileOwnStatusRequest`]. */\nexport type VersionedHostProfileOwnStatusRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfileOwnStatusRequest: Codec;\n/** Versioned envelope for [`HostProfileOwnStatusResponse`]. */\nexport type VersionedHostProfileOwnStatusResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfileOwnStatusResponse;\n};\nexport const VersionedHostProfileOwnStatusResponse: Codec;\n/** Versioned envelope for [`HostProfilePlaceContactAvatarsError`]. */\nexport type VersionedHostProfilePlaceContactAvatarsError = \n/** Version 3 payload. */\n{\n tag: \"V3\";\n value: HostProfilePlaceContactAvatarsError;\n};\nexport const VersionedHostProfilePlaceContactAvatarsError: Codec;\n/** Versioned envelope for [`HostProfilePlaceContactAvatarsRequest`]. */\nexport type VersionedHostProfilePlaceContactAvatarsRequest = \n/** Version 3 payload. */\n{\n tag: \"V3\";\n value: HostProfilePlaceContactAvatarsRequest;\n};\nexport const VersionedHostProfilePlaceContactAvatarsRequest: Codec;\n/** Versioned envelope for [`HostProfilePlaceContactAvatarsResponse`]. */\nexport type VersionedHostProfilePlaceContactAvatarsResponse = \n/** Version 3 (no payload). */\n{\n tag: \"V3\";\n value?: undefined;\n};\nexport const VersionedHostProfilePlaceContactAvatarsResponse: Codec;\n/** Versioned envelope for [`HostProfilePresentContactError`]. */\nexport type VersionedHostProfilePresentContactError = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProfilePresentContactError;\n};\nexport const VersionedHostProfilePresentContactError: Codec;\n/** Versioned envelope for [`HostProfilePresentContactRequest`]. */\nexport type VersionedHostProfilePresentContactRequest = \n/** Version 2 payload. */\n{\n tag: \"V2\";\n value: HostProfilePresentContactRequest;\n};\nexport const VersionedHostProfilePresentContactRequest: Codec;\n/** Versioned envelope for [`HostProfilePresentContactResponse`]. */\nexport type VersionedHostProfilePresentContactResponse = \n/** Version 2 (no payload). */\n{\n tag: \"V2\";\n value?: undefined;\n};\nexport const VersionedHostProfilePresentContactResponse: Codec;\n/** Versioned envelope for [`HostProfilePresentError`]. */\nexport type VersionedHostProfilePresentError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfilePresentError;\n};\nexport const VersionedHostProfilePresentError: Codec;\n/** Versioned envelope for [`HostProfilePresentOwnError`]. */\nexport type VersionedHostProfilePresentOwnError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfilePresentOwnError;\n};\nexport const VersionedHostProfilePresentOwnError: Codec;\n/** Versioned envelope for [`HostProfilePresentOwnRequest`]. */\nexport type VersionedHostProfilePresentOwnRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfilePresentOwnRequest: Codec;\n/** Versioned envelope for [`HostProfilePresentOwnResponse`]. */\nexport type VersionedHostProfilePresentOwnResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfilePresentOwnResponse: Codec;\n/** Versioned envelope for [`HostProfilePresentRequest`]. */\nexport type VersionedHostProfilePresentRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfilePresentRequest;\n};\nexport const VersionedHostProfilePresentRequest: Codec;\n/** Versioned envelope for [`HostProfilePresentResponse`]. */\nexport type VersionedHostProfilePresentResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfilePresentResponse: Codec;\n/** Versioned envelope for [`HostProfileRetractError`]. */\nexport type VersionedHostProfileRetractError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostProfileRetractError;\n};\nexport const VersionedHostProfileRetractError: Codec;\n/** Versioned envelope for [`HostProfileRetractRequest`]. */\nexport type VersionedHostProfileRetractRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfileRetractRequest: Codec;\n/** Versioned envelope for [`HostProfileRetractResponse`]. */\nexport type VersionedHostProfileRetractResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostProfileRetractResponse: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelError`]. */\nexport type VersionedHostPushNotificationCancelError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostPushNotificationCancelError: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelRequest`]. */\nexport type VersionedHostPushNotificationCancelRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationCancelRequest;\n};\nexport const VersionedHostPushNotificationCancelRequest: Codec;\n/** Versioned envelope for [`HostPushNotificationCancelResponse`]. */\nexport type VersionedHostPushNotificationCancelResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostPushNotificationCancelResponse: Codec;\n/** Versioned envelope for [`HostPushNotificationError`]. */\nexport type VersionedHostPushNotificationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationError;\n};\nexport const VersionedHostPushNotificationError: Codec;\n/** Versioned envelope for [`HostPushNotificationRequest`]. */\nexport type VersionedHostPushNotificationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationRequest;\n};\nexport const VersionedHostPushNotificationRequest: Codec;\n/** Versioned envelope for [`HostPushNotificationResponse`]. */\nexport type VersionedHostPushNotificationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostPushNotificationResponse;\n};\nexport const VersionedHostPushNotificationResponse: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeError`]. */\nexport type VersionedHostRendererActionSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostRendererActionSubscribeError: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeItem`]. */\nexport type VersionedHostRendererActionSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRendererActionSubscribeItem;\n};\nexport const VersionedHostRendererActionSubscribeItem: Codec;\n/** Versioned envelope for [`HostRendererActionSubscribeRequest`]. */\nexport type VersionedHostRendererActionSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostRendererActionSubscribeRequest: Codec;\n/** Versioned envelope for [`HostRequestLoginError`]. */\nexport type VersionedHostRequestLoginError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginError;\n};\nexport const VersionedHostRequestLoginError: Codec;\n/** Versioned envelope for [`HostRequestLoginRequest`]. */\nexport type VersionedHostRequestLoginRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginRequest;\n};\nexport const VersionedHostRequestLoginRequest: Codec;\n/** Versioned envelope for [`HostRequestLoginResponse`]. */\nexport type VersionedHostRequestLoginResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestLoginResponse;\n};\nexport const VersionedHostRequestLoginResponse: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationError`]. */\nexport type VersionedHostRequestResourceAllocationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ResourceAllocationError;\n};\nexport const VersionedHostRequestResourceAllocationError: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationRequest`]. */\nexport type VersionedHostRequestResourceAllocationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestResourceAllocationRequest;\n};\nexport const VersionedHostRequestResourceAllocationRequest: Codec;\n/** Versioned envelope for [`HostRequestResourceAllocationResponse`]. */\nexport type VersionedHostRequestResourceAllocationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostRequestResourceAllocationResponse;\n};\nexport const VersionedHostRequestResourceAllocationResponse: Codec;\n/**\n * Full Substrate extrinsic signing payload with all fields needed for signature\n * generation.\n */\nexport interface HostSignPayloadData {\n /** Reference block hash. */\n blockHash: HexString;\n /** Reference block number. */\n blockNumber: HexString;\n /** Mortality era encoding. */\n era: HexString;\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** SCALE-encoded call data. */\n method: HexString;\n /** Account nonce. */\n nonce: HexString;\n /** Runtime spec version. */\n specVersion: HexString;\n /** Transaction tip. */\n tip: HexString;\n /** Transaction format version. */\n transactionVersion: HexString;\n /** Extension identifiers. */\n signedExtensions: Array;\n /** Extrinsic version. */\n version: number;\n /** For multi-asset tips. */\n assetId?: HexString;\n /** CheckMetadataHash extension. */\n metadataHash?: HexString;\n /** Metadata mode. */\n mode?: number;\n /** Request signed transaction back, encoded as one byte: absent, true, or false. */\n withSignedTransaction?: boolean;\n}\nexport const HostSignPayloadData: Codec;\n/** Versioned envelope for [`HostSignPayloadError`]. */\nexport type VersionedHostSignPayloadError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignPayloadError: Codec;\n/** Versioned envelope for [`HostSignPayloadRequest`]. */\nexport type VersionedHostSignPayloadRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadRequest;\n};\nexport const VersionedHostSignPayloadRequest: Codec;\n/** Versioned envelope for [`HostSignPayloadResponse`]. */\nexport type VersionedHostSignPayloadResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignPayloadResponse: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountError`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountRequest`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadWithLegacyAccountRequest;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostSignPayloadWithLegacyAccountResponse`]. */\nexport type VersionedHostSignPayloadWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignPayloadWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostSignRawError`]. */\nexport type VersionedHostSignRawError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignRawError: Codec;\n/** Versioned envelope for [`HostSignRawRequest`]. */\nexport type VersionedHostSignRawRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignRawRequest;\n};\nexport const VersionedHostSignRawRequest: Codec;\n/** Versioned envelope for [`HostSignRawResponse`]. */\nexport type VersionedHostSignRawResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignRawResponse: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountError`]. */\nexport type VersionedHostSignRawWithLegacyAccountError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadError;\n};\nexport const VersionedHostSignRawWithLegacyAccountError: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountRequest`]. */\nexport type VersionedHostSignRawWithLegacyAccountRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignRawWithLegacyAccountRequest;\n};\nexport const VersionedHostSignRawWithLegacyAccountRequest: Codec;\n/** Versioned envelope for [`HostSignRawWithLegacyAccountResponse`]. */\nexport type VersionedHostSignRawWithLegacyAccountResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostSignPayloadResponse;\n};\nexport const VersionedHostSignRawWithLegacyAccountResponse: Codec;\n/** Versioned envelope for [`HostThemeSubscribeError`]. */\nexport type VersionedHostThemeSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedHostThemeSubscribeError: Codec;\n/** Versioned envelope for [`HostThemeSubscribeItem`]. */\nexport type VersionedHostThemeSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostThemeSubscribeItem;\n};\nexport const VersionedHostThemeSubscribeItem: Codec;\n/** Versioned envelope for [`HostThemeSubscribeRequest`]. */\nexport type VersionedHostThemeSubscribeRequest = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostThemeSubscribeRequest: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationError`]. */\nexport type VersionedHostWorkerBeginOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerOperationError;\n};\nexport const VersionedHostWorkerBeginOperationError: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationRequest`]. */\nexport type VersionedHostWorkerBeginOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerBeginOperationRequest;\n};\nexport const VersionedHostWorkerBeginOperationRequest: Codec;\n/** Versioned envelope for [`HostWorkerBeginOperationResponse`]. */\nexport type VersionedHostWorkerBeginOperationResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerBeginOperationResponse;\n};\nexport const VersionedHostWorkerBeginOperationResponse: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationError`]. */\nexport type VersionedHostWorkerEndOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerOperationError;\n};\nexport const VersionedHostWorkerEndOperationError: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationRequest`]. */\nexport type VersionedHostWorkerEndOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HostWorkerEndOperationRequest;\n};\nexport const VersionedHostWorkerEndOperationRequest: Codec;\n/** Versioned envelope for [`HostWorkerEndOperationResponse`]. */\nexport type VersionedHostWorkerEndOperationResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedHostWorkerEndOperationResponse: Codec;\n/** Pending-operation error. */\nexport type HostWorkerOperationError = \n/**\n * The product is already at the host's per-product limit of open\n * operations.\n */\n{\n tag: \"TooManyOpen\";\n value?: undefined;\n}\n/** Catch-all host failure. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostWorkerOperationError: Codec;\n/** How an image meets the box its modifiers size. */\nexport type ImageFit = \"None\" | \"Fill\" | \"Cover\" | \"Contain\" | \"ScaleDown\";\nexport const ImageFit: Codec;\n/** Properties of an `Image`. */\nexport interface ImageProps {\n /** Where the image bytes come from. */\n source: ImageSource;\n /** Defaults to `Fill`. */\n fit?: ImageFit;\n}\nexport const ImageProps: Codec;\n/** Where image bytes come from. The host fetches them; the tree carries no URL. */\nexport type ImageSource = \n/** A Bulletin chain blob, addressed by its CID. */\n{\n tag: \"Bulletin\";\n value: string;\n}\n/**\n * A file inside the product's executable archive, as a path relative to\n * the archive root.\n */\n | {\n tag: \"Archive\";\n value: string;\n};\nexport const ImageSource: Codec;\n/**\n * A user-imported (legacy) account: public key plus an optional user-chosen\n * display name.\n *\n * Returned by [`HostGetLegacyAccountsResponse`]. Distinct from\n * [`ProductAccount`], which is protocol-derived and never carries a label.\n */\nexport interface LegacyAccount {\n /** The account public key (variable-length bytes). */\n publicKey: HexString;\n /** Optional user-chosen display name. */\n name?: string;\n}\nexport const LegacyAccount: Codec;\n/**\n * Transaction payload for a legacy (non-product) account.\n *\n * Identical to [`ProductAccountTxPayload`] except the signer is a raw\n * 32-byte account identifier.\n */\nexport interface LegacyAccountTxPayload {\n /** Raw 32-byte public key of the legacy account. */\n signer: HexString;\n /** Chain where the transaction will execute. */\n genesisHash: HexString;\n /** SCALE-encoded Call data. */\n callData: HexString;\n /** Transaction extensions supplied by the caller. */\n extensions: Array;\n /**\n * Version of the transaction extensions in `extensions`, as the runtime\n * numbers them.\n */\n txExtVersion: number;\n}\nexport const LegacyAccountTxPayload: Codec;\n/** Layout and styling applied to one node. */\nexport type Modifier = \n/** Outer spacing. */\n{\n tag: \"Margin\";\n value: Dimensions;\n}\n/** Inner spacing. */\n | {\n tag: \"Padding\";\n value: Dimensions;\n}\n/** Background fill. */\n | {\n tag: \"Background\";\n value: Background;\n}\n/** Border. */\n | {\n tag: \"Border\";\n value: BorderStyle;\n}\n/** Fixed height. */\n | {\n tag: \"Height\";\n value: Size;\n}\n/** Fixed width. */\n | {\n tag: \"Width\";\n value: Size;\n}\n/** Minimum width. */\n | {\n tag: \"MinWidth\";\n value: Size;\n}\n/** Minimum height. */\n | {\n tag: \"MinHeight\";\n value: Size;\n}\n/** Fill the available width. */\n | {\n tag: \"FillWidth\";\n value: boolean;\n}\n/** Fill the available height. */\n | {\n tag: \"FillHeight\";\n value: boolean;\n}\n/** 0 is transparent, 255 is opaque. */\n | {\n tag: \"Opacity\";\n value: number;\n}\n/** Compositing mode against what is behind the node. */\n | {\n tag: \"BlendingMode\";\n value: BlendingMode;\n};\nexport const Modifier: Codec;\n/** Outcome of starting a chain-head operation. */\nexport type OperationStartedResult = \n/** The operation was accepted; results arrive as follow events. */\n{\n tag: \"Started\";\n value: {\n operationId: string;\n };\n}\n/** Too many operations are in progress; retry after some complete. */\n | {\n tag: \"LimitReached\";\n value?: undefined;\n};\nexport const OperationStartedResult: Codec;\n/** Where the product draws the signed-in user's own avatar. */\nexport interface OwnAvatarSlot {\n /** Product-chosen id, unique within this placement. */\n slot: number;\n /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */\n rect: AvatarRect;\n /** Visible region the avatar is cut to. */\n clip: AvatarRect;\n}\nexport const OwnAvatarSlot: Codec;\n/**\n * Source for a payment top-up operation.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type PaymentTopUpSource = \n/** Fund from one of the calling product's scoped accounts. */\n{\n tag: \"ProductAccount\";\n value: {\n derivationIndex: DerivationIndex;\n };\n}\n/**\n * Fund from a one-time account represented by its private key. This is a\n * standard account holding public funds, not a coin key.\n */\n | {\n tag: \"PrivateKey\";\n value: {\n sr25519SecretKey: HexString;\n };\n}\n/**\n * Fund directly from coin secret keys. Each key is an sr25519 secret\n * controlling a single coin.\n */\n | {\n tag: \"Coins\";\n value: {\n sr25519SecretKeys: Array;\n };\n};\nexport const PaymentTopUpSource: Codec;\n/** One of the calling product's Pocket cards. */\nexport interface PocketCard {\n /** Card label declared by the product, unique within the product. */\n cardId: string;\n /** Placed by the host itself; removable by neither the user nor the product. */\n privileged: boolean;\n}\nexport const PocketCard: Codec;\n/** Preimage submission error. */\nexport type PreimageSubmitError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const PreimageSubmitError: Codec;\n/** A product account: public key only, no display name. */\nexport interface ProductAccount {\n /** The account public key (variable-length bytes). */\n publicKey: HexString;\n}\nexport const ProductAccount: Codec;\n/**\n * Identifies a product-specific account by combining a dotNS domain name with a\n * derivation index.\n */\nexport interface ProductAccountId {\n /** A dotNS domain name identifier (e.g., `\"my-product.dot\"`). */\n dotNsIdentifier: string;\n /** Account selector within the product subtree. */\n derivationIndex: DerivationIndex;\n}\nexport const ProductAccountId: Codec;\n/**\n * Transaction payload for a product account.\n *\n * Contains everything the host needs to construct a signed extrinsic.\n * The signer is a [`ProductAccountId`]; the host resolves the\n * corresponding key pair through its account management layer.\n */\nexport interface ProductAccountTxPayload {\n /** Product account that will sign the transaction. */\n signer: ProductAccountId;\n /** Chain where the transaction will execute. */\n genesisHash: HexString;\n /** SCALE-encoded Call data. */\n callData: HexString;\n /** Transaction extensions supplied by the caller. */\n extensions: Array;\n /**\n * Version of the transaction extensions in `extensions`, as the runtime\n * numbers them.\n */\n txExtVersion: number;\n /**\n * Contact handles `call_data` names, which the host replaces with the\n * accounts they resolve to before anything is signed or shown.\n *\n * A product declares them rather than passing offsets: an offset is a\n * number it computes about its own encoding and gets wrong silently,\n * while a declared handle is either in the call or it is not, and a host\n * that cannot find one refuses rather than signing a call that names\n * somebody else. A call naming nobody leaves this empty.\n */\n contacts: Array;\n}\nexport const ProductAccountTxPayload: Codec;\n/**\n * A product-scoped proof context: a product and a context within it.\n *\n * Hashed (with a `product//` prefix) into the 32-byte context bound\n * to a ring VRF proof, so contexts cannot collide across products and the same\n * member key under different contexts yields unlinkable aliases.\n */\nexport interface ProductProofContext {\n /** dotNS product identifier (e.g. `\"my-product.dot\"`) scoping the context. */\n productId: string;\n /**\n * Selector distinguishing contexts within the product; expands to the\n * same 32-byte derivation index as [`ProductAccountId::derivation_index`].\n */\n suffix: DerivationIndex;\n}\nexport const ProductProofContext: Codec;\n/** Versioned envelope for [`ProductRendererRenderError`]. */\nexport type VersionedProductRendererRenderError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedProductRendererRenderError: Codec;\n/** Versioned envelope for [`ProductRendererRenderItem`]. */\nexport type VersionedProductRendererRenderItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RendererNode;\n};\nexport const VersionedProductRendererRenderItem: Codec;\n/** Versioned envelope for [`ProductRendererRenderRequest`]. */\nexport type VersionedProductRendererRenderRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: ProductRendererRenderRequest;\n};\nexport const VersionedProductRendererRenderRequest: Codec;\n/** Recipients of one profile reference. Multiple audiences form a union. */\nexport type ProfileAudience = \n/** Every ready Chat App, with profiles scoped to that App. */\n{\n tag: \"ChatApps\";\n value?: undefined;\n}\n/** Contacts of this Chat App, with profiles scoped to that App. */\n | {\n tag: \"App\";\n value: {\n productId: string;\n };\n}\n/** Selected contacts, with profiles available in any receiving App. */\n | {\n tag: \"Contacts\";\n value: {\n handles: Array;\n };\n};\nexport const ProfileAudience: Codec;\n/** A contact named without exposing a handle's account to the product. */\nexport type ProfileContact = \n/** An authenticated Chat network identity already known to the product. */\n{\n tag: \"Peer\";\n value: {\n peerIdentity: HexString;\n };\n}\n/** An opaque host-issued contact selection. */\n | {\n tag: \"Handle\";\n value: {\n handle: ContactHandle;\n };\n};\nexport const ProfileContact: Codec;\n/** Raw data to sign -- either binary bytes or a string message. */\nexport type RawPayload = \n/** Raw binary data to sign. */\n{\n tag: \"Bytes\";\n value: {\n bytes: HexString;\n };\n}\n/** String message to sign. */\n | {\n tag: \"Payload\";\n value: {\n payload: string;\n };\n};\nexport const RawPayload: Codec;\n/** A registered ring-VRF key entry. */\nexport interface RegisteredRingVrfKey {\n /** Stable public name of the key. */\n handle: ProductAccountId;\n /** Rings the owning product declared this key for. */\n rings: Array;\n /** Present when the caller owns the key or requested/granted disclosure. */\n publicKey?: HexString;\n}\nexport const RegisteredRingVrfKey: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyError`]. */\nexport type VersionedRemoteChainHeadBodyError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadBodyError: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyRequest`]. */\nexport type VersionedRemoteChainHeadBodyRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadBodyRequest;\n};\nexport const VersionedRemoteChainHeadBodyRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadBodyResponse`]. */\nexport type VersionedRemoteChainHeadBodyResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadBodyResponse;\n};\nexport const VersionedRemoteChainHeadBodyResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallError`]. */\nexport type VersionedRemoteChainHeadCallError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadCallError: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallRequest`]. */\nexport type VersionedRemoteChainHeadCallRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadCallRequest;\n};\nexport const VersionedRemoteChainHeadCallRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadCallResponse`]. */\nexport type VersionedRemoteChainHeadCallResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadCallResponse;\n};\nexport const VersionedRemoteChainHeadCallResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueError`]. */\nexport type VersionedRemoteChainHeadContinueError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadContinueError: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueRequest`]. */\nexport type VersionedRemoteChainHeadContinueRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadContinueRequest;\n};\nexport const VersionedRemoteChainHeadContinueRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadContinueResponse`]. */\nexport type VersionedRemoteChainHeadContinueResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadContinueResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowError`]. */\nexport type VersionedRemoteChainHeadFollowError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadFollowError: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowItem`]. */\nexport type VersionedRemoteChainHeadFollowItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadFollowItem;\n};\nexport const VersionedRemoteChainHeadFollowItem: Codec;\n/** Versioned envelope for [`RemoteChainHeadFollowRequest`]. */\nexport type VersionedRemoteChainHeadFollowRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadFollowRequest;\n};\nexport const VersionedRemoteChainHeadFollowRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderError`]. */\nexport type VersionedRemoteChainHeadHeaderError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadHeaderError: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderRequest`]. */\nexport type VersionedRemoteChainHeadHeaderRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadHeaderRequest;\n};\nexport const VersionedRemoteChainHeadHeaderRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadHeaderResponse`]. */\nexport type VersionedRemoteChainHeadHeaderResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadHeaderResponse;\n};\nexport const VersionedRemoteChainHeadHeaderResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationError`]. */\nexport type VersionedRemoteChainHeadStopOperationError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadStopOperationError: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationRequest`]. */\nexport type VersionedRemoteChainHeadStopOperationRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStopOperationRequest;\n};\nexport const VersionedRemoteChainHeadStopOperationRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadStopOperationResponse`]. */\nexport type VersionedRemoteChainHeadStopOperationResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadStopOperationResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageError`]. */\nexport type VersionedRemoteChainHeadStorageError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadStorageError: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageRequest`]. */\nexport type VersionedRemoteChainHeadStorageRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStorageRequest;\n};\nexport const VersionedRemoteChainHeadStorageRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadStorageResponse`]. */\nexport type VersionedRemoteChainHeadStorageResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadStorageResponse;\n};\nexport const VersionedRemoteChainHeadStorageResponse: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinError`]. */\nexport type VersionedRemoteChainHeadUnpinError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainHeadUnpinError: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinRequest`]. */\nexport type VersionedRemoteChainHeadUnpinRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainHeadUnpinRequest;\n};\nexport const VersionedRemoteChainHeadUnpinRequest: Codec;\n/** Versioned envelope for [`RemoteChainHeadUnpinResponse`]. */\nexport type VersionedRemoteChainHeadUnpinResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainHeadUnpinResponse: Codec;\n/** Versioned envelope for [`RemoteChainInfoError`]. */\nexport type VersionedRemoteChainInfoError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoError;\n};\nexport const VersionedRemoteChainInfoError: Codec;\n/** Versioned envelope for [`RemoteChainInfoRequest`]. */\nexport type VersionedRemoteChainInfoRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoRequest;\n};\nexport const VersionedRemoteChainInfoRequest: Codec;\n/** Versioned envelope for [`RemoteChainInfoResponse`]. */\nexport type VersionedRemoteChainInfoResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainInfoResponse;\n};\nexport const VersionedRemoteChainInfoResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameError`]. */\nexport type VersionedRemoteChainSpecChainNameError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecChainNameError: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameRequest`]. */\nexport type VersionedRemoteChainSpecChainNameRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecChainNameRequest;\n};\nexport const VersionedRemoteChainSpecChainNameRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecChainNameResponse`]. */\nexport type VersionedRemoteChainSpecChainNameResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecChainNameResponse;\n};\nexport const VersionedRemoteChainSpecChainNameResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashError`]. */\nexport type VersionedRemoteChainSpecGenesisHashError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecGenesisHashError: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashRequest`]. */\nexport type VersionedRemoteChainSpecGenesisHashRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecGenesisHashRequest;\n};\nexport const VersionedRemoteChainSpecGenesisHashRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecGenesisHashResponse`]. */\nexport type VersionedRemoteChainSpecGenesisHashResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecGenesisHashResponse;\n};\nexport const VersionedRemoteChainSpecGenesisHashResponse: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesError`]. */\nexport type VersionedRemoteChainSpecPropertiesError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainSpecPropertiesError: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesRequest`]. */\nexport type VersionedRemoteChainSpecPropertiesRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecPropertiesRequest;\n};\nexport const VersionedRemoteChainSpecPropertiesRequest: Codec;\n/** Versioned envelope for [`RemoteChainSpecPropertiesResponse`]. */\nexport type VersionedRemoteChainSpecPropertiesResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainSpecPropertiesResponse;\n};\nexport const VersionedRemoteChainSpecPropertiesResponse: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastError`]. */\nexport type VersionedRemoteChainTransactionBroadcastError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainTransactionBroadcastError: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastRequest`]. */\nexport type VersionedRemoteChainTransactionBroadcastRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionBroadcastRequest;\n};\nexport const VersionedRemoteChainTransactionBroadcastRequest: Codec;\n/** Versioned envelope for [`RemoteChainTransactionBroadcastResponse`]. */\nexport type VersionedRemoteChainTransactionBroadcastResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionBroadcastResponse;\n};\nexport const VersionedRemoteChainTransactionBroadcastResponse: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopError`]. */\nexport type VersionedRemoteChainTransactionStopError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteChainTransactionStopError: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopRequest`]. */\nexport type VersionedRemoteChainTransactionStopRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteChainTransactionStopRequest;\n};\nexport const VersionedRemoteChainTransactionStopRequest: Codec;\n/** Versioned envelope for [`RemoteChainTransactionStopResponse`]. */\nexport type VersionedRemoteChainTransactionStopResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteChainTransactionStopResponse: Codec;\n/**\n * One remote-operation permission requested by the product (RFC 0002).\n *\n * `ChainSubmit`, `PreimageSubmit`, and `StatementSubmit` are also triggered\n * implicitly by the corresponding business calls when not yet granted.\n */\nexport type RemotePermission = \n/**\n * Outbound HTTP/WebSocket access to a set of domains. External navigation\n * uses [`HostDevicePermissionRequest::OpenUrl`] instead.\n */\n{\n tag: \"Remote\";\n value: {\n domains: Array;\n };\n}\n/**\n * WebRTC access.\n *\n * The container authorizes each peer connection through Rust before its\n * first network method. Later methods on that connection share the same\n * decision, so a one-use grant permits one connection. New connections\n * check current permissions without requiring a page reload.\n *\n * Camera and microphone capture is gated by the OS permission prompts and\n * [`HostDevicePermissionRequest`], not by this permission.\n */\n | {\n tag: \"WebRtc\";\n value?: undefined;\n}\n/** Submitting transactions on behalf of the user via `remote_chain_transaction_broadcast`. */\n | {\n tag: \"ChainSubmit\";\n value?: undefined;\n}\n/** Submitting preimages on behalf of the user via `remote_preimage_submit`. */\n | {\n tag: \"PreimageSubmit\";\n value?: undefined;\n}\n/** Submitting statements on behalf of the user via `remote_statement_store_submit`. */\n | {\n tag: \"StatementSubmit\";\n value?: undefined;\n};\nexport const RemotePermission: Codec;\n/** Versioned envelope for [`RemotePermissionError`]. */\nexport type VersionedRemotePermissionError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemotePermissionError: Codec;\n/** Versioned envelope for [`RemotePermissionRequest`]. */\nexport type VersionedRemotePermissionRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePermissionRequest;\n};\nexport const VersionedRemotePermissionRequest: Codec;\n/** Versioned envelope for [`RemotePermissionResponse`]. */\nexport type VersionedRemotePermissionResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePermissionResponse;\n};\nexport const VersionedRemotePermissionResponse: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeError`]. */\nexport type VersionedRemotePreimageLookupSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemotePreimageLookupSubscribeError: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeItem`]. */\nexport type VersionedRemotePreimageLookupSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePreimageLookupSubscribeItem;\n};\nexport const VersionedRemotePreimageLookupSubscribeItem: Codec;\n/** Versioned envelope for [`RemotePreimageLookupSubscribeRequest`]. */\nexport type VersionedRemotePreimageLookupSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemotePreimageLookupSubscribeRequest;\n};\nexport const VersionedRemotePreimageLookupSubscribeRequest: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitError`]. */\nexport type VersionedRemotePreimageSubmitError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: PreimageSubmitError;\n};\nexport const VersionedRemotePreimageSubmitError: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitRequest`]. */\nexport type VersionedRemotePreimageSubmitRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedRemotePreimageSubmitRequest: Codec;\n/** Versioned envelope for [`RemotePreimageSubmitResponse`]. */\nexport type VersionedRemotePreimageSubmitResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: HexString;\n};\nexport const VersionedRemotePreimageSubmitResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedError`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofError;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedRequest`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: Statement;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofAuthorizedResponse`]. */\nexport type VersionedRemoteStatementStoreCreateProofAuthorizedResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofResponse;\n};\nexport const VersionedRemoteStatementStoreCreateProofAuthorizedResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofError`]. */\nexport type VersionedRemoteStatementStoreCreateProofError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofError;\n};\nexport const VersionedRemoteStatementStoreCreateProofError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofRequest`]. */\nexport type VersionedRemoteStatementStoreCreateProofRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofRequest;\n};\nexport const VersionedRemoteStatementStoreCreateProofRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreCreateProofResponse`]. */\nexport type VersionedRemoteStatementStoreCreateProofResponse = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreCreateProofResponse;\n};\nexport const VersionedRemoteStatementStoreCreateProofResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitError`]. */\nexport type VersionedRemoteStatementStoreSubmitError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteStatementStoreSubmitError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitRequest`]. */\nexport type VersionedRemoteStatementStoreSubmitRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: SignedStatement;\n};\nexport const VersionedRemoteStatementStoreSubmitRequest: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubmitResponse`]. */\nexport type VersionedRemoteStatementStoreSubmitResponse = \n/** Version 1 (no payload). */\n{\n tag: \"V1\";\n value?: undefined;\n};\nexport const VersionedRemoteStatementStoreSubmitResponse: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeError`]. */\nexport type VersionedRemoteStatementStoreSubscribeError = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: GenericError;\n};\nexport const VersionedRemoteStatementStoreSubscribeError: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeItem`]. */\nexport type VersionedRemoteStatementStoreSubscribeItem = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreSubscribeItem;\n};\nexport const VersionedRemoteStatementStoreSubscribeItem: Codec;\n/** Versioned envelope for [`RemoteStatementStoreSubscribeRequest`]. */\nexport type VersionedRemoteStatementStoreSubscribeRequest = \n/** Version 1 payload. */\n{\n tag: \"V1\";\n value: RemoteStatementStoreSubscribeRequest;\n};\nexport const VersionedRemoteStatementStoreSubscribeRequest: Codec;\n/** Where a product-rendered body lives, and the id that names it there. */\nexport type RenderContext = \n/** A message in a chat room. */\n{\n tag: \"ChatMessage\";\n value: {\n roomId: string;\n messageId: string;\n messageType: string;\n };\n}\n/** A candidate answered to an input query. */\n | {\n tag: \"InputWidget\";\n value: {\n candidateId: string;\n };\n}\n/** A card face in the host's Pocket collection. */\n | {\n tag: \"PocketCard\";\n value: {\n cardId: string;\n };\n};\nexport const RenderContext: Codec;\n/**\n * A node in a product-rendered tree. Container variants recurse through\n * `children`.\n */\nexport type RendererNode = \n/** Draws nothing. */\n{\n tag: \"Nil\";\n value?: undefined;\n}\n/** A text run. */\n | {\n tag: \"String\";\n value: {\n text: string;\n };\n}\n/** Generic container. */\n | {\n tag: \"Box\";\n value: {\n modifiers: Array;\n props: BoxProps;\n children: Array;\n };\n}\n/** Vertical layout. */\n | {\n tag: \"Column\";\n value: {\n modifiers: Array;\n props: ColumnProps;\n children: Array;\n };\n}\n/** Horizontal layout. */\n | {\n tag: \"Row\";\n value: {\n modifiers: Array;\n props: RowProps;\n children: Array;\n };\n}\n/** Flexible space. */\n | {\n tag: \"Spacer\";\n value: {\n modifiers: Array;\n };\n}\n/** Styled text. */\n | {\n tag: \"Text\";\n value: {\n modifiers: Array;\n props: TextProps;\n children: Array;\n };\n}\n/** Interactive button. */\n | {\n tag: \"Button\";\n value: {\n modifiers: Array;\n props: ButtonProps;\n children: Array;\n };\n}\n/** Single-line text input. */\n | {\n tag: \"TextField\";\n value: {\n modifiers: Array;\n props: TextFieldProps;\n };\n}\n/** Image, sized by modifiers. */\n | {\n tag: \"Image\";\n value: {\n modifiers: Array;\n props: ImageProps;\n };\n}\n/** Applies its effect to its children. */\n | {\n tag: \"Effect\";\n value: {\n props: EffectProps;\n children: Array;\n };\n};\nexport const RendererNode: Codec;\n/** Error from [`crate::api::ResourceAllocation::request`]. */\nexport type ResourceAllocationError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const ResourceAllocationError: Codec;\n/**\n * Locates a ring for ring VRF operations using only identifiers that are\n * stable across membership changes.\n */\nexport interface RingLocation {\n /** Genesis hash of the chain hosting the ring. */\n chainId: HexString;\n /** Path addressing the ring within the chain. */\n junctions: Array;\n}\nexport const RingLocation: Codec;\n/** A single step in a [`RingLocation`] path, addressing a ring within a chain. */\nexport type RingLocationJunction = \n/** Pallet instance hosting the ring collection. */\n{\n tag: \"PalletInstance\";\n value: number;\n}\n/** Ring collection identifier within the pallet. */\n | {\n tag: \"CollectionId\";\n value: HexString;\n};\nexport const RingLocationJunction: Codec;\n/** How much of a registry entry the caller asks for. */\nexport type RingVrfKeyDisclosure = \"Anonymized\" | \"PublicKey\";\nexport const RingVrfKeyDisclosure: Codec;\n/** Properties of a `Row`. */\nexport interface RowProps {\n /** Cross-axis alignment of children. */\n verticalAlignment?: VerticalAlignment;\n /** Main-axis distribution of children. */\n horizontalArrangement?: Arrangement;\n}\nexport const RowProps: Codec;\n/** One entry of a runtime's supported API list. */\nexport interface RuntimeApi {\n /** Runtime API name. */\n name: string;\n /** Runtime API version. */\n version: number;\n}\nexport const RuntimeApi: Codec;\n/** Runtime version information for a block's runtime. */\nexport interface RuntimeSpec {\n /** Specification name. */\n specName: string;\n /** Implementation name. */\n implName: string;\n /** Spec version number. */\n specVersion: number;\n /** Implementation version. */\n implVersion: number;\n /** Transaction format version. */\n transactionVersion?: number;\n /** Supported runtime APIs. */\n apis: Array;\n}\nexport const RuntimeSpec: Codec;\n/** Runtime attached to follow events, either a decoded spec or a decode error. */\nexport type RuntimeType = \n/** Runtime spec decoded successfully. */\n{\n tag: \"Valid\";\n value: RuntimeSpec;\n}\n/** The runtime could not be decoded. */\n | {\n tag: \"Invalid\";\n value: {\n error: string;\n };\n};\nexport const RuntimeType: Codec;\n/** Outline of a background or border. */\nexport type Shape = \n/** Rounded corners with the given radius. */\n{\n tag: \"Rounded\";\n value: Size;\n}\n/** Circular shape. */\n | {\n tag: \"Circle\";\n value?: undefined;\n}\n/** Square corners. */\n | {\n tag: \"Square\";\n value?: undefined;\n};\nexport const Shape: Codec;\n/** A statement with a required (not optional) proof. */\nexport interface SignedStatement {\n /** Required cryptographic proof. */\n proof: StatementProof;\n /** Optional decryption key. */\n decryptionKey?: HexString;\n /** Optional Unix timestamp expiry. */\n expiry?: bigint;\n /** Optional channel. */\n channel?: HexString;\n /** [u8; 32] tags. */\n topics: Array;\n /** Optional data payload. */\n data?: HexString;\n}\nexport const SignedStatement: Codec;\n/** A size in logical pixels, SCALE-encoded as `Compact`. */\nexport type Size = number | bigint;\nexport const Size: Codec;\n/** A statement with optional proof and metadata. */\nexport interface Statement {\n /** Optional cryptographic proof. */\n proof?: StatementProof;\n /** Optional decryption key. */\n decryptionKey?: HexString;\n /** Optional Unix timestamp expiry. */\n expiry?: bigint;\n /** Optional channel. */\n channel?: HexString;\n /** [u8; 32] tags. */\n topics: Array;\n /** Optional data payload. */\n data?: HexString;\n}\nexport const Statement: Codec;\n/** Cryptographic proof for a statement. */\nexport type StatementProof = \n/** Sr25519 signature proof. */\n{\n tag: \"Sr25519\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** Ed25519 signature proof. */\n | {\n tag: \"Ed25519\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** ECDSA signature proof. */\n | {\n tag: \"Ecdsa\";\n value: {\n signature: HexString;\n signer: HexString;\n };\n}\n/** On-chain event proof. */\n | {\n tag: \"OnChain\";\n value: {\n who: HexString;\n blockHash: HexString;\n event: bigint;\n };\n};\nexport const StatementProof: Codec;\n/** A single key query within a chain-head storage request. */\nexport interface StorageQueryItem {\n /** Storage key to query. */\n key: HexString;\n /** What to return. */\n queryType: StorageQueryType;\n}\nexport const StorageQueryItem: Codec;\n/** What a chain-head storage query returns for a key. */\nexport type StorageQueryType = \"Value\" | \"Hash\" | \"ClosestDescendantMerkleValue\" | \"DescendantsValues\" | \"DescendantsHashes\";\nexport const StorageQueryType: Codec;\n/** Result for one queried storage key. */\nexport interface StorageResultItem {\n /** The queried key. */\n key: HexString;\n /** Value, if requested. */\n value?: HexString;\n /** Hash, if requested. */\n hash?: HexString;\n /** Merkle value, if requested. */\n closestDescendantMerkleValue?: HexString;\n}\nexport const StorageResultItem: Codec;\n/** Properties of a `TextField`. */\nexport interface TextFieldProps {\n /** Current value. */\n text: string;\n /** Shown when the value is empty. */\n placeholder?: string;\n /** Field label. */\n label?: string;\n /** Whether the field accepts input. Absent leaves the default to the host. */\n enabled?: boolean;\n /**\n * Action triggered on every value change. The action carries the new\n * value as UTF-8 bytes, with no length prefix.\n */\n valueChangeAction?: string;\n}\nexport const TextFieldProps: Codec;\n/** Properties of a `Text`. */\nexport interface TextProps {\n /** Typography preset. */\n style?: TypographyStyle;\n /** Text color. */\n color?: ColorToken;\n}\nexport const TextProps: Codec;\n/** Identifies a named theme. */\nexport type ThemeName = \n/** A custom named theme. */\n{\n tag: \"Custom\";\n value: string;\n}\n/** The host's default theme. */\n | {\n tag: \"Default\";\n value?: undefined;\n};\nexport const ThemeName: Codec;\n/** Light or dark variant. */\nexport type ThemeVariant = \"Light\" | \"Dark\";\nexport const ThemeVariant: Codec;\n/** A signed extension for a transaction payload. */\nexport interface TxPayloadExtension {\n /** Extension name (e.g., `\"CheckSpecVersion\"`). */\n id: string;\n /** SCALE-encoded extra data (in extrinsic body). */\n extra: HexString;\n /** SCALE-encoded implicit data (signed, not in body). */\n additionalSigned: HexString;\n}\nexport const TxPayloadExtension: Codec;\n/** Typography presets, resolved by the host's design system. */\nexport type TypographyStyle = \"HeadlineLarge\" | \"TitleMediumRegular\" | \"BodyLargeRegular\" | \"BodyMediumRegular\" | \"BodySmallRegular\";\nexport const TypographyStyle: Codec;\n/** One avatar the product draws for a chat contact. */\nexport interface ContactAvatarSlot {\n /**\n * Product-chosen id, stable for one on-screen avatar (a list row, a\n * header). The host uses it only to keep what it draws stable across\n * updates.\n */\n slot: number;\n /** The contact's authenticated root identity, as the chat API names it. */\n peerIdentity: HexString;\n /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */\n rect: AvatarRect;\n /** Visible region the avatar is cut to, such as the scroll area. */\n clip: AvatarRect;\n}\nexport const ContactAvatarSlot: Codec;\n/** User's authentication state. */\nexport type HostAccountConnectionStatusSubscribeItem = \"Disconnected\" | \"Connected\";\nexport const HostAccountConnectionStatusSubscribeItem: Codec;\n/** Error returned when ring VRF proof creation fails. */\nexport type HostAccountCreateProofError = \n/** Ring not available at the specified location. */\n{\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** The registered member key is not a member of the requested ring. */\n | {\n tag: \"NotMember\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The key handle is not registered for the requested ring. */\n | {\n tag: \"KeyNotInRing\";\n value?: undefined;\n}\n/** The foreign key owner has not allowlisted the caller. */\n | {\n tag: \"NotAllowlisted\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountCreateProofError: Codec;\n/** Request to create a ring VRF proof. */\nexport interface HostAccountCreateProofRequest {\n /** Ring-VRF key handle naming the member key to use. */\n keyHandle: ProductAccountId;\n /** Product-scoped context the derived alias is bound to. */\n context: ProductProofContext;\n /** Ring to generate the proof against. */\n ringLocation: RingLocation;\n /** Opaque message bound into the proof. */\n message: HexString;\n}\nexport const HostAccountCreateProofRequest: Codec;\n/**\n * Response containing a ring VRF proof and the values needed to verify it\n * against a downstream precompile.\n */\nexport interface HostAccountCreateProofResponse {\n /** Variable-length ring VRF proof bytes. */\n proof: HexString;\n /** Alias derived for the request's context. */\n contextualAlias: ContextualAlias;\n /** Index of the selected member key within the ring. */\n ringIndex: number;\n /** Ring revision the proof was generated against. */\n ringRevision: number;\n}\nexport const HostAccountCreateProofResponse: Codec;\n/** Error returned when contextual alias derivation fails. */\nexport type HostAccountGetAliasError = \n/** Ring not available at the specified location. */\n{\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** The registered member key is not a member of the requested ring. */\n | {\n tag: \"NotMember\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The key handle is not registered for the requested ring. */\n | {\n tag: \"KeyNotInRing\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountGetAliasError: Codec;\n/** Request to retrieve the contextual alias for a context and ring. */\nexport interface HostAccountGetAliasRequest {\n /** Ring-VRF key handle naming the member key to use. */\n keyHandle: ProductAccountId;\n /** Product-scoped context to derive the alias for. */\n context: ProductProofContext;\n /** Ring whose member key the host should use; matches `create_proof`. */\n ringLocation: RingLocation;\n}\nexport const HostAccountGetAliasRequest: Codec;\n/** Error returned when credential/account requests fail. */\nexport type HostAccountGetError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected the request. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Domain identifier is invalid. */\n | {\n tag: \"DomainNotValid\";\n value?: undefined;\n}\n/** Catch-all error with reason. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountGetError: Codec;\n/** Request to retrieve a product-scoped account. */\nexport interface HostAccountGetRequest {\n /** Product account to retrieve. */\n productAccountId: ProductAccountId;\n}\nexport const HostAccountGetRequest: Codec;\n/** Response containing a product-scoped account. */\nexport interface HostAccountGetResponse {\n /** Retrieved product account. */\n account: ProductAccount;\n}\nexport const HostAccountGetResponse: Codec;\n/** Error returned when listing ring-VRF keys fails. */\nexport type HostAccountListRingVrfKeysError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountListRingVrfKeysError: Codec;\n/** Request to list registered ring-VRF keys for an owner product. */\nexport interface HostAccountListRingVrfKeysRequest {\n /** Product whose registry entries should be listed. */\n owner: string;\n /** Disclosure level requested by the caller. */\n disclosure: RingVrfKeyDisclosure;\n}\nexport const HostAccountListRingVrfKeysRequest: Codec;\n/** Error returned when ring-VRF key registration fails. */\nexport type HostAccountRegisterRingVrfKeyError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Ring not available at the specified location. */\n | {\n tag: \"RingNotFound\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountRegisterRingVrfKeyError: Codec;\n/** Request to register a ring-VRF key owned by the calling product. */\nexport interface HostAccountRegisterRingVrfKeyRequest {\n /** Key derivation index within the caller's ring-VRF domain. */\n index: DerivationIndex;\n /** Ring this key is declared for. */\n ring: RingLocation;\n}\nexport const HostAccountRegisterRingVrfKeyRequest: Codec;\n/** Error returned when direct ring-VRF key signing fails. */\nexport type HostAccountRingVrfSignError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** The key handle is not registered. */\n | {\n tag: \"KeyNotRegistered\";\n value?: undefined;\n}\n/** The foreign key owner has not allowlisted the caller. */\n | {\n tag: \"NotAllowlisted\";\n value?: undefined;\n}\n/** User or host rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountRingVrfSignError: Codec;\n/** Request to sign bytes with a registered ring-VRF key. */\nexport interface HostAccountRingVrfSignRequest {\n /** Registered key handle. */\n keyHandle: ProductAccountId;\n /** Opaque message to sign. */\n message: HexString;\n}\nexport const HostAccountRingVrfSignRequest: Codec;\n/** Error returned when VRF signing fails. */\nexport type HostAccountSignVrfError = \n/** User is not logged in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** User or host rejected the signing confirmation. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostAccountSignVrfError: Codec;\n/**\n * Request to produce an sr25519 VRF signature from a product account over a\n * caller-supplied Merlin transcript.\n */\nexport interface HostAccountSignVrfRequest {\n /** Account whose key signs the VRF. */\n account: ProductAccountId;\n /** Root domain-separation label: `Transcript::new(transcript_label)`. */\n transcriptLabel: HexString;\n /** Transcript items replayed in order as `append_message(label, value)`. */\n items: Array;\n}\nexport const HostAccountSignVrfRequest: Codec;\n/** A chat action received from the host. */\nexport interface HostChatActionSubscribeItem {\n /** Room where the action occurred. */\n roomId: string;\n /** Peer who initiated the action. */\n peer: string;\n /** The action payload. */\n payload: ChatActionPayload;\n}\nexport const HostChatActionSubscribeItem: Codec;\n/** Chat room registration error. */\nexport type HostChatCreateRoomError = \n/** Not allowed. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatCreateRoomError: Codec;\n/** Request to create a chat room. */\nexport interface HostChatCreateRoomRequest {\n /** Unique room identifier. */\n roomId: string;\n /** Room display name. */\n name: string;\n /** URL or base64 image. */\n icon: string;\n}\nexport const HostChatCreateRoomRequest: Codec;\n/** Result of a room registration. */\nexport interface HostChatCreateRoomResponse {\n /** `New` or `Exists`. */\n status: ChatRoomRegistrationStatus;\n}\nexport const HostChatCreateRoomResponse: Codec;\n/** Item containing the current chat rooms. */\nexport interface HostChatListSubscribeItem {\n /** Chat rooms the product participates in. */\n rooms: Array;\n}\nexport const HostChatListSubscribeItem: Codec;\n/** Chat message posting error. */\nexport type HostChatPostMessageError = \n/** Message exceeded size limit. */\n{\n tag: \"MessageTooLarge\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatPostMessageError: Codec;\n/** Request to post a message to a chat room. */\nexport interface HostChatPostMessageRequest {\n /** Room to post to. */\n roomId: string;\n /** Message content. */\n payload: ChatMessageContent;\n}\nexport const HostChatPostMessageRequest: Codec;\n/** Result of posting a message. */\nexport interface HostChatPostMessageResponse {\n /**\n * Host-assigned message id, and the correlation key for any action the\n * message carries: a trigger names it in [`ActionTrigger::message_id`].\n */\n messageId: string;\n}\nexport const HostChatPostMessageResponse: Codec;\n/** Chat bot registration error. */\nexport type HostChatRegisterBotError = \n/** Not allowed. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostChatRegisterBotError: Codec;\n/** Request to register a chat bot. */\nexport interface HostChatRegisterBotRequest {\n /** Unique bot identifier. */\n botId: string;\n /** Bot display name. */\n name: string;\n /** URL or base64 image. */\n icon: string;\n}\nexport const HostChatRegisterBotRequest: Codec;\n/** Result of a bot registration. */\nexport interface HostChatRegisterBotResponse {\n /** `New` or `Exists`. */\n status: ChatBotRegistrationStatus;\n}\nexport const HostChatRegisterBotResponse: Codec;\n/** Request to create a cheque from a local purse to a receivable. */\nexport interface HostCoinPaymentCreateChequeRequest {\n /** Source purse. */\n from: number;\n /** Destination receivable. */\n to: HexString;\n /** Payment amount. */\n amount: number;\n}\nexport const HostCoinPaymentCreateChequeRequest: Codec;\n/** Created cheque response. */\nexport interface HostCoinPaymentCreateChequeResponse {\n /** Encrypted cheque. */\n cheque: CoinPaymentCheque;\n}\nexport const HostCoinPaymentCreateChequeResponse: Codec;\n/** Request to create a new firewalled CoinPayment purse. */\nexport interface HostCoinPaymentCreatePurseRequest {\n /** Human-readable purse name. */\n name: string;\n}\nexport const HostCoinPaymentCreatePurseRequest: Codec;\n/** Created purse identifier. */\nexport interface HostCoinPaymentCreatePurseResponse {\n /** Assigned purse identifier. */\n purse: number;\n}\nexport const HostCoinPaymentCreatePurseResponse: Codec;\n/** Request to create a fresh receivable for a purse. */\nexport interface HostCoinPaymentCreateReceivableRequest {\n /** Target purse for future deposits. */\n into: number;\n}\nexport const HostCoinPaymentCreateReceivableRequest: Codec;\n/** Created receivable response. */\nexport interface HostCoinPaymentCreateReceivableResponse {\n /** Receivable public key. */\n receivable: HexString;\n}\nexport const HostCoinPaymentCreateReceivableResponse: Codec;\n/** Request to delete a purse after draining its balance. */\nexport interface HostCoinPaymentDeletePurseRequest {\n /** Purse to delete. */\n target: number;\n /** Purse that receives drained funds. */\n drainInto: number;\n}\nexport const HostCoinPaymentDeletePurseRequest: Codec;\n/** Request to deposit a cheque into the purse associated with its receivable. */\nexport interface HostCoinPaymentDepositRequest {\n /** Cheque to deposit. */\n cheque: CoinPaymentCheque;\n}\nexport const HostCoinPaymentDepositRequest: Codec;\n/** Stream item for `host_coin_payment_listen_for`. */\nexport type HostCoinPaymentListenForItem = \n/** Handoff channel suitable for inclusion in an invoice. */\n{\n tag: \"Channel\";\n value: CoinPaymentTransmissionChannel;\n}\n/** Cheque received through the handoff channel. */\n | {\n tag: \"Cheque\";\n value: CoinPaymentCheque;\n};\nexport const HostCoinPaymentListenForItem: Codec;\n/** Request to listen for a cheque delivered to a receivable. */\nexport interface HostCoinPaymentListenForRequest {\n /** Receivable to listen for. */\n receivable: HexString;\n}\nexport const HostCoinPaymentListenForRequest: Codec;\n/** Request to query product-visible purse metadata. */\nexport interface HostCoinPaymentQueryPurseRequest {\n /** Purse to query. */\n purse: number;\n}\nexport const HostCoinPaymentQueryPurseRequest: Codec;\n/** Product-visible purse metadata response. */\nexport interface HostCoinPaymentQueryPurseResponse {\n /** Purse information. */\n info: CoinPaymentPurseInfo;\n}\nexport const HostCoinPaymentQueryPurseResponse: Codec;\n/** Request to transfer balance between local purses. */\nexport interface HostCoinPaymentRebalancePurseRequest {\n /** Source purse. */\n from: number;\n /** Destination purse. */\n to: number;\n /** Amount to move. */\n amount: number;\n}\nexport const HostCoinPaymentRebalancePurseRequest: Codec;\n/** Request to refund coins associated with a receivable. */\nexport interface HostCoinPaymentRefundRequest {\n /** Receivable to refund. */\n receivable: HexString;\n}\nexport const HostCoinPaymentRefundRequest: Codec;\n/**\n * Error returned by the contact picker.\n *\n * Neither a dismissal nor an empty contact list is an error; both are outcomes.\n * A host that serves no picker at all answers `Unsupported` at the framework\n * level rather than through this enum.\n */\nexport type HostContactsPickError = \n/** No active session. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostContactsPickError: Codec;\n/** Failure before a complete selection can be confirmed. */\nexport type HostContactsPickManyError = \n/** No active session, or the session changed while choosing. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** The selection exceeds the bound or contains an unresolved handle. */\n | {\n tag: \"InvalidSelection\";\n value?: undefined;\n}\n/** The host could not complete the picker. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostContactsPickManyError: Codec;\n/** Open the host's picker with the product's current selection. */\nexport interface HostContactsPickManyRequest {\n /**\n * At most 256 handles. Duplicates are ignored; an unresolved handle\n * rejects the entire request rather than changing the selected audience.\n */\n selected: Array;\n}\nexport const HostContactsPickManyRequest: Codec;\n/** The user's confirmed selection or reason no selection was made. */\nexport interface HostContactsPickManyResponse {\n /** How the picker ended. */\n outcome: ContactPickManyOutcome;\n}\nexport const HostContactsPickManyResponse: Codec;\n/**\n * Request to open the host's contact picker.\n *\n * Carries no arguments: the host owns the overlay, draws it from its own chat\n * contacts, and nothing the product supplies appears in it.\n */\nexport interface HostContactsPickRequest {\n}\nexport const HostContactsPickRequest: Codec;\n/** Outcome of a pick. */\nexport interface HostContactsPickResponse {\n /** How the pick ended. */\n outcome: ContactPickOutcome;\n}\nexport const HostContactsPickResponse: Codec;\n/** Placement failure, never the availability of any individual contact. */\nexport type HostContactsPlaceLabelsError = \n/** The host cannot draw labels over the product surface. */\n{\n tag: \"Unsupported\";\n value?: undefined;\n}\n/** No active session, or it changed while placing labels. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** The surface, slot count, slot ids or rectangles are invalid. */\n | {\n tag: \"InvalidPlacement\";\n value?: undefined;\n}\n/** The host could not place the labels. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostContactsPlaceLabelsError: Codec;\n/** Replace the contact names drawn over a product's surface. */\nexport interface HostContactsPlaceLabelsRequest {\n /** Surface width in framebuffer pixels or web viewport CSS pixels, 1 to 16384. */\n surfaceWidth: number;\n /** Surface height in the same units, 1 to 16384. */\n surfaceHeight: number;\n /** At most 256 slots. Empty clears the previous placement. */\n slots: Array;\n}\nexport const HostContactsPlaceLabelsRequest: Codec;\n/** Acknowledges placement without revealing any contact's name or availability. */\nexport interface HostContactsPlaceLabelsResponse {\n}\nexport const HostContactsPlaceLabelsResponse: Codec;\n/** Transaction creation error. */\nexport type HostCreateTransactionError = \n/** Payload could not be deserialized. */\n{\n tag: \"FailedToDecode\";\n value?: undefined;\n}\n/** User rejected. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Unsupported payload version or extension. */\n | {\n tag: \"NotSupported\";\n value: {\n reason: string;\n };\n}\n/** Not authenticated. */\n | {\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n}\n/**\n * A declared contact handle names nobody this host has a contact for, or\n * does not appear in the call it was declared for, or a handle appears in\n * the call without being declared. One refusal for all three, because\n * telling them apart would say whether a handle is current.\n */\n | {\n tag: \"UnknownContact\";\n value?: undefined;\n};\nexport const HostCreateTransactionError: Codec;\n/** Response containing a created transaction. */\nexport interface HostCreateTransactionResponse {\n /**\n * SCALE-encoded transaction, signed unless the request supplied its own\n * V5 `VerifyMultiSignature` extension.\n */\n transaction: HexString;\n}\nexport const HostCreateTransactionResponse: Codec;\n/** Response containing a transaction created with a non-product account. */\nexport interface HostCreateTransactionWithLegacyAccountResponse {\n /**\n * SCALE-encoded transaction, signed unless the request supplied its own\n * V5 `VerifyMultiSignature` extension.\n */\n transaction: HexString;\n}\nexport const HostCreateTransactionWithLegacyAccountResponse: Codec;\n/** Error from [`crate::api::Entropy::derive`] (RFC 0007). */\nexport type HostDeriveEntropyError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostDeriveEntropyError: Codec;\n/**\n * Request to derive deterministic per-product entropy (RFC 0007).\n *\n * The host derives 32 bytes from product-scoped seed material and `context`.\n * Repeated calls with the same `context` for the same product yield the same\n * entropy.\n */\nexport interface HostDeriveEntropyRequest {\n /** Domain-separated derivation context. */\n context: HexString;\n}\nexport const HostDeriveEntropyRequest: Codec;\n/** Response carrying 32 bytes of deterministically derived entropy. */\nexport interface HostDeriveEntropyResponse {\n /** 32 bytes of derived entropy. */\n entropy: HexString;\n}\nexport const HostDeriveEntropyResponse: Codec;\n/**\n * Device-capability permission requested from the host (RFC 0002).\n *\n * Lasting grants and denials survive app restarts. A host may also offer a\n * one-use grant, held in memory until a permission-gated operation consumes it.\n *\n * That decision is about this product. The OS grant behind it belongs to the\n * host application and can move independently, so a host that can read OS\n * state has the capability resolve only while both allow it: a stored grant\n * whose OS grant was revoked answers `granted: false` without a prompt. An OS\n * grant that is merely undetermined does not change the answer, because the OS\n * resolves its own gate when the capability is used.\n */\nexport type HostDevicePermissionRequest = \"Notifications\" | \"Camera\" | \"Microphone\" | \"Bluetooth\" | \"NFC\" | \"Location\" | \"Clipboard\" | \"OpenUrl\" | \"Biometrics\";\nexport const HostDevicePermissionRequest: Codec;\n/** Outcome of a device-permission request. */\nexport interface HostDevicePermissionResponse {\n /** Whether the permission was granted. */\n granted: boolean;\n}\nexport const HostDevicePermissionResponse: Codec;\n/** Request to query whether a feature is supported by the host. */\nexport type HostFeatureSupportedRequest = \n/** Ask whether the host can interact with the chain identified by genesis hash. */\n{\n tag: \"Chain\";\n value: {\n genesisHash: HexString;\n };\n};\nexport const HostFeatureSupportedRequest: Codec;\n/** Response to a feature-support query. */\nexport interface HostFeatureSupportedResponse {\n /** Whether the feature is supported. */\n supported: boolean;\n}\nexport const HostFeatureSupportedResponse: Codec;\n/** Response containing all legacy (user-imported) accounts owned by the user. */\nexport interface HostGetLegacyAccountsResponse {\n /** Legacy accounts. */\n accounts: Array;\n}\nexport const HostGetLegacyAccountsResponse: Codec;\n/** Response containing the product context bound to the current host runtime. */\nexport interface HostGetProductContextResponse {\n /** Full canonical identifier used for authorization and account derivation. */\n productId: string;\n}\nexport const HostGetProductContextResponse: Codec;\n/** Error from [`crate::api::Account::get_user_id`]. */\nexport type HostGetUserIdError = \n/** User denied the identity disclosure request. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** User is not logged in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostGetUserIdError: Codec;\n/** The user's primary DotNS account identity. */\nexport interface HostGetUserIdResponse {\n /** The user's primary DotNS username. */\n primaryUsername: string;\n}\nexport const HostGetUserIdResponse: Codec;\n/**\n * Error from [`crate::api::System::handshake`] (RFC 0009).\n *\n * The handshake is the first call on a fresh connection; it does not require\n * user authentication and is used to negotiate the wire codec version.\n */\nexport type HostHandshakeError = \n/** Host did not complete the handshake in time. */\n{\n tag: \"Timeout\";\n value?: undefined;\n}\n/** Host does not speak the codec version requested by the product. */\n | {\n tag: \"UnsupportedProtocolVersion\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: GenericError;\n};\nexport const HostHandshakeError: Codec;\n/** Wire-codec negotiation payload sent by the product (RFC 0009). */\nexport interface HostHandshakeRequest {\n /** Wire codec version requested by the product. */\n codecVersion: number;\n}\nexport const HostHandshakeRequest: Codec;\n/** A change to a subscribed storage key, pushed to the subscriber. */\nexport interface HostLocalStorageChangeItem {\n /** Value after the change. `Some` on write, `None` after clear. */\n value?: HexString;\n}\nexport const HostLocalStorageChangeItem: Codec;\n/** Request to clear a local storage key. */\nexport interface HostLocalStorageClearRequest {\n /** Storage key to clear. */\n key: string;\n}\nexport const HostLocalStorageClearRequest: Codec;\n/** Local storage operation error. */\nexport type V01HostLocalStorageReadError = \n/** Storage quota exceeded. */\n{\n tag: \"Full\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const V01HostLocalStorageReadError: Codec;\n/** Request to read a local storage value. */\nexport interface V01HostLocalStorageReadRequest {\n /** Storage key to read. */\n key: string;\n}\nexport const V01HostLocalStorageReadRequest: Codec;\n/** Response containing an optional local storage value. */\nexport interface HostLocalStorageReadResponse {\n /** Stored value, if present. */\n value?: HexString;\n}\nexport const HostLocalStorageReadResponse: Codec;\n/** Request to subscribe to changes of one local storage key. */\nexport interface HostLocalStorageSubscribeRequest {\n /** Storage key to observe. */\n key: string;\n}\nexport const HostLocalStorageSubscribeRequest: Codec;\n/** Request to write a value into local storage. */\nexport interface HostLocalStorageWriteRequest {\n /** Storage key to write. */\n key: string;\n /** Value to store at the key. */\n value: HexString;\n}\nexport const HostLocalStorageWriteRequest: Codec;\n/** Locale the host currently presents its interface in, pushed to subscribers. */\nexport interface V01HostLocaleSubscribeItem {\n /**\n * BCP 47 language tag, such as `en`, `pt-BR` or `zh-Hans`. The set is\n * open: a product that does not ship the tag chooses its own fallback.\n */\n languageTag: string;\n}\nexport const V01HostLocaleSubscribeItem: Codec;\n/** Error from [`crate::api::System::navigate_to`]. */\nexport type HostNavigateToError = \n/**\n * The target host is not authorized for outbound access: the user answered\n * no to the prompt, a stored decision already refused it, or no prompt\n * could be put to the user.\n */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostNavigateToError: Codec;\n/** Request to navigate the host to an external URL. */\nexport interface HostNavigateToRequest {\n /** URL to open. */\n url: string;\n}\nexport const HostNavigateToRequest: Codec;\n/**\n * Error from [`crate::api::Payment::balance_subscribe`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentBalanceSubscribeError = \n/** User denied the balance disclosure request. */\n{\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentBalanceSubscribeError: Codec;\n/**\n * Current payment balance state pushed to subscribers.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport interface HostPaymentBalanceSubscribeItem {\n /** Balance that can be spent right now. */\n available: bigint;\n}\nexport const HostPaymentBalanceSubscribeItem: Codec;\n/** Request to subscribe to payment balance updates. */\nexport interface HostPaymentBalanceSubscribeRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n purse?: number;\n}\nexport const HostPaymentBalanceSubscribeRequest: Codec;\n/**\n * Error from [`crate::api::Payment::request`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentError = \n/** User rejected the payment request. */\n{\n tag: \"Rejected\";\n value?: undefined;\n}\n/** User's available balance is not sufficient for the requested amount. */\n | {\n tag: \"InsufficientBalance\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentError: Codec;\n/** Request to initiate a payment to another account. */\nexport interface HostPaymentRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n from?: number;\n /** Amount to pay. */\n amount: bigint;\n /** Destination account. */\n destination: HexString;\n}\nexport const HostPaymentRequest: Codec;\n/**\n * Receipt returned after a successful payment request.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport interface HostPaymentResponse {\n /** The assigned payment identifier. */\n id: string;\n}\nexport const HostPaymentResponse: Codec;\n/**\n * Error from [`crate::api::Payment::status_subscribe`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentStatusSubscribeError = \n/** Payment ID was not found or does not belong to the current product. */\n{\n tag: \"PaymentNotFound\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentStatusSubscribeError: Codec;\n/**\n * Payment lifecycle status pushed to subscribers.\n *\n * Once a terminal state (`Completed` or `Failed`) is reached, the host\n * delivers it and may close the subscription.\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentStatusSubscribeItem = \n/** Payment is being processed. */\n{\n tag: \"Processing\";\n value?: undefined;\n}\n/** Payment has been settled successfully. */\n | {\n tag: \"Completed\";\n value?: undefined;\n}\n/** Payment has failed. */\n | {\n tag: \"Failed\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentStatusSubscribeItem: Codec;\n/** Request to subscribe to a payment status. */\nexport interface HostPaymentStatusSubscribeRequest {\n /** Payment identifier to watch. */\n paymentId: string;\n}\nexport const HostPaymentStatusSubscribeRequest: Codec;\n/**\n * Error from [`crate::api::Payment::top_up`].\n *\n * See [RFC 0006].\n *\n * [RFC 0006]: https://github.com/paritytech/triangle-js-sdks/pull/94\n */\nexport type HostPaymentTopUpError = \n/** The source account does not hold sufficient funds. */\n{\n tag: \"InsufficientFunds\";\n value?: undefined;\n}\n/** The source account was not found or is invalid. */\n | {\n tag: \"InvalidSource\";\n value?: undefined;\n}\n/** Some coins were claimed but the total fell short of the requested amount. */\n | {\n tag: \"PartialPayment\";\n value: {\n credited: bigint;\n };\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPaymentTopUpError: Codec;\n/** Request to top up the product payment balance. */\nexport interface HostPaymentTopUpRequest {\n /** Optional purse selector. `None` means MAIN_PURSE. */\n into?: number;\n /** Amount to top up. */\n amount: bigint;\n /** Funding source for the top-up. */\n source: PaymentTopUpSource;\n}\nexport const HostPaymentTopUpRequest: Codec;\n/** The calling product's cards: the whole set on subscribe and after every change. */\nexport interface HostPocketListSubscribeItem {\n /** Cards currently in Pocket for the calling product. */\n cards: Array;\n}\nexport const HostPocketListSubscribeItem: Codec;\n/** Card removal failure. */\nexport type HostPocketRemoveCardError = \n/** The card is privileged and stays in Pocket. */\n{\n tag: \"Privileged\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPocketRemoveCardError: Codec;\n/** Request to remove one of the calling product's cards. */\nexport interface HostPocketRemoveCardRequest {\n /** Card to remove. A card that is not present is already removed. */\n cardId: string;\n}\nexport const HostPocketRemoveCardRequest: Codec;\n/** Profile disclosure failure. */\nexport type HostProfileDiscloseError = \n/** The reference is empty, too long, or not printable ASCII. */\n{\n tag: \"InvalidReference\";\n value?: undefined;\n}\n/**\n * The user declined to let this product disclose a profile to their\n * chat contacts.\n */\n | {\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** No user is signed in, so there are no contacts to disclose to. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfileDiscloseError: Codec;\n/**\n * Request to give the user's chat contacts a profile reference.\n *\n * The reference is a bearer capability for everyone the host relays it to.\n * The host stores it as the user's own and never parses it.\n */\nexport interface V01HostProfileDiscloseRequest {\n /** Opaque profile reference, e.g. a Seity contacts reference. */\n reference: string;\n}\nexport const V01HostProfileDiscloseRequest: Codec;\n/** Failure while querying the signed-in user's profile status. */\nexport type HostProfileOwnStatusError = \n/** No user is signed in. */\n{\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfileOwnStatusError: Codec;\n/**\n * Whether the signed-in user currently has a profile disclosed through the\n * host. The reference itself never crosses into the product.\n */\nexport interface HostProfileOwnStatusResponse {\n /** `true` when the host holds a current own-profile reference. */\n configured: boolean;\n}\nexport const HostProfileOwnStatusResponse: Codec;\n/** Contact avatar placement failure. Says nothing about any one slot. */\nexport type HostProfilePlaceContactAvatarsError = \n/** This host cannot draw over the product's surface. */\n{\n tag: \"Unsupported\";\n value?: undefined;\n}\n/** No user is signed in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all, including a malformed placement. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfilePlaceContactAvatarsError: Codec;\n/**\n * Where a chat product draws contact avatars, so the host can draw the\n * photo and mood ring each contact shared over them, on its own layer.\n *\n * The product sends geometry only. The host decides which slots it can fill\n * and never says which, so the product cannot learn who shared a profile.\n */\nexport interface V01HostProfilePlaceContactAvatarsRequest {\n /**\n * Width of the product's drawing surface, in the units of every rect:\n * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport\n * for a web product. 1 to 16384.\n */\n surfaceWidth: number;\n /** Height of the drawing surface, in the same units. 1 to 16384. */\n surfaceHeight: number;\n /**\n * Replaces the product's previous placement entirely; empty clears it.\n * At most 64, each with its own `slot`.\n */\n slots: Array;\n}\nexport const V01HostProfilePlaceContactAvatarsRequest: Codec;\n/** Contact profile presentation failure. */\nexport type HostProfilePresentContactError = \n/** This contact has not shared a profile with the user. */\n{\n tag: \"NotShared\";\n value?: undefined;\n}\n/** The host holds a reference it cannot parse. */\n | {\n tag: \"InvalidReference\";\n value?: undefined;\n}\n/** No user is signed in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfilePresentContactError: Codec;\n/**\n * Request to show a chat contact's profile in host-owned UI.\n *\n * The product names the contact, never a reference: the host looks up the\n * reference that contact's host sent, so the product cannot read, keep or\n * substitute it.\n */\nexport interface V01HostProfilePresentContactRequest {\n /** The contact's authenticated root identity, as the chat API names it. */\n peerIdentity: HexString;\n}\nexport const V01HostProfilePresentContactRequest: Codec;\n/** Profile presentation failure. */\nexport type HostProfilePresentError = \n/** The reference is malformed or names a format this host cannot open. */\n{\n tag: \"InvalidReference\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfilePresentError: Codec;\n/** Failure while presenting the signed-in user's profile. */\nexport type HostProfilePresentOwnError = \n/** The signed-in user has not configured a profile. */\n{\n tag: \"NotConfigured\";\n value?: undefined;\n}\n/** The host holds a reference it cannot parse. */\n | {\n tag: \"InvalidReference\";\n value?: undefined;\n}\n/** No user is signed in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfilePresentOwnError: Codec;\n/**\n * Request to show a profile the calling product references in host-owned UI.\n *\n * The reference is a bearer capability: whoever holds it can read the profile\n * it names. The host resolves and renders it itself, so profile bytes, the\n * avatar image included, never reach the product.\n */\nexport interface HostProfilePresentRequest {\n /** Opaque profile reference, e.g. a Seity `#` blob reference. */\n reference: string;\n}\nexport const HostProfilePresentRequest: Codec;\n/** Profile retraction failure. */\nexport type HostProfileRetractError = \n/** Another product disclosed the reference the host holds. */\n{\n tag: \"NotDiscloser\";\n value?: undefined;\n}\n/** No user is signed in. */\n | {\n tag: \"NotConnected\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostProfileRetractError: Codec;\n/** Request to cancel a previously scheduled notification. */\nexport interface HostPushNotificationCancelRequest {\n /** The notification identifier returned by [`HostPushNotificationResponse`]. */\n id: number;\n}\nexport const HostPushNotificationCancelRequest: Codec;\n/** Push notification error. */\nexport type HostPushNotificationError = \n/** The host-wide queue of pending scheduled notifications is full. */\n{\n tag: \"ScheduleLimitReached\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostPushNotificationError: Codec;\n/**\n * Push notification payload.\n *\n * When `scheduled_at` is `Some`, the notification is deferred to the given\n * wall-clock instant (Unix milliseconds UTC). `None` fires immediately,\n * preserving prior behaviour. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\nexport interface HostPushNotificationRequest {\n /** Notification text. */\n text: string;\n /** Optional URL to open on tap. */\n deeplink?: string;\n /**\n * Optional Unix timestamp in milliseconds (UTC) at which the notification\n * should fire. `None` fires immediately.\n */\n scheduledAt?: bigint;\n}\nexport const HostPushNotificationRequest: Codec;\n/** Successful push notification response carrying the assigned id. */\nexport interface HostPushNotificationResponse {\n /** Host-assigned notification identifier. */\n id: number;\n}\nexport const HostPushNotificationResponse: Codec;\n/** An action triggered inside a product-rendered body. */\nexport interface HostRendererActionSubscribeItem {\n /** Where the body lives. */\n context: RenderContext;\n /** Which action was triggered, as named in the renderer tree. */\n actionId: string;\n /**\n * Data the node attached to the action. A `Button` press carries an\n * empty payload; a `TextField` value change carries the UTF-8 bytes of\n * the new value, with no length prefix.\n */\n payload: HexString;\n}\nexport const HostRendererActionSubscribeItem: Codec;\n/** Login request error. */\nexport type HostRequestLoginError = \n/** Catch-all. */\n{\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostRequestLoginError: Codec;\n/** Request to present the host login flow. */\nexport interface HostRequestLoginRequest {\n /** Optional human-readable reason shown in the login UI. */\n reason?: string;\n}\nexport const HostRequestLoginRequest: Codec;\n/** Result of a login request. */\nexport type HostRequestLoginResponse = \"Success\" | \"AlreadyConnected\" | \"Rejected\";\nexport const HostRequestLoginResponse: Codec;\n/** Batched resource pre-allocation request (RFC 0010). */\nexport interface HostRequestResourceAllocationRequest {\n /** Resources to allocate. */\n resources: Array;\n}\nexport const HostRequestResourceAllocationRequest: Codec;\n/** Per-resource outcomes for a batched allocation request (RFC 0010). */\nexport interface HostRequestResourceAllocationResponse {\n /** Per-resource allocation outcomes, in the same order as the request. */\n outcomes: Array;\n}\nexport const HostRequestResourceAllocationResponse: Codec;\n/** Signing operation error. */\nexport type HostSignPayloadError = \n/** Payload could not be deserialized. */\n{\n tag: \"FailedToDecode\";\n value?: undefined;\n}\n/** User rejected signing. */\n | {\n tag: \"Rejected\";\n value?: undefined;\n}\n/** Not authenticated. */\n | {\n tag: \"PermissionDenied\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostSignPayloadError: Codec;\n/** Request to sign an extrinsic payload with a product account. */\nexport interface HostSignPayloadRequest {\n /** Product account that will sign this payload. */\n account: ProductAccountId;\n /** The extrinsic payload to sign. */\n payload: HostSignPayloadData;\n}\nexport const HostSignPayloadRequest: Codec;\n/** Result of a signing operation. */\nexport interface HostSignPayloadResponse {\n /** The cryptographic signature. */\n signature: HexString;\n /** Full signed transaction, if requested. */\n signedTransaction?: HexString;\n}\nexport const HostSignPayloadResponse: Codec;\n/**\n * Sign a Substrate extrinsic payload with a non-product (legacy) account.\n * Contains the same fields as [`HostSignPayloadRequest`] minus `address`\n * (replaced by `signer`).\n */\nexport interface HostSignPayloadWithLegacyAccountRequest {\n /** Signer address (SS58 or hex) of the legacy account. */\n signer: string;\n /** The extrinsic payload to sign. */\n payload: HostSignPayloadData;\n}\nexport const HostSignPayloadWithLegacyAccountRequest: Codec;\n/** A raw signing request pairing an account with the payload to sign. */\nexport interface HostSignRawRequest {\n /** Product account that will sign this payload. */\n account: ProductAccountId;\n /** The payload to sign. */\n payload: RawPayload;\n}\nexport const HostSignRawRequest: Codec;\n/**\n * Sign raw bytes with a non-product (legacy) account. The signer field\n * identifies which legacy account to use.\n */\nexport interface HostSignRawWithLegacyAccountRequest {\n /** Signer address (SS58 or hex) of the legacy account. */\n signer: string;\n /** The data to sign. */\n payload: RawPayload;\n}\nexport const HostSignRawWithLegacyAccountRequest: Codec;\n/** Current theme state pushed to subscribers. */\nexport interface HostThemeSubscribeItem {\n /** Theme name. */\n name: ThemeName;\n /** Light or dark variant. */\n variant: ThemeVariant;\n}\nexport const HostThemeSubscribeItem: Codec;\n/** Request to begin a pending operation. */\nexport interface HostWorkerBeginOperationRequest {\n /** Optional label for host logs and UI. */\n label?: string;\n}\nexport const HostWorkerBeginOperationRequest: Codec;\n/** Response carrying the id of a newly begun operation. */\nexport interface HostWorkerBeginOperationResponse {\n /** Id to pass to `end_operation`. */\n id: number;\n}\nexport const HostWorkerBeginOperationResponse: Codec;\n/** Request to end a pending operation. */\nexport interface HostWorkerEndOperationRequest {\n /** Id returned by `begin_operation`. */\n id: number;\n}\nexport const HostWorkerEndOperationRequest: Codec;\n/** A body the host needs drawn. */\nexport interface ProductRendererRenderRequest {\n /** Where the body lives. */\n context: RenderContext;\n /** Product-defined payload, opaque to the host. */\n payload: HexString;\n}\nexport const ProductRendererRenderRequest: Codec;\n/** Request to fetch the body of a pinned block. */\nexport interface RemoteChainHeadBodyRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n}\nexport const RemoteChainHeadBodyRequest: Codec;\n/** Response to a body request; results arrive as follow events. */\nexport interface RemoteChainHeadBodyResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadBodyResponse: Codec;\n/** Request to invoke a runtime call at a pinned block. */\nexport interface RemoteChainHeadCallRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n /** Runtime API function name. */\n function: string;\n /** SCALE-encoded call parameters. */\n callParameters: HexString;\n}\nexport const RemoteChainHeadCallRequest: Codec;\n/** Response to a runtime call request; the output arrives as a follow event. */\nexport interface RemoteChainHeadCallResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadCallResponse: Codec;\n/** Request to continue a paused chain-head operation. */\nexport interface RemoteChainHeadContinueRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Operation identifier. */\n operationId: string;\n}\nexport const RemoteChainHeadContinueRequest: Codec;\n/** Event emitted on a chain-head follow subscription. */\nexport type RemoteChainHeadFollowItem = \n/** First event of the subscription, describing the current finalized blocks. */\n{\n tag: \"Initialized\";\n value: {\n finalizedBlockHashes: Array;\n finalizedBlockRuntime?: RuntimeType;\n };\n}\n/** A new non-finalized block was announced. */\n | {\n tag: \"NewBlock\";\n value: {\n blockHash: HexString;\n parentBlockHash: HexString;\n newRuntime?: RuntimeType;\n };\n}\n/** The best block has changed. */\n | {\n tag: \"BestBlockChanged\";\n value: {\n bestBlockHash: HexString;\n };\n}\n/** One or more blocks were finalized. */\n | {\n tag: \"Finalized\";\n value: {\n finalizedBlockHashes: Array;\n prunedBlockHashes: Array;\n };\n}\n/** A body operation completed. */\n | {\n tag: \"OperationBodyDone\";\n value: {\n operationId: string;\n value: Array;\n };\n}\n/** A runtime call operation completed. */\n | {\n tag: \"OperationCallDone\";\n value: {\n operationId: string;\n output: HexString;\n };\n}\n/** A storage operation produced a batch of results. */\n | {\n tag: \"OperationStorageItems\";\n value: {\n operationId: string;\n items: Array;\n };\n}\n/** A storage operation finished emitting results. */\n | {\n tag: \"OperationStorageDone\";\n value: {\n operationId: string;\n };\n}\n/** A storage operation is paused until the product requests continuation. */\n | {\n tag: \"OperationWaitingForContinue\";\n value: {\n operationId: string;\n };\n}\n/** The operation failed because the required data was not accessible; it can be retried. */\n | {\n tag: \"OperationInaccessible\";\n value: {\n operationId: string;\n };\n}\n/** The operation failed with an error. */\n | {\n tag: \"OperationError\";\n value: {\n operationId: string;\n error: string;\n };\n}\n/** The subscription was stopped by the host and is no longer valid. */\n | {\n tag: \"Stop\";\n value?: undefined;\n};\nexport const RemoteChainHeadFollowItem: Codec;\n/** Request to start a chain-head follow subscription. */\nexport interface RemoteChainHeadFollowRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Whether to include runtime information in events. */\n withRuntime: boolean;\n}\nexport const RemoteChainHeadFollowRequest: Codec;\n/** Request to fetch the header of a pinned block. */\nexport interface RemoteChainHeadHeaderRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n}\nexport const RemoteChainHeadHeaderRequest: Codec;\n/** Response containing the requested block header. */\nexport interface RemoteChainHeadHeaderResponse {\n /** SCALE-encoded block header. */\n header?: HexString;\n}\nexport const RemoteChainHeadHeaderResponse: Codec;\n/** Request to stop an in-progress chain-head operation. */\nexport interface RemoteChainHeadStopOperationRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Operation identifier. */\n operationId: string;\n}\nexport const RemoteChainHeadStopOperationRequest: Codec;\n/** Request to query storage at a pinned block. */\nexport interface RemoteChainHeadStorageRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hash. */\n hash: HexString;\n /** Storage items to query. */\n items: Array;\n /** Optional child trie. */\n childTrie?: HexString;\n}\nexport const RemoteChainHeadStorageRequest: Codec;\n/** Response to a storage request; results arrive as follow events. */\nexport interface RemoteChainHeadStorageResponse {\n /** Started operation result. */\n operation: OperationStartedResult;\n}\nexport const RemoteChainHeadStorageResponse: Codec;\n/** Request to release pinned blocks. */\nexport interface RemoteChainHeadUnpinRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Follow subscription identifier. */\n followSubscriptionId: string;\n /** Block hashes to unpin. */\n hashes: Array;\n}\nexport const RemoteChainHeadUnpinRequest: Codec;\n/** Error from [`crate::api::Chain::get_chain_info`]. */\nexport type RemoteChainInfoError = \n/** The host does not serve the requested chain. */\n{\n tag: \"NotSupported\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: GenericError;\n};\nexport const RemoteChainInfoError: Codec;\n/** Request to resolve one chain identifier against the host's environment. */\nexport interface RemoteChainInfoRequest {\n /** Chain to resolve. */\n chain: ChainIdentifier;\n}\nexport const RemoteChainInfoRequest: Codec;\n/** Response carrying the resolved chain data. */\nexport interface RemoteChainInfoResponse {\n /** Ecosystem the host is configured for, e.g. \"polkadot\", \"kusama\", \"paseo\". */\n network: string;\n /** Chain this response resolves, echoed from the request. */\n chain: ChainIdentifier;\n /** Genesis hash identifying the chain in all chain-scoped calls. */\n genesisHash: HexString;\n}\nexport const RemoteChainInfoResponse: Codec;\n/** Request for the display name of a chain. */\nexport interface RemoteChainSpecChainNameRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecChainNameRequest: Codec;\n/** Response containing the chain display name. */\nexport interface RemoteChainSpecChainNameResponse {\n /** Chain display name. */\n chainName: string;\n}\nexport const RemoteChainSpecChainNameResponse: Codec;\n/** Request for the canonical genesis hash of a chain. */\nexport interface RemoteChainSpecGenesisHashRequest {\n /** Chain genesis hash requested by the product. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecGenesisHashRequest: Codec;\n/** Response containing the canonical genesis hash. */\nexport interface RemoteChainSpecGenesisHashResponse {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecGenesisHashResponse: Codec;\n/** Request for the JSON-encoded properties of a chain. */\nexport interface RemoteChainSpecPropertiesRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n}\nexport const RemoteChainSpecPropertiesRequest: Codec;\n/** Response containing the chain properties. */\nexport interface RemoteChainSpecPropertiesResponse {\n /** JSON-encoded properties. */\n properties: string;\n}\nexport const RemoteChainSpecPropertiesResponse: Codec;\n/** Request to broadcast a signed transaction. */\nexport interface RemoteChainTransactionBroadcastRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Signed transaction bytes. */\n transaction: HexString;\n}\nexport const RemoteChainTransactionBroadcastRequest: Codec;\n/** Response to a transaction broadcast request. */\nexport interface RemoteChainTransactionBroadcastResponse {\n /** Broadcast operation identifier, if available. */\n operationId?: string;\n}\nexport const RemoteChainTransactionBroadcastResponse: Codec;\n/** Request to stop broadcasting a transaction. */\nexport interface RemoteChainTransactionStopRequest {\n /** Chain genesis hash. */\n genesisHash: HexString;\n /** Operation identifier of the broadcast to stop. */\n operationId: string;\n}\nexport const RemoteChainTransactionStopRequest: Codec;\n/** remote-permission request (RFC 0002). */\nexport interface RemotePermissionRequest {\n /** Permission requested by the product. */\n permission: RemotePermission;\n}\nexport const RemotePermissionRequest: Codec;\n/** Outcome of a remote-permission request. */\nexport interface RemotePermissionResponse {\n /** Whether the permission was granted. */\n granted: boolean;\n}\nexport const RemotePermissionResponse: Codec;\n/** Item containing an optional preimage lookup result. */\nexport interface RemotePreimageLookupSubscribeItem {\n /** Preimage data, if found. */\n value?: HexString;\n}\nexport const RemotePreimageLookupSubscribeItem: Codec;\n/** Request to subscribe to preimage lookup results. */\nexport interface RemotePreimageLookupSubscribeRequest {\n /** Hash of the preimage. */\n key: HexString;\n}\nexport const RemotePreimageLookupSubscribeRequest: Codec;\n/** Statement proof creation error. */\nexport type RemoteStatementStoreCreateProofError = \n/** Signing operation failed. */\n{\n tag: \"UnableToSign\";\n value?: undefined;\n}\n/** Account not recognized. */\n | {\n tag: \"UnknownAccount\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const RemoteStatementStoreCreateProofError: Codec;\n/** Request to create a cryptographic proof for a statement. */\nexport interface RemoteStatementStoreCreateProofRequest {\n /** Product account that should create the proof. */\n productAccountId: ProductAccountId;\n /** Statement to prove. */\n statement: Statement;\n}\nexport const RemoteStatementStoreCreateProofRequest: Codec;\n/** Response containing a statement proof. */\nexport interface RemoteStatementStoreCreateProofResponse {\n /** Created statement proof. */\n proof: StatementProof;\n}\nexport const RemoteStatementStoreCreateProofResponse: Codec;\n/**\n * Page of signed statements delivered by the statement store subscription\n * (RFC 0008). The `is_complete` flag distinguishes the historical-dump phase\n * (`false`) from the live-update phase (`true`).\n */\nexport interface RemoteStatementStoreSubscribeItem {\n /** Signed statements matching the subscription. */\n statements: Array;\n /**\n * `false` while the host is still streaming the historical dump (more\n * pages to follow). `true` once the dump is complete; all subsequent\n * pages are also `true` and carry only newly-arrived statements.\n */\n isComplete: boolean;\n}\nexport const RemoteStatementStoreSubscribeItem: Codec;\n/** Request to subscribe to statements via a topic filter (RFC 0008). */\nexport type RemoteStatementStoreSubscribeRequest = \n/** AND: statement must contain every listed topic. */\n{\n tag: \"MatchAll\";\n value: Array;\n}\n/** OR: statement must contain at least one listed topic. */\n | {\n tag: \"MatchAny\";\n value: Array;\n};\nexport const RemoteStatementStoreSubscribeRequest: Codec;\n/** Local storage read failure. */\nexport type HostLocalStorageReadError = \n/** Storage quota exceeded. */\n{\n tag: \"Full\";\n value?: undefined;\n}\n/**\n * The addressed storage belongs to another product that has not granted\n * this caller the `storage` scope.\n *\n * One variant answers every reason: the product does not resolve, it\n * published no manifest, or its manifest grants this caller nothing.\n * Distinguishing them would make the call a probe for which products exist\n * and which hold data.\n */\n | {\n tag: \"AccessNotGranted\";\n value?: undefined;\n}\n/** Catch-all. */\n | {\n tag: \"Unknown\";\n value: {\n reason: string;\n };\n};\nexport const HostLocalStorageReadError: Codec;\n/**\n * Request to read a local storage value.\n *\n * Storage is private by default: `product: None` addresses the caller's own\n * storage, which is what every v0.1 read resolved to. Naming another product\n * reads that product's storage instead, and succeeds only if that product's\n * manifest grants this caller the `storage` scope.\n */\nexport interface HostLocalStorageReadRequest {\n /**\n * Product whose storage is read. `None`, or the caller's own id, means the\n * caller, and consults no grant.\n */\n product?: string;\n /** Storage key to read. */\n key: string;\n}\nexport const HostLocalStorageReadRequest: Codec;\n/** Convert UTC instants using a snapshot of the host's locale subscription. */\nexport interface HostLocaleLocalizeTimestampsRequest {\n /** At most 128 Unix millisecond instants, no later than year 9999. */\n timestampsMs: Array;\n /** Language tag from the locale subscription, not a guessed language. */\n languageTag: string;\n /** Time zone from the locale subscription; evaluated separately at each instant. */\n timeZone: string;\n}\nexport const HostLocaleLocalizeTimestampsRequest: Codec;\n/** Local timestamps in exactly the request's order. */\nexport interface HostLocaleLocalizeTimestampsResponse {\n /** One result per requested timestamp; partial success is not returned. */\n timestamps: Array;\n}\nexport const HostLocaleLocalizeTimestampsResponse: Codec;\n/** Host language and local time zone, replaced together when either changes. */\nexport interface HostLocaleSubscribeItem {\n /** BCP 47 language tag selected by the host. */\n languageTag: string;\n /** IANA time zone, or absent when the host cannot supply local time. */\n timeZone?: string;\n}\nexport const HostLocaleSubscribeItem: Codec;\n/** Failure of a Host-owned Chat operation before a public update is available. */\nexport type HostProductDeviceChatError = \"NotConnected\" | \"AccessNotGranted\" | \"UserRejected\" | \"AllowanceRequired\" | \"PeerNotReady\" | \"OperationConflict\" | \"InvalidRequest\" | \"InvalidStatement\" | \"RecipientNotFound\" | \"InsufficientBalance\" | \"StorageUnavailable\" | \"NetworkUnavailable\" | \"OperationNotFound\" | \"AttachmentsUnavailable\";\nexport const HostProductDeviceChatError: Codec;\n/** An operation on the calling product's Host-owned native Chat device. */\nexport type V02HostProductDeviceChatRequest = \n/** Restore the installation's public device and durable conversation state. */\n{\n tag: \"Initialize\";\n value?: undefined;\n}\n/** Resolve a username in the configured network and send a fresh invitation. */\n | {\n tag: \"Invite\";\n value: {\n username: string;\n text: string;\n };\n}\n/** Authenticate, decrypt and durably process a native statement. */\n | {\n tag: \"Receive\";\n value: {\n statement: SignedStatement;\n };\n}\n/** Accept an invitation previously authenticated and retained by the Host. */\n | {\n tag: \"AcceptInvitation\";\n value: {\n invitationId: HexString;\n };\n}\n/** Reject an invitation previously authenticated and retained by the Host. */\n | {\n tag: \"RejectInvitation\";\n value: {\n invitationId: HexString;\n };\n}\n/** Send ordinary messages to an established, Host-authenticated peer roster. */\n | {\n tag: \"Send\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n messages: Array;\n };\n}\n/** Propose one main-purse payment; this operation always requires Host review. */\n | {\n tag: \"SendPayment\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n amountCents: bigint;\n };\n}\n/** Read a payment's durable status without authorizing another spend. */\n | {\n tag: \"PaymentStatus\";\n value: {\n operationId: HexString;\n };\n}\n/** Resume durable transport work and return newly available public views. */\n | {\n tag: \"Reconcile\";\n value?: undefined;\n}\n/** Select immutable files in trusted Host UI and send native rich content. */\n | {\n tag: \"SendAttachments\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n text?: string;\n };\n}\n/** Resume a private download and present or export through trusted Host UI. */\n | {\n tag: \"OpenAttachment\";\n value: {\n attachmentId: HexString;\n };\n};\nexport const V02HostProductDeviceChatRequest: Codec;\n/** Public updates from a Host-owned Chat operation. */\nexport interface V02HostProductDeviceChatResponse {\n /** Public local device metadata, including its allowance account. */\n device: HostNativeChatDevice;\n /** Current authenticated peers and subscription channels. */\n peers: Array;\n /** Invitations still awaiting a user decision. */\n invitations: Array;\n /** Newly processed safe ordinary messages. */\n messages: Array;\n /** Newly processed native delivery acknowledgments. */\n acknowledgments: Array;\n /** Current public payment statuses belonging to the calling product. */\n payments: Array;\n /** Safe rich-content views and their current private-transfer progress. */\n richMessages: Array;\n}\nexport const V02HostProductDeviceChatResponse: Codec;\n/**\n * Replace the user's disclosed reference and its complete set of audiences.\n *\n * An empty audience retains the user's own profile but withdraws all delivery\n * grants. A contact handle that no longer resolves rejects the whole request.\n */\nexport interface HostProfileDiscloseRequest {\n /** Opaque bearer reference, retained and relayed only by the host. */\n reference: string;\n /** Independent grants for this reference, at most 64. */\n audiences: Array;\n}\nexport const HostProfileDiscloseRequest: Codec;\n/**\n * Where a chat product draws avatars the host fills in: its contacts' and,\n * optionally, the signed-in user's own.\n *\n * v0.2 adds `own` to the v0.1 placement. A v0.1 placement is this one with no\n * own slot, which is exactly what v0.1 meant. Both kinds live in one\n * placement so a product never has two placements replacing each other's\n * overlay.\n */\nexport interface V02HostProfilePlaceContactAvatarsRequest {\n /**\n * Width of the product's drawing surface, in the units of every rect:\n * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport\n * for a web product. 1 to 16384.\n */\n surfaceWidth: number;\n /** Height of the drawing surface, in the same units. 1 to 16384. */\n surfaceHeight: number;\n /**\n * Where the signed-in user's own avatar is drawn, if the product draws\n * one. The host fills it only when the user has disclosed a profile.\n */\n own?: OwnAvatarSlot;\n /**\n * Replaces the product's previous placement entirely; empty clears it.\n * At most 64, each with its own `slot`, unique across `own` too.\n */\n slots: Array;\n}\nexport const V02HostProfilePlaceContactAvatarsRequest: Codec;\n/**\n * Ask the host to present a contact's available profile.\n *\n * Unknown handles, absent profiles and presentation failures return success,\n * without disclosing whether the contact shares a profile.\n */\nexport interface HostProfilePresentContactRequest {\n /** The contact whose profile the host may present. */\n contact: ProfileContact;\n}\nexport const HostProfilePresentContactRequest: Codec;\n/** Geometry and opaque contact selection for one host-rendered avatar. */\nexport interface V03ContactAvatarSlot {\n /** Product-chosen id, unique across contact and own slots. */\n slot: number;\n /** A peer identity or host-issued handle. Unresolved handles remain blank. */\n contact: ProfileContact;\n /** Square avatar bounds, from 1 to 1024 units per side. */\n rect: AvatarRect;\n /** Visible region to which the avatar is clipped. */\n clip: AvatarRect;\n}\nexport const V03ContactAvatarSlot: Codec;\n/** An operation using the calling product's non-exportable Host Chat device. */\nexport type HostProductDeviceChatRequest = \n/** Restore public metadata, pending ciphertext, and private file-transfer progress. */\n{\n tag: \"Initialize\";\n value?: undefined;\n}\n/** Independently resolve and bind a peer on the trusted network. */\n | {\n tag: \"Bind\";\n value: {\n username: string;\n };\n}\n/** Validate native plaintext and return signed ciphertext for product delivery. */\n | {\n tag: \"Prepare\";\n value: {\n peerIdentity: HexString;\n route: HostNativeChatRoute;\n plaintext: HexString;\n };\n}\n/** Authenticate and decrypt a complete external native statement, never own output. */\n | {\n tag: \"Open\";\n value: {\n statement: SignedStatement;\n };\n}\n/** Propose one main-purse payment; this operation requires trusted Host review. */\n | {\n tag: \"SendPayment\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n amountCents: bigint;\n };\n}\n/** Read durable payment status without authorizing another spend. */\n | {\n tag: \"PaymentStatus\";\n value: {\n operationId: HexString;\n };\n}\n/** Reconcile payment custody and return opaque statements for product delivery. */\n | {\n tag: \"ReconcilePayments\";\n value?: undefined;\n}\n/** Select files in trusted Host UI and prepare native rich content without delivery. */\n | {\n tag: \"PrepareAttachments\";\n value: {\n peerIdentity: HexString;\n requestId: string;\n text?: string;\n };\n}\n/** Resume a private download and present or export through trusted Host UI. */\n | {\n tag: \"OpenAttachment\";\n value: {\n attachmentId: HexString;\n };\n}\n/** Acknowledge durable product storage of the legacy view and ordinary ciphertext. */\n | {\n tag: \"CommitMigration\";\n value: {\n migrationId: HexString;\n };\n}\n/** Continue a Host-authenticated incoming batch without supplying new ciphertext. */\n | {\n tag: \"ContinueOpen\";\n value: {\n openId: HexString;\n cursor: number;\n };\n}\n/** Continue a bounded snapshot of custody metadata and pending prepared statements. */\n | {\n tag: \"ContinueState\";\n value: {\n stateId: HexString;\n cursor: number;\n };\n}\n/** Read configured raw chain units per native Coinage cent, without spending. */\n | {\n tag: \"PaymentDenomination\";\n value?: undefined;\n};\nexport const HostProductDeviceChatRequest: Codec;\n/** Cryptographic results and custody metadata; products drive delivery and import. */\nexport interface HostProductDeviceChatResponse {\n /** Public local device metadata, including its allowance account. */\n device: HostNativeChatDevice;\n /** Host-authenticated peer and device metadata. */\n peers: Array;\n /** Newly resolved peer binding, when requested. */\n binding?: HostNativeChatBinding;\n /** Authenticated incoming plaintext; incoming payment import is product-owned. */\n opened: Array;\n /** Signed ciphertext for product submission and exact-identity retries. */\n prepared: Array;\n /** Durable public payment status, never outgoing bearer secrets. */\n payments: Array;\n /** Rich-content metadata and trusted private-transfer progress. */\n richMessages: Array;\n /** Legacy public view retained until the product durably commits migration. */\n migration?: V02HostProductDeviceChatResponse;\n /** Snapshot identifier to acknowledge only after persisting its view and ciphertext. */\n migrationId?: HexString;\n /** Continuation of an authenticated incoming batch, when opening is paginated. */\n openPage?: HostNativeChatOpenPage;\n /** Native request identities for invitations in the legacy migration view. */\n migrationInvitations: Array;\n /** Continuation of a bounded public state snapshot, when metadata is paginated. */\n statePage?: HostNativeChatStatePage;\n /**\n * Configured raw chain units per native Coinage cent, only when requested.\n * This is positive denomination metadata, never a balance or fiat price.\n */\n coinageCentsUnit?: bigint;\n}\nexport const HostProductDeviceChatResponse: Codec;\n/** A host-rendered avatar placement using peer identities or opaque handles. */\nexport interface HostProfilePlaceContactAvatarsRequest {\n /** Width of the drawing surface, from 1 to 16384 units. */\n surfaceWidth: number;\n /** Height of the drawing surface, from 1 to 16384 units. */\n surfaceHeight: number;\n /** Optional slot for the signed-in user's own disclosed profile. */\n own?: OwnAvatarSlot;\n /** Complete replacement of the contact slots, at most 64. */\n slots: Array;\n}\nexport const HostProfilePlaceContactAvatarsRequest: Codec;\n/** Cross-axis alignment of `Row` children. */\nexport type VerticalAlignment = \"Top\" | \"Center\" | \"Bottom\";\nexport const VerticalAlignment: Codec;\n/** An sr25519 (schnorrkel) VRF signature: the VRF pre-output and its proof. */\nexport interface VrfSignature {\n /** schnorrkel `VRFPreOut` \u2014 the 32-byte VRF output point. */\n preOutput: HexString;\n /** schnorrkel `VRFProof` \u2014 the 64-byte DLEQ proof. */\n proof: HexString;\n}\nexport const VrfSignature: Codec;\n/** One `append_message` call replayed against the signing transcript. */\nexport interface VrfTranscriptItem {\n /** Merlin `append_message` label. */\n label: HexString;\n /** Merlin `append_message` value. */\n value: HexString;\n}\nexport const VrfTranscriptItem: Codec;\n\n}\n\n\n// re-export namespace T at module top level (mirrors index.d.ts `export *`)\n\nexport import ActionTrigger = T.ActionTrigger;\nexport import AllocatableResource = T.AllocatableResource;\nexport import AllocationOutcome = T.AllocationOutcome;\nexport import Arrangement = T.Arrangement;\nexport import AvatarRect = T.AvatarRect;\nexport import Background = T.Background;\nexport import BlendingMode = T.BlendingMode;\nexport import BorderStyle = T.BorderStyle;\nexport import BoxProps = T.BoxProps;\nexport import ButtonProps = T.ButtonProps;\nexport import ButtonVariant = T.ButtonVariant;\nexport import Bytes32 = T.Bytes32;\nexport import ChainIdentifier = T.ChainIdentifier;\nexport import ChatAction = T.ChatAction;\nexport import ChatActionLayout = T.ChatActionLayout;\nexport import ChatActionPayload = T.ChatActionPayload;\nexport import ChatActions = T.ChatActions;\nexport import ChatBotRegistrationStatus = T.ChatBotRegistrationStatus;\nexport import ChatCommand = T.ChatCommand;\nexport import ChatCustomMessage = T.ChatCustomMessage;\nexport import ChatFile = T.ChatFile;\nexport import ChatMedia = T.ChatMedia;\nexport import ChatMessageContent = T.ChatMessageContent;\nexport import ChatReaction = T.ChatReaction;\nexport import ChatRichText = T.ChatRichText;\nexport import ChatRoom = T.ChatRoom;\nexport import ChatRoomParticipation = T.ChatRoomParticipation;\nexport import ChatRoomRegistrationStatus = T.ChatRoomRegistrationStatus;\nexport import CoinPaymentCheque = T.CoinPaymentCheque;\nexport import CoinPaymentClearingReference = T.CoinPaymentClearingReference;\nexport import CoinPaymentError = T.CoinPaymentError;\nexport import CoinPaymentPurseInfo = T.CoinPaymentPurseInfo;\nexport import CoinPaymentStatus = T.CoinPaymentStatus;\nexport import CoinPaymentTransmissionChannel = T.CoinPaymentTransmissionChannel;\nexport import ColorToken = T.ColorToken;\nexport import ColumnProps = T.ColumnProps;\nexport import ContactHandle = T.ContactHandle;\nexport import ContactLabelSlot = T.ContactLabelSlot;\nexport import ContactPickManyOutcome = T.ContactPickManyOutcome;\nexport import ContactPickOutcome = T.ContactPickOutcome;\nexport import ContentAlignment = T.ContentAlignment;\nexport import ContextualAlias = T.ContextualAlias;\nexport import DerivationIndex = T.DerivationIndex;\nexport import Dimensions = T.Dimensions;\nexport import Effect = T.Effect;\nexport import EffectProps = T.EffectProps;\nexport import GenericError = T.GenericError;\nexport import HorizontalAlignment = T.HorizontalAlignment;\nexport import VersionedHostAccountConnectionStatusSubscribeError = T.VersionedHostAccountConnectionStatusSubscribeError;\nexport import VersionedHostAccountConnectionStatusSubscribeItem = T.VersionedHostAccountConnectionStatusSubscribeItem;\nexport import VersionedHostAccountConnectionStatusSubscribeRequest = T.VersionedHostAccountConnectionStatusSubscribeRequest;\nexport import VersionedHostAccountCreateProofError = T.VersionedHostAccountCreateProofError;\nexport import VersionedHostAccountCreateProofRequest = T.VersionedHostAccountCreateProofRequest;\nexport import VersionedHostAccountCreateProofResponse = T.VersionedHostAccountCreateProofResponse;\nexport import VersionedHostAccountGetAliasError = T.VersionedHostAccountGetAliasError;\nexport import VersionedHostAccountGetAliasRequest = T.VersionedHostAccountGetAliasRequest;\nexport import VersionedHostAccountGetAliasResponse = T.VersionedHostAccountGetAliasResponse;\nexport import VersionedHostAccountGetError = T.VersionedHostAccountGetError;\nexport import VersionedHostAccountGetRequest = T.VersionedHostAccountGetRequest;\nexport import VersionedHostAccountGetResponse = T.VersionedHostAccountGetResponse;\nexport import VersionedHostAccountListRingVrfKeysError = T.VersionedHostAccountListRingVrfKeysError;\nexport import VersionedHostAccountListRingVrfKeysRequest = T.VersionedHostAccountListRingVrfKeysRequest;\nexport import VersionedHostAccountListRingVrfKeysResponse = T.VersionedHostAccountListRingVrfKeysResponse;\nexport import VersionedHostAccountRegisterRingVrfKeyError = T.VersionedHostAccountRegisterRingVrfKeyError;\nexport import VersionedHostAccountRegisterRingVrfKeyRequest = T.VersionedHostAccountRegisterRingVrfKeyRequest;\nexport import VersionedHostAccountRegisterRingVrfKeyResponse = T.VersionedHostAccountRegisterRingVrfKeyResponse;\nexport import VersionedHostAccountRingVrfSignError = T.VersionedHostAccountRingVrfSignError;\nexport import VersionedHostAccountRingVrfSignRequest = T.VersionedHostAccountRingVrfSignRequest;\nexport import VersionedHostAccountRingVrfSignResponse = T.VersionedHostAccountRingVrfSignResponse;\nexport import VersionedHostAccountSignVrfError = T.VersionedHostAccountSignVrfError;\nexport import VersionedHostAccountSignVrfRequest = T.VersionedHostAccountSignVrfRequest;\nexport import VersionedHostAccountSignVrfResponse = T.VersionedHostAccountSignVrfResponse;\nexport import VersionedHostChatActionSubscribeError = T.VersionedHostChatActionSubscribeError;\nexport import VersionedHostChatActionSubscribeItem = T.VersionedHostChatActionSubscribeItem;\nexport import VersionedHostChatActionSubscribeRequest = T.VersionedHostChatActionSubscribeRequest;\nexport import VersionedHostChatCreateRoomError = T.VersionedHostChatCreateRoomError;\nexport import VersionedHostChatCreateRoomRequest = T.VersionedHostChatCreateRoomRequest;\nexport import VersionedHostChatCreateRoomResponse = T.VersionedHostChatCreateRoomResponse;\nexport import VersionedHostChatListSubscribeError = T.VersionedHostChatListSubscribeError;\nexport import VersionedHostChatListSubscribeItem = T.VersionedHostChatListSubscribeItem;\nexport import VersionedHostChatListSubscribeRequest = T.VersionedHostChatListSubscribeRequest;\nexport import VersionedHostChatPostMessageError = T.VersionedHostChatPostMessageError;\nexport import VersionedHostChatPostMessageRequest = T.VersionedHostChatPostMessageRequest;\nexport import VersionedHostChatPostMessageResponse = T.VersionedHostChatPostMessageResponse;\nexport import VersionedHostChatRegisterBotError = T.VersionedHostChatRegisterBotError;\nexport import VersionedHostChatRegisterBotRequest = T.VersionedHostChatRegisterBotRequest;\nexport import VersionedHostChatRegisterBotResponse = T.VersionedHostChatRegisterBotResponse;\nexport import VersionedHostCoinPaymentCreateChequeError = T.VersionedHostCoinPaymentCreateChequeError;\nexport import VersionedHostCoinPaymentCreateChequeRequest = T.VersionedHostCoinPaymentCreateChequeRequest;\nexport import VersionedHostCoinPaymentCreateChequeResponse = T.VersionedHostCoinPaymentCreateChequeResponse;\nexport import VersionedHostCoinPaymentCreatePurseError = T.VersionedHostCoinPaymentCreatePurseError;\nexport import VersionedHostCoinPaymentCreatePurseRequest = T.VersionedHostCoinPaymentCreatePurseRequest;\nexport import VersionedHostCoinPaymentCreatePurseResponse = T.VersionedHostCoinPaymentCreatePurseResponse;\nexport import VersionedHostCoinPaymentCreateReceivableError = T.VersionedHostCoinPaymentCreateReceivableError;\nexport import VersionedHostCoinPaymentCreateReceivableRequest = T.VersionedHostCoinPaymentCreateReceivableRequest;\nexport import VersionedHostCoinPaymentCreateReceivableResponse = T.VersionedHostCoinPaymentCreateReceivableResponse;\nexport import VersionedHostCoinPaymentDeletePurseError = T.VersionedHostCoinPaymentDeletePurseError;\nexport import VersionedHostCoinPaymentDeletePurseItem = T.VersionedHostCoinPaymentDeletePurseItem;\nexport import VersionedHostCoinPaymentDeletePurseRequest = T.VersionedHostCoinPaymentDeletePurseRequest;\nexport import VersionedHostCoinPaymentDepositError = T.VersionedHostCoinPaymentDepositError;\nexport import VersionedHostCoinPaymentDepositItem = T.VersionedHostCoinPaymentDepositItem;\nexport import VersionedHostCoinPaymentDepositRequest = T.VersionedHostCoinPaymentDepositRequest;\nexport import VersionedHostCoinPaymentListenForError = T.VersionedHostCoinPaymentListenForError;\nexport import VersionedHostCoinPaymentListenForItem = T.VersionedHostCoinPaymentListenForItem;\nexport import VersionedHostCoinPaymentListenForRequest = T.VersionedHostCoinPaymentListenForRequest;\nexport import VersionedHostCoinPaymentQueryPurseError = T.VersionedHostCoinPaymentQueryPurseError;\nexport import VersionedHostCoinPaymentQueryPurseRequest = T.VersionedHostCoinPaymentQueryPurseRequest;\nexport import VersionedHostCoinPaymentQueryPurseResponse = T.VersionedHostCoinPaymentQueryPurseResponse;\nexport import VersionedHostCoinPaymentRebalancePurseError = T.VersionedHostCoinPaymentRebalancePurseError;\nexport import VersionedHostCoinPaymentRebalancePurseItem = T.VersionedHostCoinPaymentRebalancePurseItem;\nexport import VersionedHostCoinPaymentRebalancePurseRequest = T.VersionedHostCoinPaymentRebalancePurseRequest;\nexport import VersionedHostCoinPaymentRefundError = T.VersionedHostCoinPaymentRefundError;\nexport import VersionedHostCoinPaymentRefundItem = T.VersionedHostCoinPaymentRefundItem;\nexport import VersionedHostCoinPaymentRefundRequest = T.VersionedHostCoinPaymentRefundRequest;\nexport import VersionedHostContactsPickError = T.VersionedHostContactsPickError;\nexport import VersionedHostContactsPickManyError = T.VersionedHostContactsPickManyError;\nexport import VersionedHostContactsPickManyRequest = T.VersionedHostContactsPickManyRequest;\nexport import VersionedHostContactsPickManyResponse = T.VersionedHostContactsPickManyResponse;\nexport import VersionedHostContactsPickRequest = T.VersionedHostContactsPickRequest;\nexport import VersionedHostContactsPickResponse = T.VersionedHostContactsPickResponse;\nexport import VersionedHostContactsPlaceLabelsError = T.VersionedHostContactsPlaceLabelsError;\nexport import VersionedHostContactsPlaceLabelsRequest = T.VersionedHostContactsPlaceLabelsRequest;\nexport import VersionedHostContactsPlaceLabelsResponse = T.VersionedHostContactsPlaceLabelsResponse;\nexport import VersionedHostCreateTransactionError = T.VersionedHostCreateTransactionError;\nexport import VersionedHostCreateTransactionRequest = T.VersionedHostCreateTransactionRequest;\nexport import VersionedHostCreateTransactionResponse = T.VersionedHostCreateTransactionResponse;\nexport import VersionedHostCreateTransactionWithLegacyAccountError = T.VersionedHostCreateTransactionWithLegacyAccountError;\nexport import VersionedHostCreateTransactionWithLegacyAccountRequest = T.VersionedHostCreateTransactionWithLegacyAccountRequest;\nexport import VersionedHostCreateTransactionWithLegacyAccountResponse = T.VersionedHostCreateTransactionWithLegacyAccountResponse;\nexport import VersionedHostDeriveEntropyError = T.VersionedHostDeriveEntropyError;\nexport import VersionedHostDeriveEntropyRequest = T.VersionedHostDeriveEntropyRequest;\nexport import VersionedHostDeriveEntropyResponse = T.VersionedHostDeriveEntropyResponse;\nexport import VersionedHostDevicePermissionError = T.VersionedHostDevicePermissionError;\nexport import VersionedHostDevicePermissionRequest = T.VersionedHostDevicePermissionRequest;\nexport import VersionedHostDevicePermissionResponse = T.VersionedHostDevicePermissionResponse;\nexport import VersionedHostFeatureSupportedError = T.VersionedHostFeatureSupportedError;\nexport import VersionedHostFeatureSupportedRequest = T.VersionedHostFeatureSupportedRequest;\nexport import VersionedHostFeatureSupportedResponse = T.VersionedHostFeatureSupportedResponse;\nexport import VersionedHostGetLegacyAccountsError = T.VersionedHostGetLegacyAccountsError;\nexport import VersionedHostGetLegacyAccountsRequest = T.VersionedHostGetLegacyAccountsRequest;\nexport import VersionedHostGetLegacyAccountsResponse = T.VersionedHostGetLegacyAccountsResponse;\nexport import VersionedHostGetProductContextError = T.VersionedHostGetProductContextError;\nexport import VersionedHostGetProductContextRequest = T.VersionedHostGetProductContextRequest;\nexport import VersionedHostGetProductContextResponse = T.VersionedHostGetProductContextResponse;\nexport import VersionedHostGetUserIdError = T.VersionedHostGetUserIdError;\nexport import VersionedHostGetUserIdRequest = T.VersionedHostGetUserIdRequest;\nexport import VersionedHostGetUserIdResponse = T.VersionedHostGetUserIdResponse;\nexport import VersionedHostHandshakeError = T.VersionedHostHandshakeError;\nexport import VersionedHostHandshakeRequest = T.VersionedHostHandshakeRequest;\nexport import VersionedHostHandshakeResponse = T.VersionedHostHandshakeResponse;\nexport import HostInfo = T.HostInfo;\nexport import VersionedHostInfoError = T.VersionedHostInfoError;\nexport import VersionedHostInfoRequest = T.VersionedHostInfoRequest;\nexport import VersionedHostInfoResponse = T.VersionedHostInfoResponse;\nexport import VersionedHostLocalStorageChangeItem = T.VersionedHostLocalStorageChangeItem;\nexport import VersionedHostLocalStorageClearError = T.VersionedHostLocalStorageClearError;\nexport import VersionedHostLocalStorageClearRequest = T.VersionedHostLocalStorageClearRequest;\nexport import VersionedHostLocalStorageClearResponse = T.VersionedHostLocalStorageClearResponse;\nexport import VersionedHostLocalStorageReadError = T.VersionedHostLocalStorageReadError;\nexport import VersionedHostLocalStorageReadRequest = T.VersionedHostLocalStorageReadRequest;\nexport import VersionedHostLocalStorageReadResponse = T.VersionedHostLocalStorageReadResponse;\nexport import VersionedHostLocalStorageSubscribeError = T.VersionedHostLocalStorageSubscribeError;\nexport import VersionedHostLocalStorageSubscribeRequest = T.VersionedHostLocalStorageSubscribeRequest;\nexport import VersionedHostLocalStorageWriteError = T.VersionedHostLocalStorageWriteError;\nexport import VersionedHostLocalStorageWriteRequest = T.VersionedHostLocalStorageWriteRequest;\nexport import VersionedHostLocalStorageWriteResponse = T.VersionedHostLocalStorageWriteResponse;\nexport import VersionedHostLocaleLocalizeTimestampsError = T.VersionedHostLocaleLocalizeTimestampsError;\nexport import VersionedHostLocaleLocalizeTimestampsRequest = T.VersionedHostLocaleLocalizeTimestampsRequest;\nexport import VersionedHostLocaleLocalizeTimestampsResponse = T.VersionedHostLocaleLocalizeTimestampsResponse;\nexport import HostLocaleLocalizedTimestamp = T.HostLocaleLocalizedTimestamp;\nexport import VersionedHostLocaleSubscribeError = T.VersionedHostLocaleSubscribeError;\nexport import VersionedHostLocaleSubscribeItem = T.VersionedHostLocaleSubscribeItem;\nexport import VersionedHostLocaleSubscribeRequest = T.VersionedHostLocaleSubscribeRequest;\nexport import HostNativeChatAcknowledgment = T.HostNativeChatAcknowledgment;\nexport import HostNativeChatAttachment = T.HostNativeChatAttachment;\nexport import HostNativeChatAttachmentKind = T.HostNativeChatAttachmentKind;\nexport import HostNativeChatAttachmentMetadata = T.HostNativeChatAttachmentMetadata;\nexport import HostNativeChatAttachmentState = T.HostNativeChatAttachmentState;\nexport import HostNativeChatBinding = T.HostNativeChatBinding;\nexport import HostNativeChatDevice = T.HostNativeChatDevice;\nexport import HostNativeChatInvitation = T.HostNativeChatInvitation;\nexport import HostNativeChatMessages = T.HostNativeChatMessages;\nexport import HostNativeChatMigrationInvitation = T.HostNativeChatMigrationInvitation;\nexport import HostNativeChatOpenPage = T.HostNativeChatOpenPage;\nexport import HostNativeChatOpened = T.HostNativeChatOpened;\nexport import HostNativeChatPayment = T.HostNativeChatPayment;\nexport import HostNativeChatPaymentDirection = T.HostNativeChatPaymentDirection;\nexport import HostNativeChatPaymentFailure = T.HostNativeChatPaymentFailure;\nexport import HostNativeChatPaymentState = T.HostNativeChatPaymentState;\nexport import HostNativeChatPeer = T.HostNativeChatPeer;\nexport import HostNativeChatPeerDevice = T.HostNativeChatPeerDevice;\nexport import HostNativeChatPrepared = T.HostNativeChatPrepared;\nexport import HostNativeChatRichMessage = T.HostNativeChatRichMessage;\nexport import HostNativeChatRichMessageKind = T.HostNativeChatRichMessageKind;\nexport import HostNativeChatRoute = T.HostNativeChatRoute;\nexport import HostNativeChatStatePage = T.HostNativeChatStatePage;\nexport import VersionedHostNavigateToError = T.VersionedHostNavigateToError;\nexport import VersionedHostNavigateToRequest = T.VersionedHostNavigateToRequest;\nexport import VersionedHostNavigateToResponse = T.VersionedHostNavigateToResponse;\nexport import VersionedHostPaymentBalanceSubscribeError = T.VersionedHostPaymentBalanceSubscribeError;\nexport import VersionedHostPaymentBalanceSubscribeItem = T.VersionedHostPaymentBalanceSubscribeItem;\nexport import VersionedHostPaymentBalanceSubscribeRequest = T.VersionedHostPaymentBalanceSubscribeRequest;\nexport import VersionedHostPaymentError = T.VersionedHostPaymentError;\nexport import VersionedHostPaymentRequest = T.VersionedHostPaymentRequest;\nexport import VersionedHostPaymentResponse = T.VersionedHostPaymentResponse;\nexport import VersionedHostPaymentStatusSubscribeError = T.VersionedHostPaymentStatusSubscribeError;\nexport import VersionedHostPaymentStatusSubscribeItem = T.VersionedHostPaymentStatusSubscribeItem;\nexport import VersionedHostPaymentStatusSubscribeRequest = T.VersionedHostPaymentStatusSubscribeRequest;\nexport import VersionedHostPaymentTopUpError = T.VersionedHostPaymentTopUpError;\nexport import VersionedHostPaymentTopUpRequest = T.VersionedHostPaymentTopUpRequest;\nexport import VersionedHostPaymentTopUpResponse = T.VersionedHostPaymentTopUpResponse;\nexport import HostPlatform = T.HostPlatform;\nexport import VersionedHostPocketListSubscribeError = T.VersionedHostPocketListSubscribeError;\nexport import VersionedHostPocketListSubscribeItem = T.VersionedHostPocketListSubscribeItem;\nexport import VersionedHostPocketListSubscribeRequest = T.VersionedHostPocketListSubscribeRequest;\nexport import VersionedHostPocketRemoveCardError = T.VersionedHostPocketRemoveCardError;\nexport import VersionedHostPocketRemoveCardRequest = T.VersionedHostPocketRemoveCardRequest;\nexport import VersionedHostPocketRemoveCardResponse = T.VersionedHostPocketRemoveCardResponse;\nexport import VersionedHostProductDeviceChatError = T.VersionedHostProductDeviceChatError;\nexport import VersionedHostProductDeviceChatRequest = T.VersionedHostProductDeviceChatRequest;\nexport import VersionedHostProductDeviceChatResponse = T.VersionedHostProductDeviceChatResponse;\nexport import VersionedHostProfileDiscloseError = T.VersionedHostProfileDiscloseError;\nexport import VersionedHostProfileDiscloseRequest = T.VersionedHostProfileDiscloseRequest;\nexport import VersionedHostProfileDiscloseResponse = T.VersionedHostProfileDiscloseResponse;\nexport import VersionedHostProfileOwnStatusError = T.VersionedHostProfileOwnStatusError;\nexport import VersionedHostProfileOwnStatusRequest = T.VersionedHostProfileOwnStatusRequest;\nexport import VersionedHostProfileOwnStatusResponse = T.VersionedHostProfileOwnStatusResponse;\nexport import VersionedHostProfilePlaceContactAvatarsError = T.VersionedHostProfilePlaceContactAvatarsError;\nexport import VersionedHostProfilePlaceContactAvatarsRequest = T.VersionedHostProfilePlaceContactAvatarsRequest;\nexport import VersionedHostProfilePlaceContactAvatarsResponse = T.VersionedHostProfilePlaceContactAvatarsResponse;\nexport import VersionedHostProfilePresentContactError = T.VersionedHostProfilePresentContactError;\nexport import VersionedHostProfilePresentContactRequest = T.VersionedHostProfilePresentContactRequest;\nexport import VersionedHostProfilePresentContactResponse = T.VersionedHostProfilePresentContactResponse;\nexport import VersionedHostProfilePresentError = T.VersionedHostProfilePresentError;\nexport import VersionedHostProfilePresentOwnError = T.VersionedHostProfilePresentOwnError;\nexport import VersionedHostProfilePresentOwnRequest = T.VersionedHostProfilePresentOwnRequest;\nexport import VersionedHostProfilePresentOwnResponse = T.VersionedHostProfilePresentOwnResponse;\nexport import VersionedHostProfilePresentRequest = T.VersionedHostProfilePresentRequest;\nexport import VersionedHostProfilePresentResponse = T.VersionedHostProfilePresentResponse;\nexport import VersionedHostProfileRetractError = T.VersionedHostProfileRetractError;\nexport import VersionedHostProfileRetractRequest = T.VersionedHostProfileRetractRequest;\nexport import VersionedHostProfileRetractResponse = T.VersionedHostProfileRetractResponse;\nexport import VersionedHostPushNotificationCancelError = T.VersionedHostPushNotificationCancelError;\nexport import VersionedHostPushNotificationCancelRequest = T.VersionedHostPushNotificationCancelRequest;\nexport import VersionedHostPushNotificationCancelResponse = T.VersionedHostPushNotificationCancelResponse;\nexport import VersionedHostPushNotificationError = T.VersionedHostPushNotificationError;\nexport import VersionedHostPushNotificationRequest = T.VersionedHostPushNotificationRequest;\nexport import VersionedHostPushNotificationResponse = T.VersionedHostPushNotificationResponse;\nexport import VersionedHostRendererActionSubscribeError = T.VersionedHostRendererActionSubscribeError;\nexport import VersionedHostRendererActionSubscribeItem = T.VersionedHostRendererActionSubscribeItem;\nexport import VersionedHostRendererActionSubscribeRequest = T.VersionedHostRendererActionSubscribeRequest;\nexport import VersionedHostRequestLoginError = T.VersionedHostRequestLoginError;\nexport import VersionedHostRequestLoginRequest = T.VersionedHostRequestLoginRequest;\nexport import VersionedHostRequestLoginResponse = T.VersionedHostRequestLoginResponse;\nexport import VersionedHostRequestResourceAllocationError = T.VersionedHostRequestResourceAllocationError;\nexport import VersionedHostRequestResourceAllocationRequest = T.VersionedHostRequestResourceAllocationRequest;\nexport import VersionedHostRequestResourceAllocationResponse = T.VersionedHostRequestResourceAllocationResponse;\nexport import HostSignPayloadData = T.HostSignPayloadData;\nexport import VersionedHostSignPayloadError = T.VersionedHostSignPayloadError;\nexport import VersionedHostSignPayloadRequest = T.VersionedHostSignPayloadRequest;\nexport import VersionedHostSignPayloadResponse = T.VersionedHostSignPayloadResponse;\nexport import VersionedHostSignPayloadWithLegacyAccountError = T.VersionedHostSignPayloadWithLegacyAccountError;\nexport import VersionedHostSignPayloadWithLegacyAccountRequest = T.VersionedHostSignPayloadWithLegacyAccountRequest;\nexport import VersionedHostSignPayloadWithLegacyAccountResponse = T.VersionedHostSignPayloadWithLegacyAccountResponse;\nexport import VersionedHostSignRawError = T.VersionedHostSignRawError;\nexport import VersionedHostSignRawRequest = T.VersionedHostSignRawRequest;\nexport import VersionedHostSignRawResponse = T.VersionedHostSignRawResponse;\nexport import VersionedHostSignRawWithLegacyAccountError = T.VersionedHostSignRawWithLegacyAccountError;\nexport import VersionedHostSignRawWithLegacyAccountRequest = T.VersionedHostSignRawWithLegacyAccountRequest;\nexport import VersionedHostSignRawWithLegacyAccountResponse = T.VersionedHostSignRawWithLegacyAccountResponse;\nexport import VersionedHostThemeSubscribeError = T.VersionedHostThemeSubscribeError;\nexport import VersionedHostThemeSubscribeItem = T.VersionedHostThemeSubscribeItem;\nexport import VersionedHostThemeSubscribeRequest = T.VersionedHostThemeSubscribeRequest;\nexport import VersionedHostWorkerBeginOperationError = T.VersionedHostWorkerBeginOperationError;\nexport import VersionedHostWorkerBeginOperationRequest = T.VersionedHostWorkerBeginOperationRequest;\nexport import VersionedHostWorkerBeginOperationResponse = T.VersionedHostWorkerBeginOperationResponse;\nexport import VersionedHostWorkerEndOperationError = T.VersionedHostWorkerEndOperationError;\nexport import VersionedHostWorkerEndOperationRequest = T.VersionedHostWorkerEndOperationRequest;\nexport import VersionedHostWorkerEndOperationResponse = T.VersionedHostWorkerEndOperationResponse;\nexport import HostWorkerOperationError = T.HostWorkerOperationError;\nexport import ImageFit = T.ImageFit;\nexport import ImageProps = T.ImageProps;\nexport import ImageSource = T.ImageSource;\nexport import LegacyAccount = T.LegacyAccount;\nexport import LegacyAccountTxPayload = T.LegacyAccountTxPayload;\nexport import Modifier = T.Modifier;\nexport import OperationStartedResult = T.OperationStartedResult;\nexport import OwnAvatarSlot = T.OwnAvatarSlot;\nexport import PaymentTopUpSource = T.PaymentTopUpSource;\nexport import PocketCard = T.PocketCard;\nexport import PreimageSubmitError = T.PreimageSubmitError;\nexport import ProductAccount = T.ProductAccount;\nexport import ProductAccountId = T.ProductAccountId;\nexport import ProductAccountTxPayload = T.ProductAccountTxPayload;\nexport import ProductProofContext = T.ProductProofContext;\nexport import VersionedProductRendererRenderError = T.VersionedProductRendererRenderError;\nexport import VersionedProductRendererRenderItem = T.VersionedProductRendererRenderItem;\nexport import VersionedProductRendererRenderRequest = T.VersionedProductRendererRenderRequest;\nexport import ProfileAudience = T.ProfileAudience;\nexport import ProfileContact = T.ProfileContact;\nexport import RawPayload = T.RawPayload;\nexport import RegisteredRingVrfKey = T.RegisteredRingVrfKey;\nexport import VersionedRemoteChainHeadBodyError = T.VersionedRemoteChainHeadBodyError;\nexport import VersionedRemoteChainHeadBodyRequest = T.VersionedRemoteChainHeadBodyRequest;\nexport import VersionedRemoteChainHeadBodyResponse = T.VersionedRemoteChainHeadBodyResponse;\nexport import VersionedRemoteChainHeadCallError = T.VersionedRemoteChainHeadCallError;\nexport import VersionedRemoteChainHeadCallRequest = T.VersionedRemoteChainHeadCallRequest;\nexport import VersionedRemoteChainHeadCallResponse = T.VersionedRemoteChainHeadCallResponse;\nexport import VersionedRemoteChainHeadContinueError = T.VersionedRemoteChainHeadContinueError;\nexport import VersionedRemoteChainHeadContinueRequest = T.VersionedRemoteChainHeadContinueRequest;\nexport import VersionedRemoteChainHeadContinueResponse = T.VersionedRemoteChainHeadContinueResponse;\nexport import VersionedRemoteChainHeadFollowError = T.VersionedRemoteChainHeadFollowError;\nexport import VersionedRemoteChainHeadFollowItem = T.VersionedRemoteChainHeadFollowItem;\nexport import VersionedRemoteChainHeadFollowRequest = T.VersionedRemoteChainHeadFollowRequest;\nexport import VersionedRemoteChainHeadHeaderError = T.VersionedRemoteChainHeadHeaderError;\nexport import VersionedRemoteChainHeadHeaderRequest = T.VersionedRemoteChainHeadHeaderRequest;\nexport import VersionedRemoteChainHeadHeaderResponse = T.VersionedRemoteChainHeadHeaderResponse;\nexport import VersionedRemoteChainHeadStopOperationError = T.VersionedRemoteChainHeadStopOperationError;\nexport import VersionedRemoteChainHeadStopOperationRequest = T.VersionedRemoteChainHeadStopOperationRequest;\nexport import VersionedRemoteChainHeadStopOperationResponse = T.VersionedRemoteChainHeadStopOperationResponse;\nexport import VersionedRemoteChainHeadStorageError = T.VersionedRemoteChainHeadStorageError;\nexport import VersionedRemoteChainHeadStorageRequest = T.VersionedRemoteChainHeadStorageRequest;\nexport import VersionedRemoteChainHeadStorageResponse = T.VersionedRemoteChainHeadStorageResponse;\nexport import VersionedRemoteChainHeadUnpinError = T.VersionedRemoteChainHeadUnpinError;\nexport import VersionedRemoteChainHeadUnpinRequest = T.VersionedRemoteChainHeadUnpinRequest;\nexport import VersionedRemoteChainHeadUnpinResponse = T.VersionedRemoteChainHeadUnpinResponse;\nexport import VersionedRemoteChainInfoError = T.VersionedRemoteChainInfoError;\nexport import VersionedRemoteChainInfoRequest = T.VersionedRemoteChainInfoRequest;\nexport import VersionedRemoteChainInfoResponse = T.VersionedRemoteChainInfoResponse;\nexport import VersionedRemoteChainSpecChainNameError = T.VersionedRemoteChainSpecChainNameError;\nexport import VersionedRemoteChainSpecChainNameRequest = T.VersionedRemoteChainSpecChainNameRequest;\nexport import VersionedRemoteChainSpecChainNameResponse = T.VersionedRemoteChainSpecChainNameResponse;\nexport import VersionedRemoteChainSpecGenesisHashError = T.VersionedRemoteChainSpecGenesisHashError;\nexport import VersionedRemoteChainSpecGenesisHashRequest = T.VersionedRemoteChainSpecGenesisHashRequest;\nexport import VersionedRemoteChainSpecGenesisHashResponse = T.VersionedRemoteChainSpecGenesisHashResponse;\nexport import VersionedRemoteChainSpecPropertiesError = T.VersionedRemoteChainSpecPropertiesError;\nexport import VersionedRemoteChainSpecPropertiesRequest = T.VersionedRemoteChainSpecPropertiesRequest;\nexport import VersionedRemoteChainSpecPropertiesResponse = T.VersionedRemoteChainSpecPropertiesResponse;\nexport import VersionedRemoteChainTransactionBroadcastError = T.VersionedRemoteChainTransactionBroadcastError;\nexport import VersionedRemoteChainTransactionBroadcastRequest = T.VersionedRemoteChainTransactionBroadcastRequest;\nexport import VersionedRemoteChainTransactionBroadcastResponse = T.VersionedRemoteChainTransactionBroadcastResponse;\nexport import VersionedRemoteChainTransactionStopError = T.VersionedRemoteChainTransactionStopError;\nexport import VersionedRemoteChainTransactionStopRequest = T.VersionedRemoteChainTransactionStopRequest;\nexport import VersionedRemoteChainTransactionStopResponse = T.VersionedRemoteChainTransactionStopResponse;\nexport import RemotePermission = T.RemotePermission;\nexport import VersionedRemotePermissionError = T.VersionedRemotePermissionError;\nexport import VersionedRemotePermissionRequest = T.VersionedRemotePermissionRequest;\nexport import VersionedRemotePermissionResponse = T.VersionedRemotePermissionResponse;\nexport import VersionedRemotePreimageLookupSubscribeError = T.VersionedRemotePreimageLookupSubscribeError;\nexport import VersionedRemotePreimageLookupSubscribeItem = T.VersionedRemotePreimageLookupSubscribeItem;\nexport import VersionedRemotePreimageLookupSubscribeRequest = T.VersionedRemotePreimageLookupSubscribeRequest;\nexport import VersionedRemotePreimageSubmitError = T.VersionedRemotePreimageSubmitError;\nexport import VersionedRemotePreimageSubmitRequest = T.VersionedRemotePreimageSubmitRequest;\nexport import VersionedRemotePreimageSubmitResponse = T.VersionedRemotePreimageSubmitResponse;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedError = T.VersionedRemoteStatementStoreCreateProofAuthorizedError;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedRequest = T.VersionedRemoteStatementStoreCreateProofAuthorizedRequest;\nexport import VersionedRemoteStatementStoreCreateProofAuthorizedResponse = T.VersionedRemoteStatementStoreCreateProofAuthorizedResponse;\nexport import VersionedRemoteStatementStoreCreateProofError = T.VersionedRemoteStatementStoreCreateProofError;\nexport import VersionedRemoteStatementStoreCreateProofRequest = T.VersionedRemoteStatementStoreCreateProofRequest;\nexport import VersionedRemoteStatementStoreCreateProofResponse = T.VersionedRemoteStatementStoreCreateProofResponse;\nexport import VersionedRemoteStatementStoreSubmitError = T.VersionedRemoteStatementStoreSubmitError;\nexport import VersionedRemoteStatementStoreSubmitRequest = T.VersionedRemoteStatementStoreSubmitRequest;\nexport import VersionedRemoteStatementStoreSubmitResponse = T.VersionedRemoteStatementStoreSubmitResponse;\nexport import VersionedRemoteStatementStoreSubscribeError = T.VersionedRemoteStatementStoreSubscribeError;\nexport import VersionedRemoteStatementStoreSubscribeItem = T.VersionedRemoteStatementStoreSubscribeItem;\nexport import VersionedRemoteStatementStoreSubscribeRequest = T.VersionedRemoteStatementStoreSubscribeRequest;\nexport import RenderContext = T.RenderContext;\nexport import RendererNode = T.RendererNode;\nexport import ResourceAllocationError = T.ResourceAllocationError;\nexport import RingLocation = T.RingLocation;\nexport import RingLocationJunction = T.RingLocationJunction;\nexport import RingVrfKeyDisclosure = T.RingVrfKeyDisclosure;\nexport import RowProps = T.RowProps;\nexport import RuntimeApi = T.RuntimeApi;\nexport import RuntimeSpec = T.RuntimeSpec;\nexport import RuntimeType = T.RuntimeType;\nexport import Shape = T.Shape;\nexport import SignedStatement = T.SignedStatement;\nexport import Size = T.Size;\nexport import Statement = T.Statement;\nexport import StatementProof = T.StatementProof;\nexport import StorageQueryItem = T.StorageQueryItem;\nexport import StorageQueryType = T.StorageQueryType;\nexport import StorageResultItem = T.StorageResultItem;\nexport import TextFieldProps = T.TextFieldProps;\nexport import TextProps = T.TextProps;\nexport import ThemeName = T.ThemeName;\nexport import ThemeVariant = T.ThemeVariant;\nexport import TxPayloadExtension = T.TxPayloadExtension;\nexport import TypographyStyle = T.TypographyStyle;\nexport import ContactAvatarSlot = T.ContactAvatarSlot;\nexport import HostAccountConnectionStatusSubscribeItem = T.HostAccountConnectionStatusSubscribeItem;\nexport import HostAccountCreateProofError = T.HostAccountCreateProofError;\nexport import HostAccountCreateProofRequest = T.HostAccountCreateProofRequest;\nexport import HostAccountCreateProofResponse = T.HostAccountCreateProofResponse;\nexport import HostAccountGetAliasError = T.HostAccountGetAliasError;\nexport import HostAccountGetAliasRequest = T.HostAccountGetAliasRequest;\nexport import HostAccountGetError = T.HostAccountGetError;\nexport import HostAccountGetRequest = T.HostAccountGetRequest;\nexport import HostAccountGetResponse = T.HostAccountGetResponse;\nexport import HostAccountListRingVrfKeysError = T.HostAccountListRingVrfKeysError;\nexport import HostAccountListRingVrfKeysRequest = T.HostAccountListRingVrfKeysRequest;\nexport import HostAccountRegisterRingVrfKeyError = T.HostAccountRegisterRingVrfKeyError;\nexport import HostAccountRegisterRingVrfKeyRequest = T.HostAccountRegisterRingVrfKeyRequest;\nexport import HostAccountRingVrfSignError = T.HostAccountRingVrfSignError;\nexport import HostAccountRingVrfSignRequest = T.HostAccountRingVrfSignRequest;\nexport import HostAccountSignVrfError = T.HostAccountSignVrfError;\nexport import HostAccountSignVrfRequest = T.HostAccountSignVrfRequest;\nexport import HostChatActionSubscribeItem = T.HostChatActionSubscribeItem;\nexport import HostChatCreateRoomError = T.HostChatCreateRoomError;\nexport import HostChatCreateRoomRequest = T.HostChatCreateRoomRequest;\nexport import HostChatCreateRoomResponse = T.HostChatCreateRoomResponse;\nexport import HostChatListSubscribeItem = T.HostChatListSubscribeItem;\nexport import HostChatPostMessageError = T.HostChatPostMessageError;\nexport import HostChatPostMessageRequest = T.HostChatPostMessageRequest;\nexport import HostChatPostMessageResponse = T.HostChatPostMessageResponse;\nexport import HostChatRegisterBotError = T.HostChatRegisterBotError;\nexport import HostChatRegisterBotRequest = T.HostChatRegisterBotRequest;\nexport import HostChatRegisterBotResponse = T.HostChatRegisterBotResponse;\nexport import HostCoinPaymentCreateChequeRequest = T.HostCoinPaymentCreateChequeRequest;\nexport import HostCoinPaymentCreateChequeResponse = T.HostCoinPaymentCreateChequeResponse;\nexport import HostCoinPaymentCreatePurseRequest = T.HostCoinPaymentCreatePurseRequest;\nexport import HostCoinPaymentCreatePurseResponse = T.HostCoinPaymentCreatePurseResponse;\nexport import HostCoinPaymentCreateReceivableRequest = T.HostCoinPaymentCreateReceivableRequest;\nexport import HostCoinPaymentCreateReceivableResponse = T.HostCoinPaymentCreateReceivableResponse;\nexport import HostCoinPaymentDeletePurseRequest = T.HostCoinPaymentDeletePurseRequest;\nexport import HostCoinPaymentDepositRequest = T.HostCoinPaymentDepositRequest;\nexport import HostCoinPaymentListenForItem = T.HostCoinPaymentListenForItem;\nexport import HostCoinPaymentListenForRequest = T.HostCoinPaymentListenForRequest;\nexport import HostCoinPaymentQueryPurseRequest = T.HostCoinPaymentQueryPurseRequest;\nexport import HostCoinPaymentQueryPurseResponse = T.HostCoinPaymentQueryPurseResponse;\nexport import HostCoinPaymentRebalancePurseRequest = T.HostCoinPaymentRebalancePurseRequest;\nexport import HostCoinPaymentRefundRequest = T.HostCoinPaymentRefundRequest;\nexport import HostContactsPickError = T.HostContactsPickError;\nexport import HostContactsPickManyError = T.HostContactsPickManyError;\nexport import HostContactsPickManyRequest = T.HostContactsPickManyRequest;\nexport import HostContactsPickManyResponse = T.HostContactsPickManyResponse;\nexport import HostContactsPickRequest = T.HostContactsPickRequest;\nexport import HostContactsPickResponse = T.HostContactsPickResponse;\nexport import HostContactsPlaceLabelsError = T.HostContactsPlaceLabelsError;\nexport import HostContactsPlaceLabelsRequest = T.HostContactsPlaceLabelsRequest;\nexport import HostContactsPlaceLabelsResponse = T.HostContactsPlaceLabelsResponse;\nexport import HostCreateTransactionError = T.HostCreateTransactionError;\nexport import HostCreateTransactionResponse = T.HostCreateTransactionResponse;\nexport import HostCreateTransactionWithLegacyAccountResponse = T.HostCreateTransactionWithLegacyAccountResponse;\nexport import HostDeriveEntropyError = T.HostDeriveEntropyError;\nexport import HostDeriveEntropyRequest = T.HostDeriveEntropyRequest;\nexport import HostDeriveEntropyResponse = T.HostDeriveEntropyResponse;\nexport import HostDevicePermissionRequest = T.HostDevicePermissionRequest;\nexport import HostDevicePermissionResponse = T.HostDevicePermissionResponse;\nexport import HostFeatureSupportedRequest = T.HostFeatureSupportedRequest;\nexport import HostFeatureSupportedResponse = T.HostFeatureSupportedResponse;\nexport import HostGetLegacyAccountsResponse = T.HostGetLegacyAccountsResponse;\nexport import HostGetProductContextResponse = T.HostGetProductContextResponse;\nexport import HostGetUserIdError = T.HostGetUserIdError;\nexport import HostGetUserIdResponse = T.HostGetUserIdResponse;\nexport import HostHandshakeError = T.HostHandshakeError;\nexport import HostHandshakeRequest = T.HostHandshakeRequest;\nexport import HostLocalStorageChangeItem = T.HostLocalStorageChangeItem;\nexport import HostLocalStorageClearRequest = T.HostLocalStorageClearRequest;\nexport import V01HostLocalStorageReadError = T.V01HostLocalStorageReadError;\nexport import V01HostLocalStorageReadRequest = T.V01HostLocalStorageReadRequest;\nexport import HostLocalStorageReadResponse = T.HostLocalStorageReadResponse;\nexport import HostLocalStorageSubscribeRequest = T.HostLocalStorageSubscribeRequest;\nexport import HostLocalStorageWriteRequest = T.HostLocalStorageWriteRequest;\nexport import V01HostLocaleSubscribeItem = T.V01HostLocaleSubscribeItem;\nexport import HostNavigateToError = T.HostNavigateToError;\nexport import HostNavigateToRequest = T.HostNavigateToRequest;\nexport import HostPaymentBalanceSubscribeError = T.HostPaymentBalanceSubscribeError;\nexport import HostPaymentBalanceSubscribeItem = T.HostPaymentBalanceSubscribeItem;\nexport import HostPaymentBalanceSubscribeRequest = T.HostPaymentBalanceSubscribeRequest;\nexport import HostPaymentError = T.HostPaymentError;\nexport import HostPaymentRequest = T.HostPaymentRequest;\nexport import HostPaymentResponse = T.HostPaymentResponse;\nexport import HostPaymentStatusSubscribeError = T.HostPaymentStatusSubscribeError;\nexport import HostPaymentStatusSubscribeItem = T.HostPaymentStatusSubscribeItem;\nexport import HostPaymentStatusSubscribeRequest = T.HostPaymentStatusSubscribeRequest;\nexport import HostPaymentTopUpError = T.HostPaymentTopUpError;\nexport import HostPaymentTopUpRequest = T.HostPaymentTopUpRequest;\nexport import HostPocketListSubscribeItem = T.HostPocketListSubscribeItem;\nexport import HostPocketRemoveCardError = T.HostPocketRemoveCardError;\nexport import HostPocketRemoveCardRequest = T.HostPocketRemoveCardRequest;\nexport import HostProfileDiscloseError = T.HostProfileDiscloseError;\nexport import V01HostProfileDiscloseRequest = T.V01HostProfileDiscloseRequest;\nexport import HostProfileOwnStatusError = T.HostProfileOwnStatusError;\nexport import HostProfileOwnStatusResponse = T.HostProfileOwnStatusResponse;\nexport import HostProfilePlaceContactAvatarsError = T.HostProfilePlaceContactAvatarsError;\nexport import V01HostProfilePlaceContactAvatarsRequest = T.V01HostProfilePlaceContactAvatarsRequest;\nexport import HostProfilePresentContactError = T.HostProfilePresentContactError;\nexport import V01HostProfilePresentContactRequest = T.V01HostProfilePresentContactRequest;\nexport import HostProfilePresentError = T.HostProfilePresentError;\nexport import HostProfilePresentOwnError = T.HostProfilePresentOwnError;\nexport import HostProfilePresentRequest = T.HostProfilePresentRequest;\nexport import HostProfileRetractError = T.HostProfileRetractError;\nexport import HostPushNotificationCancelRequest = T.HostPushNotificationCancelRequest;\nexport import HostPushNotificationError = T.HostPushNotificationError;\nexport import HostPushNotificationRequest = T.HostPushNotificationRequest;\nexport import HostPushNotificationResponse = T.HostPushNotificationResponse;\nexport import HostRendererActionSubscribeItem = T.HostRendererActionSubscribeItem;\nexport import HostRequestLoginError = T.HostRequestLoginError;\nexport import HostRequestLoginRequest = T.HostRequestLoginRequest;\nexport import HostRequestLoginResponse = T.HostRequestLoginResponse;\nexport import HostRequestResourceAllocationRequest = T.HostRequestResourceAllocationRequest;\nexport import HostRequestResourceAllocationResponse = T.HostRequestResourceAllocationResponse;\nexport import HostSignPayloadError = T.HostSignPayloadError;\nexport import HostSignPayloadRequest = T.HostSignPayloadRequest;\nexport import HostSignPayloadResponse = T.HostSignPayloadResponse;\nexport import HostSignPayloadWithLegacyAccountRequest = T.HostSignPayloadWithLegacyAccountRequest;\nexport import HostSignRawRequest = T.HostSignRawRequest;\nexport import HostSignRawWithLegacyAccountRequest = T.HostSignRawWithLegacyAccountRequest;\nexport import HostThemeSubscribeItem = T.HostThemeSubscribeItem;\nexport import HostWorkerBeginOperationRequest = T.HostWorkerBeginOperationRequest;\nexport import HostWorkerBeginOperationResponse = T.HostWorkerBeginOperationResponse;\nexport import HostWorkerEndOperationRequest = T.HostWorkerEndOperationRequest;\nexport import ProductRendererRenderRequest = T.ProductRendererRenderRequest;\nexport import RemoteChainHeadBodyRequest = T.RemoteChainHeadBodyRequest;\nexport import RemoteChainHeadBodyResponse = T.RemoteChainHeadBodyResponse;\nexport import RemoteChainHeadCallRequest = T.RemoteChainHeadCallRequest;\nexport import RemoteChainHeadCallResponse = T.RemoteChainHeadCallResponse;\nexport import RemoteChainHeadContinueRequest = T.RemoteChainHeadContinueRequest;\nexport import RemoteChainHeadFollowItem = T.RemoteChainHeadFollowItem;\nexport import RemoteChainHeadFollowRequest = T.RemoteChainHeadFollowRequest;\nexport import RemoteChainHeadHeaderRequest = T.RemoteChainHeadHeaderRequest;\nexport import RemoteChainHeadHeaderResponse = T.RemoteChainHeadHeaderResponse;\nexport import RemoteChainHeadStopOperationRequest = T.RemoteChainHeadStopOperationRequest;\nexport import RemoteChainHeadStorageRequest = T.RemoteChainHeadStorageRequest;\nexport import RemoteChainHeadStorageResponse = T.RemoteChainHeadStorageResponse;\nexport import RemoteChainHeadUnpinRequest = T.RemoteChainHeadUnpinRequest;\nexport import RemoteChainInfoError = T.RemoteChainInfoError;\nexport import RemoteChainInfoRequest = T.RemoteChainInfoRequest;\nexport import RemoteChainInfoResponse = T.RemoteChainInfoResponse;\nexport import RemoteChainSpecChainNameRequest = T.RemoteChainSpecChainNameRequest;\nexport import RemoteChainSpecChainNameResponse = T.RemoteChainSpecChainNameResponse;\nexport import RemoteChainSpecGenesisHashRequest = T.RemoteChainSpecGenesisHashRequest;\nexport import RemoteChainSpecGenesisHashResponse = T.RemoteChainSpecGenesisHashResponse;\nexport import RemoteChainSpecPropertiesRequest = T.RemoteChainSpecPropertiesRequest;\nexport import RemoteChainSpecPropertiesResponse = T.RemoteChainSpecPropertiesResponse;\nexport import RemoteChainTransactionBroadcastRequest = T.RemoteChainTransactionBroadcastRequest;\nexport import RemoteChainTransactionBroadcastResponse = T.RemoteChainTransactionBroadcastResponse;\nexport import RemoteChainTransactionStopRequest = T.RemoteChainTransactionStopRequest;\nexport import RemotePermissionRequest = T.RemotePermissionRequest;\nexport import RemotePermissionResponse = T.RemotePermissionResponse;\nexport import RemotePreimageLookupSubscribeItem = T.RemotePreimageLookupSubscribeItem;\nexport import RemotePreimageLookupSubscribeRequest = T.RemotePreimageLookupSubscribeRequest;\nexport import RemoteStatementStoreCreateProofError = T.RemoteStatementStoreCreateProofError;\nexport import RemoteStatementStoreCreateProofRequest = T.RemoteStatementStoreCreateProofRequest;\nexport import RemoteStatementStoreCreateProofResponse = T.RemoteStatementStoreCreateProofResponse;\nexport import RemoteStatementStoreSubscribeItem = T.RemoteStatementStoreSubscribeItem;\nexport import RemoteStatementStoreSubscribeRequest = T.RemoteStatementStoreSubscribeRequest;\nexport import HostLocalStorageReadError = T.HostLocalStorageReadError;\nexport import HostLocalStorageReadRequest = T.HostLocalStorageReadRequest;\nexport import HostLocaleLocalizeTimestampsRequest = T.HostLocaleLocalizeTimestampsRequest;\nexport import HostLocaleLocalizeTimestampsResponse = T.HostLocaleLocalizeTimestampsResponse;\nexport import HostLocaleSubscribeItem = T.HostLocaleSubscribeItem;\nexport import HostProductDeviceChatError = T.HostProductDeviceChatError;\nexport import V02HostProductDeviceChatRequest = T.V02HostProductDeviceChatRequest;\nexport import V02HostProductDeviceChatResponse = T.V02HostProductDeviceChatResponse;\nexport import HostProfileDiscloseRequest = T.HostProfileDiscloseRequest;\nexport import V02HostProfilePlaceContactAvatarsRequest = T.V02HostProfilePlaceContactAvatarsRequest;\nexport import HostProfilePresentContactRequest = T.HostProfilePresentContactRequest;\nexport import V03ContactAvatarSlot = T.V03ContactAvatarSlot;\nexport import HostProductDeviceChatRequest = T.HostProductDeviceChatRequest;\nexport import HostProductDeviceChatResponse = T.HostProductDeviceChatResponse;\nexport import HostProfilePlaceContactAvatarsRequest = T.HostProfilePlaceContactAvatarsRequest;\nexport import VerticalAlignment = T.VerticalAlignment;\nexport import VrfSignature = T.VrfSignature;\nexport import VrfTranscriptItem = T.VrfTranscriptItem;\n\n// index.d.ts\n\n\n// transport.d.ts\n/**\n * Wire trait discriminant reserved for method-independent protocol errors. No\n * API trait may declare it, so no method is ever addressed here.\n **/\nexport declare const PROTOCOL_ERROR_TRAIT_ID: 255;\n/** Wire method discriminant reserved for method-independent protocol errors. **/\nexport declare const PROTOCOL_ERROR_METHOD_ID: 255;\n/** The peer rejected an outbound frame because it does not support its API. **/\nexport declare class UnsupportedMessageError extends Error {\n /** Trait discriminant of the unsupported outbound frame. **/\n readonly traitId: number;\n /** Method discriminant of the unsupported outbound frame. **/\n readonly methodId: number;\n constructor(traitId: number, methodId: number);\n}\n/** The host connection ended; interrupted operations are not retried. */\nexport declare class ConnectionResetError extends Error {\n constructor(options?: ErrorOptions);\n}\n/** Call result returned when the peer does not recognize a request frame. **/\nexport type UnsupportedCallError = Extract, {\n tag: \"Unsupported\";\n}>;\n/**\n * Handle returned by TrUAPI subscription APIs.\n **/\nexport interface Subscription {\n /**\n * Stop the subscription. Calling this more than once has no additional effect.\n **/\n unsubscribe: () => void;\n /**\n * Transport-assigned request id for the subscription start frame.\n *\n * Methods that accept a `followSubscriptionId` use this value to scope\n * follow-up requests to a specific active subscription.\n **/\n subscriptionId: string;\n}\n/**\n * Terminal error delivered through `Observer.error` for every non-normal\n * subscription end. When the peer interrupted the stream with a typed payload,\n * `reason` carries the decoded `Reason`; otherwise `reason` is `undefined` and\n * the underlying transport/decode error is preserved on `cause`.\n *\n * Discriminate with `error.reason !== undefined` (or `'reason' in error`).\n **/\nexport declare class SubscriptionError extends Error {\n /**\n * Typed payload supplied by the peer when it interrupted the subscription.\n * `undefined` when the stream ended for any other reason (transport close,\n * decode failure, malformed interrupt payload).\n **/\n readonly reason?: Reason;\n constructor(message: string, options?: {\n reason?: Reason;\n cause?: unknown;\n });\n}\n/**\n * Minimal Observable-compatible observer shape used by generated subscription\n * APIs without depending on RxJS.\n *\n * `Reason` is the typed interrupt payload for the originating subscription.\n * Methods without a typed interrupt resolve `Reason` to `never`, leaving\n * `error.reason` typed as `undefined`.\n **/\nexport interface Observer {\n /**\n * Called with each successfully decoded subscription item.\n **/\n next(value: Item): void;\n /**\n * Called once when the stream terminates with an error. Inspect\n * `error.reason` to distinguish a typed peer interrupt from a transport or\n * decode failure (`error.cause` carries the underlying failure in the\n * latter case).\n **/\n error(error: SubscriptionError): void;\n /**\n * Called once when the peer normally completes the stream.\n **/\n complete(): void;\n}\ndeclare global {\n interface SymbolConstructor {\n readonly observable: unique symbol;\n }\n}\n/**\n * Minimal Observable-compatible object returned by generated subscription APIs.\n *\n * Implements the ES Observable interop protocol so that consumers can pass\n * an instance straight to `rxjs.from(...)`.\n **/\nexport interface ObservableLike {\n /**\n * Start the stream and receive `next`, `error`, and `complete` callbacks.\n **/\n subscribe(observer?: Partial>): Subscription;\n /**\n * Observable interop hook. Returns `this`.\n **/\n [Symbol.observable](): ObservableLike;\n}\n/**\n * Product-side handler for a subscription the native host initiates.\n *\n * It receives the decoded request and two callbacks: `send` delivers one item\n * to the host, and `interrupt` ends the stream, cleanly when called with no\n * argument and with the method's interrupt value otherwise. The returned\n * teardown, if any, runs once the stream ends: on the host's stop frame, on\n * `interrupt`, when the transport closes, or when the host restarts the same\n * request id.\n **/\nexport type HostInitiatedSubscriptionHandler = (request: Request, send: (item: Item) => void, interrupt: (reason?: Reason) => void) => (() => void) | void;\n/**\n * Wire discriminant pair addressing a method. One id addresses a method\n * regardless of shape (request/response, or a subscription's four phases):\n * which leg of the exchange a frame carries is the wire's own `messageType`\n * byte, not a separate id per leg.\n **/\nexport interface MethodIds {\n /**\n * Wire trait discriminant.\n **/\n trait: number;\n /**\n * Wire method discriminant within the trait.\n **/\n method: number;\n /**\n * Whether this method's legs follow the request/response shape or the\n * subscription shape (`\"subscription\"` covers both plain and result\n * subscriptions, which share the same four-leg wire shape). The one piece\n * of shape a payload-blind reader needs to interpret a frame's own\n * `messageType` byte without decoding the payload.\n **/\n kind: \"request\" | \"subscription\";\n}\n/**\n * Per-call options every generated request method accepts as its last\n * argument.\n **/\nexport interface CallOptions {\n /** See {@link RequestParams.signal}. **/\n signal?: AbortSignal;\n}\n/**\n * Options accepted by `TrUApiTransport.request`.\n **/\nexport interface RequestParams {\n /**\n * Wire discriminants for this request method.\n **/\n ids: MethodIds;\n /**\n * SCALE-encoded request wrapper payload bytes (its own `V` tag is the\n * wire's only version signal), constructed by the generated caller.\n **/\n payload: Uint8Array;\n /**\n * Decode a `Response`-leg frame's raw payload bytes into the typed Ok/Err\n * outcome. Implementations decode `Result<{Method}Response,\n * CallError<{Method}Error>>` directly. The transport unwraps the result\n * into `ResultAsync`.\n **/\n decodeResponse: (payload: Uint8Array) => ResultPayload;\n /**\n * Withdraw the call. Aborting sends a `Cancel` frame on this method's own\n * address; the promise still settles on the response the host sends, which\n * for a call the host stopped is `CallError::Cancelled`. A signal already\n * aborted when the call is made sends nothing and rejects immediately.\n *\n * A host that predates the `Cancel` leg drops the frame, so an aborted call\n * against one settles on its deadline instead. There is no way to detect that\n * first: `system.featureSupported` answers only about chains, so an abort\n * against an older host is indistinguishable from one it honoured.\n **/\n signal?: AbortSignal;\n}\n/**\n * Options accepted by `TrUApiTransport.subscribeRaw`.\n **/\nexport interface SubscribeRawParams {\n /**\n * Wire discriminants for this subscription method.\n **/\n ids: MethodIds;\n /**\n * SCALE-encoded `Start`-leg payload bytes: the request wrapper's own\n * encoding, or empty bytes for a method with no request at all,\n * constructed by the generated caller.\n **/\n payload: Uint8Array;\n /**\n * Called with a `Receive`-leg frame's raw payload bytes.\n **/\n onReceive: (payload: Uint8Array) => void;\n /**\n * Called with an `Interrupt`-leg frame's raw payload bytes.\n **/\n onInterrupt?: (payload: Uint8Array) => void;\n /**\n * Called when a transport-level error or unsupported start frame terminates\n * the subscription.\n **/\n onClose?: (error: Error) => void;\n}\n/** Product-side registration for one host-initiated subscription method. **/\nexport interface HostInitiatedSubscriptionRegistration {\n /** Install or replace the handler used for future start frames. **/\n setHandler(handler: HostInitiatedSubscriptionHandler): {\n unsubscribe(): void;\n };\n}\n/** Options used to register a host-initiated subscription method. **/\nexport interface RegisterHostInitiatedSubscriptionParams {\n /** Wire discriminants for the host-initiated subscription. **/\n ids: MethodIds;\n /**\n * Decode a `Start`-leg frame's raw payload bytes into the typed request.\n **/\n decodeRequest(payload: Uint8Array): Request;\n /**\n * Encode one product emission as a `Receive`-leg frame's raw payload bytes.\n **/\n encodeItem(item: Item): Uint8Array;\n /**\n * Encode an `Interrupt`-leg frame's raw payload bytes: the stream's clean\n * end when `reason` is omitted, and the method's interrupt value otherwise.\n **/\n encodeInterrupt(reason?: Reason): Uint8Array;\n /**\n * Exact payload used when the transport ends a stream the product's handler\n * never got to serve.\n **/\n declinePayload: Uint8Array;\n /** Number of starts retained before a handler is installed. **/\n bufferCapacity: number;\n}\n/**\n * Byte-level transport used by generated client stubs.\n **/\nexport interface TrUApiTransport {\n /**\n * Send a one-shot request and resolve with the typed Ok/Err outcome.\n **/\n request(params: RequestParams): ResultAsync;\n /**\n * Start a subscription and return a handle that can stop it.\n **/\n subscribeRaw(params: SubscribeRawParams): Subscription;\n /** Register product-side handling for a host-initiated subscription. **/\n registerHostInitiatedSubscription(params: RegisterHostInitiatedSubscriptionParams): HostInitiatedSubscriptionRegistration;\n /**\n * Tear down the transport and release the listeners it registered on the\n * underlying `WireProvider`. Pending requests reject and live subscriptions\n * receive `onClose`. Idempotent.\n *\n * The provider itself is left alone; the caller decides whether to also\n * call `provider.dispose()` (long-lived hosts that swap providers will\n * typically dispose the transport but keep the provider).\n **/\n dispose(): void;\n}\n/**\n * Tagged payload inside a TrUAPI wire frame.\n **/\nexport interface Payload {\n /**\n * Wire-table trait discriminant: first byte of the `(trait, method)` pair.\n **/\n traitId: number;\n /**\n * Wire-table method discriminant within the trait: second byte of the pair.\n **/\n methodId: number;\n /**\n * Which leg of the method's exchange this frame carries: `Request`/`Start`\n * = 0, `Response`/`Receive` = 1, `Interrupt` = 2, `Stop` = 3. Third byte of\n * the wire frame \u2014 readable generically, without decoding `value`.\n **/\n messageType: number;\n /**\n * SCALE-encoded payload body: that leg's own versioned wrapper, with no\n * further tag identifying direction or version beyond the wrapper's own.\n **/\n value: Uint8Array;\n}\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_REQUEST = 0;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_START = 0;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_RESPONSE = 1;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_RECEIVE = 1;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_INTERRUPT = 2;\n/** See {@link Payload.messageType}. */\nexport declare const MESSAGE_TYPE_STOP = 3;\n/**\n * A request's withdrawal, correlated by the same `requestId` and carrying no\n * payload. The call still settles with exactly one response; this only fires\n * the handler's cancellation token on the far side.\n **/\nexport declare const MESSAGE_TYPE_CANCEL = 4;\n/**\n * Top-level TrUAPI wire message.\n **/\nexport interface ProtocolMessage {\n /**\n * Request id used to correlate request/response and subscription frames.\n **/\n requestId: string;\n /**\n * Tagged SCALE payload carried by this frame.\n **/\n payload: Payload;\n}\n/**\n * Raw SCALE-wire-frame pipe abstraction used by the transport. A `WireProvider`\n * is the low-level channel (a `MessagePort` or iframe `postMessage` link) that\n * carries encoded frames between the product and the host.\n **/\nexport interface WireProvider {\n /**\n * Send a complete SCALE-encoded wire frame to the peer.\n **/\n postMessage(message: Uint8Array): void;\n /**\n * Register a callback for inbound SCALE-encoded wire frames.\n **/\n subscribe(callback: (message: Uint8Array) => void): () => void;\n /**\n * Register a callback for provider-level close or failure events.\n *\n * Providers keep a terminal close reason. The callback fires at most once\n * for an active subscription, and fires immediately when registered after\n * the provider has already closed.\n **/\n subscribeClose?(callback: (error: Error) => void): () => void;\n /** End current operations while keeping the provider available for new work. */\n subscribeReset?(callback: (error: Error) => void): () => void;\n /**\n * Release provider resources and close the underlying pipe.\n **/\n dispose(): void;\n}\n/**\n * A {@link WireProvider} backed by a WebSocket, which reports when its socket\n * is up. Awaiting {@link WebSocketWireProvider.opened} is optional: frames\n * posted earlier are queued and flushed on open.\n **/\nexport interface WebSocketWireProvider extends WireProvider {\n /** Resolves once the socket is open, rejects if it never connects. */\n opened: Promise;\n}\n/**\n * Encode a `ProtocolMessage` into a SCALE wire frame.\n **/\nexport declare function encodeWireMessage(message: ProtocolMessage): Result;\n/**\n * Decode a SCALE wire frame into a `ProtocolMessage`.\n **/\nexport declare function decodeWireMessage(message: Uint8Array): Result;\n/**\n * Create a provider for the child side of an iframe `postMessage` channel.\n *\n * `target` is the `Window` the provider posts to (typically `window.parent`);\n * `hostOrigin` is the pinned `targetOrigin` for outbound frames and the\n * required `event.origin` of inbound frames. The provider only delivers\n * frames whose `event.source === target` and `event.origin === hostOrigin`,\n * so it cannot be coerced by an unrelated frame parent.\n **/\nexport declare function createIframeProvider(options: {\n target: Window;\n hostOrigin: string;\n}): WireProvider;\n/**\n * Create a provider from a web or Electron `MessagePort`.\n **/\nexport declare function createMessagePortProvider(port: MessagePort | Promise): WireProvider;\n/**\n * Wire provider over a binary WebSocket, one message per SCALE frame.\n *\n * This is the transport a host exposes on a loopback socket: the Rust core's\n * `ws-bridge`, and `truapi-host signing-host --frame-listen`. The frame bytes\n * are identical to what the {@link createMessagePortProvider} path carries, so\n * this is a pipe and nothing more.\n *\n * Frames posted before the socket opens are queued and flushed on open, so a\n * caller never has to await {@link WebSocketWireProvider.opened} first.\n **/\nexport declare function createWebSocketProvider(url: string): WebSocketWireProvider;\n/** Capture native socket APIs before product code installs network gates. */\nexport declare function createWebSocketProviderFactory(): (url: string) => WebSocketWireProvider;\n\n\n// client.d.ts\nexport type { Subscription, TrUApiTransport };\n/** A request received no matching response before its transport deadline. */\nexport declare class RequestTimeoutError extends Error {\n /** Transport-assigned request identifier. */\n readonly requestId: string;\n /** Trait discriminant of the unanswered request. */\n readonly traitId: number;\n /** Method discriminant of the unanswered request. */\n readonly methodId: number;\n /** Deadline that elapsed, in milliseconds. */\n readonly timeoutMs: number;\n constructor(requestId: string, traitId: number, methodId: number, timeoutMs: number);\n}\n/**\n * Options accepted when constructing a transport.\n */\nexport interface CreateTransportOptions {\n /** Request ID namespace when multiple transports share a connection. Defaults to `p:`. */\n requestIdPrefix?: string;\n /** Wait for connection readiness before sending a request or starting a subscription. */\n prepare?: (ids: MethodIds) => Promise;\n /** Replace a failed connection after a malformed frame; otherwise the transport closes permanently. */\n onProtocolError?: (error: Error) => void;\n /**\n * Maximum time to wait for a matching response before rejecting the request.\n *\n * Defaults to 120 seconds. This bounds dead hosts and missed transport\n * handshakes while leaving interactive approval flows enough time to finish.\n * The handshake keeps its own shorter deadline, since a codec mismatch means\n * no answer is ever coming.\n */\n requestTimeoutMs?: number;\n}\n/**\n * Build a `TrUApiTransport` on top of a `WireProvider`, adding request/response\n * correlation and subscription start/receive/stop lifecycle handling.\n */\nexport declare function createTransport(provider: WireProvider, options?: CreateTransportOptions): TrUApiTransport;\n\n\n// generated/index.d.ts\n\n\n// generated/client.d.ts\nexport { ResultAsync, SubscriptionError };\nexport type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport };\nexport declare const TRUAPI_VERSION: 3;\nexport declare const TRUAPI_CODEC_VERSION: 3;\nexport declare const TRUAPI_WIRE_SCHEMA_HASH: \"6bbdd3b23a6400bb\";\n/** Account lookup, aliasing, and proof generation. */\nexport declare class AccountClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to account connection status changes. */\n connectionStatusSubscribe(): ObservableLike>;\n /** Retrieve a product-scoped account. */\n getAccount(request: T.HostAccountGetRequest, options?: CallOptions): ResultAsync>;\n /** Retrieve the contextual alias for a context and ring. */\n getAccountAlias(request: T.HostAccountGetAliasRequest, options?: CallOptions): ResultAsync>;\n /** Generate a ring VRF proof with an explicitly registered member key. */\n createAccountProof(request: T.HostAccountCreateProofRequest, options?: CallOptions): ResultAsync>;\n /**\n * Produce an sr25519 (schnorrkel) VRF signature from a product account.\n *\n * The host builds a Merlin transcript from `transcriptLabel` and `items`\n * and signs it with the account's key, returning the VRF pre-output and\n * proof. Authorized like signing: local when `AutoSigning` covers the\n * account, otherwise a per-call user confirmation.\n */\n signVrf(request: T.HostAccountSignVrfRequest, options?: CallOptions): ResultAsync>;\n /** Register a ring-VRF key owned by the calling product. */\n registerRingVrfKey(request: T.HostAccountRegisterRingVrfKeyRequest, options?: CallOptions): ResultAsync>;\n /** List registered ring-VRF keys owned by a product. */\n listRingVrfKeys(request: T.HostAccountListRingVrfKeysRequest, options?: CallOptions): ResultAsync, S.CallErrorValue>;\n /** Sign bytes directly with a registered ring-VRF member key. */\n ringVrfSign(request: T.HostAccountRingVrfSignRequest, options?: CallOptions): ResultAsync>;\n /**\n * Use a non-exportable Host Chat device for native cryptographic operations\n * and reviewed main-purse payments. The product owns native lifecycle frames,\n * subscriptions, delivery, retries, history, and acknowledgments.\n *\n * `Bind` resolves the peer independently. `Prepare` validates native plaintext\n * and returns signed ciphertext for product submission. `Open` authenticates\n * complete external statements and rejects reflected local output; it is not\n * an arbitrary decryption primitive. Incoming plaintext can contain incoming\n * bearer coin keys: persist the import intent securely and use generic payment\n * top-up before acknowledging. Wallet/device keys and outgoing main-purse\n * coin secrets never leave the Host.\n *\n * `Initialize` also advances private file transfers. Persist any legacy\n * migration view and ordinary prepared statements before `CommitMigration`.\n * `ContinueOpen` retrieves the next bounded page of an authenticated batch.\n * `ContinueState` retrieves remaining pages of a stable public state snapshot;\n * persist every page before committing its migration.\n *\n * Method 11 (the former raw-crypto interface) and method 12's former V1 actor\n * operations are retired, not forwarded. This boundary uses V2 payloads.\n */\n deviceChat(request: T.HostProductDeviceChatRequest, options?: CallOptions): ResultAsync>;\n /**\n * List non-product accounts the user owns.\n *\n * Current hosts do not expose non-product accounts, so the list is empty.\n */\n getLegacyAccounts(options?: CallOptions): ResultAsync>;\n /** Fetch the user's primary identity. */\n getUserId(options?: CallOptions): ResultAsync>;\n /**\n * Request the host to present the login flow to the user.\n *\n * Products should call this in response to a user action (e.g. tapping a\n * \"Sign in\" button), not automatically on load.\n */\n requestLogin(request: T.HostRequestLoginRequest, options?: CallOptions): ResultAsync>;\n}\n/** Chain interaction methods. */\nexport declare class ChainClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Follow the chain head and receive block events. */\n followHeadSubscribe({ request }: {\n request: T.RemoteChainHeadFollowRequest;\n }): ObservableLike>;\n /** Fetch a block header. */\n getHeadHeader(request: T.RemoteChainHeadHeaderRequest, options?: CallOptions): ResultAsync>;\n /** Fetch a block body. */\n getHeadBody(request: T.RemoteChainHeadBodyRequest, options?: CallOptions): ResultAsync>;\n /** Query runtime storage at a specific block. */\n getHeadStorage(request: T.RemoteChainHeadStorageRequest, options?: CallOptions): ResultAsync>;\n /** Invoke a runtime call at a specific block. */\n callHead(request: T.RemoteChainHeadCallRequest, options?: CallOptions): ResultAsync>;\n /** Release pinned blocks. */\n unpinHead(request: T.RemoteChainHeadUnpinRequest, options?: CallOptions): ResultAsync>;\n /** Continue a paused chain-head operation. */\n continueHead(request: T.RemoteChainHeadContinueRequest, options?: CallOptions): ResultAsync>;\n /** Stop a chain-head operation. */\n stopHeadOperation(request: T.RemoteChainHeadStopOperationRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the canonical genesis hash for a chain. */\n getSpecGenesisHash(request: T.RemoteChainSpecGenesisHashRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the display name of a chain. */\n getSpecChainName(request: T.RemoteChainSpecChainNameRequest, options?: CallOptions): ResultAsync>;\n /** Fetch the JSON-encoded properties of a chain. */\n getSpecProperties(request: T.RemoteChainSpecPropertiesRequest, options?: CallOptions): ResultAsync>;\n /** Broadcast a signed transaction. */\n broadcastTransaction(request: T.RemoteChainTransactionBroadcastRequest, options?: CallOptions): ResultAsync>;\n /** Stop a transaction broadcast. */\n stopTransaction(request: T.RemoteChainTransactionStopRequest, options?: CallOptions): ResultAsync>;\n /**\n * Resolve a chain identifier to its genesis hash against the host's\n * configured environment (RFC 0026).\n */\n getChainInfo(request: T.RemoteChainInfoRequest, options?: CallOptions): ResultAsync>;\n}\n/** Chat room, bot, and message APIs. */\nexport declare class ChatClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Create a chat room. */\n createRoom(request: T.HostChatCreateRoomRequest, options?: CallOptions): ResultAsync>;\n /** Register a chat bot. */\n registerBot(request: T.HostChatRegisterBotRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to the list of chat rooms. */\n listSubscribe(): ObservableLike>;\n /**\n * Post a message to a chat room.\n *\n * The host bounds and screens what it forwards. Message text is capped at\n * 16 KiB and keeps line breaks and tabs, but is rejected for other\n * control characters and for bidirectional overrides. Identifiers and\n * display names are normalized and screened. A message carries at most 32\n * actions and 32 media items, a custom payload at most 256 KiB, and a URL\n * at most 2 KiB which must be `https` or an inline raster image. A\n * rejection reports `MessageTooLarge` when the body or custom payload is\n * over budget, and `Unknown` with a reason naming the field otherwise.\n *\n * The returned `messageId` is the correlation key for any action the\n * message carries: a later `actionSubscribe` trigger names it.\n */\n postMessage(request: T.HostChatPostMessageRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to received chat actions. */\n actionSubscribe(): ObservableLike>;\n}\n/**\n * CoinPayment operations.\n *\n * RFC 0017 describes `Resolvable` values for long-running operations.\n * TrUAPI represents those as subscriptions whose items are the RFC status\n * updates.\n */\nexport declare class CoinPaymentClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Create a new firewalled CoinPayment purse. */\n createPurse(request: T.HostCoinPaymentCreatePurseRequest, options?: CallOptions): ResultAsync>;\n /** Query product-visible purse metadata and balance. */\n queryPurse(request: T.HostCoinPaymentQueryPurseRequest, options?: CallOptions): ResultAsync>;\n /** Transfer balance between local purses. */\n rebalancePurse({ request }: {\n request: T.HostCoinPaymentRebalancePurseRequest;\n }): ObservableLike>;\n /** Delete a purse after draining its balance into another local purse. */\n deletePurse({ request }: {\n request: T.HostCoinPaymentDeletePurseRequest;\n }): ObservableLike>;\n /** Create a receivable public key for depositing into a purse. */\n createReceivable(request: T.HostCoinPaymentCreateReceivableRequest, options?: CallOptions): ResultAsync>;\n /** Create a cheque paying from a local purse to a receivable. */\n createCheque(request: T.HostCoinPaymentCreateChequeRequest, options?: CallOptions): ResultAsync>;\n /** Claim coins from a cheque into the receivable's purse. */\n deposit({ request }: {\n request: T.HostCoinPaymentDepositRequest;\n }): ObservableLike>;\n /** Attempt to return coins associated with a receivable. */\n refund({ request }: {\n request: T.HostCoinPaymentRefundRequest;\n }): ObservableLike>;\n /** Listen for a cheque delivered through a standard transmission channel. */\n listenForPayment({ request }: {\n request: T.HostCoinPaymentListenForRequest;\n }): ObservableLike>;\n}\n/**\n * User-mediated access to the user's contacts.\n *\n * A product never reads the contact list. It opens the host's picker; the host\n * renders an overlay from the chat lists its chat extensions hold, and\n * returns only handles for the people the user selected. Names, accounts, and\n * every other contact the user did not pick stay host-side.\n *\n * That is also why there is no permission to request: the user choosing a\n * contact in host UI is the consent, and a product that is never handed the\n * list has nothing to be granted.\n */\nexport declare class ContactsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Ask the host to let the user pick one contact.\n *\n * Resolves with the chosen contact's handle, or with why nothing was\n * chosen. A host that serves no picker answers `Unsupported`.\n *\n * The handle is not an address and cannot be turned into one by a product.\n * To pay the person, put the handle where the recipient goes in the call\n * and list it in `contacts` on the transaction payload: the host replaces\n * it with their account before anything is signed or shown. Profile also\n * accepts handles as disclosure recipients and as contacts to present or\n * draw avatars for, without returning accounts or profile contents.\n */\n pick(request: T.HostContactsPickRequest, options?: CallOptions): ResultAsync>;\n /**\n * Edit a complete selection in the host's multi-select contact picker.\n *\n * `selected` preselects existing handles. Confirming none returns `Picked`\n * with an empty `handles` list; dismissing never changes the selection.\n * Unresolvable initial handles reject the entire request.\n */\n pickMany(request: T.HostContactsPickManyRequest, options?: CallOptions): ResultAsync>;\n /**\n * Draw contact names in host-owned rectangles over the product surface.\n *\n * Labels do not require a shared Profile photo or disclosure. The response\n * reveals no name, identity or per-slot availability. Each call replaces\n * the previous placement; empty `slots` clears it.\n */\n placeLabels(request: T.HostContactsPlaceLabelsRequest, options?: CallOptions): ResultAsync>;\n}\n/** Deterministic entropy derivation. */\nexport declare class EntropyClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Derive deterministic entropy. */\n derive(request: T.HostDeriveEntropyRequest, options?: CallOptions): ResultAsync>;\n}\n/** Local key/value storage scoped to the calling product. */\nexport declare class LocalStorageClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Read a value by key. */\n read(request: T.HostLocalStorageReadRequest, options?: CallOptions): ResultAsync>;\n /** Write a value to a key. */\n write(request: T.HostLocalStorageWriteRequest, options?: CallOptions): ResultAsync>;\n /** Clear a value by key. */\n clear(request: T.HostLocalStorageClearRequest, options?: CallOptions): ResultAsync>;\n /**\n * Subscribe to changes of one key in the product's own storage namespace.\n *\n * Emits the current value immediately, then one item per later write or\n * clear of the key by any of the product's runtimes. A write that leaves\n * the stored bytes unchanged emits nothing.\n */\n subscribe({ request }: {\n request: T.HostLocalStorageSubscribeRequest;\n }): ObservableLike>;\n}\n/** Host locale subscription. */\nexport declare class LocaleClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to the host's selected locale. */\n subscribe(): ObservableLike>;\n /** Localize a bounded batch of UTC instants in a host locale snapshot. */\n localizeTimestamps(request: T.HostLocaleLocalizeTimestampsRequest, options?: CallOptions): ResultAsync>;\n}\n/** Notification methods for locally-rendered push notifications. */\nexport declare class NotificationsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Send a push notification to the user.\n *\n * Returns a notification id that can be\n * passed to [`cancel_push_notification`](Self::cancel_push_notification)\n * to retract a scheduled notification. When `scheduled_at` is set the host\n * persists the notification across restarts and fires it through the\n * platform-native scheduler. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\n sendPushNotification(request: T.HostPushNotificationRequest, options?: CallOptions): ResultAsync>;\n /**\n * Cancels a previously issued push notification.\n *\n * Cancellation is idempotent: returns `Ok(())` whether the notification is\n * still pending, already fired, or was never issued. See [RFC 0019].\n *\n * [RFC 0019]: https://github.com/paritytech/trinity-user-agents/blob/main/docs/rfcs/0019-scheduled-notifications.md\n */\n cancelPushNotification(request: T.HostPushNotificationCancelRequest, options?: CallOptions): ResultAsync>;\n}\n/** Payment request and balance/status subscription methods. */\nexport declare class PaymentClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to payment balance updates. */\n balanceSubscribe({ request }: {\n request: T.HostPaymentBalanceSubscribeRequest;\n }): ObservableLike>;\n /** Request a payment from the user. */\n request(request: T.HostPaymentRequest, options?: CallOptions): ResultAsync>;\n /** Subscribe to payment lifecycle updates for a specific payment. */\n statusSubscribe({ request }: {\n request: T.HostPaymentStatusSubscribeRequest;\n }): ObservableLike>;\n /** Top up the user's payment balance. */\n topUp(request: T.HostPaymentTopUpRequest, options?: CallOptions): ResultAsync>;\n}\n/** Permission request methods. */\nexport declare class PermissionsClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Request a device-capability permission from the user. */\n requestDevicePermission(request: T.HostDevicePermissionRequest, options?: CallOptions): ResultAsync>;\n /**\n * Request a remote-operation permission.\n *\n * This example makes live requests to Frankfurter after permission is granted.\n */\n requestRemotePermission(request: T.RemotePermissionRequest, options?: CallOptions): ResultAsync>;\n}\n/**\n * Pocket cards backed by the calling product.\n *\n * The host owns the collection: a product observes its own cards and may\n * remove them, but cannot add one.\n */\nexport declare class PocketClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Subscribe to the calling product's cards.\n *\n * Emits the whole set on subscribe and again after every change.\n */\n listSubscribe(): ObservableLike>;\n /**\n * Remove one of the calling product's cards.\n *\n * Removing a card that is not present succeeds. A privileged card is\n * refused with `Privileged`.\n */\n removeCard(request: T.HostPocketRemoveCardRequest, options?: CallOptions): ResultAsync>;\n}\n/** Preimage lookup and submission methods. */\nexport declare class PreimageClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to preimage lookups for a given key. */\n lookupSubscribe({ request }: {\n request: T.RemotePreimageLookupSubscribeRequest;\n }): ObservableLike>;\n /** Submit a preimage. Returns the preimage key (hash) on success. */\n submit(request: HexString, options?: CallOptions): ResultAsync>;\n}\n/**\n * Profiles shown in host-owned UI.\n *\n * The product hands over an opaque reference; the host resolves, decrypts and\n * renders it. Profile bytes never return to the product.\n */\nexport declare class ProfileClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Show the referenced profile in host-owned UI.\n *\n * Resolves once the host has taken the presentation, not when the user\n * dismisses it. Loading and fetch failures are shown to the user, not\n * returned; a reference this host cannot parse is `InvalidReference`.\n */\n present(request: T.HostProfilePresentRequest, options?: CallOptions): ResultAsync>;\n /**\n * Store the user's profile and replace its independent delivery audiences.\n *\n * `ChatApps` shares within every ready Chat App. `App` selects one Chat\n * App's audience. `Contacts` shares personally with picked opaque handles;\n * those received profiles may render in any App. An empty audience list\n * retains the own profile but withdraws all grants. Unknown handles reject\n * the whole disclosure. App executions only. The first disclosure asks\n * the user once per product; a refusal is `PermissionDenied`.\n * v0.1 callers retain the `ChatApps` audience.\n */\n disclose(request: T.HostProfileDiscloseRequest, options?: CallOptions): ResultAsync>;\n /**\n * Withdraw the reference this product disclosed. Contacts are told to\n * drop what they hold. A product that did not disclose it is refused.\n */\n retract(options?: CallOptions): ResultAsync>;\n /**\n * Show a contact's available profile in host-owned UI.\n *\n * The selector names a Chat peer or a picked opaque handle. App-scoped\n * profiles take precedence over personal profiles. References, names,\n * resolved accounts and availability never return to the product. Unknown\n * handles, absent profiles and host presentation failures return the same\n * success. v0.1 callers retain their `NotShared` and presentation errors\n * for App-scoped shares only; personal drawers require v0.2 so a legacy\n * raw-peer request cannot disclose personal sharing availability.\n */\n presentContact(request: T.HostProfilePresentContactRequest, options?: CallOptions): ResultAsync>;\n /**\n * Tell the host where this product draws contacts' avatars, and\n * optionally the signed-in user's own, so it can draw each shared photo\n * and mood ring over them on its own layer.\n *\n * Each call replaces the product's placement; an empty `slots` and no\n * `own` clears it. The own slot is filled only while the user has\n * disclosed a profile, and redrawn when they disclose or retract one.\n * The host draws only for contacts who shared a profile with the user,\n * and keeps the placement current as they share or withdraw one, until\n * the product replaces it or goes away. The answer is the same whoever\n * shared: nothing about any slot, and no profile data, returns to the\n * product. Taps still reach the product, which opens a profile with\n * `presentContact`.\n *\n * App executions only. Rects are in the units of the surface size the\n * product gives: framebuffer pixels for a PolkaVM product, CSS pixels of\n * its viewport for a web product. A placement with more than 64 slots, a\n * surface side outside 1 to 16384, an avatar that is not square or is\n * outside 1 to 1024 a side, or a `slot` repeated across `own` and `slots`\n * is `Unknown`. A host that cannot draw over the product is\n * `Unsupported`; with no user signed in the call is `NotConnected`.\n */\n placeContactAvatars(request: T.HostProfilePlaceContactAvatarsRequest, options?: CallOptions): ResultAsync>;\n /**\n * Report whether the signed-in user has configured a profile.\n *\n * Only the boolean status returns. The profile reference and contents\n * remain host-owned.\n */\n ownStatus(options?: CallOptions): ResultAsync>;\n /** Show the signed-in user's profile in host-owned UI. */\n presentOwn(options?: CallOptions): ResultAsync>;\n}\n/** Product-rendered bodies and the actions triggered inside them. */\nexport declare class RendererClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Streams renderer trees for one product-rendered body. Each item\n * replaces the previous tree. The stream stays open while the body is\n * displayed so the product can redraw in place.\n */\n onRender(handler: HostInitiatedSubscriptionHandler>): {\n unsubscribe(): void;\n };\n /** Subscribe to actions triggered inside this product's rendered bodies. */\n actionSubscribe(): ObservableLike>;\n}\n/** Resource pre-allocation (allowance management). */\nexport declare class ResourceAllocationClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Request the host to pre-allocate one or more resources. */\n request(request: T.HostRequestResourceAllocationRequest, options?: CallOptions): ResultAsync>;\n}\n/** Signing operations. */\nexport declare class SigningClient {\n #private;\n constructor(transport: TrUApiTransport);\n /**\n * Construct a transaction for a product account.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n *\n * Under Extrinsic V5, omitting `VerifyMultiSignature` from `extensions`\n * lets the host sign with the signer's key. Listing it \u2014 as `Disabled`,\n * with a proof in a later extension \u2014 encodes the given bytes verbatim and\n * returns an unsigned transaction.\n *\n * `txExtVersion` is the version of the transaction extensions in\n * `extensions`, as the runtime numbers them. The host picks the extrinsic\n * format from it. V4 always uses version 0, so a non-zero version builds a\n * V5 general transaction. Version 0 builds V5 when it includes\n * `VerifyMultiSignature`, and a signed V4 transaction otherwise.\n *\n * `contacts` lists the contact handles `callData` names, and the host\n * replaces each with the account it resolves to before the call is shown\n * or signed. A declared handle the call does not contain, or one no\n * contact matches, refuses the whole call as `UnknownContact` rather than\n * signing something that names somebody else. A call paying nobody from\n * the picker leaves it empty.\n */\n createTransaction(request: T.ProductAccountTxPayload, options?: CallOptions): ResultAsync>;\n /**\n * Construct a transaction for a non-product (legacy) account.\n *\n * The V5 `VerifyMultiSignature` rule is the same as\n * [`Signing::create_transaction`]: omit it and the host signs, list it and\n * the given bytes are used with no host signature.\n */\n createTransactionWithLegacyAccount(request: T.LegacyAccountTxPayload, options?: CallOptions): ResultAsync>;\n /** Sign raw bytes with a non-product account. */\n signRawWithLegacyAccount(request: T.HostSignRawWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n /** Sign an extrinsic payload with a non-product account. */\n signPayloadWithLegacyAccount(request: T.HostSignPayloadWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign raw bytes or a message.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n */\n signRaw(request: T.HostSignRawRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign an extrinsic payload.\n *\n * Served locally without a user confirmation when an RFC-0010 `AutoSigning`\n * grant covers the account; otherwise each call is confirmed by the user.\n */\n signPayload(request: T.HostSignPayloadRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign the supplied data without adding or removing a watermark.\n *\n * Temporary compatibility API for runtime ownership proofs, including the\n * 32-byte Resources alias used by Humanity. Payload decoding matches\n * watermarked signing, but the decoded bytes are signed exactly as supplied.\n * This permits transaction-shaped data and requires signing authorization\n * and explicit user confirmation.\n *\n * @deprecated Temporary unwatermarked signing; migrate to watermarked signing when the runtime supports it. This API will be removed. See \n */\n signRawUnwatermarkedDeprecated(request: T.HostSignRawRequest, options?: CallOptions): ResultAsync>;\n /**\n * Sign the supplied data without adding or removing a watermark.\n *\n * Temporary compatibility API for runtime ownership proofs, including the\n * 32-byte Resources alias used by Humanity. Payload decoding matches\n * watermarked signing, but the decoded bytes are signed exactly as supplied.\n * This permits transaction-shaped data and requires signing authorization\n * and explicit user confirmation.\n *\n * @deprecated Temporary unwatermarked signing; migrate to watermarked signing when the runtime supports it. This API will be removed. See \n */\n signRawUnwatermarkedDeprecatedWithLegacyAccount(request: T.HostSignRawWithLegacyAccountRequest, options?: CallOptions): ResultAsync>;\n}\n/** Statement store methods. */\nexport declare class StatementStoreClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to statements matching a topic filter. */\n subscribe({ request }: {\n request: T.RemoteStatementStoreSubscribeRequest;\n }): ObservableLike>;\n /**\n * Create a proof for a statement.\n *\n * **Deprecated:** use [`create_proof_authorized`](Self::create_proof_authorized)\n * instead, which uses a pre-allocated allowance account and does not\n * require a per-call signing prompt. Pairing hosts may reject this method\n * when their signing channel cannot sign statement proof payloads exactly.\n */\n createProof(request: T.RemoteStatementStoreCreateProofRequest, options?: CallOptions): ResultAsync>;\n /**\n * Create a proof for a statement using a pre-allocated allowance account,\n * bypassing the per-call signing prompt.\n */\n createProofAuthorized(request: T.Statement, options?: CallOptions): ResultAsync>;\n /**\n * Submit a signed statement to the network. The request body is the\n * [`SignedStatement`](crate::v01::SignedStatement) directly (no wrapping\n * struct), matching upstream `triangle-js-sdks`.\n */\n submit(request: T.SignedStatement, options?: CallOptions): ResultAsync>;\n}\n/**\n * General-purpose TrUAPI methods for handshake, feature detection,\n * navigation, and runtime information.\n */\nexport declare class SystemClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Negotiate the wire codec version with the product. */\n handshake(options?: CallOptions): ResultAsync>;\n /** Query whether the host supports a specific feature. */\n featureSupported(request: T.HostFeatureSupportedRequest, options?: CallOptions): ResultAsync>;\n /**\n * Request the host to open a URL.\n *\n * An `http` or `https` URL outside the ecosystem needs a\n * `RemotePermission::Remote` grant for the target host, and prompts for one\n * on first use. dotNS names, `localhost`, and the app-handoff schemes\n * (`mailto:`, `tel:`, `polkadot:`, `dot:`) consume no grant. The grant is\n * per host and shared with outbound data access to that host, so approving\n * one covers the other.\n */\n navigateTo(request: T.HostNavigateToRequest, options?: CallOptions): ResultAsync>;\n /**\n * Report the host's identity and version.\n *\n * Returns the host's platform, name, and version so a product knows\n * exactly which host \u2014 and which build of it \u2014 is running it: for\n * adapting to the host, telemetry, and attributing behaviour to a\n * concrete build in diagnostics and bug reports.\n */\n info(options?: CallOptions): ResultAsync>;\n /** Return the product context bound to the current host runtime. */\n getProductContext(options?: CallOptions): ResultAsync>;\n}\n/** Host theme subscription. */\nexport declare class ThemeClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Subscribe to host theme changes. */\n subscribe(): ObservableLike>;\n}\n/**\n * Worker background-operation APIs.\n *\n * The host keeps a product's worker running while it holds at least one open\n * operation, which is how a worker outlives the surface that started it.\n */\nexport declare class WorkerClient {\n #private;\n constructor(transport: TrUApiTransport);\n /** Begin a pending operation. */\n beginOperation(request: T.HostWorkerBeginOperationRequest, options?: CallOptions): ResultAsync>;\n /**\n * End a pending operation. Idempotent: an unknown or already-ended id\n * succeeds, so a retry after an ambiguous failure is safe.\n */\n endOperation(request: T.HostWorkerEndOperationRequest, options?: CallOptions): ResultAsync>;\n}\nexport interface TrUApiClient {\n readonly account: AccountClient;\n readonly chain: ChainClient;\n readonly chat: ChatClient;\n readonly coinPayment: CoinPaymentClient;\n readonly contacts: ContactsClient;\n readonly entropy: EntropyClient;\n readonly localStorage: LocalStorageClient;\n readonly locale: LocaleClient;\n readonly notifications: NotificationsClient;\n readonly payment: PaymentClient;\n readonly permissions: PermissionsClient;\n readonly pocket: PocketClient;\n readonly preimage: PreimageClient;\n readonly profile: ProfileClient;\n readonly renderer: RendererClient;\n readonly resourceAllocation: ResourceAllocationClient;\n readonly signing: SigningClient;\n readonly statementStore: StatementStoreClient;\n readonly system: SystemClient;\n readonly theme: ThemeClient;\n readonly worker: WorkerClient;\n}\nexport type Client = TrUApiClient;\n/** Creates the generated client facade by binding each service namespace to the\n * shared transport instance. */\nexport declare function createClient(transport: TrUApiTransport): TrUApiClient;\n\n\n// development.d.ts\n/** Same as `HostAccountCreateProofRequest`, with the 32-byte context given raw. */\nexport interface DevelopmentCreateProofRequest extends Omit {\n /** The exact 32 bytes the proof is bound to, as `0x`-prefixed hex. */\n context: HexString;\n}\n/**\n * `account.createAccountProof` with a verbatim 32-byte proof context instead of\n * a product-namespaced one.\n *\n */\nexport declare function development_createAccountProof(client: Pick, request: DevelopmentCreateProofRequest): ResultAsync>;\n"; diff --git a/vendor/truapi/dist/playground/codegen/truapi-dts.js b/vendor/truapi/dist/playground/codegen/truapi-dts.js index 0820cb436..d73644e43 100644 --- a/vendor/truapi/dist/playground/codegen/truapi-dts.js +++ b/vendor/truapi/dist/playground/codegen/truapi-dts.js @@ -600,6 +600,18 @@ export const AllocationOutcome: Codec; /** Main-axis distribution of children. */ export type Arrangement = "Start" | "End" | "Center" | "SpaceBetween" | "SpaceAround" | "SpaceEvenly"; export const Arrangement: Codec; +/** A rectangle in surface units, relative to the surface's top-left corner. */ +export interface AvatarRect { + /** Left edge. */ + x: number; + /** Top edge. */ + y: number; + /** Width. */ + width: number; + /** Height. */ + height: number; +} +export const AvatarRect: Codec; /** Background styling. */ export interface Background { /** Background color. */ @@ -907,6 +919,38 @@ export interface ContactHandle { bytes: Bytes32; } export const ContactHandle: Codec; +/** Geometry for a host-owned contact name, independent of profile sharing. */ +export interface ContactLabelSlot { + /** Product-chosen id, unique within this placement. */ + slot: number; + /** Opaque handle for the contact whose name the host draws. */ + handle: ContactHandle; + /** Name bounds in surface units, with sides from 1 to 16384. */ + rect: AvatarRect; + /** Visible region in surface units; a zero side hides the label. */ + clip: AvatarRect; +} +export const ContactLabelSlot: Codec; +/** Selection confirmed in the host's multi-contact picker. */ +export type ContactPickManyOutcome = +/** The user confirmed this complete selection, including an empty one. */ +{ + tag: "Picked"; + value: { + handles: Array; + }; +} +/** The user closed the picker without confirming a change. */ + | { + tag: "Dismissed"; + value?: undefined; +} +/** There are no contacts to show. */ + | { + tag: "NoContacts"; + value?: undefined; +}; +export const ContactPickManyOutcome: Codec; /** * How a contact pick ended. * @@ -1540,6 +1584,30 @@ export type VersionedHostContactsPickError = value: HostContactsPickError; }; export const VersionedHostContactsPickError: Codec; +/** Versioned envelope for [\`HostContactsPickManyError\`]. */ +export type VersionedHostContactsPickManyError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyError; +}; +export const VersionedHostContactsPickManyError: Codec; +/** Versioned envelope for [\`HostContactsPickManyRequest\`]. */ +export type VersionedHostContactsPickManyRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyRequest; +}; +export const VersionedHostContactsPickManyRequest: Codec; +/** Versioned envelope for [\`HostContactsPickManyResponse\`]. */ +export type VersionedHostContactsPickManyResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPickManyResponse; +}; +export const VersionedHostContactsPickManyResponse: Codec; /** Versioned envelope for [\`HostContactsPickRequest\`]. */ export type VersionedHostContactsPickRequest = /** Version 1 payload. */ @@ -1556,6 +1624,30 @@ export type VersionedHostContactsPickResponse = value: HostContactsPickResponse; }; export const VersionedHostContactsPickResponse: Codec; +/** Versioned envelope for [\`HostContactsPlaceLabelsError\`]. */ +export type VersionedHostContactsPlaceLabelsError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsError; +}; +export const VersionedHostContactsPlaceLabelsError: Codec; +/** Versioned envelope for [\`HostContactsPlaceLabelsRequest\`]. */ +export type VersionedHostContactsPlaceLabelsRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsRequest; +}; +export const VersionedHostContactsPlaceLabelsRequest: Codec; +/** Versioned envelope for [\`HostContactsPlaceLabelsResponse\`]. */ +export type VersionedHostContactsPlaceLabelsResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostContactsPlaceLabelsResponse; +}; +export const VersionedHostContactsPlaceLabelsResponse: Codec; /** Versioned envelope for [\`HostCreateTransactionError\`]. */ export type VersionedHostCreateTransactionError = /** Version 1 payload. */ @@ -2502,6 +2594,174 @@ export type VersionedHostProductDeviceChatResponse = value: HostProductDeviceChatResponse; }; export const VersionedHostProductDeviceChatResponse: Codec; +/** Versioned envelope for [\`HostProfileDiscloseError\`]. */ +export type VersionedHostProfileDiscloseError = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfileDiscloseError; +}; +export const VersionedHostProfileDiscloseError: Codec; +/** Versioned envelope for [\`HostProfileDiscloseRequest\`]. */ +export type VersionedHostProfileDiscloseRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfileDiscloseRequest; +}; +export const VersionedHostProfileDiscloseRequest: Codec; +/** Versioned envelope for [\`HostProfileDiscloseResponse\`]. */ +export type VersionedHostProfileDiscloseResponse = +/** Version 2 (no payload). */ +{ + tag: "V2"; + value?: undefined; +}; +export const VersionedHostProfileDiscloseResponse: Codec; +/** Versioned envelope for [\`HostProfileOwnStatusError\`]. */ +export type VersionedHostProfileOwnStatusError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileOwnStatusError; +}; +export const VersionedHostProfileOwnStatusError: Codec; +/** Versioned envelope for [\`HostProfileOwnStatusRequest\`]. */ +export type VersionedHostProfileOwnStatusRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfileOwnStatusRequest: Codec; +/** Versioned envelope for [\`HostProfileOwnStatusResponse\`]. */ +export type VersionedHostProfileOwnStatusResponse = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileOwnStatusResponse; +}; +export const VersionedHostProfileOwnStatusResponse: Codec; +/** Versioned envelope for [\`HostProfilePlaceContactAvatarsError\`]. */ +export type VersionedHostProfilePlaceContactAvatarsError = +/** Version 3 payload. */ +{ + tag: "V3"; + value: HostProfilePlaceContactAvatarsError; +}; +export const VersionedHostProfilePlaceContactAvatarsError: Codec; +/** Versioned envelope for [\`HostProfilePlaceContactAvatarsRequest\`]. */ +export type VersionedHostProfilePlaceContactAvatarsRequest = +/** Version 3 payload. */ +{ + tag: "V3"; + value: HostProfilePlaceContactAvatarsRequest; +}; +export const VersionedHostProfilePlaceContactAvatarsRequest: Codec; +/** Versioned envelope for [\`HostProfilePlaceContactAvatarsResponse\`]. */ +export type VersionedHostProfilePlaceContactAvatarsResponse = +/** Version 3 (no payload). */ +{ + tag: "V3"; + value?: undefined; +}; +export const VersionedHostProfilePlaceContactAvatarsResponse: Codec; +/** Versioned envelope for [\`HostProfilePresentContactError\`]. */ +export type VersionedHostProfilePresentContactError = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfilePresentContactError; +}; +export const VersionedHostProfilePresentContactError: Codec; +/** Versioned envelope for [\`HostProfilePresentContactRequest\`]. */ +export type VersionedHostProfilePresentContactRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProfilePresentContactRequest; +}; +export const VersionedHostProfilePresentContactRequest: Codec; +/** Versioned envelope for [\`HostProfilePresentContactResponse\`]. */ +export type VersionedHostProfilePresentContactResponse = +/** Version 2 (no payload). */ +{ + tag: "V2"; + value?: undefined; +}; +export const VersionedHostProfilePresentContactResponse: Codec; +/** Versioned envelope for [\`HostProfilePresentError\`]. */ +export type VersionedHostProfilePresentError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentError; +}; +export const VersionedHostProfilePresentError: Codec; +/** Versioned envelope for [\`HostProfilePresentOwnError\`]. */ +export type VersionedHostProfilePresentOwnError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentOwnError; +}; +export const VersionedHostProfilePresentOwnError: Codec; +/** Versioned envelope for [\`HostProfilePresentOwnRequest\`]. */ +export type VersionedHostProfilePresentOwnRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfilePresentOwnRequest: Codec; +/** Versioned envelope for [\`HostProfilePresentOwnResponse\`]. */ +export type VersionedHostProfilePresentOwnResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfilePresentOwnResponse: Codec; +/** Versioned envelope for [\`HostProfilePresentRequest\`]. */ +export type VersionedHostProfilePresentRequest = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfilePresentRequest; +}; +export const VersionedHostProfilePresentRequest: Codec; +/** Versioned envelope for [\`HostProfilePresentResponse\`]. */ +export type VersionedHostProfilePresentResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfilePresentResponse: Codec; +/** Versioned envelope for [\`HostProfileRetractError\`]. */ +export type VersionedHostProfileRetractError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProfileRetractError; +}; +export const VersionedHostProfileRetractError: Codec; +/** Versioned envelope for [\`HostProfileRetractRequest\`]. */ +export type VersionedHostProfileRetractRequest = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfileRetractRequest: Codec; +/** Versioned envelope for [\`HostProfileRetractResponse\`]. */ +export type VersionedHostProfileRetractResponse = +/** Version 1 (no payload). */ +{ + tag: "V1"; + value?: undefined; +}; +export const VersionedHostProfileRetractResponse: Codec; /** Versioned envelope for [\`HostPushNotificationCancelError\`]. */ export type VersionedHostPushNotificationCancelError = /** Version 1 payload. */ @@ -2986,6 +3246,16 @@ export type OperationStartedResult = value?: undefined; }; export const OperationStartedResult: Codec; +/** Where the product draws the signed-in user's own avatar. */ +export interface OwnAvatarSlot { + /** Product-chosen id, unique within this placement. */ + slot: number; + /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */ + rect: AvatarRect; + /** Visible region the avatar is cut to. */ + clip: AvatarRect; +} +export const OwnAvatarSlot: Codec; /** * Source for a payment top-up operation. * @@ -3132,6 +3402,45 @@ export type VersionedProductRendererRenderRequest = value: ProductRendererRenderRequest; }; export const VersionedProductRendererRenderRequest: Codec; +/** Recipients of one profile reference. Multiple audiences form a union. */ +export type ProfileAudience = +/** Every ready Chat App, with profiles scoped to that App. */ +{ + tag: "ChatApps"; + value?: undefined; +} +/** Contacts of this Chat App, with profiles scoped to that App. */ + | { + tag: "App"; + value: { + productId: string; + }; +} +/** Selected contacts, with profiles available in any receiving App. */ + | { + tag: "Contacts"; + value: { + handles: Array; + }; +}; +export const ProfileAudience: Codec; +/** A contact named without exposing a handle's account to the product. */ +export type ProfileContact = +/** An authenticated Chat network identity already known to the product. */ +{ + tag: "Peer"; + value: { + peerIdentity: HexString; + }; +} +/** An opaque host-issued contact selection. */ + | { + tag: "Handle"; + value: { + handle: ContactHandle; + }; +}; +export const ProfileContact: Codec; /** Raw data to sign -- either binary bytes or a string message. */ export type RawPayload = /** Raw binary data to sign. */ @@ -4081,6 +4390,22 @@ export const TxPayloadExtension: Codec; /** Typography presets, resolved by the host's design system. */ export type TypographyStyle = "HeadlineLarge" | "TitleMediumRegular" | "BodyLargeRegular" | "BodyMediumRegular" | "BodySmallRegular"; export const TypographyStyle: Codec; +/** One avatar the product draws for a chat contact. */ +export interface ContactAvatarSlot { + /** + * Product-chosen id, stable for one on-screen avatar (a list row, a + * header). The host uses it only to keep what it draws stable across + * updates. + */ + slot: number; + /** The contact's authenticated root identity, as the chat API names it. */ + peerIdentity: HexString; + /** Bounding box of the avatar circle: square, 1 to 1024 units a side. */ + rect: AvatarRect; + /** Visible region the avatar is cut to, such as the scroll area. */ + clip: AvatarRect; +} +export const ContactAvatarSlot: Codec; /** User's authentication state. */ export type HostAccountConnectionStatusSubscribeItem = "Disconnected" | "Connected"; export const HostAccountConnectionStatusSubscribeItem: Codec; @@ -4597,6 +4922,41 @@ export type HostContactsPickError = }; }; export const HostContactsPickError: Codec; +/** Failure before a complete selection can be confirmed. */ +export type HostContactsPickManyError = +/** No active session, or the session changed while choosing. */ +{ + tag: "NotConnected"; + value?: undefined; +} +/** The selection exceeds the bound or contains an unresolved handle. */ + | { + tag: "InvalidSelection"; + value?: undefined; +} +/** The host could not complete the picker. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostContactsPickManyError: Codec; +/** Open the host's picker with the product's current selection. */ +export interface HostContactsPickManyRequest { + /** + * At most 256 handles. Duplicates are ignored; an unresolved handle + * rejects the entire request rather than changing the selected audience. + */ + selected: Array; +} +export const HostContactsPickManyRequest: Codec; +/** The user's confirmed selection or reason no selection was made. */ +export interface HostContactsPickManyResponse { + /** How the picker ended. */ + outcome: ContactPickManyOutcome; +} +export const HostContactsPickManyResponse: Codec; /** * Request to open the host's contact picker. * @@ -4612,6 +4972,45 @@ export interface HostContactsPickResponse { outcome: ContactPickOutcome; } export const HostContactsPickResponse: Codec; +/** Placement failure, never the availability of any individual contact. */ +export type HostContactsPlaceLabelsError = +/** The host cannot draw labels over the product surface. */ +{ + tag: "Unsupported"; + value?: undefined; +} +/** No active session, or it changed while placing labels. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** The surface, slot count, slot ids or rectangles are invalid. */ + | { + tag: "InvalidPlacement"; + value?: undefined; +} +/** The host could not place the labels. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostContactsPlaceLabelsError: Codec; +/** Replace the contact names drawn over a product's surface. */ +export interface HostContactsPlaceLabelsRequest { + /** Surface width in framebuffer pixels or web viewport CSS pixels, 1 to 16384. */ + surfaceWidth: number; + /** Surface height in the same units, 1 to 16384. */ + surfaceHeight: number; + /** At most 256 slots. Empty clears the previous placement. */ + slots: Array; +} +export const HostContactsPlaceLabelsRequest: Codec; +/** Acknowledges placement without revealing any contact's name or availability. */ +export interface HostContactsPlaceLabelsResponse { +} +export const HostContactsPlaceLabelsResponse: Codec; /** Transaction creation error. */ export type HostCreateTransactionError = /** Payload could not be deserialized. */ @@ -5104,6 +5503,221 @@ export interface HostPocketRemoveCardRequest { cardId: string; } export const HostPocketRemoveCardRequest: Codec; +/** Profile disclosure failure. */ +export type HostProfileDiscloseError = +/** The reference is empty, too long, or not printable ASCII. */ +{ + tag: "InvalidReference"; + value?: undefined; +} +/** + * The user declined to let this product disclose a profile to their + * chat contacts. + */ + | { + tag: "PermissionDenied"; + value?: undefined; +} +/** No user is signed in, so there are no contacts to disclose to. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfileDiscloseError: Codec; +/** + * Request to give the user's chat contacts a profile reference. + * + * The reference is a bearer capability for everyone the host relays it to. + * The host stores it as the user's own and never parses it. + */ +export interface V01HostProfileDiscloseRequest { + /** Opaque profile reference, e.g. a Seity contacts reference. */ + reference: string; +} +export const V01HostProfileDiscloseRequest: Codec; +/** Failure while querying the signed-in user's profile status. */ +export type HostProfileOwnStatusError = +/** No user is signed in. */ +{ + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfileOwnStatusError: Codec; +/** + * Whether the signed-in user currently has a profile disclosed through the + * host. The reference itself never crosses into the product. + */ +export interface HostProfileOwnStatusResponse { + /** \`true\` when the host holds a current own-profile reference. */ + configured: boolean; +} +export const HostProfileOwnStatusResponse: Codec; +/** Contact avatar placement failure. Says nothing about any one slot. */ +export type HostProfilePlaceContactAvatarsError = +/** This host cannot draw over the product's surface. */ +{ + tag: "Unsupported"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all, including a malformed placement. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfilePlaceContactAvatarsError: Codec; +/** + * Where a chat product draws contact avatars, so the host can draw the + * photo and mood ring each contact shared over them, on its own layer. + * + * The product sends geometry only. The host decides which slots it can fill + * and never says which, so the product cannot learn who shared a profile. + */ +export interface V01HostProfilePlaceContactAvatarsRequest { + /** + * Width of the product's drawing surface, in the units of every rect: + * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport + * for a web product. 1 to 16384. + */ + surfaceWidth: number; + /** Height of the drawing surface, in the same units. 1 to 16384. */ + surfaceHeight: number; + /** + * Replaces the product's previous placement entirely; empty clears it. + * At most 64, each with its own \`slot\`. + */ + slots: Array; +} +export const V01HostProfilePlaceContactAvatarsRequest: Codec; +/** Contact profile presentation failure. */ +export type HostProfilePresentContactError = +/** This contact has not shared a profile with the user. */ +{ + tag: "NotShared"; + value?: undefined; +} +/** The host holds a reference it cannot parse. */ + | { + tag: "InvalidReference"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfilePresentContactError: Codec; +/** + * Request to show a chat contact's profile in host-owned UI. + * + * The product names the contact, never a reference: the host looks up the + * reference that contact's host sent, so the product cannot read, keep or + * substitute it. + */ +export interface V01HostProfilePresentContactRequest { + /** The contact's authenticated root identity, as the chat API names it. */ + peerIdentity: HexString; +} +export const V01HostProfilePresentContactRequest: Codec; +/** Profile presentation failure. */ +export type HostProfilePresentError = +/** The reference is malformed or names a format this host cannot open. */ +{ + tag: "InvalidReference"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfilePresentError: Codec; +/** Failure while presenting the signed-in user's profile. */ +export type HostProfilePresentOwnError = +/** The signed-in user has not configured a profile. */ +{ + tag: "NotConfigured"; + value?: undefined; +} +/** The host holds a reference it cannot parse. */ + | { + tag: "InvalidReference"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfilePresentOwnError: Codec; +/** + * Request to show a profile the calling product references in host-owned UI. + * + * The reference is a bearer capability: whoever holds it can read the profile + * it names. The host resolves and renders it itself, so profile bytes, the + * avatar image included, never reach the product. + */ +export interface HostProfilePresentRequest { + /** Opaque profile reference, e.g. a Seity \`#\` blob reference. */ + reference: string; +} +export const HostProfilePresentRequest: Codec; +/** Profile retraction failure. */ +export type HostProfileRetractError = +/** Another product disclosed the reference the host holds. */ +{ + tag: "NotDiscloser"; + value?: undefined; +} +/** No user is signed in. */ + | { + tag: "NotConnected"; + value?: undefined; +} +/** Catch-all. */ + | { + tag: "Unknown"; + value: { + reason: string; + }; +}; +export const HostProfileRetractError: Codec; /** Request to cancel a previously scheduled notification. */ export interface HostPushNotificationCancelRequest { /** The notification identifier returned by [\`HostPushNotificationResponse\`]. */ @@ -5854,6 +6468,72 @@ export interface V02HostProductDeviceChatResponse { richMessages: Array; } export const V02HostProductDeviceChatResponse: Codec; +/** + * Replace the user's disclosed reference and its complete set of audiences. + * + * An empty audience retains the user's own profile but withdraws all delivery + * grants. A contact handle that no longer resolves rejects the whole request. + */ +export interface HostProfileDiscloseRequest { + /** Opaque bearer reference, retained and relayed only by the host. */ + reference: string; + /** Independent grants for this reference, at most 64. */ + audiences: Array; +} +export const HostProfileDiscloseRequest: Codec; +/** + * Where a chat product draws avatars the host fills in: its contacts' and, + * optionally, the signed-in user's own. + * + * v0.2 adds \`own\` to the v0.1 placement. A v0.1 placement is this one with no + * own slot, which is exactly what v0.1 meant. Both kinds live in one + * placement so a product never has two placements replacing each other's + * overlay. + */ +export interface V02HostProfilePlaceContactAvatarsRequest { + /** + * Width of the product's drawing surface, in the units of every rect: + * framebuffer pixels for a PolkaVM product, CSS pixels of its viewport + * for a web product. 1 to 16384. + */ + surfaceWidth: number; + /** Height of the drawing surface, in the same units. 1 to 16384. */ + surfaceHeight: number; + /** + * Where the signed-in user's own avatar is drawn, if the product draws + * one. The host fills it only when the user has disclosed a profile. + */ + own?: OwnAvatarSlot; + /** + * Replaces the product's previous placement entirely; empty clears it. + * At most 64, each with its own \`slot\`, unique across \`own\` too. + */ + slots: Array; +} +export const V02HostProfilePlaceContactAvatarsRequest: Codec; +/** + * Ask the host to present a contact's available profile. + * + * Unknown handles, absent profiles and presentation failures return success, + * without disclosing whether the contact shares a profile. + */ +export interface HostProfilePresentContactRequest { + /** The contact whose profile the host may present. */ + contact: ProfileContact; +} +export const HostProfilePresentContactRequest: Codec; +/** Geometry and opaque contact selection for one host-rendered avatar. */ +export interface V03ContactAvatarSlot { + /** Product-chosen id, unique across contact and own slots. */ + slot: number; + /** A peer identity or host-issued handle. Unresolved handles remain blank. */ + contact: ProfileContact; + /** Square avatar bounds, from 1 to 1024 units per side. */ + rect: AvatarRect; + /** Visible region to which the avatar is clipped. */ + clip: AvatarRect; +} +export const V03ContactAvatarSlot: Codec; /** An operation using the calling product's non-exportable Host Chat device. */ export type HostProductDeviceChatRequest = /** Restore public metadata, pending ciphertext, and private file-transfer progress. */ @@ -5983,6 +6663,18 @@ export interface HostProductDeviceChatResponse { coinageCentsUnit?: bigint; } export const HostProductDeviceChatResponse: Codec; +/** A host-rendered avatar placement using peer identities or opaque handles. */ +export interface HostProfilePlaceContactAvatarsRequest { + /** Width of the drawing surface, from 1 to 16384 units. */ + surfaceWidth: number; + /** Height of the drawing surface, from 1 to 16384 units. */ + surfaceHeight: number; + /** Optional slot for the signed-in user's own disclosed profile. */ + own?: OwnAvatarSlot; + /** Complete replacement of the contact slots, at most 64. */ + slots: Array; +} +export const HostProfilePlaceContactAvatarsRequest: Codec; /** Cross-axis alignment of \`Row\` children. */ export type VerticalAlignment = "Top" | "Center" | "Bottom"; export const VerticalAlignment: Codec; @@ -6012,6 +6704,7 @@ export import ActionTrigger = T.ActionTrigger; export import AllocatableResource = T.AllocatableResource; export import AllocationOutcome = T.AllocationOutcome; export import Arrangement = T.Arrangement; +export import AvatarRect = T.AvatarRect; export import Background = T.Background; export import BlendingMode = T.BlendingMode; export import BorderStyle = T.BorderStyle; @@ -6044,6 +6737,8 @@ export import CoinPaymentTransmissionChannel = T.CoinPaymentTransmissionChannel; export import ColorToken = T.ColorToken; export import ColumnProps = T.ColumnProps; export import ContactHandle = T.ContactHandle; +export import ContactLabelSlot = T.ContactLabelSlot; +export import ContactPickManyOutcome = T.ContactPickManyOutcome; export import ContactPickOutcome = T.ContactPickOutcome; export import ContentAlignment = T.ContentAlignment; export import ContextualAlias = T.ContextualAlias; @@ -6120,8 +6815,14 @@ export import VersionedHostCoinPaymentRefundError = T.VersionedHostCoinPaymentRe export import VersionedHostCoinPaymentRefundItem = T.VersionedHostCoinPaymentRefundItem; export import VersionedHostCoinPaymentRefundRequest = T.VersionedHostCoinPaymentRefundRequest; export import VersionedHostContactsPickError = T.VersionedHostContactsPickError; +export import VersionedHostContactsPickManyError = T.VersionedHostContactsPickManyError; +export import VersionedHostContactsPickManyRequest = T.VersionedHostContactsPickManyRequest; +export import VersionedHostContactsPickManyResponse = T.VersionedHostContactsPickManyResponse; export import VersionedHostContactsPickRequest = T.VersionedHostContactsPickRequest; export import VersionedHostContactsPickResponse = T.VersionedHostContactsPickResponse; +export import VersionedHostContactsPlaceLabelsError = T.VersionedHostContactsPlaceLabelsError; +export import VersionedHostContactsPlaceLabelsRequest = T.VersionedHostContactsPlaceLabelsRequest; +export import VersionedHostContactsPlaceLabelsResponse = T.VersionedHostContactsPlaceLabelsResponse; export import VersionedHostCreateTransactionError = T.VersionedHostCreateTransactionError; export import VersionedHostCreateTransactionRequest = T.VersionedHostCreateTransactionRequest; export import VersionedHostCreateTransactionResponse = T.VersionedHostCreateTransactionResponse; @@ -6220,6 +6921,27 @@ export import VersionedHostPocketRemoveCardResponse = T.VersionedHostPocketRemov export import VersionedHostProductDeviceChatError = T.VersionedHostProductDeviceChatError; export import VersionedHostProductDeviceChatRequest = T.VersionedHostProductDeviceChatRequest; export import VersionedHostProductDeviceChatResponse = T.VersionedHostProductDeviceChatResponse; +export import VersionedHostProfileDiscloseError = T.VersionedHostProfileDiscloseError; +export import VersionedHostProfileDiscloseRequest = T.VersionedHostProfileDiscloseRequest; +export import VersionedHostProfileDiscloseResponse = T.VersionedHostProfileDiscloseResponse; +export import VersionedHostProfileOwnStatusError = T.VersionedHostProfileOwnStatusError; +export import VersionedHostProfileOwnStatusRequest = T.VersionedHostProfileOwnStatusRequest; +export import VersionedHostProfileOwnStatusResponse = T.VersionedHostProfileOwnStatusResponse; +export import VersionedHostProfilePlaceContactAvatarsError = T.VersionedHostProfilePlaceContactAvatarsError; +export import VersionedHostProfilePlaceContactAvatarsRequest = T.VersionedHostProfilePlaceContactAvatarsRequest; +export import VersionedHostProfilePlaceContactAvatarsResponse = T.VersionedHostProfilePlaceContactAvatarsResponse; +export import VersionedHostProfilePresentContactError = T.VersionedHostProfilePresentContactError; +export import VersionedHostProfilePresentContactRequest = T.VersionedHostProfilePresentContactRequest; +export import VersionedHostProfilePresentContactResponse = T.VersionedHostProfilePresentContactResponse; +export import VersionedHostProfilePresentError = T.VersionedHostProfilePresentError; +export import VersionedHostProfilePresentOwnError = T.VersionedHostProfilePresentOwnError; +export import VersionedHostProfilePresentOwnRequest = T.VersionedHostProfilePresentOwnRequest; +export import VersionedHostProfilePresentOwnResponse = T.VersionedHostProfilePresentOwnResponse; +export import VersionedHostProfilePresentRequest = T.VersionedHostProfilePresentRequest; +export import VersionedHostProfilePresentResponse = T.VersionedHostProfilePresentResponse; +export import VersionedHostProfileRetractError = T.VersionedHostProfileRetractError; +export import VersionedHostProfileRetractRequest = T.VersionedHostProfileRetractRequest; +export import VersionedHostProfileRetractResponse = T.VersionedHostProfileRetractResponse; export import VersionedHostPushNotificationCancelError = T.VersionedHostPushNotificationCancelError; export import VersionedHostPushNotificationCancelRequest = T.VersionedHostPushNotificationCancelRequest; export import VersionedHostPushNotificationCancelResponse = T.VersionedHostPushNotificationCancelResponse; @@ -6265,6 +6987,7 @@ export import LegacyAccount = T.LegacyAccount; export import LegacyAccountTxPayload = T.LegacyAccountTxPayload; export import Modifier = T.Modifier; export import OperationStartedResult = T.OperationStartedResult; +export import OwnAvatarSlot = T.OwnAvatarSlot; export import PaymentTopUpSource = T.PaymentTopUpSource; export import PocketCard = T.PocketCard; export import PreimageSubmitError = T.PreimageSubmitError; @@ -6275,6 +6998,8 @@ export import ProductProofContext = T.ProductProofContext; export import VersionedProductRendererRenderError = T.VersionedProductRendererRenderError; export import VersionedProductRendererRenderItem = T.VersionedProductRendererRenderItem; export import VersionedProductRendererRenderRequest = T.VersionedProductRendererRenderRequest; +export import ProfileAudience = T.ProfileAudience; +export import ProfileContact = T.ProfileContact; export import RawPayload = T.RawPayload; export import RegisteredRingVrfKey = T.RegisteredRingVrfKey; export import VersionedRemoteChainHeadBodyError = T.VersionedRemoteChainHeadBodyError; @@ -6365,6 +7090,7 @@ export import ThemeName = T.ThemeName; export import ThemeVariant = T.ThemeVariant; export import TxPayloadExtension = T.TxPayloadExtension; export import TypographyStyle = T.TypographyStyle; +export import ContactAvatarSlot = T.ContactAvatarSlot; export import HostAccountConnectionStatusSubscribeItem = T.HostAccountConnectionStatusSubscribeItem; export import HostAccountCreateProofError = T.HostAccountCreateProofError; export import HostAccountCreateProofRequest = T.HostAccountCreateProofRequest; @@ -6408,8 +7134,14 @@ export import HostCoinPaymentQueryPurseResponse = T.HostCoinPaymentQueryPurseRes export import HostCoinPaymentRebalancePurseRequest = T.HostCoinPaymentRebalancePurseRequest; export import HostCoinPaymentRefundRequest = T.HostCoinPaymentRefundRequest; export import HostContactsPickError = T.HostContactsPickError; +export import HostContactsPickManyError = T.HostContactsPickManyError; +export import HostContactsPickManyRequest = T.HostContactsPickManyRequest; +export import HostContactsPickManyResponse = T.HostContactsPickManyResponse; export import HostContactsPickRequest = T.HostContactsPickRequest; export import HostContactsPickResponse = T.HostContactsPickResponse; +export import HostContactsPlaceLabelsError = T.HostContactsPlaceLabelsError; +export import HostContactsPlaceLabelsRequest = T.HostContactsPlaceLabelsRequest; +export import HostContactsPlaceLabelsResponse = T.HostContactsPlaceLabelsResponse; export import HostCreateTransactionError = T.HostCreateTransactionError; export import HostCreateTransactionResponse = T.HostCreateTransactionResponse; export import HostCreateTransactionWithLegacyAccountResponse = T.HostCreateTransactionWithLegacyAccountResponse; @@ -6450,6 +7182,18 @@ export import HostPaymentTopUpRequest = T.HostPaymentTopUpRequest; export import HostPocketListSubscribeItem = T.HostPocketListSubscribeItem; export import HostPocketRemoveCardError = T.HostPocketRemoveCardError; export import HostPocketRemoveCardRequest = T.HostPocketRemoveCardRequest; +export import HostProfileDiscloseError = T.HostProfileDiscloseError; +export import V01HostProfileDiscloseRequest = T.V01HostProfileDiscloseRequest; +export import HostProfileOwnStatusError = T.HostProfileOwnStatusError; +export import HostProfileOwnStatusResponse = T.HostProfileOwnStatusResponse; +export import HostProfilePlaceContactAvatarsError = T.HostProfilePlaceContactAvatarsError; +export import V01HostProfilePlaceContactAvatarsRequest = T.V01HostProfilePlaceContactAvatarsRequest; +export import HostProfilePresentContactError = T.HostProfilePresentContactError; +export import V01HostProfilePresentContactRequest = T.V01HostProfilePresentContactRequest; +export import HostProfilePresentError = T.HostProfilePresentError; +export import HostProfilePresentOwnError = T.HostProfilePresentOwnError; +export import HostProfilePresentRequest = T.HostProfilePresentRequest; +export import HostProfileRetractError = T.HostProfileRetractError; export import HostPushNotificationCancelRequest = T.HostPushNotificationCancelRequest; export import HostPushNotificationError = T.HostPushNotificationError; export import HostPushNotificationRequest = T.HostPushNotificationRequest; @@ -6513,8 +7257,13 @@ export import HostLocaleSubscribeItem = T.HostLocaleSubscribeItem; export import HostProductDeviceChatError = T.HostProductDeviceChatError; export import V02HostProductDeviceChatRequest = T.V02HostProductDeviceChatRequest; export import V02HostProductDeviceChatResponse = T.V02HostProductDeviceChatResponse; +export import HostProfileDiscloseRequest = T.HostProfileDiscloseRequest; +export import V02HostProfilePlaceContactAvatarsRequest = T.V02HostProfilePlaceContactAvatarsRequest; +export import HostProfilePresentContactRequest = T.HostProfilePresentContactRequest; +export import V03ContactAvatarSlot = T.V03ContactAvatarSlot; export import HostProductDeviceChatRequest = T.HostProductDeviceChatRequest; export import HostProductDeviceChatResponse = T.HostProductDeviceChatResponse; +export import HostProfilePlaceContactAvatarsRequest = T.HostProfilePlaceContactAvatarsRequest; export import VerticalAlignment = T.VerticalAlignment; export import VrfSignature = T.VrfSignature; export import VrfTranscriptItem = T.VrfTranscriptItem; @@ -6970,9 +7719,9 @@ export declare function createTransport(provider: WireProvider, options?: Create // generated/client.d.ts export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; -export declare const TRUAPI_VERSION: 2; +export declare const TRUAPI_VERSION: 3; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "6bbdd3b23a6400bb"; /** Account lookup, aliasing, and proof generation. */ export declare class AccountClient { #private; @@ -7150,8 +7899,8 @@ export declare class CoinPaymentClient { * * A product never reads the contact list. It opens the host's picker; the host * renders an overlay from the chat lists its chat extensions hold, and - * returns only the person the user selected. Names, accounts, and every other - * contact the user did not pick stay host-side. + * returns only handles for the people the user selected. Names, accounts, and + * every other contact the user did not pick stay host-side. * * That is also why there is no permission to request: the user choosing a * contact in host UI is the consent, and a product that is never handed the @@ -7166,13 +7915,30 @@ export declare class ContactsClient { * Resolves with the chosen contact's handle, or with why nothing was * chosen. A host that serves no picker answers \`Unsupported\`. * - * The handle is not an address and cannot be turned into one. To pay the - * person it names, put the handle where the recipient goes in the call and - * list it in \`contacts\` on the transaction payload: the host replaces it - * with their account before anything is signed or shown. A handle sent - * anywhere else is 32 bytes that resolve to nobody. + * The handle is not an address and cannot be turned into one by a product. + * To pay the person, put the handle where the recipient goes in the call + * and list it in \`contacts\` on the transaction payload: the host replaces + * it with their account before anything is signed or shown. Profile also + * accepts handles as disclosure recipients and as contacts to present or + * draw avatars for, without returning accounts or profile contents. */ pick(request: T.HostContactsPickRequest, options?: CallOptions): ResultAsync>; + /** + * Edit a complete selection in the host's multi-select contact picker. + * + * \`selected\` preselects existing handles. Confirming none returns \`Picked\` + * with an empty \`handles\` list; dismissing never changes the selection. + * Unresolvable initial handles reject the entire request. + */ + pickMany(request: T.HostContactsPickManyRequest, options?: CallOptions): ResultAsync>; + /** + * Draw contact names in host-owned rectangles over the product surface. + * + * Labels do not require a shared Profile photo or disclosure. The response + * reveals no name, identity or per-slot availability. Each call replaces + * the previous placement; empty \`slots\` clears it. + */ + placeLabels(request: T.HostContactsPlaceLabelsRequest, options?: CallOptions): ResultAsync>; } /** Deterministic entropy derivation. */ export declare class EntropyClient { @@ -7301,6 +8067,86 @@ export declare class PreimageClient { /** Submit a preimage. Returns the preimage key (hash) on success. */ submit(request: HexString, options?: CallOptions): ResultAsync>; } +/** + * Profiles shown in host-owned UI. + * + * The product hands over an opaque reference; the host resolves, decrypts and + * renders it. Profile bytes never return to the product. + */ +export declare class ProfileClient { + #private; + constructor(transport: TrUApiTransport); + /** + * Show the referenced profile in host-owned UI. + * + * Resolves once the host has taken the presentation, not when the user + * dismisses it. Loading and fetch failures are shown to the user, not + * returned; a reference this host cannot parse is \`InvalidReference\`. + */ + present(request: T.HostProfilePresentRequest, options?: CallOptions): ResultAsync>; + /** + * Store the user's profile and replace its independent delivery audiences. + * + * \`ChatApps\` shares within every ready Chat App. \`App\` selects one Chat + * App's audience. \`Contacts\` shares personally with picked opaque handles; + * those received profiles may render in any App. An empty audience list + * retains the own profile but withdraws all grants. Unknown handles reject + * the whole disclosure. App executions only. The first disclosure asks + * the user once per product; a refusal is \`PermissionDenied\`. + * v0.1 callers retain the \`ChatApps\` audience. + */ + disclose(request: T.HostProfileDiscloseRequest, options?: CallOptions): ResultAsync>; + /** + * Withdraw the reference this product disclosed. Contacts are told to + * drop what they hold. A product that did not disclose it is refused. + */ + retract(options?: CallOptions): ResultAsync>; + /** + * Show a contact's available profile in host-owned UI. + * + * The selector names a Chat peer or a picked opaque handle. App-scoped + * profiles take precedence over personal profiles. References, names, + * resolved accounts and availability never return to the product. Unknown + * handles, absent profiles and host presentation failures return the same + * success. v0.1 callers retain their \`NotShared\` and presentation errors + * for App-scoped shares only; personal drawers require v0.2 so a legacy + * raw-peer request cannot disclose personal sharing availability. + */ + presentContact(request: T.HostProfilePresentContactRequest, options?: CallOptions): ResultAsync>; + /** + * Tell the host where this product draws contacts' avatars, and + * optionally the signed-in user's own, so it can draw each shared photo + * and mood ring over them on its own layer. + * + * Each call replaces the product's placement; an empty \`slots\` and no + * \`own\` clears it. The own slot is filled only while the user has + * disclosed a profile, and redrawn when they disclose or retract one. + * The host draws only for contacts who shared a profile with the user, + * and keeps the placement current as they share or withdraw one, until + * the product replaces it or goes away. The answer is the same whoever + * shared: nothing about any slot, and no profile data, returns to the + * product. Taps still reach the product, which opens a profile with + * \`presentContact\`. + * + * App executions only. Rects are in the units of the surface size the + * product gives: framebuffer pixels for a PolkaVM product, CSS pixels of + * its viewport for a web product. A placement with more than 64 slots, a + * surface side outside 1 to 16384, an avatar that is not square or is + * outside 1 to 1024 a side, or a \`slot\` repeated across \`own\` and \`slots\` + * is \`Unknown\`. A host that cannot draw over the product is + * \`Unsupported\`; with no user signed in the call is \`NotConnected\`. + */ + placeContactAvatars(request: T.HostProfilePlaceContactAvatarsRequest, options?: CallOptions): ResultAsync>; + /** + * Report whether the signed-in user has configured a profile. + * + * Only the boolean status returns. The profile reference and contents + * remain host-owned. + */ + ownStatus(options?: CallOptions): ResultAsync>; + /** Show the signed-in user's profile in host-owned UI. */ + presentOwn(options?: CallOptions): ResultAsync>; +} /** Product-rendered bodies and the actions triggered inside them. */ export declare class RendererClient { #private; @@ -7504,6 +8350,7 @@ export interface TrUApiClient { readonly permissions: PermissionsClient; readonly pocket: PocketClient; readonly preimage: PreimageClient; + readonly profile: ProfileClient; readonly renderer: RendererClient; readonly resourceAllocation: ResourceAllocationClient; readonly signing: SigningClient;